📄 jawegraphmodel.java
字号:
* Inserts the <code>roots</code> and connections into the model. * Notifies the model- and undo listeners of the change. The passed-in * edits are executed if they implement the * <code>GraphModelEvent.ExecutableGraphChange</code> interface * in ascending array-order, after execution of the model change. * (Note: The external order is important in a * special case: After insertion on a partial view, ie. one that does not * display all cells of the model, the cell is made visible after * it is inserted into the model. This requires the inserting view * to be able to add the cell to the visible set before it is * inserted into the model.) * Note: The passed-in propertyMap may contains PortViews * which must be turned into Points when stored in the model. */ public void insertAndEdit(Object[] pRoots, Map pAttributes, ConnectionSet pCs, ParentMap pPm, UndoableEdit[] pEdits, String pUndoMsg) { GraphModelEdit edit = createInsertEdit(pRoots, pAttributes, pCs, pPm, pEdits, pUndoMsg); if (edit != null) { edit.execute(); if (pEdits != null) { for (int i = 0; i < pEdits.length; i++) if (pEdits[i] instanceof GraphLayoutCache.GraphLayoutCacheEdit) ((GraphLayoutCache.GraphLayoutCacheEdit) pEdits[i]).execute(); } postEdit(edit); } } /** * Removes <code>cells</code> from the model and edits cells given in * a <code>propertyMap</code>. If <code>removeChildren</code> * is <code>true</code>, the children are also removed. * Notifies the model- and undo listeners of the change. */ public void removeAndEdit(Object[] pRoots, Map pAttributes, String pName) { GraphModelEdit edit = createRemoveAndCellEdit(pRoots, pAttributes, pName); if (edit != null) { edit.execute(); postEdit(edit); } } /** * Sends <code>cells</code> to back. */ public void toBack(Object[] cells) { GraphModelLayerEdit edit = createLayerEdit(cells, GraphModelLayerEdit.BACK); if (edit != null) { edit.execute(); postEdit(edit); } } /** * Brings <code>cells</code> to front. */ public void toFront(Object[] cells) { GraphModelLayerEdit edit = createLayerEdit(cells, GraphModelLayerEdit.FRONT); if (edit != null) { edit.execute(); postEdit(edit); } } // // Edit Creation // protected GraphModelLayerEdit createLayerEdit(Object[] cells, int layer) { return new GraphModelLayerEdit(cells, layer); } /** * Returns an edit that represents an insert. */ protected GraphModelEdit createInsertEdit(Object[] cells, Map attributeMap, ConnectionSet cs, ParentMap pm, UndoableEdit[] edits, String name) { //GraphModelEdit edit = new GraphModelEdit(cells, cs, pm, attributeMap); GraphModelEdit edit = createEdit(cells, null, attributeMap, cs, pm, name); if (edit != null) { if (edits != null) for (int i = 0; i < edits.length; i++) edit.addEdit(edits[i]); edit.end(); } return edit; } /** * Returns an edit that represents a remove. */ protected GraphModelEdit createRemoveEdit(Object[] cells, String name) { // Remove from GraphStructure ConnectionSet cs = ConnectionSet.create(this, cells, true); // Remove from Group Structure ParentMap pm = ParentMap.create(this, cells, true, false); // Construct Edit //GraphModelEdit edit = new GraphModelEdit(cells, cs, pm); GraphModelEdit edit = createEdit(null, cells, null, cs, pm, name); if (edit != null) edit.end(); return edit; } /** * Returns an edit that represents a change. */ protected GraphModelEdit createCellEdit(Map attributes, ConnectionSet cs, ParentMap pm, UndoableEdit[] edits, String name) { //GraphModelEdit edit = new GraphModelEdit(cs, propertyMap, pm); GraphModelEdit edit = createEdit(null, null, attributes, cs, pm, name); if (edit != null) { if (edits != null) for (int i = 0; i < edits.length; i++) edit.addEdit(edits[i]); edit.end(); } return edit; } protected GraphModelEdit createEdit(Object[] inserted, Object[] removed, Map attributes, ConnectionSet cs, ParentMap pm, String name) { return new GraphModelEdit(inserted, removed, attributes, cs, pm, name); } /** * Returns an edit that represents a remove and a change. */ protected GraphModelEdit createRemoveAndCellEdit(Object[] cells, Map attributes, String name) { // Remove from GraphStructure ConnectionSet cs = ConnectionSet.create(this, cells, true); // Remove from Group Structure ParentMap pm = ParentMap.create(this, cells, true, false); // Construct Edit GraphModelEdit edit = createEdit(null, cells, attributes, cs, pm, name); if (edit != null) { edit.end(); } return edit; } // // Change Handling // /** * Inserts <code>cells</code> into the model. Returns * the cells that were inserted (including descendants). */ protected Object[] handleInsert(Object[] cells) { Object[] inserted = null; if (cells != null) { for (int i = 0; i < cells.length; i++) // Add to Roots if no parent if (getParent(cells[i]) == null) roots.add(cells[i]); // Return *all* inserted cells inserted = getDescendantList(this, cells).toArray(); } return inserted; } /** * Removes <code>cells</code> from the model. Returns * the cells that were removed as roots. */ protected Object[] handleRemove(Object[] cells) { List removedRoots = new ArrayList(); if (cells != null) for (int i = 0; i < cells.length; i++) if (getParent(cells[i]) == null && roots.remove(cells[i])) removedRoots.add(cells[i]); return removedRoots.toArray(); } /** * Applies <code>cells</code> to the model. Returns * a parent map that may be used to undo this change. */ protected ParentMap handleParentMap(ParentMap parentMap) { if (parentMap != null) { ParentMap undo = new ParentMap(); Iterator it = parentMap.entries(); while (it.hasNext()) { ParentMap.Entry entry = (ParentMap.Entry) it.next(); Object child = entry.getChild(); Object parent = entry.getParent(); undo.addEntry(child, getParent(child)); if (parent == null) { if (child instanceof MutableTreeNode) { ((MutableTreeNode) child).removeFromParent(); } } else { if (parent instanceof DefaultMutableTreeNode && child instanceof MutableTreeNode) { ((DefaultMutableTreeNode) parent).add((MutableTreeNode) child); } } boolean isRoot = roots.contains(child); if (parent == null && !isRoot) roots.add(child); else if (parent != null && isRoot) roots.remove(child); } return undo; } return null; } /** * Applies <code>attributes</code> to the cells specified as keys. * Returns the <code>attributes</code> to undo the change. */ protected Map handleAttributes(Map attributes) { if (attributes != null) { Hashtable undo = new Hashtable(attributes.size()); Iterator it = attributes.entrySet().iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); Object cell = entry.getKey(); Map deltaNew = (Map) entry.getValue(); // System.out.println("deltaNew="+deltaNew); // System.out.println("stateOld="+getAttributes(cell)); // Handle New Values Map deltaOld = null; AttributeMap attr = getAttributes(cell); if (attr != null) { deltaOld = attr.applyMap(deltaNew); // System.out.println("stateNew="+getAttributes(cell)); // System.out.println("deltaOld="+deltaOld); undo.put(cell, deltaOld); } else { // Make room for the value deltaOld = new Hashtable(2); } // Handle new values Object newValue = deltaNew.get(GraphConstants.VALUE); if (newValue != null) { Object oldValue = valueForCellChanged(cell, newValue); if (oldValue != null) GraphConstants.setValue(deltaOld, oldValue); // TODO: Userobject of null is probably invalid else GraphConstants.setRemoveAttributes(deltaOld, new Object[] { GraphConstants.VALUE }); } } return undo; } return null; } /** * Applies the new value to the specified cell. Unfortunately for cloning * the user object you must still override the attribute map and provide a * custom cloneUserObject method. This is because the cloning of a cell is * local to the cell, which in turn has a reference to its attribute map. * * @param cell * @param newValue * @return the old value for the cell, if any */ public Object valueForCellChanged(Object cell, Object newValue) { if (cell instanceof DefaultMutableTreeNode) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) cell; Object oldValue = node.getUserObject(); node.setUserObject(newValue); return oldValue; } return null; } // // Connection Set Handling // /** * Applies <code>connectionSet</code> to the model. Returns * a connection set that may be used to undo this change. */ protected ConnectionSet handleConnectionSet(ConnectionSet cs) { if (cs != null) { ConnectionSet csundo = new ConnectionSet(); Iterator it = cs.connections(); while (it.hasNext()) { ConnectionSet.Connection c = (ConnectionSet.Connection) it.next(); Object edge = c.getEdge(); if (c.isSource()) csundo.connect(edge, getSource(edge), true); else csundo.connect(edge, getTarget(edge), false); handleConnection(c); } return csundo; } return null; } /** * Inserts the specified connection into the model. */ protected void handleConnection(ConnectionSet.Connection c) { Object edge = c.getEdge(); Object old = (c.isSource()) ? getSource(edge) : getTarget(edge); Object port = c.getPort(); connect(edge, old, c.isSource(), false); connect(edge, port, c.isSource(), true); } /** * Connects or disconnects the edge and port in this model based on * <code>remove</code>. Subclassers should override this to update * connectivity datastructures. */ protected void connect(Object edge, Object port, boolean isSource, boolean insert) { if (port instanceof Port) if (insert) ((Port) port).addEdge(edge); else ((Port) port).removeEdge(edge); if (!insert) port = null; if (edge instanceof Edge) { if (isSource) ((Edge) edge).setSource(port); else ((Edge) edge).setTarget(port); } } // // GraphModelListeners // /** * Adds a listener for the GraphModelEvent posted after the graph changes. * * @see #removeGraphModelListener * @param l the listener to add */ public void addGraphModelListener(GraphModelListener l) { listenerList.add(GraphModelListener.class, l); } /** * Removes a listener previously added with <B>addGraphModelListener()</B>. * * @see #addGraphModelListener * @param l the listener to remove */ public void removeGraphModelListener(GraphModelListener l) { listenerList.remove(GraphModelListener.class, l); } public void cellsChanged(final Object[] cells) { if (cells != null) { fireGraphChanged(this, new GraphModelEvent.GraphModelChange() { public Object[] getInserted() { return null; } public Object[] getRemoved() { return null; } public Map getPreviousAttributes() { return null; } public ConnectionSet getConnectionSet() { return null; } public ConnectionSet getPreviousConnectionSet() { return null; } public ParentMap getParentMap() { return null; } public ParentMap getPreviousParentMap() { return null; } public void putViews(GraphLayoutCache view, CellView[] cellViews) { } public CellView[] getViews(GraphLayoutCache view) { return null; } public Object getSource() { return this; } public Object[] getChanged() { return cells; } public Map getAttributes() { return null; } public Object[] getContext() { return null; } }); } } /* * Notify all listeners that have registered interest for * notification on this event type. The event instance * is lazily created using the parameters passed into * the fire method. * @see EventListenerList */ protected void fireGraphChanged(Object source, GraphModelEvent.GraphModelChange edit) { // Guaranteed to return a non-null array Object[] ls = listenerList.getListenerList(); GraphModelEvent e = null; // Process the listeners last to first, notifying // those that are interested in this event for (int i = ls.length - 2; i >= 0; i -= 2) { if (ls[i] == GraphModelListener.class) { // Lazily create the event: if (e == null) e = new GraphModelEvent(source, edit); ((GraphModelListener) ls[i + 1]).graphChanged(e); } } } /** * Return an array of all GraphModelListeners that were added to this model. */ public GraphModelListener[] getGraphModelListeners() { return (GraphModelListener[]) listenerList.getListeners(GraphModelListener.class); } // // GraphModelEdit // /** * An implementation of GraphModelChange that can be added to the model * event. */ public class GraphModelEdit extends CompoundEdit implements GraphModelEvent.GraphModelChange { /* Edit name. */ protected String name; /* Cells that were inserted/removed/changed during the last execution. */ protected Object[] insert, changed, remove, context; /* Cells that were inserted/removed/changed during the last execution. */ protected Object[] inserted, removed; /* Property map for the next execution. Attribute Map is passed to the views on inserts. */ protected Map attributes, previousAttributes; /* Parent map for the next execution. */ protected ParentMap parentMap, previousParentMap; /* ConnectionSet for the next execution. */ protected ConnectionSet connectionSet, previousConnectionSet; /* Piggybacked undo from the views. */ protected Map cellViews = new Hashtable(); /** * * Constructs an edit record. * * @param inserted a set of roots that were inserted * @param removed a set of elements that were removed * @param attributes
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -