| 1 10 11 package org.enhydra.jawe; 12 13 import org.enhydra.jawe.graph.*; 14 15 import org.jgraph.JGraph; 16 import org.jgraph.graph.*; 17 import org.jgraph.event.*; 18 19 import java.io.*; 20 import java.util.*; 21 import javax.swing.undo.*; 22 import javax.swing.tree.*; 23 import java.awt.Rectangle ; 24 import javax.swing.event.*; 25 26 29 public class JaWEGraphModel 30 extends UndoableEditSupport 31 implements Serializable, GraphModel { 32 33 34 protected transient EventListenerList listenerList = 35 new EventListenerList(); 36 37 38 protected transient Iterator emptyIterator = new EmptyIterator(); 39 40 41 protected List roots = new ArrayList(); 42 43 44 protected boolean asksAllowsChildren = false; 45 46 49 public JaWEGraphModel() { 50 } 51 52 56 62 public int getRootCount() { 63 return roots.size(); 64 } 65 66 74 public Object getRootAt(int index) { 75 return roots.get(index); 76 } 77 78 85 public int getIndexOfRoot(Object root) { 86 return roots.indexOf(root); 87 } 88 89 95 public boolean contains(Object node) { 96 Object parentNode = null; 97 while ((parentNode = getParent(node)) 98 != null) 99 node = parentNode; 100 return roots.contains(node); 101 } 102 103 110 public Map getAttributes(Object node) { 111 if (node instanceof GraphCell) 112 return ((GraphCell) node).getAttributes(); 113 return null; 114 } 115 116 120 126 public Object getSource(Object edge) { 127 if (edge instanceof Edge) 128 return ((Edge) edge).getSource(); 129 return null; 130 } 131 132 138 public Object getTarget(Object edge) { 139 if (edge instanceof Edge) 140 return ((Edge) edge).getTarget(); 141 return null; 142 } 143 144 152 public boolean acceptsSource(Object edge, Object port) { 153 return true; 154 } 155 156 164 public boolean acceptsTarget(Object edge, Object port) { 165 return true; 166 } 167 168 176 public Iterator edges(Object port) { 177 if (port instanceof Port) 178 return ((Port) port).edges(); 179 return emptyIterator; 180 } 181 182 187 public boolean isEdge(Object edge) { 188 return edge instanceof Edge; 189 } 190 191 197 public boolean isPort(Object port) { 198 return port instanceof Port; 199 } 200 204 209 public Map cloneCells(Object [] cells) { 210 Map map = new Hashtable(); 211 ArrayList q = new ArrayList(); 213 for (int i = 0; i < cells.length; i++) 214 q.add(cells[i]); 215 while (!q.isEmpty()) { 217 Object node = q.remove(0); 219 if (node instanceof DefaultGraphCell) { 220 for (int i = 0; i < getChildCount(node); i++) 222 q.add(getChild(node, i)); 223 DefaultGraphCell cell = (DefaultGraphCell) node; 225 DefaultGraphCell clone = (DefaultGraphCell) cell.clone(); 226 Object par = getParent(cell); 227 if (par != null) { 228 DefaultMutableTreeNode p = 229 (DefaultMutableTreeNode) map.get(par); 230 if (p != null) 231 p.add(clone); 232 } 233 map.put(cell, clone); 235 } 236 } 237 Iterator it = map.values().iterator(); 239 while (it.hasNext()) { 240 Object obj = it.next(); 241 if (obj instanceof Port) { 243 Object anchor = ((Port) obj).getAnchor(); 244 if (anchor != null) 246 ((Port) obj).setAnchor((Port) map.get(anchor)); 247 } 248 } 249 return map; 250 } 251 252 253 262 public Object getParent(Object child) { 263 if (child != null && child instanceof TreeNode) 264 return ((TreeNode) child).getParent(); 265 return null; 266 } 267 268 276 public int getIndexOfChild(Object parent, Object child) { 277 if (parent == null || child == null) 278 return -1; 279 return ((TreeNode) parent).getIndex((TreeNode) child); 280 } 281 282 292 public Object getChild(Object parent, int index) { 293 if (parent instanceof TreeNode) 294 return ((TreeNode) parent).getChildAt(index); 295 return null; 296 } 297 298 306 public int getChildCount(Object parent) { 307 if (parent instanceof TreeNode) 308 return ((TreeNode) parent).getChildCount(); 309 return 0; 310 } 311 312 319 public boolean isLeaf(Object node) { 320 if (asksAllowsChildren && node instanceof TreeNode) 321 return !((TreeNode) node).getAllowsChildren(); 322 return ((TreeNode) node).isLeaf(); 323 } 324 325 326 330 345 public void insert( 346 Object [] roots, 347 Map attributes, 348 ConnectionSet cs, 349 ParentMap pm, 350 UndoableEdit[] edits) { 351 String undoMsg=ResourceManager.getLanguageDependentString("MessageInsertingObjects"); 352 GraphModelEdit edit = 353 createInsertEdit(roots, attributes, cs, pm, edits, undoMsg); 354 if (edit != null) { 355 edit.execute(); 356 if (edits != null) { 357 for (int i = 0; i < edits.length; i++) 358 if (edits[i] 359 instanceof GraphModelEvent.ExecutableGraphChange) 360 ((GraphModelEvent.ExecutableGraphChange) edits[i]) 361 .execute(); 362 } 363 postEdit(edit); 364 } 365 } 366 367 368 372 public void remove(Object [] roots) { 373 String undoMsg=ResourceManager.getLanguageDependentString("MessageRemovingObjects"); 374 GraphModelEdit edit = createRemoveEdit(roots,undoMsg); 375 if (edit != null) { 376 edit.execute(); 377 postEdit(edit); 378 } 379 } 380 381 394 public void edit( 395 Map attributes, 396 ConnectionSet cs, 397 ParentMap pm, 398 UndoableEdit[] edits) { 399 if ((attributes == null || attributes.isEmpty()) 400 && (cs == null || cs.isEmpty()) 401 && pm == null 402 && edits != null 403 && edits.length == 1) { 404 if (edits[0] instanceof GraphModelEvent.ExecutableGraphChange) 405 ((GraphModelEvent.ExecutableGraphChange) edits[0]).execute(); 406 postEdit(edits[0]); } else { 408 String undoMsg=ResourceManager.getLanguageDependentString("MessageEditingObject"); 409 GraphModelEdit edit = createCellEdit(attributes, cs, pm, edits, undoMsg); 410 if (edit != null) { 412 edit.execute(); 413 if (edits != null) { 414 for (int i = 0; i < edits.length; i++) 415 if (edits[i] 416 instanceof GraphModelEvent.ExecutableGraphChange) 417 ((GraphModelEvent.ExecutableGraphChange) edits[i]) 418 .execute(); 419 } 420 postEdit(edit); 421 } 422 } 423 } 424 425 428 public void editFonts(Map attributes) { 429 GraphModelEdit edit = createCellEdit(attributes, null, null, null, null); 430 if (edit != null) { 432 edit.execute(); 433 } 434 } 435 436 437 440 public void removeBubbles (Object [] bubbles,GraphModelListener gml) { 441 removeGraphModelListener(gml); 442 GraphModelEdit edit = createRemoveEdit(bubbles,null); 443 if (edit != null) { 444 edit.execute(); 445 } 446 addGraphModelListener(gml); 447 } 448 449 464 public void insertAndEdit( 465 Object [] roots, 466 Map attributes, 467 ConnectionSet cs, 468 ParentMap pm, 469 UndoableEdit[] edits, 470 String undoMsg) { 471 GraphModelEdit edit = 472 createInsertEdit(roots, attributes, cs, pm, edits, undoMsg); 473 if (edit != null) { 474 edit.execute(); 475 if (edits != null) { 476 for (int i = 0; i < edits.length; i++) 477 if (edits[i] 478 instanceof GraphModelEvent.ExecutableGraphChange) 479 ((GraphModelEvent.ExecutableGraphChange) edits[i]) 480 .execute(); 481 } 482 postEdit(edit); 483 } 484 } 485 486 492 public void removeAndEdit(Object [] roots,Map attributes,String name) { 493 GraphModelEdit edit = createRemoveAndCellEdit(roots,attributes,name); 494 if (edit!=null) { 495 edit.execute(); 496 postEdit(edit); 497 } 498 } 499 500 503 public void toBack(Object [] cells) { 504 GraphModelLayerEdit edit = 505 createLayerEdit(cells, GraphModelLayerEdit.BACK); 506 if (edit != null) { 507 edit.execute(); 508 postEdit(edit); 509 } 510 } 511 512 515 public void toFront(Object [] cells) { 516 GraphModelLayerEdit edit = 517 createLayerEdit(cells, GraphModelLayerEdit.FRONT); 518 if (edit != null) { 519 edit.execute(); 520 postEdit(edit); 521 } 522 } 523 524 528 protected GraphModelLayerEdit createLayerEdit(Object [] cells, int layer) { 529 return new GraphModelLayerEdit(cells, layer); 530 } 531 532 535 protected GraphModelEdit createInsertEdit( 536 Object [] cells, 537 Map attributeMap, 538 ConnectionSet cs, 539 ParentMap pm, 540 UndoableEdit[] edits, 541 String name) { 542 GraphModelEdit edit = 544 createEdit(cells, null, attributeMap, cs, pm, name); 545 if (edit != null) { 546 if (edits != null) 547 for (int i = 0; i < edits.length; i++) 548 edit.addEdit(edits[i]); 549 edit.end(); 550 } 551 return edit; 552 } 553 554 557 protected GraphModelEdit createRemoveEdit(Object [] cells,String name) { 558 ConnectionSet cs = ConnectionSet.create(this, cells, true); 560 ParentMap pm = ParentMap.create(this, cells, true, false); 562 GraphModelEdit edit = createEdit(null, cells, null, cs, pm, name); 565 if (edit != null) 566 edit.end(); 567 return edit; 568 } 569 570 573 protected GraphModelEdit createCellEdit( 574 Map attributes, 575 ConnectionSet cs, 576 ParentMap pm, 577 UndoableEdit[] edits, 578 String name) { 579 GraphModelEdit edit = createEdit(null, null, attributes, cs, pm, name); 581 if (edit != null) { 582 if (edits != null) 583 for (int i = 0; i < edits.length; i++) 584 edit.addEdit(edits[i]); 585 edit.end(); 586 } 587 return edit; 588 } 589 590 591 protected GraphModelEdit createEdit( 592 Object [] inserted, 593 Object [] removed, 594 Map attributes, 595 ConnectionSet cs, 596 ParentMap pm, 597 String name) { 598 return new GraphModelEdit( 599 inserted, 600 removed, 601 attributes, 602 cs, 603 pm, 604 name); 605 } 606 607 610 protected GraphModelEdit createRemoveAndCellEdit(Object [] cells, 611 Map attributes,String name) { 612 ConnectionSet cs = ConnectionSet.create(this, cells, true); 614 ParentMap pm = ParentMap.create(this, cells, true, false); 616 GraphModelEdit edit = createEdit (null,cells,attributes,cs,pm,name); 618 if (edit!=null) { 619 edit.end(); 620 } 621 return edit; 622 } 623 624 628 632 protected Object [] handleInsert(Object [] cells) { 633 Object [] inserted = null; 634 if (cells != null) { 635 for (int i = 0; i < cells.length; i++) 636 if (getParent(cells[i]) == null) 638 roots.add(cells[i]); 639 inserted = getDescendants(this, cells).toArray(); 641 } 642 return inserted; 643 } 644 645 649 protected Object [] handleRemove(Object [] cells) { 650 List removedRoots = new ArrayList(); 651 if (cells != null) 652 for (int i = 0; i < cells.length; i++) 653 if (getParent(cells[i]) == null && roots.remove(cells[i])) 654 removedRoots.add(cells[i]); 655 return removedRoots.toArray(); 656 } 657 658 662 protected ParentMap handleParentMap(ParentMap parentMap) { 663 if (parentMap != null) { 664 ParentMap undo = new ParentMap(); 665 Iterator it = parentMap.entries(); 666 while (it.hasNext()) { 667 ParentMap.Entry entry = (ParentMap.Entry) it.next(); 668 Object child = entry.getChild(); 669 Object parent = entry.getParent(); 670 undo.addEntry(child, getParent(child)); 671 if (parent == null){ 672 if (child instanceof MutableTreeNode){ 673 ((MutableTreeNode)child).removeFromParent(); 674 } 675 } else { 676 if (parent instanceof DefaultMutableTreeNode && 677 child instanceof MutableTreeNode){ 678 ((DefaultMutableTreeNode)parent).add((MutableTreeNode)child); 679 } 680 } 681 682 boolean isRoot = roots.contains(child); 683 if (parent == null && !isRoot) 684 roots.add(child); 685 else if (parent != null && isRoot) 686 roots.remove(child); 687 } 688 return undo; 689 } 690 return null; 691 } 692 693 697 protected Map handleAttributes(Map attributes) { 698 if (attributes != null) { 699 Hashtable undo = new Hashtable(); 700 Iterator it = attributes.entrySet().iterator(); 701 while (it.hasNext()) { 702 Map.Entry entry = (Map.Entry) it.next(); 703 Object cell = entry.getKey(); 704 Map deltaNew = (Map) entry.getValue(); 705 if (cell instanceof GraphCell){ 708 Map deltaOld = ((GraphCell)cell).changeAttributes(deltaNew); 709 undo.put(cell, deltaOld); 712 } else { 713 Map attr = getAttributes(cell); 714 if (attr != null){ 715 Map deltaOld = GraphConstants.applyMap(deltaNew, attr); 716 undo.put(cell, deltaOld); 719 } 720 } 721 } 722 return undo; 723 } 724 return null; 725 } 726 727 731 735 protected ConnectionSet handleConnectionSet(ConnectionSet cs) { 736 if (cs != null) { 737 ConnectionSet csundo = new ConnectionSet(); 738 Iterator it = cs.connections(); 739 while (it.hasNext()) { 740 ConnectionSet.Connection c = 741 (ConnectionSet.Connection) it.next(); 742 Object edge = c.getEdge(); 743 if (c.isSource()) 744 csundo.connect(edge, getSource(edge), true); 745 else 746 csundo.connect(edge, getTarget(edge), false); 747 handleConnection(c); 748 } 749 return csundo; 750 } 751 return null; 752 } 753 754 757 protected void handleConnection(ConnectionSet.Connection c) { 758 Object edge = c.getEdge(); 759 Object old = (c.isSource()) ? getSource(edge) : getTarget(edge); 760 Object port = c.getPort(); 761 if (port != old) { 762 connect(edge, old, c.isSource(), true); 763 if (contains(port) && contains(edge)) 764 connect(edge, port, c.isSource(), false); 765 } 766 } 767 768 773 protected void connect( 774 Object edge, 775 Object port, 776 boolean isSource, 777 boolean remove) { 778 if (port instanceof Port) 779 if (remove) 780 ((Port) port).removeEdge(edge); 781 else 782 ((Port) port).addEdge(edge); 783 if (remove) 784 port = null; 785 if (edge instanceof Edge) { 786 if (isSource) 787 ((Edge) edge).setSource(port); 788 else 789 ((Edge) edge).setTarget(port); 790 } 791 } 792 793 797 803 public void addGraphModelListener(GraphModelListener l) { 804 listenerList.add(GraphModelListener.class, l); 805 } 806 807 813 public void removeGraphModelListener(GraphModelListener l) { 814 listenerList.remove(GraphModelListener.class, l); 815 } 816 817 824 protected void fireGraphChanged( 825 Object source, 826 GraphModelEvent.GraphModelChange edit) { 827 Object [] listeners = listenerList.getListenerList(); 829 GraphModelEvent e = null; 830 for (int i = listeners.length - 2; i >= 0; i -= 2) { 833 if (listeners[i] == GraphModelListener.class) { 834 if (e == null) 836 e = new GraphModelEvent(source, edit); 837 ((GraphModelListener) listeners[i + 1]).graphChanged(e); 838 } 839 } 840 } 841 842 845 public GraphModelListener[] getGraphModelListeners() { 846 return (GraphModelListener[]) listenerList.getListeners( 847 GraphModelListener.class); 848 } 849 850 854 858 public class GraphModelEdit 859 extends CompoundEdit 860 implements 861 GraphModelEvent.GraphModelChange, 862 GraphModelEvent.ExecutableGraphChange { 863 864 865 protected String name; 866 867 868 protected Object [] insert, changed, remove, context; 869 870 871 protected Object [] inserted, removed; 872 873 875 protected Map attributes, previousAttributes; 876 877 878 protected ParentMap parentMap, previousParentMap; 879 880 881 protected ConnectionSet connectionSet, previousConnectionSet; 882 883 884 protected Map cellViews = new Hashtable(); 885 886 897 public GraphModelEdit( 898 Object [] inserted, 899 Object [] removed, 900 Map attributes, 901 ConnectionSet connectionSet, 902 ParentMap parentMap, 903 String name) { 904 super(); 905 this.insert = inserted; 906 this.remove = removed; 907 this.connectionSet = connectionSet; 908 this.attributes = attributes; 909 this.parentMap = parentMap; 910 this.name=name; 911 previousAttributes = attributes; 912 previousConnectionSet = connectionSet; 913 previousParentMap = parentMap; 914 if (parentMap != null) { 916 932 } 933 } 934 935 936 public Object [] filterParents(Map childCount, int children) { 937 ArrayList list = new ArrayList(); 938 Iterator it = childCount.entrySet().iterator(); 939 while (it.hasNext()) { 940 Map.Entry entry = (Map.Entry) it.next(); 941 if (entry.getValue() instanceof Integer ) { 942 if (((Integer ) entry.getValue()).intValue() == children) 943 list.add(entry.getKey()); 944 } 945 } 946 return list.toArray(); 947 } 948 949 |