diff java/src/uk/ac/qmul/eecs/ccmi/gui/DiagramPanel.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 9418ab7b7f3f
children d66dd5880081
line wrap: on
line diff
--- a/java/src/uk/ac/qmul/eecs/ccmi/gui/DiagramPanel.java	Mon Feb 06 12:54:06 2012 +0000
+++ b/java/src/uk/ac/qmul/eecs/ccmi/gui/DiagramPanel.java	Wed Apr 25 17:09:09 2012 +0100
@@ -1,6 +1,6 @@
 /*  
  CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool
-  
+
  Copyright (C) 2002 Cay S. Horstmann (http://horstmann.com)
  Copyright (C) 2011  Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)
 
@@ -16,11 +16,12 @@
 
  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
+ */
 
 package uk.ac.qmul.eecs.ccmi.gui;
 
 import java.awt.BorderLayout;
+import java.io.IOException;
 
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
@@ -28,105 +29,270 @@
 import javax.swing.event.ChangeEvent;
 import javax.swing.event.ChangeListener;
 
+import uk.ac.qmul.eecs.ccmi.gui.awareness.AwarenessPanel;
+import uk.ac.qmul.eecs.ccmi.gui.awareness.DisplayFilter;
+import uk.ac.qmul.eecs.ccmi.network.NetDiagram;
+
 /**
  * It's the panel which displays a diagram. It contains a {@link GraphPanel}, a {@link DiagramTree} 
- * and a {@link GraphToolbar} 
- *
+ * a {@link GraphToolbar} and the {@code AwarenessPanel}.
+ * It's backed up by an instance of {@code Diagram}.
  */
 @SuppressWarnings("serial")
 public class DiagramPanel extends JPanel{
-   
-   public DiagramPanel(Diagram diagram, EditorTabbedPane tabbedPane){
-	  this.diagram = diagram;
-	  this.tabbedPane = tabbedPane;
-	  setName(diagram.getLabel());
-	  setLayout(new BorderLayout());
-	  
-	  modelChangeListener = new ChangeListener(){
-		  @Override
-		  public void stateChanged(ChangeEvent e) {
-			  setModified(true);
-		  }
-	  };
-	  
-      toolbar = new GraphToolbar(diagram);
-      graphPanel = new GraphPanel(diagram, toolbar);
-      /* the focus must be hold by the tree and the tab panel only */
-      toolbar.setFocusable(false);
-      graphPanel.setFocusable(false);
-      
-      tree = new DiagramTree(diagram);
-      
-      /* the panel containing the graph and the toolbar */
-      JPanel graphAndToolbarPanel = new JPanel(new BorderLayout());
-      graphAndToolbarPanel.add(toolbar, BorderLayout.NORTH);
-      graphAndToolbarPanel.add(new JScrollPane(graphPanel),BorderLayout.CENTER);
-      
-      JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
-            new JScrollPane(tree),
-      		graphAndToolbarPanel);
-      splitPane.setDividerLocation((int)tree.getPreferredSize().width*2);
-      add(splitPane, BorderLayout.CENTER);
-      
-      diagram.getCollectionModel().addChangeListener(modelChangeListener);
-   }
 
-   public String getFilePath(){
-      return filePath;
-   }
+	/**
+	 * Creates a new instance of {@code DiagramPanel} holding the diagram passed as argument. 
+	 * 	
+	 * @param diagram the diagram this panel is backed up by
+	 * @param tabbedPane the tabbed pane this DiagramPanel will be added to. This reference 
+	 * is used to updated the tab label when the diagram is modified or save (in the former
+	 * case a star is added to the label, in the latter case the star is removed)
+	 */
+	public DiagramPanel(Diagram diagram, EditorTabbedPane tabbedPane){
+		this.diagram = diagram;
+		this.tabbedPane = tabbedPane;
 
-   public void setFilePath(String newValue){
-      filePath = newValue;
-   }
-   
-   public Diagram getDiagram(){
-	   return diagram;
-   }
-   
-   public void setDiagram(Diagram diagram){
-	   /* remove the listener from the old model  */
-	   this.diagram.getCollectionModel().removeChangeListener(modelChangeListener);
-	   diagram.getCollectionModel().addChangeListener(modelChangeListener);
-	   
-	   this.diagram = diagram;
-	   tree.setDiagram(diagram);
-	   graphPanel.setModelUpdater(diagram.getModelUpdater());
-	   setName(diagram.getLabel());
-	   /* set the * according to the new diagram's model modification status */
-	   setModified(isModified());
-   }
-   
-   public GraphPanel getGraphPanel(){
-	   return graphPanel;
-   }
-   
-   public DiagramTree getTree(){
-	   return tree;
-   }
-   
-   /** This method is for changing the 'modified' status of the diagram.       * 
-    * When called passing false as argument listeners are notified that the   *
-    * diagram has been saved. 											      */
-   public void setModified(boolean modified){
-	   if(!modified)
-		   diagram.getCollectionModel().setUnmodified();
-	   /* add an asterisk to notify that the diagram has changed */
-       if(modified)
-     	  setName(getName()+"*");
-       else 
-    	   setName(diagram.getLabel());
-       tabbedPane.refreshComponentTabTitle(this);
-   }
-   
-   public boolean isModified(){
-	   return diagram.getCollectionModel().isModified();
-   }
+		setName(diagram.getLabel());
+		setLayout(new BorderLayout());
 
-   private Diagram diagram;
-   private GraphPanel graphPanel;
-   private DiagramTree tree;
-   private GraphToolbar toolbar;
-   private String filePath;
-   private ChangeListener modelChangeListener;
-   private EditorTabbedPane tabbedPane;
+		modelChangeListener = new ChangeListener(){
+			@Override
+			public void stateChanged(ChangeEvent e) {
+				setModified(true);
+			}
+		};
+
+		toolbar = new GraphToolbar(diagram);
+		graphPanel = new GraphPanel(diagram, toolbar);
+		/* the focus must be hold by the tree and the tab panel only */
+		toolbar.setFocusable(false);
+		graphPanel.setFocusable(false);
+
+		tree = new DiagramTree(diagram);
+
+		/* the panel containing the graph and the toolbar and the awareness panel */
+		visualPanel = new JPanel(new BorderLayout());
+		visualPanel.add(toolbar, BorderLayout.NORTH);
+		visualPanel.add(new JScrollPane(graphPanel),BorderLayout.CENTER);
+		awarenessSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
+		awarenessSplitPane.setTopComponent(visualPanel);
+
+		/* divides the tree from the visual diagram */
+		JSplitPane treeSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
+				new JScrollPane(tree),
+				awarenessSplitPane);
+		treeSplitPane.setDividerLocation((int)tree.getPreferredSize().width*2);
+		add(treeSplitPane, BorderLayout.CENTER);
+		diagram.getCollectionModel().addChangeListener(modelChangeListener);
+	}
+
+	/**
+	 * When a diagram is saved on the file system the its path is associated to the diagram panel 
+	 * and it's shown when the user hover on the its tab title.  
+	 * 
+	 * @return the path of the file where this diagram has been saved last time or {@code null}  
+	 */
+	public String getFilePath(){
+		return filePath;
+	}
+	
+	/**
+	 * Sets the file path to a new path. This method should be called after the backing diagram has
+	 * been saved to a file.
+	 * 
+	 * @param newValue the path of the file where the backing diagram has been saved last time
+	 */
+	public void setFilePath(String newValue){
+		filePath = newValue;
+	}
+
+	/**
+	 * Returns a reference to the backing diagram of this diagram panel.
+	 * 
+	 * @return a reference to the backing diagram of this diagram panel
+	 */
+	public Diagram getDiagram(){
+		return diagram;
+	}
+
+	/**
+	 * Enables or disables the awareness panel of this diagram panel. As default the awareness panel 
+	 * is disabled but if the diagram is shared (either on a local or on a remote server) the awareness 
+	 * panel gets enabled. In fact, from now on, awareness messages will be received from the server and,
+	 * even if the awareness panel is not visible, some messages (username messages) 
+	 * will still have to be taken into account.
+	 *    
+	 * @param enabled {@code true} if the panel is to be enabled, {@code false} otherwise.
+	 */
+	public void setAwarenessPanelEnabled(boolean enabled){
+		if(!(diagram instanceof NetDiagram))
+			return;
+		/* if the display filter has not been created yet, do create it */
+		DisplayFilter filter = DisplayFilter.getInstance();
+		if(filter == null)
+			try{
+				filter = DisplayFilter.createInstance();
+			}catch(IOException ioe){
+				SpeechOptionPane.showMessageDialog(this, ioe.getLocalizedMessage());
+				return;
+			}
+
+			NetDiagram netDiagram = (NetDiagram)diagram;
+			if(enabled){
+				awarenessPanel = new AwarenessPanel(diagram.getName());
+				awarenessPanelScrollPane = new JScrollPane(awarenessPanel);
+				netDiagram.enableAwareness(awarenessPanel);
+				if(awarenessPanelListener != null)
+					awarenessPanelListener.awarenessPanelEnabled(true);
+			}else{ //disabled
+				netDiagram.disableAwareness(awarenessPanel);
+				if(awarenessSplitPane.getRightComponent() != null){
+					// hide the panel
+					awarenessSplitPane.remove(awarenessPanelScrollPane);
+				}
+				awarenessPanelScrollPane = null;
+				awarenessPanel = null;
+				awarenessSplitPane.validate();
+				if(awarenessPanelListener != null)
+					awarenessPanelListener.awarenessPanelEnabled(false);
+			}
+	}
+
+	/**
+	 * Makes the awareness panel visible or invisible, assuming that it has been enabled beforehand. If the 
+	 * awareness panel hasn't been enables this call has no effect.  
+	 * 
+	 * @param visible {@code true} if the panel is to be made visible, {@code false} otherwise.
+	 */
+	public void setAwarenessPanelVisible(boolean visible){
+		if(awarenessPanelScrollPane == null)
+			return;
+		if(visible){
+			awarenessSplitPane.setRightComponent(awarenessPanelScrollPane);
+			awarenessSplitPane.setDividerLocation(0.8);
+			awarenessSplitPane.setResizeWeight(1.0);
+			awarenessSplitPane.validate();
+			if(awarenessPanelListener != null)
+				awarenessPanelListener.awarenessPanelVisible(true);
+		}else{
+			awarenessSplitPane.remove(awarenessPanelScrollPane);
+			awarenessSplitPane.validate();
+			if(awarenessPanelListener != null)
+				awarenessPanelListener.awarenessPanelVisible(false);
+		}
+	}
+
+	/**
+	 * Queries the diagram panel on whether the awareness panel is currently visible.  
+	 * 
+	 * @return {@code true} if the awareness panel is currently visible, {@code false} otherwise. 
+	 */
+	public boolean isAwarenessPanelVisible(){
+		return (awarenessSplitPane.getRightComponent() != null);
+	}
+
+	/**
+	 * Returns a reference to the inner awareness panel. 
+	 * 
+	 * @return the inner awareness panel if it has been enabled of {@code null} otherwise
+	 */
+	public AwarenessPanel getAwarenessPanel(){
+		return awarenessPanel;
+	}
+
+	/**
+	 * Sets the backing diagram for this panel. This method is used when a diagram is shared 
+	 * (or reverted). A shared diagram has a different way of updating the   
+	 * The modified status is changed according to
+	 * the modified status of the {@code DiagramModel} internal to the new {@code Diagram}   
+	 * 
+	 * @param diagram
+	 */
+	public void setDiagram(Diagram diagram){
+		/* remove the listener from the old model  */
+		this.diagram.getCollectionModel().removeChangeListener(modelChangeListener);
+		diagram.getCollectionModel().addChangeListener(modelChangeListener);
+
+		this.diagram = diagram;
+		tree.setDiagram(diagram);
+		graphPanel.setModelUpdater(diagram.getModelUpdater());
+		setName(diagram.getLabel());
+		/* set the * according to the new diagram's model modification status */
+		setModified(isModified());
+	}
+
+	/**
+	 * Returns a reference to the graph panel in this diagram panel. The tree's model is the 
+	 * model returned by a calling {@code getTreeModel()} on the backing diagram.   
+	 * 
+	 * @return the graph panel  contained by this diagram panel 
+	 */
+	public GraphPanel getGraphPanel(){
+		return graphPanel;
+	}
+
+	/**
+	 * Returns a reference to the tree in this diagram panel. The graph model is the 
+	 * model returned by a calling {@code getCollectionModel()} on the backing diagram.   
+	 * 
+	 * @return the tree contained by this diagram panel 
+	 */
+	public DiagramTree getTree(){
+		return tree;
+	}
+
+	/**
+	 * Changes the {@code modified} status of the backing diagram of this panel. If set to {@code true} 
+	 * then a star will appear after the name of the diagram, returned by {@code getName()}. 
+	 * 
+	 * When called passing false as argument (which should be done after the diagram is saved on a file)  
+	 * listeners are notified that the diagram has been saved. 
+	 * 
+	 * @param modified {@code true} when the diagram has been modified, {@code false} when it has been saved 	
+	 */
+	public void setModified(boolean modified){
+		if(!modified)
+			diagram.getCollectionModel().setUnmodified();
+		/* add an asterisk to notify that the diagram has changed */
+		if(modified)
+			setName(getName()+"*");
+		else 
+			setName(diagram.getLabel());
+		tabbedPane.refreshComponentTabTitle(this);
+	}
+
+	/**
+	 * Whether the backing diagram has been modified. The diagram is modified as a result of changes
+	 * to the {@code TreeModel} or {@code CollectionModel} it contains. To change the {@code modified}
+	 * status of the diagram (and of its models) {@code setModified()} must be used. 
+	 * 
+	 * @return
+	 */
+	public boolean isModified(){
+		return diagram.getCollectionModel().isModified();
+	}
+
+	void setAwarenessPanelListener(AwarenessPanelEnablingListener listener){
+		awarenessPanelListener = listener;
+	}
+
+	private Diagram diagram;
+	private GraphPanel graphPanel;
+	private JSplitPane awarenessSplitPane;
+	private DiagramTree tree;
+	private JPanel visualPanel;
+	private GraphToolbar toolbar;
+	private AwarenessPanel awarenessPanel;
+	private JScrollPane awarenessPanelScrollPane;
+	private String filePath;
+	private ChangeListener modelChangeListener;
+	private EditorTabbedPane tabbedPane;
+	private AwarenessPanelEnablingListener awarenessPanelListener;
 }
+
+interface AwarenessPanelEnablingListener {
+	public void awarenessPanelEnabled(boolean enabled);
+	public void awarenessPanelVisible(boolean visible);
+}
+