1
28 package demo.view.entityrelationship;
29
30 import demo.view.DemoBase;
31 import demo.view.entityrelationship.painters.ErdAttributesNodeLabelModel;
32 import demo.view.entityrelationship.painters.ErdRealizerFactory;
33 import demo.view.flowchart.FlowchartView;
34 import y.base.Edge;
35 import y.io.GraphMLIOHandler;
36 import y.io.graphml.graph2d.Graph2DGraphMLHandler;
37 import y.layout.orthogonal.EdgeLayoutDescriptor;
38 import y.layout.orthogonal.OrthogonalLayouter;
39 import y.module.ModuleEvent;
40 import y.module.ModuleListener;
41 import demo.layout.module.OrthogonalLayoutModule;
42 import y.option.OptionHandler;
43 import y.util.DataProviderAdapter;
44 import y.view.Arrow;
45 import y.view.EdgeRealizer;
46 import y.view.EditMode;
47 import y.view.Graph2D;
48 import y.view.Graph2DView;
49 import y.view.Graph2DViewActions;
50 import y.view.HitInfo;
51 import y.view.NodeLabel;
52 import y.view.NodeRealizer;
53 import y.view.ViewMode;
54
55 import javax.swing.AbstractAction;
56 import javax.swing.Action;
57 import javax.swing.BorderFactory;
58 import javax.swing.JComponent;
59 import javax.swing.JLabel;
60 import javax.swing.JMenu;
61 import javax.swing.JMenuBar;
62 import javax.swing.JMenuItem;
63 import javax.swing.JPanel;
64 import javax.swing.JSplitPane;
65 import javax.swing.JToolBar;
66 import java.awt.BorderLayout;
67 import java.awt.Color;
68 import java.awt.EventQueue;
69 import java.awt.Font;
70 import java.awt.event.ActionEvent;
71 import java.beans.PropertyChangeEvent;
72 import java.beans.PropertyChangeListener;
73 import java.util.Iterator;
74 import java.util.Locale;
75
76
90 public class EntityRelationshipDemo extends DemoBase {
91
92
93 private static final String[] EXAMPLES_FILE_NAMES = {
94 "chen.graphml",
95 "crows_foot.graphml",
96 "space_database.graphml",
97 "hospital.graphml"
98 };
99
100
101 EntityRelationshipPalette palette;
102
103 private OrthogonalLayoutModule module;
104
105
106 public EntityRelationshipDemo(){
107 super();
108
109 JPanel panelPalette = createTitledPanel(palette, "ERD Palette");
110 contentPane.add(new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, panelPalette, view), BorderLayout.CENTER);
111
112 loadGraph("resource/graphs/" + EXAMPLES_FILE_NAMES[0]);
113 }
114
115
116 protected void initialize() {
117 palette = new EntityRelationshipPalette(view);
118 palette.setSnapMode(true);
119
120 module = new OrthogonalLayoutModule();
122 OptionHandler defaultSettings = module.getOptionHandler();
123 defaultSettings.set("LAYOUT", "STYLE", "NORMAL_TREE");
124 defaultSettings.set("LAYOUT", "GRID", new Integer(5));
125 defaultSettings.set("LAYOUT", "USE_FACE_MAXIMIZATION", Boolean.TRUE);
126 defaultSettings.set("LABELING", "EDGE_LABELING", "GENERIC");
127 defaultSettings.set("LABELING", "EDGE_LABEL_MODEL", "AS_IS");
128 defaultSettings.getItem("LAYOUT", "MINIMUM_FIRST_SEGMENT_LENGTH").setEnabled(false);
129 defaultSettings.getItem("LAYOUT", "MINIMUM_LAST_SEGMENT_LENGTH").setEnabled(false);
130 defaultSettings.getItem("LAYOUT", "MINIMUM_SEGMENT_LENGTH").setEnabled(false);
131
132 module.addModuleListener(new ModuleListener() {
135 public void moduleEventHappened(ModuleEvent moduleEvent) {
136 short type = moduleEvent.getEventType();
137 final Graph2D graph = view.getGraph2D();
138 if (type == ModuleEvent.TYPE_MODULE_INITIALIZING) {
139 graph.addDataProvider(OrthogonalLayouter.EDGE_LAYOUT_DESCRIPTOR_DPKEY,
141 new DataProviderAdapter() {
142 public Object get(Object dataHolder) {
143 EdgeRealizer realizer = graph.getRealizer(
144 ((Edge) dataHolder));
145 Arrow sourceArrow = realizer.getSourceArrow();
146 Arrow targetArrow = realizer.getTargetArrow();
147 EdgeLayoutDescriptor descriptor = new EdgeLayoutDescriptor();
148 descriptor.setMinimumFirstSegmentLength(getArrowLength(sourceArrow) + 10);
149 descriptor.setMinimumLastSegmentLength(getArrowLength(targetArrow) + 10);
150 return descriptor;
151 }
152 });
153 } else if (type == ModuleEvent.TYPE_MODULE_DISPOSED) {
154 graph.removeDataProvider(OrthogonalLayouter.EDGE_LAYOUT_DESCRIPTOR_DPKEY);
156 }
157 }
158
159 private double getArrowLength(Arrow arrow) {
160 switch (arrow.getType()) {
161 case Arrow.CROWS_FOOT_ONE_TYPE:
162 return 10;
163 case Arrow.CROWS_FOOT_ONE_MANDATORY_TYPE:
164 return 15;
165 case Arrow.CROWS_FOOT_ONE_OPTIONAL_TYPE:
166 return 20;
167 case Arrow.CROWS_FOOT_MANY_TYPE:
168 return 10;
169 case Arrow.CROWS_FOOT_MANY_MANDATORY_TYPE:
170 return 15;
171 case Arrow.CROWS_FOOT_MANY_OPTIONAL_TYPE:
172 return 20;
173 default:
174 return arrow.getArrowLength();
175 }
176 }
177 });
178 }
179
180
181 protected void registerViewActions() {
182 super.registerViewActions();
183 final Action action = view.getCanvasComponent().getActionMap().get(Graph2DViewActions.EDIT_LABEL);
184 action.putValue("PROPERTY_CHANGE_LISTENER", new LabelChangeHandler());
185 }
186
187
188 protected void registerViewModes() {
189 }
190
191
197 protected GraphMLIOHandler createGraphMLIOHandler() {
198 GraphMLIOHandler graphMLIOHandler = super.createGraphMLIOHandler();
199 Graph2DGraphMLHandler graphMLHandler = graphMLIOHandler.getGraphMLHandler();
200 ErdAttributesNodeLabelModel.Handler handler = new ErdAttributesNodeLabelModel.Handler();
201 graphMLHandler.addSerializationHandler(handler);
202 graphMLHandler.addDeserializationHandler(handler);
203
204 return graphMLIOHandler;
205 }
206
207
211 protected JMenuBar createMenuBar() {
212 JMenu examplesMenu = new JMenu("Examples");
213 for (int i = 0; i < EXAMPLES_FILE_NAMES.length; i++) {
214 final String fileName = EXAMPLES_FILE_NAMES[i];
215 examplesMenu.add(new JMenuItem(new AbstractAction(fileName) {
216 public void actionPerformed(ActionEvent e) {
217 loadGraph("resource/graphs/" + fileName);
218 }
219 }));
220 }
221
222 JMenuBar menuBar = super.createMenuBar();
223 menuBar.add(examplesMenu);
224 return menuBar;
225 }
226
227
232 protected JToolBar createToolBar() {
233 JToolBar toolBar = super.createToolBar();
234 toolBar.addSeparator();
235 toolBar.add(createActionControl(createOrthogonalLayoutAction()));
236 toolBar.addSeparator();
237 toolBar.add(createCrowsFootNotationAction());
238 toolBar.addSeparator(TOOLBAR_SMALL_SEPARATOR);
239 toolBar.add(createChenNotationAction());
240 return toolBar;
241 }
242
243
247 private Action createCrowsFootNotationAction(){
248 Action action = new AbstractAction("Convert to Crow's Foot") {
249
250 public void actionPerformed(ActionEvent e){
251 Graph2D graph = view.getGraph2D();
252 try{
253 graph.firePreEvent();
254 ErdNotationConverter.convertToCrowFoot(graph);
255 module.start(view.getGraph2D());
256 }finally {
257 graph.firePostEvent();
258 }
259
260 view.fitContent();
261 view.updateView();
262 }
263 };
264
265 return action;
266 }
267
268
272 private Action createChenNotationAction(){
273 Action action = new AbstractAction("Convert to Chen") {
274
275 public void actionPerformed(ActionEvent e){
276 Graph2D graph = view.getGraph2D();
277 try{
278 graph.firePreEvent();
279 ErdNotationConverter.convertToChen(graph);
280 module.start(view.getGraph2D());
281 }finally {
282 graph.firePostEvent();
283 }
284
285 view.fitContent();
286 view.updateView();
287 }
288 };
289
290 return action;
291 }
292
293
298 private Action createOrthogonalLayoutAction() {
299 Action action = new AbstractAction("Layout") {
300 public void actionPerformed(ActionEvent e) {
301 OptionSupport.showDialog(module, view.getGraph2D(), true, view.getFrame());
302 }
303 };
304 action.putValue(Action.SHORT_DESCRIPTION, "Configure and run the layout algorithm");
305 action.putValue(Action.SMALL_ICON, SHARED_LAYOUT_ICON);
306
307 return action;
308 }
309
310
316 protected JPanel createTitledPanel(JComponent content, String title) {
317 JLabel label = new JLabel(title);
318 label.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
319 label.setBackground(new Color(231, 219, 182));
320 label.setOpaque(true);
321 label.setForeground(Color.DARK_GRAY);
322 label.setFont(label.getFont().deriveFont(Font.BOLD));
323 label.setFont(label.getFont().deriveFont(13.0f));
324
325 JPanel panel = new JPanel();
326 panel.setLayout(new BorderLayout());
327 panel.add(label, BorderLayout.NORTH);
328 panel.add(content, BorderLayout.CENTER);
329 return panel;
330 }
331
332
335 protected Graph2DView createGraphView() {
336 Graph2DView view = new FlowchartView();
337 for (Iterator iterator = view.getViewModes(); iterator.hasNext(); ) {
338 final Object next = iterator.next();
339 if (next instanceof EditMode) {
340 final EditMode editMode = (EditMode) next;
341 editMode.setCyclicSelectionEnabled(true);
342 editMode.setPopupMode(new EntityRelationshipPopupMode());
343 }
344 }
345 view.addViewMode(new ViewMode(){
346
347 public void mouseClicked(double x, double y) {
349 if(lastClickEvent != null && lastClickEvent.getClickCount() == 2){
350 final HitInfo hitInfo = getHitInfo(x, y);
351 if (hitInfo.hasHitNodeLabels()) {
352 view.openLabelEditor(hitInfo.getHitNodeLabel(),x,y,new LabelChangeHandler(), true);
353 }else {
354 if (hitInfo.hasHitNodes()){
355 final NodeRealizer realizer = view.getGraph2D().getRealizer(hitInfo.getHitNode());
356 for(int i=realizer.labelCount(); i --> 0;){
357 final NodeLabel label = realizer.getLabel(i);
358 if (label.contains(x,y)) {
359 view.openLabelEditor(label,x,y,new LabelChangeHandler(), true);
360 return;
361 }
362 }
363 }
364 }
365 }
366 }
367 });
368 view.setFitContentOnResize(true);
369 return view;
370 }
371
372
376 public static void main(String[] args) {
377 EventQueue.invokeLater(new Runnable() {
378
379 public void run() {
380 Locale.setDefault(Locale.ENGLISH);
381 initLnF();
382 final EntityRelationshipDemo demo = new EntityRelationshipDemo();
383 demo.start();
384 }
385 });
386 }
387
388
392 private class LabelChangeHandler implements PropertyChangeListener {
393 public void propertyChange(PropertyChangeEvent e) {
394 final Object source = e.getSource();
395 if (source instanceof NodeLabel){
396 NodeLabel srcLabel = (NodeLabel) source;
397 NodeRealizer realizer = view.getGraph2D().getRealizer(srcLabel.getNode());
398 if(ErdRealizerFactory.isBigEntityRealizer(realizer)
399 || ErdRealizerFactory.isSmallEntityRealizer(realizer)){
400 double newHeight = 0;
401 double newWidth = 0;
402 for (int i=0; i < realizer.labelCount(); i++){
403 newHeight += realizer.getLabel(i).getBox().getHeight();
404 newWidth = Math.max(newWidth, realizer.getLabel(i).getBox().getWidth());
405 }
406 if(newHeight > realizer.getHeight()) {
407 realizer.setHeight(newHeight + 15);
408 }
409 if(newWidth > realizer.getWidth()) {
410 realizer.setWidth(newWidth + 15);
411 }
412 }
413 }
414 }
415 }
416 }
417