Mercurial > hg > accesspd
diff java/src/uk/ac/qmul/eecs/ccmi/gui/DiagramPanel.java @ 0:78b7fc5391a2
first import, outcome of NIME 2014 hackaton
author | Fiore Martin <f.martin@qmul.ac.uk> |
---|---|
date | Tue, 08 Jul 2014 16:28:59 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java/src/uk/ac/qmul/eecs/ccmi/gui/DiagramPanel.java Tue Jul 08 16:28:59 2014 +0100 @@ -0,0 +1,298 @@ +/* + 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/) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + 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; +import javax.swing.JSplitPane; +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} + * a {@link GraphToolbar} and the {@code AwarenessPanel}. + * It's backed up by an instance of {@code Diagram}. + */ +@SuppressWarnings("serial") +public class DiagramPanel extends JPanel{ + + /** + * 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; + + 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 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 up delegate 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 the backing up delegate 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 {@code true} if the diagram is modified, {@code false} otherwise + */ + 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); +} +