1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package zeus.gui.graph;
25
26 import java.awt.*;
27 import java.awt.event.*;
28 import java.util.*;
29 import javax.swing.*;
30 import javax.swing.event.*;
31
32 import zeus.util.*;
33
34 public class Graph extends MovePanel
35 implements GraphIconListener,
36 GraphModelListener,
37 GraphNodeEditorListener {
38
39 public static final int VERTICAL_PARENT_CHILD = 0;
40 public static final int VERTICAL_CHILD_PARENT = 1;
41 public static final int HORIZONTAL_PARENT_CHILD = 2;
42 public static final int HORIZONTAL_CHILD_PARENT = 3;
43 public static final int CENTRED = 4;
44 public static final int CIRCLES = 5;
45
46 protected static final int ORG_DX = 20;
47 protected static final int ORG_DY = 20;
48
49 protected static final double HEIGHT_FACTOR = 2.0;
50
51 protected static final int BETA = 30;
52 protected static final int GAMMA = 20;
53
54 protected static final int BOTTOM_EDGE = 1;
55 protected static final int TOP_EDGE = 2;
56 protected static final int LEFT_EDGE = 3;
57 protected static final int RIGHT_EDGE = 4;
58
59 protected Hashtable ViewList = new Hashtable();
60 protected GraphModel model;
61 protected GraphNodeRenderer nodeRenderer = null;
62 protected GraphNodeEditor nodeEditor = null;
63 protected Component nodeEditorComponent = null;
64 protected JLayeredPane pane = null;
65 protected boolean isNodeEditable;
66 protected boolean isLinkEditable;
67 protected int viewMode;
68
69 private Point startPoint = null;
70 private Point lastPoint = null;
71 private Point stretchedPoint= null;
72 private GraphIcon sourceIcon = null;
73 private GraphIcon destIcon = null;
74
75 public Graph(int viewMode, GraphModel model, boolean isNodeEditable,
76 boolean isLinkEditable) {
77 super(2000,2000);
78 this.setLayout(new BulletinLayout());
79 this.model = model;
80 this.isNodeEditable = isNodeEditable;
81 this.isLinkEditable = isLinkEditable;
82 this.viewMode = viewMode;
83 model.addGraphModelListener(this);
84 }
85
86
87 public Graph(GraphModel model, boolean isNodeEditable,
88 boolean isLinkEditable) {
89 this(HORIZONTAL_CHILD_PARENT,model,isNodeEditable,isLinkEditable);
90 }
91
92
93 public Graph(GraphModel model) {
94 this(HORIZONTAL_CHILD_PARENT,model,true,true);
95 }
96
97
98
99
100 public void setModel(GraphModel model) {
101 this.model.removeGraphModelListener(this);
102 this.model = model;
103 this.model.addGraphModelListener(this);
104 reset();
105 }
106
107
108 public GraphModel getModel() { return model; }
109
110 public void setViewMode(int mode) {
111 switch( mode ) {
112 case HORIZONTAL_PARENT_CHILD:
113 case HORIZONTAL_CHILD_PARENT:
114 case VERTICAL_PARENT_CHILD:
115 case VERTICAL_CHILD_PARENT:
116 case CIRCLES:
117 case CENTRED:
118 viewMode = mode;
119 break;
120 default:
121 Core.USER_ERROR("Attempt to set an illegal view mode: " + mode);
122 break;
123 }
124 }
125
126 public GraphNodeRenderer getNodeRenderer() {
127 return nodeRenderer;
128 }
129
130
131 public void setNodeRenderer(GraphNodeRenderer nodeRenderer) {
132 this.nodeRenderer = nodeRenderer;
133 }
134
135
136 public GraphNodeEditor getNodeEditor() {
137 return nodeEditor;
138 }
139
140
141 public void setNodeEditor(GraphNodeEditor nodeEditor) {
142 if ( this.nodeEditor != null )
143 this.nodeEditor.removeGraphNodeEditorListener(this);
144
145 this.nodeEditor = nodeEditor;
146
147 if ( this.nodeEditor != null )
148 this.nodeEditor.addGraphNodeEditorListener(this);
149 }
150
151
152 public void addNotify() {
153 super.addNotify();
154 reset();
155 }
156
157
158 public boolean isVisible(GraphNode node) {
159 GraphIcon icon = (GraphIcon)ViewList.get(node);
160 return icon != null && icon.isVisible();
161 }
162
163
164 public Rectangle getBounds(GraphNode node) {
165 GraphIcon icon = (GraphIcon)ViewList.get(node);
166 if ( icon != null )
167 return icon.getBounds();
168 else {
169 Core.USER_ERROR("getBounds called on a null node");
170 return new Rectangle(0,0,0,0);
171 }
172 }
173
174 protected void reset() {
175
176 GraphIcon icon;
177 Enumeration enum = ViewList.elements();
178 while( enum.hasMoreElements() ) {
179 icon = (GraphIcon)enum.nextElement();
180 icon.removeGraphIconListener(this);
181 }
182
183 ViewList.clear();
184 this.removeAll();
185
186 enum = model.nodes();
187 while( enum.hasMoreElements() )
188 addNode((GraphNode)enum.nextElement());
189 recompute();
190 }
191
192
193 protected void addNode(GraphNode node) {
194 GraphIcon icon;
195 Rectangle rect = new Rectangle(0,0,0,0);
196 Enumeration enum = ViewList.elements();
197 while( enum.hasMoreElements() ) {
198 icon = (GraphIcon)enum.nextElement();
199 rect = rect.union(icon.getBounds());
200 }
201 icon = new GraphIcon(node,this);
202 ViewList.put(node,icon);
203 this.add(icon);
204 icon.setLocation(new Point(rect.x+rect.width,rect.y));
205 icon.addGraphIconListener(this);
206 }
207
208
209 protected void removeNode(GraphNode node) {
210 GraphIcon icon = (GraphIcon)ViewList.remove(node);
211 if ( icon != null ) {
212 this.remove(icon);
213 icon.removeGraphIconListener(this);
214 }
215 }
216 protected void updateNode(GraphNode node) {
217 GraphIcon icon = (GraphIcon)ViewList.get(node);
218 if ( icon != null )
219 icon.reset();
220 }
221
222 public void hide() {
223 GraphIcon icon;
224 Enumeration enum = ViewList.elements();
225 while( enum.hasMoreElements() ) {
226 icon = (GraphIcon)enum.nextElement();
227 if ( icon.isSelected() ) icon.setVisible(false);
228 }
229 repaint();
230 }
231
232 public void show() {
233 GraphIcon icon;
234 Enumeration enum = ViewList.elements();
235 while( enum.hasMoreElements() ) {
236 icon = (GraphIcon)enum.nextElement();
237 if ( !icon.isVisible() ) icon.setVisible(true);
238 }
239 repaint();
240 }
241
242 public void collapse() {
243 GraphIcon icon;
244 Enumeration enum = ViewList.elements();
245 while( enum.hasMoreElements() ) {
246 icon = (GraphIcon)enum.nextElement();
247 if ( icon.isSelected() )
248 collapseNode(icon.getGraphNode(), new Vector());
249 }
250 repaint();
251 }
252
253 public void expand() {
254 GraphIcon icon;
255 Enumeration enum = ViewList.elements();
256 while( enum.hasMoreElements() ) {
257 icon = (GraphIcon)enum.nextElement();
258 if ( icon.isSelected() )
259 expandNode(icon.getGraphNode(), new Vector());
260 }
261 repaint();
262 }
263
264 public GraphNode[] getSelectedNodes() {
265 GraphIcon icon;
266 Vector items = new Vector();
267 Enumeration enum = ViewList.elements();
268 while( enum.hasMoreElements() ) {
269 icon = (GraphIcon)enum.nextElement();
270 if ( icon.isSelected() )
271 items.addElement(icon);
272 }
273
274 GraphNode[] out = new GraphNode[items.size()];
275 for(int i = 0; i < out.length; i++ )
276 out[i] = ((GraphIcon)items.elementAt(i)).getGraphNode();
277 return out;
278 }
279
280 protected void collapseNode(GraphNode node, Vector doneList) {
281 GraphNode[] children = node.getChildren();
282 doneList.addElement(node);
283 for(int i = 0; i < children.length; i++ ) {
284 GraphIcon icon = (GraphIcon)ViewList.get(children[i]);
285 if ( icon != null ) {
286 icon.setVisible(false);
287 icon.setSelected(false);
288 if ( !doneList.contains(children[i]) )
289 collapseNode(children[i],doneList);
290 }
291 }
292 }
293
294 protected void expandNode(GraphNode node, Vector doneList) {
295 GraphNode[] children = node.getChildren();
296 doneList.addElement(node);
297 for(int i = 0; i < children.length; i++ ) {
298 GraphIcon icon = (GraphIcon)ViewList.get(children[i]);
299 if ( icon != null ) {
300 icon.setVisible(true);
301 if ( !doneList.contains(children[i]) )
302 expandNode(children[i],doneList);
303 }
304 }
305 }
306
307 public void select() {
308 Vector items;
309 GraphIcon icon;
310 if ( (items = this.boundedItems()) != null ) {
311 boolean all_selected = true;
312 for( int i = 0; i < items.size(); i++ ) {
313 icon = (GraphIcon)items.elementAt(i);
314 all_selected = all_selected && icon.isSelected();
315 if ( !all_selected) break;
316 }
317
318 for( int i = 0; i < items.size(); i++ ) {
319 icon = (GraphIcon)items.elementAt(i);
320 if ( all_selected )
321 icon.setSelected(false);
322 else
323 icon.setSelected(true);
324 }
325 }
326 }
327
328 public void selectAll() {
329 GraphIcon icon;
330 boolean all_selected = true;
331 Enumeration enum = ViewList.elements();
332 while( enum.hasMoreElements() ) {
333 icon = (GraphIcon)enum.nextElement();
334 all_selected = all_selected && icon.isSelected();
335 if ( !all_selected) break;
336 }
337
338 enum = ViewList.elements();
339 while( enum.hasMoreElements() ) {
340 icon = (GraphIcon)enum.nextElement();
341 if ( all_selected )
342 icon.setSelected(false);
343 else
344 icon.setSelected(true);
345 }
346 }
347
348 public void recompute() {
349 Point p = new Point(0,0);
350 GraphNode node;
351 GraphIcon icon;
352 Enumeration enum;
353
354 Rectangle bb;
355 Point pt;
356 Rectangle rect;
357
358 Vector doneList = new Vector();
359 switch( viewMode ) {
360 case VERTICAL_PARENT_CHILD:
361 case VERTICAL_CHILD_PARENT:
362 p.x = ORG_DX; p.y = ORG_DY;
363 enum = ViewList.elements();
364 while( enum.hasMoreElements() ) {
365 icon = (GraphIcon)enum.nextElement();
366 node = icon.getGraphNode();
367 if ( icon.isVisible() && node.getNodeType() == GraphNode.PARENT )
368 computeVerticalPosition(node,doneList,p);
369 }
370
371 enum = ViewList.elements();
372 while( enum.hasMoreElements() ) {
373 icon = (GraphIcon)enum.nextElement();
374 node = icon.getGraphNode();
375 if ( icon.isVisible() && node.getNodeType() == GraphNode.CHILD &&
376 !doneList.contains(node) )
377 computeVerticalPosition(node,doneList,p);
378 }
379
380 if ( viewMode == VERTICAL_PARENT_CHILD )
381 break;
382
383 rect = getDrawArea(doneList);
384 int ym = rect.y + rect.height/2;
385 enum = doneList.elements();
386 while( enum.hasMoreElements() ) {
387 node = (GraphNode)enum.nextElement();
388 icon = (GraphIcon)ViewList.get(node);
389 bb = icon.getBounds();
390 pt = new Point(bb.x,bb.y+bb.height);
391
392 pt = new Point(pt.x, 2*ym - pt.y);
393
394 icon.setLocation(pt);
395 }
396 break;
397
398 case HORIZONTAL_PARENT_CHILD:
399 case HORIZONTAL_CHILD_PARENT:
400 enum = ViewList.elements();
401 while( enum.hasMoreElements() ) {
402 icon = (GraphIcon)enum.nextElement();
403 node = icon.getGraphNode();
404 if ( icon.isVisible() && node.getNodeType() == GraphNode.PARENT )
405 computeHorizontalPosition(node,doneList,p);
406 }
407
408 enum = ViewList.elements();
409 while( enum.hasMoreElements() ) {
410 icon = (GraphIcon)enum.nextElement();
411 node = icon.getGraphNode();
412 if ( icon.isVisible() && node.getNodeType() == GraphNode.CHILD &&
413 !doneList.contains(node) )
414 computeHorizontalPosition(node,doneList,p);
415 }
416
417 rect = getDrawArea(doneList);
418
419 enum = doneList.elements();
420 while( enum.hasMoreElements() ) {
421 node = (GraphNode)enum.nextElement();
422 icon = (GraphIcon)ViewList.get(node);
423 pt = icon.getLocation();
424 icon.setLocation(pt.x-rect.x+ORG_DX,pt.y-rect.y+ORG_DY);
425 }
426
427 if ( viewMode == HORIZONTAL_CHILD_PARENT )
428 break;
429
430 rect = getDrawArea(doneList);
431 int xm = rect.x + rect.width/2;
432 enum = doneList.elements();
433 while( enum.hasMoreElements() ) {
434 node = (GraphNode)enum.nextElement();
435 icon = (GraphIcon)ViewList.get(node);
436 bb = icon.getBounds();
437 pt = new Point(bb.x + bb.width, bb.y);
438
439 pt = new Point(2*xm - pt.x + ORG_DX, pt.y - ORG_DY);
440 icon.setLocation(pt);
441 }
442 break;
443
444
445 case CENTRED:
446 GraphNode[] nodes = getSelectedNodes();
447 node = null;
448 boolean found = false;
449 if ( nodes.length > 0 ) {
450 for(int i = 0; !found && i < nodes.length; i++ ) {
451 node = nodes[i];
452 icon = (GraphIcon)ViewList.get(node);
453 found = icon.isVisible();
454 }
455 }
456
457 if ( !found && !ViewList.isEmpty() ) {
458 enum = ViewList.keys();
459 while( !found && enum.hasMoreElements() ) {
460 node = (GraphNode)enum.nextElement();
461 icon = (GraphIcon)ViewList.get(node);
462 found = icon.isVisible();
463 }
464 }
465 if ( !found ) break;
466
467 GraphNode middleNode = node;
468
469 enum = ViewList.keys();
470 while( enum.hasMoreElements() ) {
471 node = (GraphNode)enum.nextElement();
472 icon = (GraphIcon)ViewList.get(node);
473 if ( icon.isVisible() )
474 doneList.addElement(node);
475 }
476 centerView(middleNode,doneList);
477 break;
478
479 case CIRCLES:
480 p.x = ORG_DX; p.y = ORG_DY;
481 enum = ViewList.elements();
482 while( enum.hasMoreElements() ) {
483 icon = (GraphIcon)enum.nextElement();
484 node = icon.getGraphNode();
485 if ( icon.isVisible() )
486 computeCircularPosition(node,doneList,p);
487 }
488 break;
489 }
490 redraw();
491 }
492
493 protected Rectangle getDrawArea(Vector doneList) {
494 Rectangle rect = new Rectangle(0,0,0,0);
495 Enumeration enum = ViewList.elements();
496 GraphIcon icon;
497 GraphNode node;
498 while( enum.hasMoreElements() ) {
499 icon = (GraphIcon)enum.nextElement();
500 node = icon.getGraphNode();
501 if ( doneList.contains(node) )
502 rect = rect.union(icon.getBounds());
503 }
504 return rect;
505 }
506
507 public void redraw() {
508 invalidate();
509 repaint();
510 }
511
512 public void paintComponent(Graphics g){
513 Dimension d = this.getSize();
514 super.paintComponent(g);
515 drawLinks(g);
516 }
517
518 protected void drawLinks(Graphics graphics) {
519 GraphNode node;
520 GraphIcon icon;
521
522 Enumeration enum = ViewList.elements();
523 while( enum.hasMoreElements() ) {
524 icon = (GraphIcon)enum.nextElement();
525 node = icon.getGraphNode();
526 if ( icon.isVisible() )
527 drawLinks(node,graphics);
528 }
529 revalidate();
530 }
531
532 protected void getRelations(Vector doList, Vector doneList) {
533 Vector items;
534 GraphNode node;
535
536 for(int i = 0; i < doList.size(); i++ ) {
537 node = (GraphNode)doList.elementAt(i);
538 if ( !doneList.contains(node) ) {
539 doneList.addElement(node);
540 items = model.getViewRelations(node);
541 items = Misc.difference(items,doneList);
542 getRelations(items,doneList);
543 }
544 }
545 }
546
547 protected boolean computeCircularPosition(GraphNode self, Vector doneList,
548 Point p) {
549
550 if ( doneList.contains(self) ) return false;
551
552 GraphIcon icon;
553 GraphNode node;
554 Dimension size;
555 int Wm, Hm, Wt, Ht, R;
556 double theta, phi;
557 int xx, yy;
558 Point pa = new Point(0,0);
559
560 Vector aList = new Vector();
561 aList.addElement(self);
562 getRelations(model.getViewRelations(self),aList);
563
564
565
566 for(int i = 0; i < aList.size(); i++ ) {
567 node = (GraphNode)aList.elementAt(i);
568 icon = (GraphIcon)ViewList.get(node);
569 doneList.addElement(node);
570 if ( !icon.isVisible() )
571 aList.removeElementAt(i--);
572 }
573
574 if ( aList.size() <= 2 ) {
575 for(int i = 0; i < aList.size(); i++ ) {
576 node = (GraphNode)aList.elementAt(i);
577 icon = (GraphIcon)ViewList.get(node);
578 size = icon.getSize();
579 pa.x = p.x+(BETA+size.width)/2;
580 pa.y = p.y+(3*GAMMA+size.height)/2;
581 icon.setLocation(new Point(pa.x - size.width/2, pa.y - size.height/2));
582 p.x += size.width+BETA;
583 }
584 return true;
585 }
586
587 Dimension[] wh = new Dimension[aList.size()];
588 Wm = Hm = 0;
589 for(int i = 0; i < aList.size(); i++ ) {
590 node = (GraphNode)aList.elementAt(i);
591 icon = (GraphIcon)ViewList.get(node);
592 wh[i] = icon.getSize();
593 Wm = Math.max(Wm,wh[i].width);
594 Hm = Math.max(Hm,wh[i].height);
595 }
596 R = (int)(HEIGHT_FACTOR*Hm/Math.tan(Math.PI/aList.size()));
597 Wt = (2*Wm+BETA+2*R);
598 Ht = (2*Hm+GAMMA+2*R);
599 xx = p.x + Wt/2;
600 yy = p.y + Ht/2;
601
602 p.x += Wt;
603
604 theta = (2*Math.PI/aList.size());
605 for(int i = 0; i < aList.size(); i++ ) {
606 phi = i*theta;
607 pa.x = (int)(xx + R*Math.cos(phi)) - wh[i].width/2;
608 pa.y = (int)(yy + R*Math.sin(phi)) - wh[i].height/2;
609 node = (GraphNode)aList.elementAt(i);
610 icon = (GraphIcon)ViewList.get(node);
611 icon.setLocation(pa);
612 }
613 return true;
614 }
615
616 protected boolean centerView(GraphNode self, Vector aList) {
617 /***
618 Centers everyone about self.
619 Only visible nodes are passed to this method.
620 */
621
622 GraphIcon icon = (GraphIcon)ViewList.get(self);
623 if ( icon == null )
624 return false;
625
626 Dimension ps;
627 if ( (getParent()).getClass() == JViewport.class ) {
628
629 JViewport viewport = (JViewport)getParent();
630 viewport.setViewPosition(new Point(0,0));
631 ps = viewport.getSize();
632 }
633 else {
634
635 ps = getSize();
636 }
637
638 Dimension ms = icon.getSize();
639 int R = Math.min(ps.width,ps.height)/2;
640
641 icon.setLocation(new Point(ps.width/2 - ms.width/2,
642 ps.height/2 - ms.height/2));
643
644 int sr = (ms.width+ms.height)/2;
645 int n = 0;
646 GraphNode node;
647 for(int i = 0; i < aList.size(); i++ ) {
648 node = (GraphNode)aList.elementAt(i);
649 if ( node != self && (icon = (GraphIcon)ViewList.get(node)) != null ) {
650 ms = icon.getSize();
651 sr += (ms.width+ms.height)/2;
652 n++;
653 }
654 }
655
656 if ( n != 0 ) {
657 R -= sr/n;
658 double phi;
659 Point pa = new Point(0,0);
660 double theta = (2*Math.PI/n);
661 int j = 0;
662 for(int i = 0; i < aList.size(); i++ ) {
663 node = (GraphNode)aList.elementAt(i);
664 if ( node != self && (icon = (GraphIcon)ViewList.get(node)) != null ) {
665 phi = j*theta;
666 pa.x = (int)(ps.width/2 + R*Math.cos(phi));
667 pa.y = (int)(ps.height/2 + R*Math.sin(phi));
668 ms = icon.getSize();
669 icon.setLocation(new Point(pa.x - ms.width/2,pa.y - ms.height/2));
670 j++;
671 }
672 }
673 }
674 return false;
675 }
676
677 public boolean computeHorizontalPosition(GraphNode self, Vector doneList,
678 Point p) {
679 GraphNode node;
680 Dimension size;
681 Point p0 = new Point(0,0);
682 Point p1 = new Point(0,0);
683 Point loc = new Point(0,0);
684
685 if ( doneList.contains(self) )
686 return false;
687
688 doneList.addElement(self);
689 GraphIcon icon = (GraphIcon)ViewList.get(self);
690 if ( icon == null )
691 return false;
692
693 if ( !icon.isVisible() )
694 return false;
695
696 GraphNode[] children = self.getChildren();
697 Vector Items = new Vector();
698 for(int i = 0; i < children.length; i++ ) {
699 if ( !doneList.contains(children[i]) )
700 Items.addElement(children[i]);
701 }
702
703 size = icon.getSize();
704 if ( Items.isEmpty() ) {
705 loc.y = p.y+(3*GAMMA+size.height)/2 - size.height/2;
706 loc.x = p.x-(BETA+size.width)/2 - size.width/2;
707
708 icon.setLocation(loc);
709
710 p.y += size.height+3*GAMMA;
711 }
712 else {
713 p0.y = p.y;
714 p0.x = p.x-(size.width+BETA);
715
716 for(int i = 0; i < Items.size(); i++ ) {
717 node = (GraphNode) Items.elementAt(i);
718 computeHorizontalPosition(node,doneList,p0);
719 }
720 loc.y = (p.y+p0.y)/2 - size.height/2;
721 loc.x = p.x-(size.width+BETA)/2 - size.width/2;
722
723 icon.setLocation(loc);
724
725 p.y = p0.y;
726 }
727
728 GraphNode[] siblings = self.getSiblings();
729 for(int i = 0; i < siblings.length; i++ ) {
730 if ( !doneList.contains(siblings[i]) )
731 computeHorizontalPosition(siblings[i],doneList,p);
732 }
733 return true;
734 }
735
736 public boolean computeVerticalPosition(GraphNode self, Vector doneList, Point p) {
737 GraphNode node;
738 Dimension size;
739 Point p0 = new Point(0,0);
740 Point p1 = new Point(0,0);
741 Point loc = new Point(0,0);
742
743 if ( doneList.contains(self) )
744 return false;
745
746 doneList.addElement(self);
747 GraphIcon icon = (GraphIcon)ViewList.get(self);
748 if ( icon == null )
749 return false;
750
751 if ( !icon.isVisible() )
752 return false;
753
754 GraphNode[] children = self.getChildren();
755 Vector Items = new Vector();
756 for(int i = 0; i < children.length; i++ ) {
757 if ( !doneList.contains(children[i]) )
758 Items.addElement(children[i]);
759 }
760
761 size = icon.getSize();
762 if ( Items.isEmpty() ) {
763 loc.x = p.x+(BETA+size.width)/2 - size.width/2;
764 loc.y = p.y+(3*GAMMA+size.height)/2 - size.height/2;
765
766 icon.setLocation(loc);
767 p.x += size.width+BETA;
768 }
769 else {
770 p0.x = p.x;
771 p0.y = p.y+size.height+3*GAMMA;
772
773 for(int i = 0; i < Items.size(); i++ ) {
774 node = (GraphNode) Items.elementAt(i);
775 computeVerticalPosition(node,doneList,p0);
776 }
777 loc.x = (p.x+p0.x)/2 - size.width/2;
778 loc.y = p.y+(size.height+3*GAMMA)/2 - size.height/2;
779
780 icon.setLocation(loc);
781
782 p.x = p0.x;
783 }
784
785 GraphNode[] siblings = self.getSiblings();
786 for(int i = 0; i < siblings.length; i++ ) {
787 if ( !doneList.contains(siblings[i]) )
788 computeVerticalPosition(siblings[i],doneList,p);
789 }
790
791 return true;
792 }
793
794
795 protected void drawLinks(GraphNode node, Graphics graphics) {
796 GraphIcon icon = (GraphIcon)ViewList.get(node);
797
798 Point p1 = new Point(0,0);
799 Point p2 = new Point(0,0);
800
801 Color color;
802 GraphNode[] parent = node.getParents();
803 for(int i = 0; i < parent.length; i++ ) {
804 if ( model.isLinkVisible(node,parent[i]) &&
805 getConnections(node,parent[i],p1,p2) ) {
806 color = model.getLinkColor(node,parent[i]);
807 drawEdge(color,p1,p2,graphics);
808 }
809 }
810
811 GraphNode[] children = node.getChildren();
812 for(int i = 0; i < children.length; i++ ) {
813 if ( model.isLinkVisible(node,children[i]) &&
814 getConnections(node,children[i],p1,p2) ) {
815 color = model.getLinkColor(node,children[i]);
816 drawEdge(color,p1,p2,graphics);
817 }
818 }
819
820 GraphNode[] sibling = node.getSiblings();
821 for(int i = 0; i < sibling.length; i++ ) {
822 if ( model.isLinkVisible(node,sibling[i]) &&
823 getConnections(node,sibling[i],p1,p2) ) {
824 color = model.getLinkColor(node,sibling[i]);
825 drawEdge(color,p1,p2,graphics);
826 }
827 }
828 }
829
830 protected void getConnection(Rectangle bb, int edge, Point p) {
831 switch( edge ) {
832 case BOTTOM_EDGE:
833 p.x = bb.x + bb.width/2;
834 p.y = bb.y;
835 return;
836
837 case TOP_EDGE:
838 p.x = bb.x + bb.width/2;
839 p.y = bb.y + bb.height;
840 return;
841
842 case LEFT_EDGE:
843 p.x = bb.x;
844 p.y = bb.y + bb.height/2;
845 return;
846
847 case RIGHT_EDGE:
848 p.x = bb.x + bb.width;
849 p.y = bb.y + bb.height/2;
850 return;
851
852 default:
853 return;
854 }
855 }
856
857 protected boolean getConnections(GraphNode node1, GraphNode node2,
858 Point p1, Point p2) {
859
860 Rectangle a, b;
861 GraphIcon icon1 = (GraphIcon)ViewList.get(node1);
862 GraphIcon icon2 = (GraphIcon)ViewList.get(node2);
863
864 if ( icon1 == null || icon2 == null ||
865 !icon1.isVisible() || !icon2.isVisible() )
866 return false;
867
868
869 a = icon1.getBounds();
870 b = icon2.getBounds();
871
872 switch( viewMode ) {
873 case HORIZONTAL_CHILD_PARENT:
874 case HORIZONTAL_PARENT_CHILD:
875 if ( b.x > a.x+a.width ) {
876 getConnection(a,RIGHT_EDGE,p1);
877 getConnection(b,LEFT_EDGE,p2);
878 return true;
879 }
880 else if ( b.x+b.width < a.x ) {
881 getConnection(a,LEFT_EDGE,p1);
882 getConnection(b,RIGHT_EDGE,p2);
883 return true;
884 }
885 else if ( b.y > a.y+a.height ) {
886 getConnection(a,TOP_EDGE,p1);
887 getConnection(b,BOTTOM_EDGE,p2);
888 return true;
889 }
890 else if ( b.y+b.height < a.y ) {
891 getConnection(a,BOTTOM_EDGE,p1);
892 getConnection(b,TOP_EDGE,p2);
893 return true;
894 }
895
896 return false;
897
898 default:
899 if ( b.y > a.y+a.height ) {
900 getConnection(a,TOP_EDGE,p1);
901 getConnection(b,BOTTOM_EDGE,p2);
902 return true;
903 }
904 else if ( b.y+b.height < a.y ) {
905 getConnection(a,BOTTOM_EDGE,p1);
906 getConnection(b,TOP_EDGE,p2);
907 return true;
908 }
909 else if ( b.x > a.x+a.width ) {
910 getConnection(a,RIGHT_EDGE,p1);
911 getConnection(b,LEFT_EDGE,p2);
912 return true;
913 }
914 else if ( b.x+b.width < a.x ) {
915 getConnection(a,LEFT_EDGE,p1);
916 getConnection(b,RIGHT_EDGE,p2);
917 return true;
918 }
919 return false;
920 }
921 }
922
923 protected void drawEdge(Color color, Point p1, Point p2, Graphics g) {
924 Point[] pts;
925
926 Color c = g.getColor();
927 g.setColor( color );
928 g.setPaintMode();
929
930 g.drawLine(p1.x,p1.y,p2.x,p2.y);
931 pts = ArrowData.getPoints((double)p1.x, (double)p1.y,
932 (double)p2.x, (double)p2.y);
933 for(int i = 0; i < 2; i++ )
934 g.drawLine(pts[i].x,pts[i].y,pts[i+1].x,pts[i+1].y);
935 g.setColor(c);
936 }
937
938 protected GraphIcon findIcon(Point pt) {
939 GraphIcon icon;
940 Rectangle region;
941 Enumeration enum = ViewList.elements();
942 while( enum.hasMoreElements() ) {
943 icon = (GraphIcon)enum.nextElement();
944 region = icon.getBounds();
945 if ( region.contains(pt.x,pt.y) )
946 return icon;
947 }
948 return null;
949 }
950
951
952
953 public void locationChanged(GraphIconEvent evt) {
954 redraw();
955 }
956 public void performLeftMouseDClickAction(GraphIconEvent evt) {
957
958 if ( nodeEditorComponent == null && isNodeEditable ) {
959 GraphIcon icon = (GraphIcon)evt.getSource();
960 GraphNode node = icon.getGraphNode();
961 if ( model.isNodeEditable(node) ) {
962 if ( nodeEditor == null ) {
963 nodeEditor = new DefaultGraphNodeEditor();
964 nodeEditor.addGraphNodeEditorListener(this);
965 }
966 nodeEditorComponent = nodeEditor.getNodeEditorComponent(this,node);
967 Component root = SwingUtilities.getRoot(this);
968 if ( !(nodeEditorComponent instanceof Window) ) {
969 if ( root instanceof JDialog )
970 pane = ((JDialog)root).getLayeredPane();
971 else if ( root instanceof JFrame )
972 pane = ((JFrame)root).getLayeredPane();
973 else
974 Core.ERROR(null,1,this);
975 pane.add(nodeEditorComponent,JLayeredPane.PALETTE_LAYER);
976 pane.moveToFront(nodeEditorComponent);
977 }
978 Point pt = SwingUtilities.convertPoint(icon,0,0,root);
979 nodeEditorComponent.setLocation(pt);
980 nodeEditorComponent.setVisible(true);
981 if ( nodeEditorComponent instanceof JComponent )
982 nodeEditorComponent.requestFocus();
983 }
984 }
985
986 }
987 public void performLeftMouseAction(GraphIconEvent evt) {
988 }
989 public void performRightMouseAction(GraphIconEvent evt) {
990 if ( !isLinkEditable ) return;
991
992 Point[] pts;
993 Graphics g = this.getGraphics();
994 Color color = g.getColor();
995 g.setColor(Color.black);
996 if (evt.isRightMousePressed() ){
997 if ( !(evt.getSource() instanceof GraphIcon) ) {
998 sourceIcon = null;
999 return;
1000 }
1001 sourceIcon = (GraphIcon)evt.getSource();
1002 lastPoint = stretchedPoint= startPoint = SwingUtilities.convertPoint(
1003 sourceIcon,evt.getPoint().x,evt.getPoint().y,this);
1004 }
1005 else if (evt.isRightMouseDragged() ){
1006 if ( sourceIcon == null ) return;
1007 lastPoint = stretchedPoint;
1008 stretchedPoint = SwingUtilities.convertPoint(
1009 sourceIcon,evt.getPoint().x,evt.getPoint().y,this);
1010
1011 g.setXORMode(this.getBackground());
1012 g.drawLine(startPoint.x,startPoint.y,lastPoint.x,lastPoint.y);
1013 g.drawLine(startPoint.x,startPoint.y,stretchedPoint.x,stretchedPoint.y);
1014 }
1015 else if (evt.isRightMouseReleased() ){
1016 if ( sourceIcon == null ) return;
1017 lastPoint = stretchedPoint;
1018 stretchedPoint = SwingUtilities.convertPoint(
1019 sourceIcon,evt.getPoint().x,evt.getPoint().y,this);
1020
1021 g.setXORMode(this.getBackground());
1022 g.drawLine(startPoint.x,startPoint.y,lastPoint.x,lastPoint.y);
1023 destIcon = findIcon(stretchedPoint);
1024 if (destIcon == null) return;
1025 g.drawLine(startPoint.x,startPoint.y,stretchedPoint.x,stretchedPoint.y);
1026 pts = ArrowData.getPoints((double)startPoint.x, (double)startPoint.y,
1027 (double)stretchedPoint.x, (double)stretchedPoint.y);
1028 for(int i = 0; i < 2; i++ )
1029 g.drawLine( pts[i].x, pts[i].y, pts[i+1].x, pts[i+1].y);
1030 }
1031 g.setColor(color);
1032 }
1033
1034 public void performMiddleMouseAction(GraphIconEvent evt) {
1035 }
1036
1037
1038 public void graphNodeEditingStopped(GraphNodeEditorEvent evt) {
1039 if ( nodeEditorComponent != null ) {
1040 nodeEditorComponent.setVisible(false);
1041 if ( !(nodeEditorComponent instanceof Window) )
1042 pane.remove(nodeEditorComponent);
1043 nodeEditorComponent = null;
1044 model.setValue(evt.getNode(),evt.getValue());
1045 }
1046 }
1047 public void graphNodeEditingCancelled(GraphNodeEditorEvent evt) {
1048 if ( nodeEditorComponent != null ) {
1049 nodeEditorComponent.setVisible(false);
1050 if ( !(nodeEditorComponent instanceof Window) )
1051 pane.remove(nodeEditorComponent);
1052 nodeEditorComponent = null;
1053 }
1054 }
1055
1056
1057 public void graphStructureChanged(GraphModelEvent evt) {
1058 if ( model == evt.getModel() )
1059 reset();
1060 }
1061 public void graphNodeAdded(GraphModelEvent evt) {
1062 if ( model == evt.getModel() ) {
1063 addNode(evt.getNode());
1064 redraw();
1065 }
1066 }
1067 public void graphNodeRemoved(GraphModelEvent evt) {
1068 if ( model == evt.getModel() ) {
1069 removeNode(evt.getNode());
1070 redraw();
1071 }
1072 }
1073 public void graphNodeStateChanged(GraphModelEvent evt) {
1074 if ( model == evt.getModel() ) {
1075 updateNode(evt.getNode());
1076 redraw();
1077 }
1078 }
1079 }