diff java/src/uk/ac/qmul/eecs/ccmi/gui/DiagramTree.java @ 3:9e67171477bc

PHANTOM Omni Heptic device release
author Fiore Martin <fiore@eecs.qmul.ac.uk>
date Wed, 25 Apr 2012 17:09:09 +0100
parents 4b2f975e35fa
children d66dd5880081
line wrap: on
line diff
--- a/java/src/uk/ac/qmul/eecs/ccmi/gui/DiagramTree.java	Mon Feb 06 12:54:06 2012 +0000
+++ b/java/src/uk/ac/qmul/eecs/ccmi/gui/DiagramTree.java	Wed Apr 25 17:09:09 2012 +0100
@@ -40,12 +40,14 @@
 import javax.swing.tree.TreeSelectionModel;
 
 import uk.ac.qmul.eecs.ccmi.diagrammodel.DiagramElement;
-import uk.ac.qmul.eecs.ccmi.diagrammodel.DiagramModelTreeNode;
+import uk.ac.qmul.eecs.ccmi.diagrammodel.DiagramTreeNode;
 import uk.ac.qmul.eecs.ccmi.diagrammodel.DiagramNode;
 import uk.ac.qmul.eecs.ccmi.diagrammodel.EdgeReferenceMutableTreeNode;
 import uk.ac.qmul.eecs.ccmi.diagrammodel.NodeReferenceMutableTreeNode;
 import uk.ac.qmul.eecs.ccmi.diagrammodel.TreeModel;
 import uk.ac.qmul.eecs.ccmi.diagrammodel.TypeMutableTreeNode;
+import uk.ac.qmul.eecs.ccmi.network.Command;
+import uk.ac.qmul.eecs.ccmi.network.DiagramEventActionSource;
 import uk.ac.qmul.eecs.ccmi.sound.PlayerListener;
 import uk.ac.qmul.eecs.ccmi.sound.SoundEvent;
 import uk.ac.qmul.eecs.ccmi.sound.SoundFactory;
@@ -54,14 +56,28 @@
 import uk.ac.qmul.eecs.ccmi.speech.SpeechUtilities;
 import uk.ac.qmul.eecs.ccmi.utils.InteractionLog;
 
+
 @SuppressWarnings("serial")
 public class DiagramTree extends JTree {
+	/**
+	 * Creates a new diagram tree. The model of this tree is set to the tree model 
+	 * held by the instance of {@code Diagram} passed as argument. The model is retrieved by a call 
+	 * to {@code getTreeModel()} on the diagram.
+	 * <p>
+	 * The tree doesn't allow interaction via the mouse. It can be navigated via the keyboard using 
+	 * the arrow keys. When a node is selected, cursoring up and down allows the user to go through
+	 * all the sibling of the selected node. Cursoring right will expand the selected node (if it has children)
+	 * and select its first child. Cursoring left will collapse a node and select its father. All the motions
+	 * trigger a text to speech utterance (possibly accompanied by sound) about the new selected node.       
+	 * 
+	 * @param diagram a reference to the diagram holding the tree model for this tree. 
+	 */
 	public DiagramTree(Diagram diagram){
 		super(diagram.getTreeModel());
 		this.diagram = diagram;
 		resources = ResourceBundle.getBundle(EditorFrame.class.getName());
 		
-		TreePath rootPath = new TreePath((DiagramModelTreeNode)diagram.getTreeModel().getRoot());
+		TreePath rootPath = new TreePath((DiagramTreeNode)diagram.getTreeModel().getRoot());
 		setSelectionPath(rootPath);
 		collapsePath(rootPath);
 		selectedNodes = new ArrayList<Node>();
@@ -70,7 +86,7 @@
 	    overwriteTreeKeystrokes();
 	    /* don't use the swing focus system as we provide one on our own */
 	    setFocusTraversalKeysEnabled(false);
-	    getAccessibleContext().setAccessibleName("");
+	    getAccessibleContext().setAccessibleName("tree");
 	}
 	
 	@SuppressWarnings("unchecked")
@@ -79,19 +95,30 @@
 		return (TreeModel<Node,Edge>)super.getModel();
 	}
 	
+	/**
+	 * @see javax.swing.JTree#setModel(javax.swing.tree.TreeModel)
+	 * 
+	 * @param newModel the new mnodel for this tree
+	 */
 	public void setModel(TreeModel<Node,Edge> newModel){
-		DiagramModelTreeNode selectedTreeNode = (DiagramModelTreeNode)getSelectionPath().getLastPathComponent();
+		DiagramTreeNode selectedTreeNode = (DiagramTreeNode)getSelectionPath().getLastPathComponent();
 		super.setModel(newModel);
 		collapseRow(0);
 		setSelectionPath(new TreePath(selectedTreeNode.getPath()));
 	}
 	
+	/**
+	 * Set a new diagram for this tree. As a result of this call the tree model 
+	 * of this tree will be set to the model return by {@code diagram.getTreeModel()} 
+	 *	
+	 * @param diagram the new diagram for this tree 
+	 */
 	public void setDiagram(Diagram diagram){
 		this.diagram = diagram;
 		setModel(diagram.getTreeModel());
 	}
 	
-	public void selectNode(final Node n){
+	private void selectNode(final Node n){
 		selectedNodes.add(n);
 		treeModel.valueForPathChanged(new TreePath(n.getPath()),n.getName());
 		
@@ -104,7 +131,7 @@
 		InteractionLog.log(INTERACTIONLOG_SOURCE,"node selected for edge",n.getName());
 	}
 	
-	public void unselectNode(final Node n){
+	private void unselectNode(final Node n){
 		selectedNodes.remove(n);
 		treeModel.valueForPathChanged(new TreePath(n.getPath()),n.getName());
 		
@@ -117,23 +144,41 @@
 		InteractionLog.log(INTERACTIONLOG_SOURCE,"node unselected for edge",DiagramElement.toLogString(n));
 	}
 	
+	/**
+	 * Returns an array containing the references to all the nodes that have so far been selected 
+	 * for edge creation. A new array is created each time this method is called. 
+	 * 
+	 * @return an array of nodes
+	 */
 	public DiagramNode[] getSelectedNodes(){
 		DiagramNode[] array = new DiagramNode[selectedNodes.size()]; 
 		return selectedNodes.toArray(array);
 	}
 	
+	/**
+	 * Makes all the nodes selected for edge creation unselected. This method should 
+	 * be called after an edge has been created, to get the user restart 
+	 * go over the selection process again.   
+	 * 
+	 */
 	public void clearNodeSelections(){
 		ArrayList<Node> tempList = new ArrayList<Node>(selectedNodes);
 		selectedNodes.clear();
 		for(Node n : tempList){
 			treeModel.valueForPathChanged(new TreePath(n.getPath()),n.getName());
-			diagram.getModelUpdater().yieldLock(n, Lock.MUST_EXIST);
+			diagram.getModelUpdater().yieldLock(n, Lock.MUST_EXIST, new DiagramEventActionSource(DiagramEventSource.TREE,Command.Name.INSERT_EDGE,n.getId(),n.getName()));
 		}
 	}
 	
+	/**
+	 * Returns a string for a text to speech synthesizer, describing the currently selected 
+	 * tree node. The one that is at the end of the current selection path. 
+	 * 
+	 * @return a description string suitable for text to speech synthesis 
+	 */
 	public String currentPathSpeech(){
 		TreePath path =	getSelectionPath();
-		DiagramModelTreeNode selectedPathTreeNode = (DiagramModelTreeNode)path.getLastPathComponent();
+		DiagramTreeNode selectedPathTreeNode = (DiagramTreeNode)path.getLastPathComponent();
 		if(selectedNodes.contains(selectedPathTreeNode))
 			/* add information about the fact that the node is selected */
 			return MessageFormat.format(resources.getString("speech.node_selected"), selectedPathTreeNode.spokenText());
@@ -142,8 +187,12 @@
 	}
 	
 	/**
-	 * this method changes the selected tree node from an edge/node reference
-	 * to the related edge/node itself
+	 * Changes the selected tree path from the current to one defined by 
+	 * the {@code JumpTo enum} 
+	 * 
+	 * @see JumpTo
+	 * 
+	 * @param jumpTo a {@code JumpTo enum}
 	 */
 	public void jump(JumpTo jumpTo){
 		final Narrator narrator = NarratorFactory.getInstance();
@@ -151,62 +200,62 @@
 		switch(jumpTo){
 		case REFERENCE :
 			oldPath = getSelectionPath();
-			DiagramModelTreeNode selectedTreeNode = (DiagramModelTreeNode)oldPath.getLastPathComponent();
+			DiagramTreeNode selectedTreeNode = (DiagramTreeNode)oldPath.getLastPathComponent();
 			if(selectedTreeNode instanceof NodeReferenceMutableTreeNode){
 				final Node n = (Node)((NodeReferenceMutableTreeNode)selectedTreeNode).getNode();
 				setSelectionPath(new TreePath(n.getPath()));
-				SoundFactory.getInstance().setPlayerListener(new PlayerListener(){
+				SoundFactory.getInstance().play(SoundEvent.JUMP, new PlayerListener(){
 					   @Override
 					   public void playEnded() {
 						   narrator.speak(MessageFormat.format(resources.getString("speech.jump"),n.spokenText()));
 					   }
-				   }, SoundEvent.JUMP);
+				});
 			}else if(selectedTreeNode instanceof EdgeReferenceMutableTreeNode){
 				final Edge e = (Edge)((EdgeReferenceMutableTreeNode)selectedTreeNode).getEdge();
 				setSelectionPath(new TreePath(e.getPath()));
-				SoundFactory.getInstance().setPlayerListener(new PlayerListener(){
+				SoundFactory.getInstance().play(SoundEvent.JUMP,new PlayerListener(){
 					   @Override
 					   public void playEnded() {
 						   narrator.speak(MessageFormat.format(resources.getString("speech.jump"),e.spokenText()));
 					   }
-				   }, SoundEvent.JUMP);
+				   });
 			}
 			/* assume the referee has only root in common with the reference and collapse everything up to the root (excluded) */
-			collapseAll(selectedTreeNode, (DiagramModelTreeNode)selectedTreeNode.getPath()[1]);
+			collapseAll(selectedTreeNode, (DiagramTreeNode)selectedTreeNode.getPath()[1]);
 			break;
 		case ROOT :
-			final DiagramModelTreeNode from =(DiagramModelTreeNode)getSelectionPath().getLastPathComponent();
+			final DiagramTreeNode from =(DiagramTreeNode)getSelectionPath().getLastPathComponent();
 			setSelectionRow(0);
 			collapseAll(from,from.getRoot());
-			SoundFactory.getInstance().setPlayerListener(new PlayerListener(){
+			SoundFactory.getInstance().play(SoundEvent.JUMP, new PlayerListener(){
 				   @Override
 				   public void playEnded() {
 					   narrator.speak(MessageFormat.format(resources.getString("speech.jump"),from.getRoot().spokenText()));
 				   }
-			   }, SoundEvent.JUMP);
+			   });
 			break;
-		case TYPE : // jumps to the ancestor type node of the current node, never used
-			oldPath = getSelectionPath();
-			int index = 0;
-			Object[] pathComponents = oldPath.getPath();
-			for(int i=0;i<pathComponents.length;i++){
-				if(pathComponents[i] instanceof TypeMutableTreeNode){
-					index=i;
-					break;
-				}
-			}
-			final DiagramModelTreeNode typeTreeNode = (DiagramModelTreeNode)oldPath.getPathComponent(index); 
-			setSelectionPath(new TreePath(typeTreeNode.getPath()));
-			collapseAll((DiagramModelTreeNode)oldPath.getLastPathComponent(),typeTreeNode);
-			SoundFactory.getInstance().setPlayerListener(new PlayerListener(){
-				   @Override
-				   public void playEnded() {
-					   narrator.speak(MessageFormat.format(resources.getString("speech.jump"),typeTreeNode.spokenText()));
-				   }
-			   }, SoundEvent.JUMP);
-			break;
+//		case TYPE : // jumps to the ancestor type node of the current node, never used
+//			oldPath = getSelectionPath();
+//			int index = 0;
+//			Object[] pathComponents = oldPath.getPath();
+//			for(int i=0;i<pathComponents.length;i++){
+//				if(pathComponents[i] instanceof TypeMutableTreeNode){
+//					index=i;
+//					break;
+//				}
+//			}
+//			final DiagramTreeNode typeTreeNode = (DiagramTreeNode)oldPath.getPathComponent(index); 
+//			setSelectionPath(new TreePath(typeTreeNode.getPath()));
+//			collapseAll((DiagramTreeNode)oldPath.getLastPathComponent(),typeTreeNode);
+//			SoundFactory.getInstance().play(SoundEvent.JUMP, new PlayerListener(){
+//				   @Override
+//				   public void playEnded() {
+//					   narrator.speak(MessageFormat.format(resources.getString("speech.jump"),typeTreeNode.spokenText()));
+//				   }
+//			   });
+//			break;
 		case SELECTED_TYPE :
-			DiagramModelTreeNode root = (DiagramModelTreeNode)getModel().getRoot();
+			DiagramTreeNode root = (DiagramTreeNode)getModel().getRoot();
 			Object[] types = new Object[root.getChildCount()];
 			for(int i=0; i< root.getChildCount();i++)
 				types[i] = ((TypeMutableTreeNode)root.getChildAt(i)).getName();//not to spokenText as it would be too long
@@ -242,13 +291,13 @@
 			}
 			setSelectionPath(new TreePath(typeNode.getPath()));
 			if(oldPath.getPath().length >= 2)
-				collapseAll((DiagramModelTreeNode)oldPath.getLastPathComponent(), (DiagramModelTreeNode)initialValue);
-			SoundFactory.getInstance().setPlayerListener(new PlayerListener(){
+				collapseAll((DiagramTreeNode)oldPath.getLastPathComponent(), (DiagramTreeNode)initialValue);
+			SoundFactory.getInstance().play(SoundEvent.JUMP, new PlayerListener(){
 				   @Override
 				   public void playEnded() {
 					   narrator.speak(MessageFormat.format(resources.getString("speech.jump"),selectedValue));
 				   }
-			   }, SoundEvent.JUMP);
+			   });
 			break;
 		case BOOKMARK :
 			TreeModel<Node,Edge> treeModel = getModel(); 
@@ -277,16 +326,16 @@
 
 			if(bookmark != null){
 				oldPath = getSelectionPath();
-				DiagramModelTreeNode treeNode = treeModel.getBookmarkedTreeNode(bookmark);
-				collapseAll((DiagramModelTreeNode)oldPath.getLastPathComponent(), (DiagramModelTreeNode)treeModel.getRoot());
+				DiagramTreeNode treeNode = treeModel.getBookmarkedTreeNode(bookmark);
+				collapseAll((DiagramTreeNode)oldPath.getLastPathComponent(), (DiagramTreeNode)treeModel.getRoot());
 				setSelectionPath(new TreePath(treeNode.getPath()));
 				final String currentPathSpeech = currentPathSpeech();
-				SoundFactory.getInstance().setPlayerListener(new PlayerListener(){
+				SoundFactory.getInstance().play(SoundEvent.JUMP, new PlayerListener(){
 					   @Override
 					   public void playEnded() {
 						   narrator.speak(currentPathSpeech);
 					   }
-				   }, SoundEvent.JUMP);
+				   });
 				InteractionLog.log(INTERACTIONLOG_SOURCE,"bookmark selected",bookmark);
 			}else{
 				/* it speaks anyway, as we set up the speech in the EditorFrame class. no need to use the narrator then */
@@ -297,13 +346,20 @@
 			break;
 			
 		}
-		InteractionLog.log(INTERACTIONLOG_SOURCE,"jumped to "+jumpTo.toString(),((DiagramModelTreeNode)getSelectionPath().getLastPathComponent()).getName());
-		SoundFactory.getInstance().play(SoundEvent.JUMP);
+		InteractionLog.log(INTERACTIONLOG_SOURCE,"jumped to "+jumpTo.toString(),((DiagramTreeNode)getSelectionPath().getLastPathComponent()).getName());
 	}
 	
+	/**
+	 * Changes the selected tree path from the current to the one from the root
+	 * to the {@code Diagramelement} passed as argument. Note that a {@code Diagramelement}
+	 * is also an instance of {@code DuagramTreeNode} and it's placed in a {@code TreeModel}
+	 * when it's inserted into a {@code DiagramModel}
+	 * 
+	 * @param de the diagram element to be selected on the tree 
+	 */
 	public void jumpTo(final DiagramElement de){
 		TreePath oldPath = getSelectionPath();
-		collapseAll((DiagramModelTreeNode)oldPath.getLastPathComponent(),de);
+		collapseAll((DiagramTreeNode)oldPath.getLastPathComponent(),de);
 		setSelectionPath(new TreePath(de.getPath()));
 		SoundFactory.getInstance().play( SoundEvent.JUMP, new PlayerListener(){
 			@Override
@@ -314,26 +370,36 @@
 	}
 	
 	/* collapse all the nodes in the path from "from" to "to" upwards(with the same direction as going from a leaf to the root)*/
-	private void collapseAll(DiagramModelTreeNode from, DiagramModelTreeNode to){
-		DiagramModelTreeNode currentNode = from;
+	private void collapseAll(DiagramTreeNode from, DiagramTreeNode to){
+		DiagramTreeNode currentNode = from;
 		while(currentNode.getParent() != null && currentNode != to){
 			currentNode = currentNode.getParent();
 			collapsePath(new TreePath(currentNode.getPath()));
 		}
 	}
 	
+	/**
+	 * Mouse events are ignored by this tree. This is just a blank method.
+	 * 
+	 * @param e a mouse event
+	 */
 	@Override
 	protected  void	processMouseEvent(MouseEvent e){
 		//do nothing as the tree does not have to be editable with mouse
 	}
 	
+	/**
+	 * Allows only cursor keys, tab key, delete, and actions (CTRL+something)
+	 * 
+	 * @param e a key event 
+	 *  
+	 */
 	@Override
 	protected void processKeyEvent(KeyEvent e){
 		/* allow only cursor keys, tab key, delete, and actions (CTRL+something) */
 		if(e.getKeyChar() == KeyEvent.CHAR_UNDEFINED 
 				|| e.getKeyCode() == KeyEvent.VK_TAB
 					|| e.getKeyCode() == KeyEvent.VK_SPACE
-						|| e.getKeyCode() == KeyEvent.VK_DELETE
 				 			|| e.isControlDown()
 				 				|| e.isAltDown())
 			super.processKeyEvent(e);
@@ -348,16 +414,16 @@
 		   getActionMap().put("down", new AbstractAction(){
 				@Override
 				public void actionPerformed(ActionEvent evt) {
-					DiagramModelTreeNode treeNode = (DiagramModelTreeNode)getLastSelectedPathComponent();
+					DiagramTreeNode treeNode = (DiagramTreeNode)getLastSelectedPathComponent();
 					/* look if we've got a sibling node after (we are not at the bottom) */
-					DiagramModelTreeNode nextTreeNode = treeNode.getNextSibling(); 
+					DiagramTreeNode nextTreeNode = treeNode.getNextSibling(); 
 					SoundEvent loop = null;
 					if(nextTreeNode == null){
-						DiagramModelTreeNode parent = treeNode.getParent();
+						DiagramTreeNode parent = treeNode.getParent();
 						if(parent == null) /* root node, just stay there */
 							nextTreeNode = treeNode;
 						else /* loop = go to first child of own parent */
-							nextTreeNode = (DiagramModelTreeNode)parent.getFirstChild();
+							nextTreeNode = (DiagramTreeNode)parent.getFirstChild();
 						loop = SoundEvent.LIST_BOTTOM_REACHED;
 					}
 					setSelectionPath(new TreePath(nextTreeNode.getPath()));
@@ -376,15 +442,15 @@
 		   getActionMap().put("up", new AbstractAction(){
 				@Override
 				public void actionPerformed(ActionEvent evt) {
-					DiagramModelTreeNode treeNode = (DiagramModelTreeNode)getLastSelectedPathComponent();
-					DiagramModelTreeNode previousTreeNode = treeNode.getPreviousSibling();
+					DiagramTreeNode treeNode = (DiagramTreeNode)getLastSelectedPathComponent();
+					DiagramTreeNode previousTreeNode = treeNode.getPreviousSibling();
 					SoundEvent loop = null;
 					if(previousTreeNode == null){
-						DiagramModelTreeNode parent = treeNode.getParent();
+						DiagramTreeNode parent = treeNode.getParent();
 						if(parent == null) /* root node */
 							previousTreeNode = treeNode;
 						else 
-							previousTreeNode = (DiagramModelTreeNode)parent.getLastChild();
+							previousTreeNode = (DiagramTreeNode)parent.getLastChild();
 						loop = SoundEvent.LIST_TOP_REACHED;
 					}
 					setSelectionPath(new TreePath(previousTreeNode.getPath()));
@@ -404,14 +470,14 @@
 			   @Override
 			   public void actionPerformed(ActionEvent evt) {
 				   TreePath path = getSelectionPath();
-				   DiagramModelTreeNode treeNode = (DiagramModelTreeNode)path.getLastPathComponent();
+				   DiagramTreeNode treeNode = (DiagramTreeNode)path.getLastPathComponent();
 				   if(treeNode.isLeaf()){
 					   notifyBorderReached(treeNode);
 					   InteractionLog.log(INTERACTIONLOG_SOURCE,"move right","border reached");
 				   }
 				   else{
 					   expandPath(path);
-					   setSelectionPath(new TreePath(((DiagramModelTreeNode)treeNode.getFirstChild()).getPath()));
+					   setSelectionPath(new TreePath(((DiagramTreeNode)treeNode.getFirstChild()).getPath()));
 					   final String currentPathSpeech = currentPathSpeech();
 					   SoundFactory.getInstance().play(SoundEvent.TREE_NODE_EXPAND,new PlayerListener(){
 						@Override
@@ -419,7 +485,7 @@
 							NarratorFactory.getInstance().speak(currentPathSpeech);
 						}
 					   });
-					   InteractionLog.log(INTERACTIONLOG_SOURCE,"move right",((DiagramModelTreeNode)treeNode.getFirstChild()).toString());
+					   InteractionLog.log(INTERACTIONLOG_SOURCE,"move right",((DiagramTreeNode)treeNode.getFirstChild()).toString());
 				   }
 			   }
 		   });
@@ -429,14 +495,14 @@
 			   @Override
 			   public void actionPerformed(ActionEvent evt) {
 				   TreePath path = getSelectionPath();
-				   DiagramModelTreeNode treeNode = (DiagramModelTreeNode)path.getLastPathComponent();
-				   DiagramModelTreeNode parent = treeNode.getParent();
+				   DiagramTreeNode treeNode = (DiagramTreeNode)path.getLastPathComponent();
+				   DiagramTreeNode parent = treeNode.getParent();
 				   if(parent == null){/* root node */
 					   notifyBorderReached(treeNode);
 					   InteractionLog.log(INTERACTIONLOG_SOURCE,"move left","border reached");
 				   }
 				   else{
-					   TreePath newPath = new TreePath(((DiagramModelTreeNode)parent).getPath());
+					   TreePath newPath = new TreePath(((DiagramTreeNode)parent).getPath());
 					   setSelectionPath(newPath);
 					   collapsePath(newPath);
 					   final String currentPathSpeech = currentPathSpeech(); 
@@ -446,7 +512,7 @@
 								NarratorFactory.getInstance().speak(currentPathSpeech);
 							}
 					   });
-					   InteractionLog.log(INTERACTIONLOG_SOURCE,"move left",((DiagramModelTreeNode)parent).toString());
+					   InteractionLog.log(INTERACTIONLOG_SOURCE,"move left",((DiagramTreeNode)parent).toString());
 				   }
 			   }
 		   });
@@ -474,7 +540,7 @@
 				   *  Narrator.getInstance().speak(builder.toString(), null);
 				   */  
 				   TreePath path = getSelectionPath();
-				   DiagramModelTreeNode treeNode = (DiagramModelTreeNode)path.getLastPathComponent();
+				   DiagramTreeNode treeNode = (DiagramTreeNode)path.getLastPathComponent();
 				   NarratorFactory.getInstance().speak(treeNode.detailedSpokenText());
 				   InteractionLog.log(INTERACTIONLOG_SOURCE,"detailed info requested","");
 			   }
@@ -486,14 +552,11 @@
 			   public void actionPerformed(ActionEvent evt) {
 				   if(getSelectionPath().getLastPathComponent() instanceof Node){
 					   Node node = (Node)getSelectionPath().getLastPathComponent();
-					   
-					   
 					   if(selectedNodes.contains(node)){
 						   unselectNode(node);
-						   diagram.getModelUpdater().yieldLock(node, Lock.MUST_EXIST);
-					   }
-					   else{
-						   if(!diagram.getModelUpdater().getLock(node, Lock.MUST_EXIST)){
+						   diagram.getModelUpdater().yieldLock(node, Lock.MUST_EXIST,new DiagramEventActionSource(DiagramEventSource.TREE,Command.Name.UNSELECT_NODE_FOR_EDGE_CREATION,node.getId(),node.getName()));
+					   }else{
+						   if(!diagram.getModelUpdater().getLock(node, Lock.MUST_EXIST,new DiagramEventActionSource(DiagramEventSource.TREE,Command.Name.SELECT_NODE_FOR_EDGE_CREATION,node.getId(),node.getName()))){
 							   InteractionLog.log(INTERACTIONLOG_SOURCE,"Could not get lock on node fro edge creation selection",DiagramElement.toLogString(node));
 							   SpeechOptionPane.showMessageDialog(
 									   SpeechOptionPane.getFrameForComponent(DiagramTree.this), 
@@ -521,7 +584,7 @@
 		   getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN,0),"none");
 	   }
 	
-	private static InputStream getTreeNodeSound(DiagramModelTreeNode node){
+	private static InputStream getTreeNodeSound(DiagramTreeNode node){
 		InputStream sound = null;
 		TreeNode[] newPath = node.getPath();
 		if(!node.isRoot()){
@@ -550,7 +613,7 @@
 		scrollPathToVisible(path);
 	}
 	
-	private void notifyBorderReached(DiagramModelTreeNode n) {
+	private void notifyBorderReached(DiagramTreeNode n) {
 		SoundFactory.getInstance().play(SoundEvent.ERROR);
 	}
 	
@@ -582,7 +645,30 @@
 	private static final char SELECTED_NODE_MARK_BEGIN = '<';
 	private static final char SELECTED_NODE_MARK_END = '>';
 	private static final String INTERACTIONLOG_SOURCE = "TREE";
-	static enum JumpTo {REFERENCE, ROOT, TYPE, SELECTED_TYPE, BOOKMARK}
+	/**
+	 * A list of possible destination for a jump (a change of the selected path without 
+	 * using the navigation arrow keys)   
+	 */
+	public static enum JumpTo {
+		/**
+		 * if the current selection is a edge/node reference tree node, the jump destination 
+		 * is the referee tree node (see {@link uk.ac.qmul.eecs.ccmi.diagrammodel.NodeReferenceMutableTreeNode} and 
+		 * {@link uk.ac.qmul.eecs.ccmi.diagrammodel.EdgeReferenceMutableTreeNode }) 
+		 */
+		REFERENCE,
+		/**
+		 * the destination is the root of the diagram
+		 */
+		ROOT,
+		/**
+		 * the destination will be a node or edge type selected 
+		 * (via a selection dialog) by the user
+		 */
+		SELECTED_TYPE, 
+		 /**	
+		  * the destination will be a bookmark selected (via a selection dialog) by the user 
+		  */
+		BOOKMARK}
 	
 	/* the methods of the TreeModelHandler are overwritten in order to provide a consistent way 
 	 * of updating the tree selection upon tree change. Bear in mind that the tree can possibly be changed
@@ -614,14 +700,14 @@
 				/* go along the path from the selected node to the root looking for a node *
 				 * attached to the tree or with sibling nodes attached to the tree         */
 				for(int i=pathArray.length-1;i>=0;i--){
-					DiagramModelTreeNode onPathTreeNode = (DiagramModelTreeNode)pathArray[i];
+					DiagramTreeNode onPathTreeNode = (DiagramTreeNode)pathArray[i];
 					if(onPathTreeNode.isNodeRelated(root)){// if can reach the root from here a.k.a. the node is still part of the tree 
 						super.treeStructureChanged(e);
 						setSelectionPath(new TreePath(onPathTreeNode.getPath()));
 						break;
 					}else{
 						/* check sibling nodes*/
-						DefaultMutableTreeNode parent = (DiagramModelTreeNode)pathArray[i-1];
+						DefaultMutableTreeNode parent = (DiagramTreeNode)pathArray[i-1];
 						if(parent.isNodeRelated(root) && parent.getChildCount() > 0){
 							super.treeStructureChanged(e);
 							setSelectionPath(new TreePath(((DefaultMutableTreeNode)parent.getLastChild()).getPath()));
@@ -645,7 +731,7 @@
 		public void treeNodesRemoved(final TreeModelEvent e){
 			/* check first if what we're removing is in the selecton path */
 			TreePath path = e.getTreePath();
-			DiagramModelTreeNode removedTreeNode = (DiagramModelTreeNode)e.getChildren()[0];
+			DiagramTreeNode removedTreeNode = (DiagramTreeNode)e.getChildren()[0];
 			boolean isInSelectionPath = false;
 			for(Object t : getSelectionPath().getPath()){
 				if(removedTreeNode == t){
@@ -653,7 +739,7 @@
 					break;
 				}
 			}
-			DiagramModelTreeNode parentTreeNode = (DiagramModelTreeNode)path.getLastPathComponent(); 
+			DiagramTreeNode parentTreeNode = (DiagramTreeNode)path.getLastPathComponent(); 
 			/* update the selection only if the tree node involved is in the selection path *
 			 * this always holds true for tree nodes deleted from the tree                  */
 			if(isInSelectionPath){
@@ -670,7 +756,7 @@
 					 * and the node has siblings than the new first sibling will be selected              */
 					int limitForParentDeletion = (parentTreeNode instanceof Edge) ? 1 : 0; // an edge with one node is to be deleted
 					if(parentTreeNode.getChildCount() > limitForParentDeletion){
-						setSelectionPath(new TreePath(((DiagramModelTreeNode)parentTreeNode.getChildAt(
+						setSelectionPath(new TreePath(((DiagramTreeNode)parentTreeNode.getChildAt(
 								/* select the n-th sibling node (see algorithm description above or the highest index sibling node */
 								Math.min(e.getChildIndices()[0],parentTreeNode.getChildCount()-1)
 						)).getPath()));
@@ -678,7 +764,7 @@
 						/* the deleted node had no siblings, thus select the node checking from the parent up in the path to the first still existing node */
 						Object[] pathArray = path.getPath();
 						for(int i=path.getPathCount()-1;i>=0;i--){
-							DiagramModelTreeNode itr = (DiagramModelTreeNode)pathArray[i];
+							DiagramTreeNode itr = (DiagramTreeNode)pathArray[i];
 							if(itr.getPath()[0] == getModel().getRoot()){
 								TreePath newPath = new TreePath(itr.getPath()); 
 								setSelectionPath(newPath);
@@ -692,7 +778,7 @@
 				super.treeNodesRemoved(e);
 
 			/* if the node was selected for edge creation, then remove it from the list */
-			DiagramModelTreeNode removedNode = (DiagramModelTreeNode)e.getChildren()[0];
+			DiagramTreeNode removedNode = (DiagramTreeNode)e.getChildren()[0];
 			selectedNodes.remove(removedNode);
 		}		
 	}