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