Mercurial > hg > ccmieditor
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 |