* Bug #12352 fixed - Critical error when closing a scope windows during
[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-en.txt
10  *
11  */
12
13 package org.scilab.modules.graphic_objects.graphicController;
14
15 import java.awt.GraphicsEnvironment;
16 import java.rmi.server.UID;
17 import java.util.Collections;
18 import java.util.ConcurrentModificationException;
19 import java.util.HashSet;
20 import java.util.Set;
21 import java.util.Vector;
22
23 import org.scilab.modules.graphic_objects.graphicModel.GraphicModel;
24 import org.scilab.modules.graphic_objects.graphicObject.GraphicObject;
25 import org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties;
26 import org.scilab.modules.graphic_objects.graphicObject.GraphicObject.Type;
27 import org.scilab.modules.graphic_objects.graphicView.FlattenTreeView;
28 import org.scilab.modules.graphic_objects.graphicView.GedTreeView;
29 import org.scilab.modules.graphic_objects.graphicView.GraphicView;
30 import org.scilab.modules.graphic_objects.graphicView.GuiLogView;
31 import org.scilab.modules.graphic_objects.graphicView.LogView;
32
33 /**
34  * GraphicController class
35  * @author Bruno JOFRET
36  */
37 public class GraphicController {
38
39     private static boolean MVCViewEnable = false;
40     private static boolean debugEnable = true;
41     private static boolean infoEnable = false;
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 UID createUID() {
115         return new UID();
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(String 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(String 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(String 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(String 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 String askObject(Type type) {
189
190         try {
191             UID id = createUID();
192             GraphicModel.getModel().createObject(id.toString(), type);
193             objectCreated(id.toString());
194
195             return id.toString();
196         } catch (Exception e) {
197             DEBUG("====== Exception caught ======");
198             DEBUG(" askObject type = " + type.name());
199             e.printStackTrace();
200             DEBUG("====== Exception caught ======");
201             return "";
202         }
203
204     }
205
206     /**
207      * Ask the model to clone an object
208      * @param id : the ID of the object to clone.
209      * @return the id of the clone.
210      */
211     public String cloneObject(String id) {
212         try {
213             UID newId = createUID();
214             GraphicModel.getModel().cloneObject(id, newId.toString());
215             objectCreated(newId.toString());
216
217             return newId.toString();
218         } catch (Exception e) {
219             DEBUG("====== Exception caught ======");
220             DEBUG("cloneObject id = " + id);
221             e.printStackTrace();
222             DEBUG("====== Exception caught ======");
223             return "";
224         }
225     }
226
227     /**
228      * Deletes an object
229      * @param id the deleted object's id
230      */
231     public void deleteObject(String id) {
232         try {
233             objectDeleted(id);
234             GraphicModel.getModel().deleteObject(id);
235         } catch (Exception e) {
236             DEBUG("====== Exception caught ======");
237             DEBUG("deleteObject id = " + id);
238             e.printStackTrace();
239             DEBUG("====== Exception caught ======");
240         }
241     }
242
243     /**
244      * Notifies the existing views that an object has been created
245      * @param id the created object's id
246      */
247     public void objectCreated(final String id) {
248         //INFO("### Create object : "+id);
249         //INFO("### type is : " + getProperty(id, GraphicObjectProperties.__GO_TYPE__));
250         Vector<Runnable> broadCastVector = new Vector<Runnable>();
251
252         try {
253             for (final GraphicView view : allViews) {
254                 broadCastVector.add(new Runnable() {
255                     public void run() {
256                         view.createObject(id);
257                     }
258                 });
259             }
260             for (final Runnable runMe : broadCastVector) {
261                 runMe.run();
262             }
263         } catch (ConcurrentModificationException e) {
264             e.printStackTrace();
265         }
266     }
267
268     /**
269      * Notified the existing views that an object has been updated
270      * @param id the updated object's id
271      * @param prop the property that has been updated
272      */
273     public void objectUpdate(final String id, final int prop) {
274         //INFO("### Update object : "+id);
275         //INFO("### type is : " + getProperty(id, GraphicObjectProperties.__GO_TYPE__));
276         //INFO("### prop is : " + prop);
277
278         Vector<Runnable> broadCastVector = new Vector<Runnable>();
279         try {
280             for (final GraphicView view : allViews) {
281                 broadCastVector.add(new Runnable() {
282                     public void run() {
283                         view.updateObject(id, prop);
284                     }
285                 });
286             }
287             for (final Runnable runMe : broadCastVector) {
288                 runMe.run();
289             }
290         } catch (ConcurrentModificationException e) {
291             e.printStackTrace();
292         }
293     }
294
295     /**
296      * Notified the existing views that an object has been deleted
297      * @param id the deleted object's id
298      */
299     public void objectDeleted(final String id) {
300         //INFO("### Delete object : "+id);
301         //INFO("### type is : " + getProperty(id, GraphicObjectProperties.__GO_TYPE__));
302         Vector<Runnable> broadCastVector = new Vector<Runnable>();
303
304         try {
305             for (final GraphicView view : allViews) {
306                 broadCastVector.add(new Runnable() {
307                     public void run() {
308                         view.deleteObject(id);
309                     }
310                 });
311             }
312             for (final Runnable runMe : broadCastVector) {
313                 runMe.run();
314             }
315         } catch (ConcurrentModificationException e) {
316             e.printStackTrace();
317         }
318     }
319
320     /**
321      * Set relationship between two object and remove old relationship.
322      * @param parentId id of the parent object.
323      * @param childId id of the child object.
324      */
325     public void setGraphicObjectRelationship(String parentId, String childId) {
326         /*
327          * All the parent and children get/set calls must be performed first,
328          * and only then the corresponding object updates.
329          */
330         Object oldParent = getProperty(childId, GraphicObjectProperties.__GO_PARENT__);
331
332         if (oldParent != null && oldParent instanceof String) {
333             String oldParentId = (String) oldParent;
334
335             if (oldParentId.equals(parentId)) {
336                 return;
337             }
338
339             if (!oldParentId.equals("")) {
340                 getObjectFromId(oldParentId).removeChild(childId);
341             }
342         }
343
344         /* Insertion occurs at the head of the children list. */
345         if (parentId != null && !parentId.equals("")) {
346             getObjectFromId(parentId).addChild(childId);
347         }
348
349         setProperty(childId, GraphicObjectProperties.__GO_PARENT__, parentId);
350
351         /* Object updates can now be performed. */
352         if (oldParent != null && oldParent instanceof String && !((String)oldParent).equals("")) {
353             objectUpdate((String)oldParent, GraphicObjectProperties.__GO_CHILDREN__);
354         }
355
356         if (parentId != null && !parentId.equals("")) {
357             objectUpdate(parentId, GraphicObjectProperties.__GO_CHILDREN__);
358         }
359
360         // Useless (already done in setProperty(childId, GraphicObjectProperties.__GO_PARENT__, parentId);)
361         //objectUpdate(childId, GraphicObjectProperties.__GO_PARENT__);
362     }
363
364     /**
365      * Remove relationship between given object and is parent.
366      * Then delete it.
367      * TODO : Manage children of deleted object.
368      * @param id deleted object identifier.
369      */
370     public void removeRelationShipAndDelete(String id) {
371         final GraphicObject killMe = getObjectFromId(id);
372         // assert that the object has not been deleted yet
373         if (killMe == null) {
374             return;
375         }
376
377         String parentUID = killMe.getParent();
378
379
380         /* Remove object from Parent's Children list */
381         if (parentUID != null && !parentUID.equals("")) {
382             getObjectFromId(parentUID).removeChild(id);
383             //setProperty(id, GraphicObjectProperties.__GO_PARENT__, "");
384
385             objectUpdate(parentUID, GraphicObjectProperties.__GO_CHILDREN__);
386             //objectUpdate(id, GraphicObjectProperties.__GO_PARENT__);
387         }
388
389         killMe.setValid(false);
390         recursiveDeleteChildren(killMe);
391
392         deleteObject(id);
393     }
394
395     private void recursiveDeleteChildren(GraphicObject killMe) {
396         String children[] = killMe.getChildren();
397
398         for (int i = 0 ; i < children.length ; ++i) {
399             GraphicObject killMeThisChild = getObjectFromId(children[i]);
400             killMeThisChild.setValid(false);
401             recursiveDeleteChildren(killMeThisChild);
402             deleteObject(children[i]);
403         }
404     }
405 }