annotate java/src/uk/ac/qmul/eecs/ccmi/gui/DiagramPanel.java @ 8:ea7885bd9bff tip

fixed bug : render solid line as dotted/dashed when moving the stylus from dotted/dashed to solid
author ccmi-guest
date Thu, 03 Jul 2014 16:12:20 +0100
parents d66dd5880081
children
rev   line source
fiore@0 1 /*
fiore@0 2 CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool
fiore@3 3
fiore@0 4 Copyright (C) 2002 Cay S. Horstmann (http://horstmann.com)
fiore@0 5 Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)
fiore@0 6
fiore@0 7 This program is free software: you can redistribute it and/or modify
fiore@0 8 it under the terms of the GNU General Public License as published by
fiore@0 9 the Free Software Foundation, either version 3 of the License, or
fiore@0 10 (at your option) any later version.
fiore@0 11
fiore@0 12 This program is distributed in the hope that it will be useful,
fiore@0 13 but WITHOUT ANY WARRANTY; without even the implied warranty of
fiore@0 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
fiore@0 15 GNU General Public License for more details.
fiore@0 16
fiore@0 17 You should have received a copy of the GNU General Public License
fiore@0 18 along with this program. If not, see <http://www.gnu.org/licenses/>.
fiore@3 19 */
fiore@0 20
fiore@0 21 package uk.ac.qmul.eecs.ccmi.gui;
fiore@0 22
fiore@0 23 import java.awt.BorderLayout;
fiore@3 24 import java.io.IOException;
fiore@0 25
fiore@0 26 import javax.swing.JPanel;
fiore@0 27 import javax.swing.JScrollPane;
fiore@0 28 import javax.swing.JSplitPane;
fiore@0 29 import javax.swing.event.ChangeEvent;
fiore@0 30 import javax.swing.event.ChangeListener;
fiore@0 31
fiore@3 32 import uk.ac.qmul.eecs.ccmi.gui.awareness.AwarenessPanel;
fiore@3 33 import uk.ac.qmul.eecs.ccmi.gui.awareness.DisplayFilter;
fiore@3 34 import uk.ac.qmul.eecs.ccmi.network.NetDiagram;
fiore@3 35
fiore@0 36 /**
fiore@0 37 * It's the panel which displays a diagram. It contains a {@link GraphPanel}, a {@link DiagramTree}
fiore@3 38 * a {@link GraphToolbar} and the {@code AwarenessPanel}.
fiore@3 39 * It's backed up by an instance of {@code Diagram}.
fiore@0 40 */
fiore@0 41 @SuppressWarnings("serial")
fiore@0 42 public class DiagramPanel extends JPanel{
fiore@0 43
fiore@3 44 /**
fiore@3 45 * Creates a new instance of {@code DiagramPanel} holding the diagram passed as argument.
fiore@3 46 *
fiore@3 47 * @param diagram the diagram this panel is backed up by
fiore@3 48 * @param tabbedPane the tabbed pane this DiagramPanel will be added to. This reference
fiore@3 49 * is used to updated the tab label when the diagram is modified or save (in the former
fiore@3 50 * case a star is added to the label, in the latter case the star is removed)
fiore@3 51 */
fiore@3 52 public DiagramPanel(Diagram diagram, EditorTabbedPane tabbedPane){
fiore@3 53 this.diagram = diagram;
fiore@3 54 this.tabbedPane = tabbedPane;
fiore@0 55
fiore@3 56 setName(diagram.getLabel());
fiore@3 57 setLayout(new BorderLayout());
fiore@0 58
fiore@3 59 modelChangeListener = new ChangeListener(){
fiore@3 60 @Override
fiore@3 61 public void stateChanged(ChangeEvent e) {
fiore@3 62 setModified(true);
fiore@3 63 }
fiore@3 64 };
fiore@3 65
fiore@3 66 toolbar = new GraphToolbar(diagram);
fiore@3 67 graphPanel = new GraphPanel(diagram, toolbar);
fiore@3 68 /* the focus must be hold by the tree and the tab panel only */
fiore@3 69 toolbar.setFocusable(false);
fiore@3 70 graphPanel.setFocusable(false);
fiore@3 71
fiore@3 72 tree = new DiagramTree(diagram);
fiore@3 73
fiore@3 74 /* the panel containing the graph and the toolbar and the awareness panel */
fiore@3 75 visualPanel = new JPanel(new BorderLayout());
fiore@3 76 visualPanel.add(toolbar, BorderLayout.NORTH);
fiore@3 77 visualPanel.add(new JScrollPane(graphPanel),BorderLayout.CENTER);
fiore@3 78 awarenessSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
fiore@3 79 awarenessSplitPane.setTopComponent(visualPanel);
fiore@3 80
fiore@3 81 /* divides the tree from the visual diagram */
fiore@3 82 JSplitPane treeSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
fiore@3 83 new JScrollPane(tree),
fiore@3 84 awarenessSplitPane);
fiore@3 85 treeSplitPane.setDividerLocation((int)tree.getPreferredSize().width*2);
fiore@3 86 add(treeSplitPane, BorderLayout.CENTER);
fiore@3 87 diagram.getCollectionModel().addChangeListener(modelChangeListener);
fiore@3 88 }
fiore@3 89
fiore@3 90 /**
fiore@3 91 * When a diagram is saved on the file system the its path is associated to the diagram panel
fiore@3 92 * and it's shown when the user hover on the its tab title.
fiore@3 93 *
fiore@3 94 * @return the path of the file where this diagram has been saved last time or {@code null}
fiore@3 95 */
fiore@3 96 public String getFilePath(){
fiore@3 97 return filePath;
fiore@3 98 }
fiore@3 99
fiore@3 100 /**
fiore@3 101 * Sets the file path to a new path. This method should be called after the backing diagram has
fiore@3 102 * been saved to a file.
fiore@3 103 *
fiore@3 104 * @param newValue the path of the file where the backing diagram has been saved last time
fiore@3 105 */
fiore@3 106 public void setFilePath(String newValue){
fiore@3 107 filePath = newValue;
fiore@3 108 }
fiore@3 109
fiore@3 110 /**
fiore@3 111 * Returns a reference to the backing diagram of this diagram panel.
fiore@3 112 *
fiore@3 113 * @return a reference to the backing diagram of this diagram panel
fiore@3 114 */
fiore@3 115 public Diagram getDiagram(){
fiore@3 116 return diagram;
fiore@3 117 }
fiore@3 118
fiore@3 119 /**
fiore@3 120 * Enables or disables the awareness panel of this diagram panel. As default the awareness panel
fiore@3 121 * is disabled but if the diagram is shared (either on a local or on a remote server) the awareness
fiore@3 122 * panel gets enabled. In fact, from now on, awareness messages will be received from the server and,
fiore@3 123 * even if the awareness panel is not visible, some messages (username messages)
fiore@3 124 * will still have to be taken into account.
fiore@3 125 *
fiore@3 126 * @param enabled {@code true} if the panel is to be enabled, {@code false} otherwise.
fiore@3 127 */
fiore@3 128 public void setAwarenessPanelEnabled(boolean enabled){
fiore@3 129 if(!(diagram instanceof NetDiagram))
fiore@3 130 return;
fiore@3 131 /* if the display filter has not been created yet, do create it */
fiore@3 132 DisplayFilter filter = DisplayFilter.getInstance();
fiore@3 133 if(filter == null)
fiore@3 134 try{
fiore@3 135 filter = DisplayFilter.createInstance();
fiore@3 136 }catch(IOException ioe){
fiore@3 137 SpeechOptionPane.showMessageDialog(this, ioe.getLocalizedMessage());
fiore@3 138 return;
fiore@3 139 }
fiore@3 140
fiore@3 141 NetDiagram netDiagram = (NetDiagram)diagram;
fiore@3 142 if(enabled){
fiore@3 143 awarenessPanel = new AwarenessPanel(diagram.getName());
fiore@3 144 awarenessPanelScrollPane = new JScrollPane(awarenessPanel);
fiore@3 145 netDiagram.enableAwareness(awarenessPanel);
fiore@3 146 if(awarenessPanelListener != null)
fiore@3 147 awarenessPanelListener.awarenessPanelEnabled(true);
fiore@3 148 }else{ //disabled
fiore@3 149 netDiagram.disableAwareness(awarenessPanel);
fiore@3 150 if(awarenessSplitPane.getRightComponent() != null){
fiore@3 151 // hide the panel
fiore@3 152 awarenessSplitPane.remove(awarenessPanelScrollPane);
fiore@3 153 }
fiore@3 154 awarenessPanelScrollPane = null;
fiore@3 155 awarenessPanel = null;
fiore@3 156 awarenessSplitPane.validate();
fiore@3 157 if(awarenessPanelListener != null)
fiore@3 158 awarenessPanelListener.awarenessPanelEnabled(false);
fiore@3 159 }
fiore@3 160 }
fiore@3 161
fiore@3 162 /**
fiore@3 163 * Makes the awareness panel visible or invisible, assuming that it has been enabled beforehand. If the
fiore@3 164 * awareness panel hasn't been enables this call has no effect.
fiore@3 165 *
fiore@3 166 * @param visible {@code true} if the panel is to be made visible, {@code false} otherwise.
fiore@3 167 */
fiore@3 168 public void setAwarenessPanelVisible(boolean visible){
fiore@3 169 if(awarenessPanelScrollPane == null)
fiore@3 170 return;
fiore@3 171 if(visible){
fiore@3 172 awarenessSplitPane.setRightComponent(awarenessPanelScrollPane);
fiore@3 173 awarenessSplitPane.setDividerLocation(0.8);
fiore@3 174 awarenessSplitPane.setResizeWeight(1.0);
fiore@3 175 awarenessSplitPane.validate();
fiore@3 176 if(awarenessPanelListener != null)
fiore@3 177 awarenessPanelListener.awarenessPanelVisible(true);
fiore@3 178 }else{
fiore@3 179 awarenessSplitPane.remove(awarenessPanelScrollPane);
fiore@3 180 awarenessSplitPane.validate();
fiore@3 181 if(awarenessPanelListener != null)
fiore@3 182 awarenessPanelListener.awarenessPanelVisible(false);
fiore@3 183 }
fiore@3 184 }
fiore@3 185
fiore@3 186 /**
fiore@3 187 * Queries the diagram panel on whether the awareness panel is currently visible.
fiore@3 188 *
fiore@3 189 * @return {@code true} if the awareness panel is currently visible, {@code false} otherwise.
fiore@3 190 */
fiore@3 191 public boolean isAwarenessPanelVisible(){
fiore@3 192 return (awarenessSplitPane.getRightComponent() != null);
fiore@3 193 }
fiore@3 194
fiore@3 195 /**
fiore@3 196 * Returns a reference to the inner awareness panel.
fiore@3 197 *
fiore@3 198 * @return the inner awareness panel if it has been enabled of {@code null} otherwise
fiore@3 199 */
fiore@3 200 public AwarenessPanel getAwarenessPanel(){
fiore@3 201 return awarenessPanel;
fiore@3 202 }
fiore@3 203
fiore@3 204 /**
fiore@5 205 * Sets the backing up delegate diagram for this panel. This method is used when a diagram is shared
fiore@3 206 * (or reverted). A shared diagram has a different way of updating the
fiore@3 207 * The modified status is changed according to
fiore@3 208 * the modified status of the {@code DiagramModel} internal to the new {@code Diagram}
fiore@3 209 *
fiore@5 210 * @param diagram the backing up delegate diagram
fiore@3 211 */
fiore@3 212 public void setDiagram(Diagram diagram){
fiore@3 213 /* remove the listener from the old model */
fiore@3 214 this.diagram.getCollectionModel().removeChangeListener(modelChangeListener);
fiore@3 215 diagram.getCollectionModel().addChangeListener(modelChangeListener);
fiore@3 216
fiore@3 217 this.diagram = diagram;
fiore@3 218 tree.setDiagram(diagram);
fiore@3 219 graphPanel.setModelUpdater(diagram.getModelUpdater());
fiore@3 220 setName(diagram.getLabel());
fiore@3 221 /* set the * according to the new diagram's model modification status */
fiore@3 222 setModified(isModified());
fiore@3 223 }
fiore@3 224
fiore@3 225 /**
fiore@3 226 * Returns a reference to the graph panel in this diagram panel. The tree's model is the
fiore@3 227 * model returned by a calling {@code getTreeModel()} on the backing diagram.
fiore@3 228 *
fiore@3 229 * @return the graph panel contained by this diagram panel
fiore@3 230 */
fiore@3 231 public GraphPanel getGraphPanel(){
fiore@3 232 return graphPanel;
fiore@3 233 }
fiore@3 234
fiore@3 235 /**
fiore@3 236 * Returns a reference to the tree in this diagram panel. The graph model is the
fiore@3 237 * model returned by a calling {@code getCollectionModel()} on the backing diagram.
fiore@3 238 *
fiore@3 239 * @return the tree contained by this diagram panel
fiore@3 240 */
fiore@3 241 public DiagramTree getTree(){
fiore@3 242 return tree;
fiore@3 243 }
fiore@3 244
fiore@3 245 /**
fiore@3 246 * Changes the {@code modified} status of the backing diagram of this panel. If set to {@code true}
fiore@3 247 * then a star will appear after the name of the diagram, returned by {@code getName()}.
fiore@3 248 *
fiore@3 249 * When called passing false as argument (which should be done after the diagram is saved on a file)
fiore@3 250 * listeners are notified that the diagram has been saved.
fiore@3 251 *
fiore@3 252 * @param modified {@code true} when the diagram has been modified, {@code false} when it has been saved
fiore@3 253 */
fiore@3 254 public void setModified(boolean modified){
fiore@3 255 if(!modified)
fiore@3 256 diagram.getCollectionModel().setUnmodified();
fiore@3 257 /* add an asterisk to notify that the diagram has changed */
fiore@3 258 if(modified)
fiore@3 259 setName(getName()+"*");
fiore@3 260 else
fiore@3 261 setName(diagram.getLabel());
fiore@3 262 tabbedPane.refreshComponentTabTitle(this);
fiore@3 263 }
fiore@3 264
fiore@3 265 /**
fiore@3 266 * Whether the backing diagram has been modified. The diagram is modified as a result of changes
fiore@3 267 * to the {@code TreeModel} or {@code CollectionModel} it contains. To change the {@code modified}
fiore@3 268 * status of the diagram (and of its models) {@code setModified()} must be used.
fiore@3 269 *
fiore@5 270 * @return {@code true} if the diagram is modified, {@code false} otherwise
fiore@3 271 */
fiore@3 272 public boolean isModified(){
fiore@3 273 return diagram.getCollectionModel().isModified();
fiore@3 274 }
fiore@3 275
fiore@3 276 void setAwarenessPanelListener(AwarenessPanelEnablingListener listener){
fiore@3 277 awarenessPanelListener = listener;
fiore@3 278 }
fiore@3 279
fiore@3 280 private Diagram diagram;
fiore@3 281 private GraphPanel graphPanel;
fiore@3 282 private JSplitPane awarenessSplitPane;
fiore@3 283 private DiagramTree tree;
fiore@3 284 private JPanel visualPanel;
fiore@3 285 private GraphToolbar toolbar;
fiore@3 286 private AwarenessPanel awarenessPanel;
fiore@3 287 private JScrollPane awarenessPanelScrollPane;
fiore@3 288 private String filePath;
fiore@3 289 private ChangeListener modelChangeListener;
fiore@3 290 private EditorTabbedPane tabbedPane;
fiore@3 291 private AwarenessPanelEnablingListener awarenessPanelListener;
fiore@0 292 }
fiore@3 293
fiore@3 294 interface AwarenessPanelEnablingListener {
fiore@3 295 public void awarenessPanelEnabled(boolean enabled);
fiore@3 296 public void awarenessPanelVisible(boolean visible);
fiore@3 297 }
fiore@3 298