Checkstyle, comment
[scilab.git] / scilab / modules / xcos / src / java / org / scilab / modules / graph / ScilabGraph.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2009 - DIGITEO - Bruno JOFRET
4  * Copyright (C) 2010 - DIGITEO - ClĂ©ment DAVID
5  *
6  * This file must be used under the terms of the CeCILL.
7  * This source file is licensed as described in the file COPYING, which
8  * you should have received as part of this distribution.  The terms
9  * are also available at
10  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
11  *
12  */
13
14 package org.scilab.modules.graph;
15
16 import java.awt.Color;
17 import java.util.List;
18
19 import org.scilab.modules.graph.utils.ScilabGraphMessages;
20 import org.scilab.modules.gui.tab.Tab;
21 import org.scilab.modules.gui.utils.UIElementMapper;
22 import org.scilab.modules.gui.window.ScilabWindow;
23 import org.scilab.modules.xcos.utils.XcosComponent;
24 import org.scilab.modules.xcos.utils.XcosConstants;
25
26 import com.mxgraph.swing.mxGraphComponent;
27 import com.mxgraph.swing.handler.mxRubberband;
28 import com.mxgraph.swing.util.mxGraphActions;
29 import com.mxgraph.util.mxEvent;
30 import com.mxgraph.util.mxEventObject;
31 import com.mxgraph.util.mxUndoManager;
32 import com.mxgraph.util.mxUndoableEdit;
33 import com.mxgraph.util.mxUndoableEdit.mxUndoableChange;
34 import com.mxgraph.view.mxGraph;
35
36 /**
37  * Represent the base diagram of Xcos.
38  * 
39  * It performs generic operations like undo/redo management, action clean-up,
40  * modification state management, Tab association, etc...
41  */
42 public class ScilabGraph extends mxGraph {
43
44         private static final int DEFAULTCOLOR = 240;
45
46         private final mxUndoManager undoManager = new mxUndoManager();
47         private final XcosComponent component;
48
49         private String title = ScilabGraphMessages.UNTITLED;
50         private String savedFile;
51         private boolean modified;
52         private Tab parentTab;
53         private boolean opened;
54         private boolean redoInAction;
55         private int undoCounter;
56         private boolean readOnly;
57         private Color originalColor;
58
59         private transient mxRubberband rubberBand;
60
61         /**
62          * Manage the modification state on change
63          */
64         private mxIEventListener changeTracker = new mxIEventListener() {
65                 public void invoke(Object source, mxEventObject evt) {
66                         setModified(true);
67                 }
68         };
69
70         /**
71          * Manage the undo/redo on change
72          */
73         private mxIEventListener undoHandler = new mxIEventListener() {
74                 public void invoke(Object source, mxEventObject evt) {
75
76                         if (!redoInAction) {
77                                 undoManager.undoableEditHappened((mxUndoableEdit) evt
78                                                 .getProperty(XcosConstants.EVENT_CHANGE_EDIT));
79                                 incrementUndoCounter();
80                         }
81                 }
82         };
83
84         /**
85          * Manage the selection on change
86          */
87         private mxIEventListener selectionHandler = new mxIEventListener() {
88                 public void invoke(Object source, mxEventObject evt) {
89                         List<mxUndoableChange> changes = ((mxUndoableEdit) evt.getProperty(XcosConstants.EVENT_CHANGE_EDIT)).getChanges();
90                         setSelectionCells(getSelectionCellsForChanges(changes));
91                 }
92         };
93
94         /**
95          * Default constructor: - disable unused actions - install listeners -
96          * Replace JGraphX components by specialized components if needed.
97          */
98         public ScilabGraph() {
99                 super();
100
101                 // Disabling the default connected action and event listeners.
102                 mxGraphActions.getSelectNextAction().setEnabled(false);
103                 mxGraphActions.getSelectPreviousAction().setEnabled(false);
104                 mxGraphActions.getSelectChildAction().setEnabled(false);
105                 mxGraphActions.getSelectParentAction().setEnabled(false);
106
107                 // Undo / Redo capabilities
108                 getModel().addListener(mxEvent.UNDO, undoHandler);
109                 getView().addListener(mxEvent.UNDO, undoHandler);
110
111                 // Keeps the selection in sync with the command history
112                 undoManager.addListener(mxEvent.UNDO, selectionHandler);
113                 undoManager.addListener(mxEvent.REDO, selectionHandler);
114
115                 component = new XcosComponent(this);
116
117                 // Adds rubberband selection
118                 rubberBand = new mxRubberband(component);
119
120                 // Modified property change
121                 getModel().addListener(mxEvent.CHANGE, changeTracker);
122         }
123
124         /**
125          * @return The previously saved file or null.
126          */
127         public String getSavedFile() {
128                 return savedFile;
129         }
130
131         /**
132          * @param savedFile
133          *            The new saved file
134          */
135         public void setSavedFile(String savedFile) {
136                 this.savedFile = savedFile;
137         }
138
139         /**
140          * @return true, if the graph has been modified ; false otherwise.
141          */
142         public boolean isModified() {
143                 return modified;
144         }
145
146         /**
147          * Modify the state of the diagram.
148          * 
149          * @param modified
150          *            The new modified state.
151          * @category UseEvent
152          */
153         public void setModified(boolean modified) {
154                 boolean oldValue = this.modified;
155                 this.modified = modified;
156
157                 getAsComponent().firePropertyChange("modified", oldValue, modified);
158         }
159
160         /**
161          * @param title
162          *            The new title of the tab
163          */
164         public void setTitle(String title) {
165                 this.title = title;
166         }
167
168         /**
169          * @return The current Tab title
170          */
171         public String getTitle() {
172                 return title;
173         }
174
175         /**
176          * @return The component associated with the current graph.
177          */
178         public mxGraphComponent getAsComponent() {
179                 return component;
180         }
181
182         /**
183          * Undo the last action
184          * 
185          * @see com.mxgraph.util.mxUndoManager
186          */
187         public void undo() {
188                 decrementUndoCounter();
189                 redoInAction = true;
190                 undoManager.undo();
191                 redoInAction = false;
192         }
193
194         /**
195          * Redo the last action com.mxgraph.util.mxUndoManager
196          */
197         public void redo() {
198             if (!redoInAction) {
199
200                 incrementUndoCounter();
201                 redoInAction = true;
202                 undoManager.redo();
203                 redoInAction = false;
204             }
205         }
206
207         /**
208          * Used internally to manage the modified state on undo/redo
209          */
210         private void incrementUndoCounter() {
211                 if (undoCounter < Integer.MAX_VALUE) {
212                         undoCounter++;
213                 }
214         }
215
216         /**
217          * Used internally to manage the modified state on undo/redo
218          */
219         private void decrementUndoCounter() {
220                 if (undoCounter > Integer.MIN_VALUE) {
221                         undoCounter--;
222                 }
223         }
224
225         /**
226          * Used internally to manage the modified state on undo/redo
227          * 
228          * @return true if the document is in a previous saved state, false
229          *         otherwise
230          */
231         protected boolean isZeroUndoCounter() {
232                 return (undoCounter == 0);
233         }
234
235         /**
236          * Used internally to manage the modified state on undo/redo
237          */
238         protected void resetUndoCounter() {
239                 undoCounter = 0;
240         }
241
242         /**
243          * @return The associated Tab
244          */
245         public Tab getParentTab() {
246                 return parentTab;
247         }
248
249         /**
250          * @param parentTab
251          *            The new associated Tab
252          */
253         public void setParentTab(Tab parentTab) {
254                 this.parentTab = parentTab;
255         }
256
257         /**
258          * The instance can be not visible but used (when using SuperBlock). The
259          * openned flag is true in this case and also when the Window/Tab is
260          * visible.
261          * 
262          * @param opened
263          *            Openned state
264          */
265         public void setOpened(boolean opened) {
266                 this.opened = opened;
267         }
268
269         /**
270          * @return Openned state
271          */
272         public boolean isOpened() {
273                 return opened;
274         }
275
276         /**
277          * Set the associated Window/Tab visible or not.
278          * 
279          * @param visible
280          *            State of visibility
281          */
282         public void setVisible(boolean visible) {
283                 if (parentTab != null) {
284                         ScilabWindow xcosWindow = (ScilabWindow) UIElementMapper
285                                         .getCorrespondingUIElement(parentTab.getParentWindowId());
286                         xcosWindow.setVisible(visible);
287                 }
288         }
289
290         /**
291          * Check if the associated Window/Tab is visible
292          * 
293          * @return State of visibility
294          */
295         public boolean isVisible() {
296                 if (parentTab != null) {
297                         ScilabWindow xcosWindow = (ScilabWindow) UIElementMapper
298                                         .getCorrespondingUIElement(parentTab.getParentWindowId());
299                         return xcosWindow.isVisible();
300                 }
301
302                 return false;
303         }
304
305         /**
306          * A read-only state will disable all actions in the graph.
307          * 
308          * @param readOnly
309          *            Read-only state
310          */
311         public void setReadOnly(boolean readOnly) {
312                 this.readOnly = readOnly;
313
314                 setCellsLocked(readOnly);
315                 if (isReadonly()) {
316                         setOriginalColor(getAsComponent().getBackground());
317                         getAsComponent().setBackground(
318                                         new Color(DEFAULTCOLOR, DEFAULTCOLOR, DEFAULTCOLOR));
319                 } else {
320                         getAsComponent().setBackground(getOriginalColor());
321                 }
322         }
323
324         /**
325          * @return True if actions are not allowed, false otherwise.
326          */
327         public boolean isReadonly() {
328                 return readOnly;
329         }
330
331         /**
332          * Useful function for the read-only property
333          * 
334          * @param originalColor
335          *            The default color to apply
336          */
337         private void setOriginalColor(Color originalColor) {
338                 this.originalColor = originalColor;
339         }
340
341         /**
342          * Useful function for the read-only property
343          * 
344          * @return The default color
345          */
346         private Color getOriginalColor() {
347                 if (originalColor != null) {
348                         return originalColor;
349                 }
350                 return Color.WHITE;
351         }
352
353         /**
354          * @return The associated RubberBand
355          * @see com.mxgraph.swing.handler.mxRubberband
356          */
357         public mxRubberband getRubberBand() {
358                 return rubberBand;
359         }
360
361         /**
362          * @return The undo manager associated with this graph
363          */
364         protected final mxUndoManager getUndoManager() {
365                 return undoManager;
366         }
367 }