Add full options management to figure
[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) {
189
190         try {
191             Integer id = createUID();
192             GraphicModel.getModel().createObject(id, type);
193             objectCreated(id);
194
195             return id;
196         } catch (Exception e) {
197             DEBUG("====== Exception caught ======");
198             DEBUG(" askObject type = " + type.name());
199             e.printStackTrace();
200             DEBUG("====== Exception caught ======");
201             return 0;
202         }
203
204     }
205
206     public Integer cloneObject(Integer id, boolean broadcastMessage) {
207         try {
208             Integer newId = createUID();
209             GraphicModel.getModel().cloneObject(id, newId);
210             if (broadcastMessage) {
211                 objectCreated(newId);
212             }
213
214             return newId;
215         } catch (Exception e) {
216             DEBUG("====== Exception caught ======");
217             DEBUG("cloneObject id = " + id);
218             e.printStackTrace();
219             DEBUG("====== Exception caught ======");
220             return 0;
221         }
222     }
223     
224     /**
225      * Ask the model to clone an object
226      * @param id : the ID of the object to clone.
227      * @return the id of the clone.
228      */
229     public Integer cloneObject(Integer id) {
230         return cloneObject(id, true);
231     }
232
233     /**
234      * Deletes an object
235      * @param id the deleted object's id
236      */
237     public void deleteObject(Integer id) {
238         try {
239             objectDeleted(id);
240             GraphicModel.getModel().deleteObject(id);
241         } catch (Exception e) {
242             DEBUG("====== Exception caught ======");
243             DEBUG("deleteObject id = " + id);
244             e.printStackTrace();
245             DEBUG("====== Exception caught ======");
246         }
247     }
248
249     /**
250      * Notifies the existing views that an object has been created
251      * @param id the created object's id
252      */
253     public void objectCreated(final Integer id) {
254         //INFO("### Create object : "+id);
255         //INFO("### type is : " + getProperty(id, GraphicObjectProperties.__GO_TYPE__));
256         Vector<Runnable> broadCastVector = new Vector<Runnable>();
257
258         try {
259             for (final GraphicView view : allViews) {
260                 broadCastVector.add(new Runnable() {
261                     public void run() {
262                         view.createObject(id);
263                     }
264                 });
265             }
266             for (final Runnable runMe : broadCastVector) {
267                 runMe.run();
268             }
269         } catch (ConcurrentModificationException e) {
270             e.printStackTrace();
271         }
272     }
273
274     /**
275      * Notified the existing views that an object has been updated
276      * @param id the updated object's id
277      * @param prop the property that has been updated
278      */
279     public void objectUpdate(final Integer id, final int prop) {
280         //INFO("### Update object : "+id);
281         //INFO("### type is : " + getProperty(id, GraphicObjectProperties.__GO_TYPE__));
282         //INFO("### prop is : " + prop);
283
284         Vector<Runnable> broadCastVector = new Vector<Runnable>();
285         try {
286             for (final GraphicView view : allViews) {
287                 broadCastVector.add(new Runnable() {
288                     public void run() {
289                         view.updateObject(id, prop);
290                     }
291                 });
292             }
293             for (final Runnable runMe : broadCastVector) {
294                 runMe.run();
295             }
296         } catch (ConcurrentModificationException e) {
297             e.printStackTrace();
298         }
299     }
300
301     /**
302      * Notified the existing views that an object has been deleted
303      * @param id the deleted object's id
304      */
305     public void objectDeleted(final Integer id) {
306         //INFO("### Delete object : "+id);
307         //INFO("### type is : " + getProperty(id, GraphicObjectProperties.__GO_TYPE__));
308         Vector<Runnable> broadCastVector = new Vector<Runnable>();
309
310         try {
311             for (final GraphicView view : allViews) {
312                 broadCastVector.add(new Runnable() {
313                     public void run() {
314                         view.deleteObject(id);
315                     }
316                 });
317             }
318             for (final Runnable runMe : broadCastVector) {
319                 runMe.run();
320             }
321         } catch (ConcurrentModificationException e) {
322             e.printStackTrace();
323         }
324     }
325
326     /**
327      * Set relationship between two object and remove old relationship.
328      * @param parentId id of the parent object.
329      * @param childId id of the child object.
330      */
331     public void setGraphicObjectRelationship(Integer parentId, Integer childId) {
332         /*
333          * All the parent and children get/set calls must be performed first,
334          * and only then the corresponding object updates.
335          */
336         Object oldParent = getProperty(childId, GraphicObjectProperties.__GO_PARENT__);
337
338         if (oldParent != null && oldParent instanceof Integer) {
339             Integer oldParentId = (Integer) oldParent;
340
341             if (oldParentId == parentId) {
342                 return;
343             }
344
345             if (oldParentId != 0) {
346                 getObjectFromId(oldParentId).removeChild(childId);
347             }
348         }
349
350         /* Insertion occurs at the head of the children list. */
351         if (parentId != null && parentId != 0) {
352             GraphicObject go = getObjectFromId(parentId);
353             if (go != null) {
354                 go.addChild(childId);
355             }
356         }
357
358         setProperty(childId, GraphicObjectProperties.__GO_PARENT__, parentId);
359
360         /* Object updates can now be performed. */
361         if (oldParent != null && oldParent instanceof Integer && ((Integer)oldParent) != 0) {
362             objectUpdate((Integer)oldParent, GraphicObjectProperties.__GO_CHILDREN__);
363         }
364
365         if (parentId != null && parentId != 0) {
366             objectUpdate(parentId, GraphicObjectProperties.__GO_CHILDREN__);
367         }
368
369         // Useless (already done in setProperty(childId, GraphicObjectProperties.__GO_PARENT__, parentId);)
370         //objectUpdate(childId, GraphicObjectProperties.__GO_PARENT__);
371     }
372
373     /**
374      * Remove relationship between given object and is parent.
375      * Then delete it.
376      * TODO : Manage children of deleted object.
377      * @param id deleted object identifier.
378      */
379     public void removeRelationShipAndDelete(Integer id) {
380         final GraphicObject killMe = getObjectFromId(id);
381         // assert that the object has not been deleted yet
382         if (killMe == null) {
383             return;
384         }
385
386         Integer parentUID = killMe.getParent();
387
388
389         /* Remove object from Parent's Children list */
390         if (parentUID != null && parentUID != 0) {
391             getObjectFromId(parentUID).removeChild(id);
392             //setProperty(id, GraphicObjectProperties.__GO_PARENT__, "");
393
394             objectUpdate(parentUID, GraphicObjectProperties.__GO_CHILDREN__);
395             objectUpdate(parentUID, GraphicObjectProperties.__GO_DATATIPS__);
396             //objectUpdate(id, GraphicObjectProperties.__GO_PARENT__);
397         }
398
399         killMe.setValid(false);
400         recursiveDeleteChildren(killMe);
401
402         deleteObject(id);
403     }
404
405     private void recursiveDeleteChildren(GraphicObject killMe) {
406         Integer children[] = killMe.getChildren();
407
408         for (int i = 0 ; i < children.length ; ++i) {
409             GraphicObject killMeThisChild = getObjectFromId(children[i]);
410             killMeThisChild.setValid(false);
411             recursiveDeleteChildren(killMeThisChild);
412             deleteObject(children[i]);
413         }
414     }
415 }