fiore@0: /* fiore@0: CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool fiore@3: fiore@0: Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) fiore@0: fiore@0: This program is free software: you can redistribute it and/or modify fiore@0: it under the terms of the GNU General Public License as published by fiore@0: the Free Software Foundation, either version 3 of the License, or fiore@0: (at your option) any later version. fiore@0: fiore@0: This program is distributed in the hope that it will be useful, fiore@0: but WITHOUT ANY WARRANTY; without even the implied warranty of fiore@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the fiore@0: GNU General Public License for more details. fiore@0: fiore@0: You should have received a copy of the GNU General Public License fiore@0: along with this program. If not, see . fiore@3: */ fiore@0: package uk.ac.qmul.eecs.ccmi.diagrammodel; fiore@0: fiore@0: import java.util.ArrayList; fiore@0: import java.util.Collection; fiore@0: import java.util.Collections; fiore@0: import java.util.Enumeration; fiore@0: import java.util.LinkedHashMap; fiore@0: import java.util.LinkedHashSet; fiore@0: import java.util.LinkedList; fiore@0: import java.util.List; fiore@0: import java.util.Map; fiore@0: import java.util.Set; fiore@3: import java.util.concurrent.locks.ReentrantLock; fiore@0: fiore@0: import javax.swing.event.ChangeEvent; fiore@0: import javax.swing.event.ChangeListener; fiore@0: import javax.swing.tree.DefaultTreeModel; fiore@0: import javax.swing.tree.MutableTreeNode; fiore@0: import javax.swing.tree.TreeNode; fiore@0: fiore@0: import uk.ac.qmul.eecs.ccmi.diagrammodel.NodeProperties.Modifiers; fiore@0: import uk.ac.qmul.eecs.ccmi.utils.InteractionLog; fiore@0: fiore@0: /** fiore@0: * This class represent a model as per in the model-view control architecture. fiore@0: * The model is "double sided" in the sense that it can be accessed through either fiore@0: * a CollectionModel or a TreeModel returned by the respective getter methods. fiore@0: * The TreeModel is suitable for JTree classes of the swing library, while fiore@0: * the CollectionModel can be used by view classes by registering a CollectionListener fiore@0: * to the CollectionModel itself. fiore@0: * It is important to notice that changes made on one side will reflect on the other, fiore@0: * eventually triggering the registered listeners. fiore@0: * The tree model is structured according to a special layout which is suitable for fiore@0: * browsing the tree view via audio interface ( text to speech synthesis and sound). fiore@0: * fiore@0: * @param a subclass of DiagramNode fiore@0: * @param a subclass of DiagramEdge fiore@0: */ fiore@0: public class DiagramModel{ fiore@0: /** fiore@0: * Create a model instance starting from some nodes and edges prototypes. fiore@0: * All subsequently added element must be clones of such prototypes. fiore@5: * @param nodePrototypes an array of {@code DiagramNode} prototypes, from which fiore@5: * nodes that will be inserted in this model will be cloned fiore@5: * @param edgePrototypes an array of {@code DiagramEdge} prototypes, from which fiore@5: * edges that will be inserted in this model will be cloned fiore@0: */ fiore@0: @SuppressWarnings("serial") fiore@0: public DiagramModel(N [] nodePrototypes, E [] edgePrototypes) { fiore@3: root = new DiagramTreeNode(ROOT_LABEL){ fiore@0: @Override fiore@0: public boolean isRoot(){ fiore@0: return true; fiore@0: } fiore@0: }; fiore@0: modified = false; fiore@3: fiore@0: nodeCounter = 0; fiore@0: edgeCounter = 0; fiore@3: fiore@3: notifier = new ReentrantLockNotifier(); fiore@3: fiore@0: treeModel = new InnerTreeModel(root); fiore@0: treeModel.setEventSource(treeModel);/* default event source is the tree itself */ fiore@0: diagramCollection = new InnerDiagramCollection(); fiore@3: fiore@0: nodes = new ArrayList(INITIAL_NODES_SIZE); fiore@0: edges = new ArrayList(INITIAL_EDGES_SIZE); fiore@0: elements = new ArrayList(INITIAL_NODES_SIZE+INITIAL_EDGES_SIZE); fiore@3: fiore@0: changeListeners = new LinkedList(); fiore@3: fiore@0: for(N n : nodePrototypes) fiore@0: addType(n); fiore@0: for(E e : edgePrototypes){ fiore@0: addType(e); fiore@0: } fiore@0: } fiore@3: fiore@0: /** fiore@0: * Returns a CollectionModel for this diagram fiore@0: * fiore@0: * @return a CollectionModel for this diagram fiore@0: */ fiore@0: public CollectionModel getDiagramCollection(){ fiore@0: return diagramCollection; fiore@0: } fiore@3: fiore@0: /** fiore@0: * Returns a TreeModel for this diagram fiore@0: * fiore@0: * @return a TreeModel for this diagram fiore@0: */ fiore@0: public TreeModel getTreeModel(){ fiore@0: return treeModel; fiore@0: } fiore@3: fiore@3: private void handleChangeListeners(Object source){ fiore@0: if(modified) // fire the listener only the first time a change happens fiore@0: return; fiore@0: modified = true; fiore@0: fireChangeListeners(source); fiore@0: } fiore@3: fiore@0: private void addChangeListener(ChangeListener l){ fiore@0: changeListeners.add(l); fiore@0: } fiore@3: fiore@0: private void removeChangeListener(ChangeListener l){ fiore@0: changeListeners.remove(l); fiore@0: } fiore@3: fiore@0: protected void fireChangeListeners(Object source){ fiore@0: ChangeEvent changeEvent = new ChangeEvent(source); fiore@0: for(ChangeListener l : changeListeners) fiore@0: l.stateChanged(changeEvent); fiore@0: } fiore@3: fiore@0: private void addType(DiagramElement element){ fiore@3: DiagramTreeNode typeNode = _lookForChild(root, element.getType()); fiore@0: if(typeNode == null){ fiore@0: typeNode = new TypeMutableTreeNode(element); fiore@0: treeModel.insertNodeInto(typeNode, root, root.getChildCount()); fiore@0: } fiore@0: } fiore@3: fiore@0: private class InnerDiagramCollection implements CollectionModel { fiore@0: fiore@0: public InnerDiagramCollection(){ fiore@0: listeners = new ArrayList(); fiore@0: } fiore@3: fiore@0: @Override fiore@3: public boolean insert(N n, Object source){ fiore@3: if(source == null) fiore@3: source = this; fiore@3: return _insert(n,source); fiore@0: } fiore@3: fiore@0: @Override fiore@3: public boolean insert(E e, Object source){ fiore@3: if(source == null) fiore@3: source = this; fiore@3: return _insert(e,source); fiore@0: } fiore@3: fiore@0: @Override fiore@3: public boolean takeOut(DiagramElement element, Object source){ fiore@3: if(source == null) fiore@3: source = this; fiore@0: if(element instanceof DiagramNode) fiore@3: return _takeOut((DiagramNode)element,source); fiore@0: if(element instanceof DiagramEdge) fiore@3: return _takeOut((DiagramEdge)element,source); fiore@0: return false; fiore@0: } fiore@0: fiore@0: @Override fiore@0: public void addCollectionListener(CollectionListener listener) { fiore@0: listeners.add(listener); fiore@0: } fiore@0: fiore@0: @Override fiore@0: public void removeCollectionListener(CollectionListener listener) { fiore@0: listeners.remove(listener); fiore@0: } fiore@3: fiore@0: protected void fireElementInserted(Object source, DiagramElement element) { fiore@0: for(CollectionListener l : listeners){ fiore@0: l.elementInserted(new CollectionEvent(source,element)); fiore@0: } fiore@0: } fiore@3: fiore@0: protected void fireElementTakenOut(Object source, DiagramElement element) { fiore@0: for(CollectionListener l : listeners){ fiore@0: l.elementTakenOut(new CollectionEvent(source,element)); fiore@0: } fiore@0: } fiore@3: fiore@0: protected void fireElementChanged(ElementChangedEvent evt){ fiore@0: for(CollectionListener l : listeners){ fiore@0: l.elementChanged(evt); fiore@0: } fiore@0: } fiore@0: fiore@0: @Override fiore@0: public Collection getNodes() { fiore@0: return Collections.unmodifiableCollection(nodes); fiore@0: } fiore@0: fiore@0: @Override fiore@0: public Collection getEdges() { fiore@0: return Collections.unmodifiableCollection(edges); fiore@0: } fiore@3: fiore@0: @Override fiore@0: public Collection getElements(){ fiore@0: return Collections.unmodifiableCollection(elements); fiore@0: } fiore@0: fiore@0: @Override fiore@3: public ReentrantLock getMonitor(){ fiore@3: return notifier; fiore@0: } fiore@3: fiore@0: @Override fiore@0: public void addChangeListener(ChangeListener l){ fiore@0: DiagramModel.this.addChangeListener(l); fiore@0: } fiore@3: fiore@0: @Override fiore@0: public void removeChangeListener(ChangeListener l){ fiore@0: DiagramModel.this.removeChangeListener(l); fiore@0: } fiore@3: fiore@0: /* sort the collections according to the id of nodes */ fiore@0: public void sort(){ fiore@0: Collections.sort(nodes, DiagramElementComparator.getInstance()); fiore@0: Collections.sort(edges, DiagramElementComparator.getInstance()); fiore@0: } fiore@3: fiore@0: public boolean isModified(){ fiore@0: return modified; fiore@0: } fiore@3: fiore@0: public void setUnmodified(){ fiore@3: modified = false; fiore@3: } fiore@3: fiore@0: protected ArrayList listeners; fiore@0: fiore@0: } fiore@3: fiore@3: @SuppressWarnings("serial") fiore@0: private class InnerTreeModel extends DefaultTreeModel implements TreeModel{ fiore@0: fiore@3: public InnerTreeModel(TreeNode root){ fiore@3: super(root); fiore@3: bookmarks = new LinkedHashMap(); fiore@3: diagramTreeNodeListeners = new ArrayList(); fiore@0: } fiore@0: fiore@0: @Override fiore@3: public boolean insertTreeNode(N treeNode, Object source){ fiore@3: if(source == null) fiore@3: source = this; fiore@3: return _insert(treeNode,source); fiore@3: } fiore@3: fiore@3: @Override fiore@3: public boolean insertTreeNode(E treeNode, Object source){ fiore@3: if(source == null) fiore@3: source = this; fiore@3: return _insert(treeNode,source); fiore@3: } fiore@3: fiore@3: @Override fiore@3: public boolean takeTreeNodeOut(DiagramElement treeNode, Object source){ fiore@3: if(source == null) fiore@3: source = this; fiore@0: boolean result; fiore@0: if(treeNode instanceof DiagramEdge){ fiore@3: result = _takeOut((DiagramEdge)treeNode,source); fiore@0: } fiore@0: else{ fiore@3: result = _takeOut((DiagramNode)treeNode,source); fiore@0: } fiore@0: /* remove the bookmarks associated with the just deleted diagram element, if any */ fiore@0: for(String key : treeNode.getBookmarkKeys()) fiore@0: bookmarks.remove(key); fiore@0: return result; fiore@0: } fiore@0: fiore@0: @Override fiore@3: public DiagramTreeNode putBookmark(String bookmark, DiagramTreeNode treeNode, Object source){ fiore@0: if(bookmark == null) fiore@0: throw new IllegalArgumentException("bookmark cannot be null"); fiore@3: if(source == null) fiore@3: source = this; fiore@3: setEventSource(source); fiore@0: treeNode.addBookmarkKey(bookmark); fiore@3: DiagramTreeNode result = bookmarks.put(bookmark, treeNode); fiore@0: nodeChanged(treeNode); fiore@0: iLog("bookmark added",bookmark); fiore@3: DiagramTreeNodeEvent evt = new DiagramTreeNodeEvent(treeNode,bookmark,source); fiore@3: for(DiagramTreeNodeListener l : diagramTreeNodeListeners){ fiore@3: l.bookmarkAdded(evt); fiore@3: } fiore@3: handleChangeListeners(this); fiore@0: return result; fiore@0: } fiore@0: fiore@0: @Override fiore@3: public DiagramTreeNode getBookmarkedTreeNode(String bookmark) { fiore@0: return bookmarks.get(bookmark); fiore@0: } fiore@3: fiore@0: @Override fiore@3: public DiagramTreeNode removeBookmark(String bookmark,Object source) { fiore@3: if(source == null) fiore@3: source = this; fiore@3: setEventSource(source); fiore@3: DiagramTreeNode treeNode = bookmarks.remove(bookmark); fiore@0: treeNode.removeBookmarkKey(bookmark); fiore@0: nodeChanged(treeNode); fiore@0: iLog("bookmark removed",bookmark); fiore@3: DiagramTreeNodeEvent evt = new DiagramTreeNodeEvent(treeNode,bookmark,source); fiore@3: for(DiagramTreeNodeListener l : diagramTreeNodeListeners){ fiore@3: l.bookmarkRemoved(evt); fiore@3: } fiore@3: handleChangeListeners(this); fiore@0: return treeNode; fiore@0: } fiore@3: fiore@0: @Override fiore@0: public Set getBookmarks(){ fiore@0: return new LinkedHashSet(bookmarks.keySet()); fiore@0: } fiore@3: fiore@0: @Override fiore@3: public void setNotes(DiagramTreeNode treeNode, String notes,Object source){ fiore@3: if(source == null) fiore@3: source = this; fiore@3: setEventSource(source); fiore@3: String oldValue = treeNode.getNotes(); fiore@3: treeNode.setNotes(notes,source); fiore@0: nodeChanged(treeNode); fiore@0: iLog("notes set for "+treeNode.getName(),"".equals(notes) ? "empty notes" : notes.replaceAll("\n", "\\\\n")); fiore@3: DiagramTreeNodeEvent evt = new DiagramTreeNodeEvent(treeNode,oldValue,source); fiore@3: for(DiagramTreeNodeListener l : diagramTreeNodeListeners){ fiore@3: l.notesChanged(evt); fiore@3: } fiore@3: handleChangeListeners(source); fiore@0: } fiore@3: fiore@0: private void setEventSource(Object source){ fiore@0: this.src = source; fiore@0: } fiore@3: fiore@0: @Override fiore@3: public ReentrantLock getMonitor(){ fiore@3: return notifier; fiore@0: } fiore@3: fiore@0: @Override fiore@3: public void addDiagramTreeNodeListener(DiagramTreeNodeListener l){ fiore@3: diagramTreeNodeListeners.add(l); fiore@0: } fiore@3: fiore@0: @Override fiore@3: public void removeDiagramTreeNodeListener(DiagramTreeNodeListener l){ fiore@3: diagramTreeNodeListeners.remove(l); fiore@0: } fiore@3: fiore@0: /* redefine the fire methods so that they set the source object according */ fiore@0: /* to whether the element was inserted from the graph or from the tree */ fiore@0: @Override fiore@0: protected void fireTreeNodesChanged(Object source, Object[] path, fiore@0: int[] childIndices, Object[] children) { fiore@0: super.fireTreeNodesChanged(src, path, childIndices, children); fiore@0: } fiore@0: fiore@0: @Override fiore@0: protected void fireTreeNodesInserted(Object source, Object[] path, fiore@0: int[] childIndices, Object[] children) { fiore@0: super.fireTreeNodesInserted(src, path, childIndices, children); fiore@0: } fiore@0: fiore@0: @Override fiore@0: protected void fireTreeNodesRemoved(Object source, Object[] path, fiore@0: int[] childIndices, Object[] children) { fiore@0: super.fireTreeNodesRemoved(src, path, childIndices, children); fiore@0: } fiore@0: fiore@0: @Override fiore@0: protected void fireTreeStructureChanged(Object source, Object[] path, fiore@0: int[] childIndices, Object[] children) { fiore@0: super.fireTreeStructureChanged(src, path, childIndices, children); fiore@0: } fiore@3: fiore@0: public boolean isModified(){ fiore@0: return modified; fiore@0: } fiore@3: fiore@0: public void setUnmodified(){ fiore@3: modified = false; fiore@3: } fiore@3: fiore@0: private Object src; fiore@3: private Map bookmarks; fiore@3: private ArrayList diagramTreeNodeListeners; fiore@3: } fiore@3: fiore@3: @SuppressWarnings("serial") fiore@3: class ReentrantLockNotifier extends ReentrantLock implements ElementNotifier { fiore@3: @Override fiore@3: public void notifyChange(ElementChangedEvent evt) { fiore@3: _change(evt); fiore@3: handleChangeListeners(evt.getDiagramElement()); fiore@3: } fiore@3: } fiore@0: fiore@3: private boolean _insert(N n, Object source) { fiore@3: assert(n != null); fiore@3: fiore@3: /* if id has already been given then sync the counter so that a surely new value is given to the next nodes */ fiore@3: if(n.getId() == DiagramElement.NO_ID) fiore@3: n.setId(++nodeCounter); fiore@3: else if(n.getId() > nodeCounter) fiore@3: nodeCounter = n.getId(); fiore@3: fiore@3: treeModel.setEventSource(source); fiore@0: nodes.add(n); fiore@0: elements.add(n); fiore@0: /* add the node to outer node's (if any) inner nodes */ fiore@0: if(n.getExternalNode() != null) fiore@0: n.getExternalNode().addInternalNode(n); fiore@3: fiore@0: /* decide where to insert the node based on whether this is an inner node or not */ fiore@0: MutableTreeNode parent; fiore@0: if(n.getExternalNode() == null){ fiore@3: DiagramTreeNode typeNode = _lookForChild(root, n.getType()); fiore@0: if(typeNode == null) fiore@0: throw new IllegalArgumentException("Node type "+n.getType()+" not present in the model"); fiore@0: parent = typeNode; fiore@0: }else{ fiore@0: parent = n.getExternalNode(); fiore@0: } fiore@3: fiore@0: /* add to the node one child per property type */ fiore@0: for(String propertyType : n.getProperties().getTypes()) fiore@0: n.insert(new PropertyTypeMutableTreeNode(propertyType,n), n.getChildCount()); fiore@3: fiore@0: /* inject the notifier for managing changes internal to the edge */ fiore@0: n.setNotifier(notifier); fiore@0: fiore@0: /* insert node into tree which fires tree listeners */ fiore@0: treeModel.insertNodeInto(n, parent, parent.getChildCount()); fiore@0: /* this is necessary to increment the child counter displayed between brackets */ fiore@0: treeModel.nodeChanged(parent); fiore@0: diagramCollection.fireElementInserted(source,n); fiore@3: handleChangeListeners(n); fiore@3: fiore@0: iLog("node inserted",DiagramElement.toLogString(n)); fiore@0: return true; fiore@3: } fiore@3: fiore@3: private boolean _takeOut(DiagramNode n, Object source) { fiore@3: treeModel.setEventSource(source); fiore@3: /* recursively remove internal nodes of this node */ fiore@0: _removeInternalNodes(n,source); fiore@0: /* clear external node and clear edges attached to this node and updates other ends of such edges */ fiore@0: _clearNodeReferences(n,source); fiore@0: /* remove the node from the tree (fires listeners) */ fiore@0: treeModel.removeNodeFromParent(n); fiore@0: /* this is necessary to increment the child counter displayed between brackets */ fiore@0: treeModel.nodeChanged(n.getParent()); fiore@0: /* remove the nodes from the collection */ fiore@0: nodes.remove(n); fiore@0: elements.remove(n); fiore@0: /* notify all the listeners a new node has been removed */ fiore@0: diagramCollection.fireElementTakenOut(source,n); fiore@3: handleChangeListeners(n); fiore@3: fiore@0: if(nodes.isEmpty()){ fiore@0: nodeCounter = 0; fiore@0: }else{ fiore@0: long lastNodeId = nodes.get(nodes.size()-1).getId(); fiore@0: if(n.getId() > lastNodeId) fiore@0: nodeCounter = lastNodeId; fiore@0: } fiore@0: iLog("node removed",DiagramElement.toLogString(n)); fiore@0: return true; fiore@3: } fiore@3: fiore@3: private boolean _insert(E e, Object source) { fiore@3: assert(e != null); fiore@3: /* executes formal controls over the edge's node, which must be specified from the outer class*/ fiore@3: if(e.getNodesNum() < 2) fiore@3: throw new MalformedEdgeException("too few (" +e.getNodesNum()+ ") nodes"); fiore@3: fiore@3: /* if id has already been given then sync the counter so that a surely new value is given to the next edges */ fiore@3: if(e.getId() > edgeCounter) fiore@3: edgeCounter = e.getId(); fiore@3: else fiore@3: e.setId(++edgeCounter); fiore@3: fiore@3: treeModel.setEventSource(source); fiore@3: edges.add(e); fiore@3: elements.add(e); fiore@3: fiore@3: /* updates the nodes' edge reference and the edge tree references */ fiore@0: for(int i = e.getNodesNum()-1; i >= 0; i--){ fiore@0: DiagramNode n = e.getNodeAt(i); fiore@0: assert(n != null); fiore@0: /* insert first the type of the edge, if not already present */ fiore@3: DiagramTreeNode edgeType = _lookForChild(n, e.getType()); fiore@0: if(edgeType == null){ fiore@0: edgeType = new EdgeReferenceHolderMutableTreeNode(e.getType()); fiore@0: treeModel.insertNodeInto(edgeType, n, 0); fiore@0: } fiore@3: fiore@3: /* insert the edge reference under its type tree node, in the node*/ fiore@0: treeModel.insertNodeInto(new EdgeReferenceMutableTreeNode(e,n), edgeType, 0); fiore@0: /* this is necessary to increment the child counter displayed between brackets */ fiore@3: treeModel.nodeChanged(edgeType); fiore@0: fiore@0: n.addEdge(e); fiore@0: /* insert the node reference into the edge tree node */ fiore@0: e.insert(new NodeReferenceMutableTreeNode(n,e), 0); fiore@0: } fiore@3: fiore@3: DiagramTreeNode parent = _lookForChild(root, e.getType()); fiore@0: if(parent == null) fiore@0: throw new IllegalArgumentException("Edge type "+e.getType()+" not present in the model"); fiore@3: fiore@0: /* inject the controller and notifier to manage changes internal to the edge */ fiore@0: e.setNotifier(notifier); fiore@3: fiore@0: /* c'mon baby light my fire */ fiore@0: treeModel.insertNodeInto(e, parent, parent.getChildCount()); fiore@0: /* this is necessary to increment the child counter displayed between brackets */ fiore@0: treeModel.nodeChanged(parent); fiore@0: diagramCollection.fireElementInserted(source,e); fiore@3: handleChangeListeners(e); fiore@3: fiore@0: StringBuilder builder = new StringBuilder(DiagramElement.toLogString(e)); fiore@0: builder.append(" connecting:"); fiore@0: for(int i=0; i lastEdgeId) fiore@0: edgeCounter = lastEdgeId; fiore@3: } fiore@3: iLog("edge removed",DiagramElement.toLogString(e)); fiore@3: return true; fiore@3: } fiore@0: fiore@3: private void _removeInternalNodes(DiagramNode n, Object source){ fiore@3: for(int i=0; i edgesToRemove = new ArrayList(edges.size()); fiore@0: for(int i=0; i empty = Collections.emptyList(); fiore@3: for(int i=0; i children = parentNode.children(); children.hasMoreElements();){ fiore@0: temp = children.nextElement(); fiore@0: if(temp.getName().equals(name)){ fiore@3: child = temp; fiore@3: break; fiore@0: } fiore@0: } fiore@3: return child; fiore@3: } fiore@3: fiore@3: private static NodeReferenceMutableTreeNode _lookForNodeReference(DiagramEdge parent, DiagramNode n){ fiore@3: NodeReferenceMutableTreeNode child = null, temp; fiore@3: for(@SuppressWarnings("unchecked") fiore@3: Enumeration children = parent.children(); children.hasMoreElements();){ fiore@3: temp = (NodeReferenceMutableTreeNode)children.nextElement(); fiore@3: if( ((NodeReferenceMutableTreeNode)temp).getNode().equals(n)){ fiore@3: child = temp; fiore@3: break; fiore@3: } fiore@3: } fiore@3: return child; fiore@3: } fiore@3: fiore@3: private static EdgeReferenceMutableTreeNode _lookForEdgeReference( DiagramNode parentNode, DiagramEdge e){ fiore@3: DiagramTreeNode edgeType = _lookForChild(parentNode, e.getType()); fiore@3: assert(edgeType != null); fiore@3: EdgeReferenceMutableTreeNode child = null, temp; fiore@3: for(@SuppressWarnings("unchecked") fiore@3: Enumeration children = edgeType.children(); children.hasMoreElements();){ fiore@3: temp = (EdgeReferenceMutableTreeNode)children.nextElement(); fiore@3: if( ((EdgeReferenceMutableTreeNode)temp).getEdge().equals(e)){ fiore@3: child = temp; fiore@3: break; fiore@3: } fiore@3: } fiore@3: return child; fiore@3: } fiore@3: fiore@3: private void iLog(String action,String args){ fiore@3: InteractionLog.log("MODEL",action,args); fiore@3: } fiore@3: fiore@3: private DiagramTreeNode root; fiore@3: private InnerDiagramCollection diagramCollection; fiore@0: private ArrayList nodes; fiore@0: private ArrayList edges; fiore@0: private ArrayList elements; fiore@0: private InnerTreeModel treeModel; fiore@3: fiore@0: private long edgeCounter; fiore@0: private long nodeCounter; fiore@3: fiore@3: private ReentrantLockNotifier notifier; fiore@0: private List changeListeners; fiore@3: fiore@0: private boolean modified; fiore@3: fiore@0: private final static String ROOT_LABEL = "Diagram"; fiore@0: private final static int INITIAL_EDGES_SIZE = 20; fiore@0: private final static int INITIAL_NODES_SIZE = 30;}