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