d318defa835d65b0da4c7f4d87443191a0ba403a
[scilab.git] / scilab / modules / graphic_objects / src / java / org / scilab / modules / graphic_objects / graphicController / GraphicController.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2010 - DIGITEO - Bruno JOFRET
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
10  *
11  */
12
13 package org.scilab.modules.graphic_objects.graphicController;
14
15 import java.awt.GraphicsEnvironment;
16 import java.util.Collections;
17 import java.util.ConcurrentModificationException;
18 import java.util.HashSet;
19 import java.util.Set;
20 import java.util.Vector;
21
22 import org.scilab.modules.graphic_objects.graphicModel.GraphicModel;
23 import org.scilab.modules.graphic_objects.graphicObject.GraphicObject;
24 import org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties;
25 import org.scilab.modules.graphic_objects.graphicObject.GraphicObject.Type;
26 import org.scilab.modules.graphic_objects.graphicView.FlattenTreeView;
27 import org.scilab.modules.graphic_objects.graphicView.GedTreeView;
28 import org.scilab.modules.graphic_objects.graphicView.GraphicView;
29 import org.scilab.modules.graphic_objects.graphicView.GuiLogView;
30 import org.scilab.modules.graphic_objects.graphicView.LogView;
31
32 /**
33  * GraphicController class
34  * @author Bruno JOFRET
35  */
36 public class GraphicController {
37
38     private static boolean MVCViewEnable = false;
39     private static boolean debugEnable = false;
40     private static boolean infoEnable = false;
41     private static Integer lastId = 0;
42
43     private static void INFO(String message) {
44         if (infoEnable == true) {
45             System.err.println("[CONTROLLER - INFO] : " + message);
46         }
47     }
48
49     private static void DEBUG(String message) {
50         if (debugEnable == true) {
51             System.err.println("[CONTROLLER - DEBUG] : " + message);
52         }
53     }
54
55     /**
56      * Set of all views attached to this controller.
57      */
58     private volatile static Set<GraphicView> allViews =  Collections.synchronizedSet(new HashSet<GraphicView>());
59
60     /**
61      * Graphic controller singleton.
62      */
63     private static GraphicController me = null;
64
65     /**
66      * Default constructor
67      */
68     private GraphicController() {
69         if (!GraphicsEnvironment.isHeadless() && MVCViewEnable) {
70             register(GuiLogView.createGuiLogView());
71             register(GedTreeView.create());
72             register(FlattenTreeView.create());
73         }
74         if (infoEnable) {
75             register(LogView.createLogView());
76         }
77     }
78
79     /**
80      * Returns the controller
81      * @return the controller
82      */
83     public static GraphicController getController() {
84         if (me == null) {
85             me = new GraphicController();
86         }
87
88         return me;
89     }
90
91     /**
92      * Register a view that will receive notification
93      * of any model changes.
94      * @param view The view to register.
95      */
96     public void register(GraphicView view) {
97         INFO("Register view : " + view.toString());
98         allViews.add(view);
99     }
100
101     /**
102      * Unregister a view.
103      * @param view The view to unregister.
104      */
105     public void unregister(GraphicView view) {
106         INFO("Unregister view : " + view.toString());
107         allViews.remove(view);
108     }
109
110     /**
111      * Creates a UID
112      * @return the created UID
113      */
114     public Integer createUID() {
115         return ++lastId;
116     }
117
118     /**
119      * Returns the object associated to an id
120      * @param id the object id
121      * @return the object
122      */
123     public GraphicObject getObjectFromId(Integer id) {
124         return GraphicModel.getModel().getObjectFromId(id);
125     }
126
127     /**
128      * Fast property set method
129      * @param id the object id
130      * @param prop the property name
131      * @param value the property value
132      * @return true if the property has been set, false otherwise
133      */
134     public boolean setProperty(Integer id, int prop, Object value) {
135         try {
136             switch (GraphicModel.getModel().setProperty(id, prop, value)) {
137                 case Success : // BroadCast Message + return true
138                     objectUpdate(id, prop);
139                     return true;
140                 case NoChange : // Do not broadcast message
141                     return true;
142                 case Fail :
143                     return false;
144             }
145             return false;
146         } catch (Exception e) {
147             DEBUG("====== Exception caught ======");
148             DEBUG("setProperty : " + id + " " + prop);
149             e.printStackTrace();
150             DEBUG("====== Exception caught ======");
151             return false;
152         }
153     }
154
155     /**
156      * Fast property get method
157      * @param id the object id
158      * @param prop the property name
159      * @return the property value
160      */
161     public Object getProperty(Integer id, int prop) {
162         try {
163             return GraphicModel.getModel().getProperty(id, prop);
164         } catch (Exception e) {
165             DEBUG("====== Exception caught ======");
166             DEBUG("getProperty : [" + id + "] " + prop);
167             e.printStackTrace();
168             DEBUG("====== Exception caught ======");
169             return null;
170         }
171     }
172
173     /**
174      * Returns a null property
175      * @param id the object id
176      * @param prop the property name
177      * @return the null property
178      */
179     public Object getNullProperty(Integer id, String prop) {
180         return GraphicModel.getModel().getNullProperty(id, prop);
181     }
182
183     /**
184      * Asks the model to create a new object
185      * @param type the object type
186      * @return the created object's id
187      */
188     public Integer askObject(Type type, boolean broadcastMessage) {
189
190         try {
191             Integer id = createUID();
192             GraphicModel.getModel().createObject(id, type);
193             if (broadcastMessage) {
194                 objectCreated(id);
195             }
196
197             return id;
198         } catch (Exception e) {
199             DEBUG("====== Exception caught ======");
200             DEBUG(" askObject type = " + type.name());
201             e.printStackTrace();
202             DEBUG("====== Exception caught ======");
203             return 0;
204         }
205
206     }
207
208     public Integer cloneObject(Integer id, boolean broadcastMessage) {
209         try {
210             Integer newId = createUID();
211             GraphicModel.getModel().cloneObject(id, newId);
212             if (broadcastMessage) {
213                 objectCreated(newId);
214             }
215
216             return newId;
217         } catch (Exception e) {
218             DEBUG("====== Exception caught ======");
219             DEBUG("cloneObject id = " + id);
220             e.printStackTrace();
221             DEBUG("====== Exception caught ======");
222             return 0;
223         }
224     }
225     
226     /**
227      * Ask the model to clone an object
228      * @param id : the ID of the object to clone.
229      * @return the id of the clone.
230      */
231     public Integer cloneObject(Integer id) {
232         return cloneObject(id, true);
233     }
234
235     public Integer askObject(Type type) {
236         return askObject(type, true);
237     }
238     
239     /**
240      * Deletes an object
241      * @param id the deleted object's id
242      */
243     public void deleteObject(Integer id) {
244         try {
245             objectDeleted(id);
246             GraphicModel.getModel().deleteObject(id);
247         } catch (Exception e) {
248             DEBUG("====== Exception caught ======");
249             DEBUG("deleteObject id = " + id);
250             e.printStackTrace();
251             DEBUG("====== Exception caught ======");
252         }
253     }
254
255     /**
256      * Notifies the existing views that an object has been created
257      * @param id the created object's id
258      */
259     public void objectCreated(final Integer id) {
260         //INFO("### Create object : "+id);
261         //INFO("### type is : " + getProperty(id, GraphicObjectProperties.__GO_TYPE__));
262         Vector<Runnable> broadCastVector = new Vector<Runnable>();
263
264         try {
265             for (final GraphicView view : allViews) {
266                 broadCastVector.add(new Runnable() {
267                     public void run() {
268                         view.createObject(id);
269                     }
270                 });
271             }
272             for (final Runnable runMe : broadCastVector) {
273                 runMe.run();
274             }
275         } catch (ConcurrentModificationException e) {
276             e.printStackTrace();
277         }
278     }
279
280     /**
281      * Notified the existing views that an object has been updated
282      * @param id the updated object's id
283      * @param prop the property that has been updated
284      */
285     public void objectUpdate(final Integer id, final int prop) {
286         //INFO("### Update object : "+id);
287         //INFO("### type is : " + getProperty(id, GraphicObjectProperties.__GO_TYPE__));
288         //INFO("### prop is : " + prop);
289
290         Vector<Runnable> broadCastVector = new Vector<Runnable>();
291         try {
292             for (final GraphicView view : allViews) {
293                 broadCastVector.add(new Runnable() {
294                     public void run() {
295                         view.updateObject(id, prop);
296                     }
297                 });
298             }
299             for (final Runnable runMe : broadCastVector) {
300                 runMe.run();
301             }
302         } catch (ConcurrentModificationException e) {
303             e.printStackTrace();
304         }
305     }
306
307     /**
308      * Notified the existing views that an object has been deleted
309      * @param id the deleted object's id
310      */
311     public void objectDeleted(final Integer id) {
312         //INFO("### Delete object : "+id);
313         //INFO("### type is : " + getProperty(id, GraphicObjectProperties.__GO_TYPE__));
314         Vector<Runnable> broadCastVector = new Vector<Runnable>();
315
316         try {
317             for (final GraphicView view : allViews) {
318                 broadCastVector.add(new Runnable() {
319                     public void run() {
320                         view.deleteObject(id);
321                     }
322                 });
323             }
324             for (final Runnable runMe : broadCastVector) {
325                 runMe.run();
326             }
327         } catch (ConcurrentModificationException e) {
328             e.printStackTrace();
329         }
330     }
331
332     /**
333      * Set relationship between two object and remove old relationship.
334      * @param parentId id of the parent object.
335      * @param childId id of the child object.
336      */
337     public void setGraphicObjectRelationship(Integer parentId, Integer childId) {
338         /*
339          * All the parent and children get/set calls must be performed first,
340          * and only then the corresponding object updates.
341          */
342         Object oldParent = getProperty(childId, GraphicObjectProperties.__GO_PARENT__);
343
344         if (oldParent != null && oldParent instanceof Integer) {
345             Integer oldParentId = (Integer) oldParent;
346
347             if (oldParentId == parentId) {
348                 return;
349             }
350
351             if (oldParentId != 0) {
352                 getObjectFromId(oldParentId).removeChild(childId);
353             }
354         }
355
356         /* Insertion occurs at the head of the children list. */
357         if (parentId != null && parentId != 0) {
358             GraphicObject go = getObjectFromId(parentId);
359             if (go != null) {
360                 go.addChild(childId);
361             }
362         }
363
364         setProperty(childId, GraphicObjectProperties.__GO_PARENT__, parentId);
365
366         /* Object updates can now be performed. */
367         if (oldParent != null && oldParent instanceof Integer && ((Integer)oldParent) != 0) {
368             objectUpdate((Integer)oldParent, GraphicObjectProperties.__GO_CHILDREN__);
369         }
370
371         if (parentId != null && parentId != 0) {
372             objectUpdate(parentId, GraphicObjectProperties.__GO_CHILDREN__);
373         }
374
375         // Useless (already done in setProperty(childId, GraphicObjectProperties.__GO_PARENT__, parentId);)
376         //objectUpdate(childId, GraphicObjectProperties.__GO_PARENT__);
377     }
378
379     /**
380      * Remove relationship between given object and is parent.
381      * Then delete it.
382      * TODO : Manage children of deleted object.
383      * @param id deleted object identifier.
384      */
385     public void removeRelationShipAndDelete(Integer id) {
386         final GraphicObject killMe = getObjectFromId(id);
387         // assert that the object has not been deleted yet
388         if (killMe == null) {
389             return;
390         }
391
392         Integer parentUID = killMe.getParent();
393
394
395         /* Remove object from Parent's Children list */
396         if (parentUID != null && parentUID != 0) {
397             getObjectFromId(parentUID).removeChild(id);
398             //setProperty(id, GraphicObjectProperties.__GO_PARENT__, "");
399
400             objectUpdate(parentUID, GraphicObjectProperties.__GO_CHILDREN__);
401             objectUpdate(parentUID, GraphicObjectProperties.__GO_DATATIPS__);
402             //objectUpdate(id, GraphicObjectProperties.__GO_PARENT__);
403         }
404
405         killMe.setValid(false);
406         recursiveDeleteChildren(killMe);
407
408         deleteObject(id);
409     }
410
411     private void recursiveDeleteChildren(GraphicObject killMe) {
412         Integer children[] = killMe.getChildren();
413
414         for (int i = 0 ; i < children.length ; ++i) {
415             GraphicObject killMeThisChild = getObjectFromId(children[i]);
416             killMeThisChild.setValid(false);
417             recursiveDeleteChildren(killMeThisChild);
418             deleteObject(children[i]);
419         }
420     }
421 }