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;}