Graphics: avoid useless redraw
[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         {
45             if (infoEnable == true)
46             {
47                 System.err.println("[CONTROLLER - INFO] : "+message);
48             }
49         }
50
51     private static void DEBUG(String message)
52         {
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             register(FlattenTreeView.create());
76         }
77         if (infoEnable) {
78             register(LogView.createLogView());
79         }
80     }
81
82     /**
83      * Returns the controller
84      * @return the controller
85      */
86     public static GraphicController getController() {
87         if (me == null) {
88             me = new GraphicController();
89         }
90
91         return me;
92     }
93
94     /**
95      * Register a view that will receive notification
96      * of any model changes.
97      * @param view The view to register.
98      */
99     public void register(GraphicView view) {
100         INFO("Register view : " + view.toString());
101         allViews.add(view);
102     }
103
104     /**
105      * Unregister a view.
106      * @param view The view to unregister.
107      */
108     public void unregister(GraphicView view) {
109         INFO("Unregister view : " + view.toString());
110         allViews.remove(view);
111     }
112
113     /**
114      * Creates a UID
115      * @return the created UID
116      */
117     public UID createUID() {
118         return new UID();
119     }
120
121     /**
122      * Returns the object associated to an id
123      * @param id the object id
124      * @return the object
125      */
126     public GraphicObject getObjectFromId(String id) {
127         return GraphicModel.getModel().getObjectFromId(id);
128     }
129
130     /**
131      * Fast property set method
132      * @param id the object id
133      * @param prop the property name
134      * @param value the property value
135      * @return true if the property has been set, false otherwise
136      */
137     public boolean setProperty(String id, int prop, Object value) {
138         try {
139             switch (GraphicModel.getModel().setProperty(id, prop, value)) {
140             case Success : // BroadCast Message + return true
141                 objectUpdate(id, prop);
142                 return true;
143             case NoChange : // Do not broadcast message
144                 return true;
145             case Fail :
146                 return false;
147             }
148             return false;
149         }
150         catch (Exception e) {
151             DEBUG("====== Exception caught ======");
152             DEBUG("setProperty : " + id + " " + prop);
153             e.printStackTrace();
154             DEBUG("====== Exception caught ======");
155             return false;
156         }
157     }
158
159     /**
160      * Fast property get method
161      * @param id the object id
162      * @param prop the property name
163      * @return the property value
164      */
165     public Object getProperty(String id, int prop) {
166         try {
167             return GraphicModel.getModel().getProperty(id, prop);
168         }
169         catch (Exception e) {
170             DEBUG("====== Exception caught ======");
171             DEBUG("getProperty : [" + id + "] " + prop);
172             e.printStackTrace();
173             DEBUG("====== Exception caught ======");
174             return null;
175         }
176     }
177
178     /**
179      * Returns a null property
180      * @param id the object id
181      * @param prop the property name
182      * @return the null property
183      */
184     public Object getNullProperty(String id, String prop) {
185         return GraphicModel.getModel().getNullProperty(id, prop);
186     }
187
188     /**
189      * Asks the model to create a new object
190      * @param type the object type
191      * @return the created object's id
192      */
193     public String askObject(Type type) {
194
195         try {
196             UID id = createUID();
197             GraphicModel.getModel().createObject(id.toString(), type);
198             objectCreated(id.toString());
199
200             return id.toString();
201         }
202         catch (Exception e) {
203             DEBUG("====== Exception caught ======");
204             DEBUG(" askObject type = " + type.name());
205             e.printStackTrace();
206             DEBUG("====== Exception caught ======");
207             return "";
208         }
209
210     }
211
212     /**
213      * Ask the model to clone an object
214      * @param id : the ID of the object to clone.
215      * @return the id of the clone.
216      */
217     public String cloneObject(String id) {
218         try {
219             UID newId = createUID();
220             GraphicModel.getModel().cloneObject(id, newId.toString());
221             objectCreated(newId.toString());
222
223             return newId.toString();
224         }
225         catch (Exception e) {
226             DEBUG("====== Exception caught ======");
227             DEBUG("cloneObject id = " + id);
228             e.printStackTrace();
229             DEBUG("====== Exception caught ======");
230             return "";
231         }
232     }
233
234     /**
235      * Deletes an object
236      * @param id the deleted object's id
237      */
238     public void deleteObject(String id) {
239         try {
240             objectDeleted(id);
241             GraphicModel.getModel().deleteObject(id);
242         }
243         catch (Exception e) {
244             DEBUG("====== Exception caught ======");
245             DEBUG("deleteObject id = " + id);
246             e.printStackTrace();
247             DEBUG("====== Exception caught ======");
248         }
249     }
250
251     /**
252      * Notifies the existing views that an object has been created
253      * @param id the created object's id
254      */
255     public void objectCreated(final String id) {
256         //INFO("### Create object : "+id);
257         //INFO("### type is : " + getProperty(id, GraphicObjectProperties.__GO_TYPE__));
258         Vector<Runnable> broadCastVector= new Vector<Runnable>();
259
260         try {
261             for (final GraphicView view : allViews) {
262                 broadCastVector.add(new Runnable() {
263                         public void run() {
264                             view.createObject(id);
265                         }
266                     });
267             }
268             for (final Runnable runMe : broadCastVector) {
269                 runMe.run();
270             }
271         } catch (ConcurrentModificationException e) {
272             e.printStackTrace();
273         }
274     }
275
276     /**
277      * Notified the existing views that an object has been updated
278      * @param id the updated object's id
279      * @param prop the property that has been updated
280      */
281     public void objectUpdate(final String id, final int prop) {
282         //INFO("### Update object : "+id);
283         //INFO("### type is : " + getProperty(id, GraphicObjectProperties.__GO_TYPE__));
284         //INFO("### prop is : " + prop);
285
286         Vector<Runnable> broadCastVector= new Vector<Runnable>();
287         try {
288             for (final GraphicView view : allViews) {
289                 broadCastVector.add(new Runnable() {
290                         public void run() {
291                             view.updateObject(id, prop);
292                         }
293                     });
294             }
295             for (final Runnable runMe : broadCastVector) {
296                 runMe.run();
297             }
298         } catch (ConcurrentModificationException e) {
299             e.printStackTrace();
300         }
301     }
302
303     /**
304      * Notified the existing views that an object has been deleted
305      * @param id the deleted object's id
306      */
307     public void objectDeleted(final String id) {
308         //INFO("### Delete object : "+id);
309         //INFO("### type is : " + getProperty(id, GraphicObjectProperties.__GO_TYPE__));
310         Vector<Runnable> broadCastVector= new Vector<Runnable>();
311
312         try {
313             for (final GraphicView view : allViews) {
314                 broadCastVector.add(new Runnable() {
315                         public void run() {
316                             view.deleteObject(id);
317                         }
318                     });
319             }
320             for (final Runnable runMe : broadCastVector) {
321                 runMe.run();
322             }
323         } catch (ConcurrentModificationException e) {
324             e.printStackTrace();
325         }
326     }
327
328     /**
329      * Set relationship between two object and remove old relationship.
330      * @param parentId id of the parent object.
331      * @param childId id of the child object.
332      */
333     public void setGraphicObjectRelationship(String parentId, String childId) {
334         /*
335          * All the parent and children get/set calls must be performed first,
336          * and only then the corresponding object updates.
337          */
338         Object oldParent = getProperty(childId, GraphicObjectProperties.__GO_PARENT__);
339
340         if (oldParent != null && oldParent instanceof String) {
341             String oldParentId = (String) oldParent;
342
343             if (oldParentId.equals(parentId)) {
344                 return;
345             }
346
347             if (!oldParentId.equals("")) {
348                 getObjectFromId(oldParentId).removeChild(childId);
349             }
350         }
351
352         /* Insertion occurs at the head of the children list. */
353         if (parentId != null && !parentId.equals("")) {
354             getObjectFromId(parentId).addChild(childId);
355         }
356
357         setProperty(childId, GraphicObjectProperties.__GO_PARENT__, parentId);
358
359         /* Object updates can now be performed. */
360         if (oldParent != null && oldParent instanceof String && !((String)oldParent).equals("")) {
361             objectUpdate((String)oldParent, GraphicObjectProperties.__GO_CHILDREN__);
362         }
363
364         if (parentId != null && !parentId.equals("")) {
365             objectUpdate(parentId, GraphicObjectProperties.__GO_CHILDREN__);
366         }
367
368         // Useless (already done in setProperty(childId, GraphicObjectProperties.__GO_PARENT__, parentId);)
369         //objectUpdate(childId, GraphicObjectProperties.__GO_PARENT__);
370     }
371
372     /**
373      * Remove relationship between given object and is parent.
374      * Then delete it.
375      * TODO : Manage children of deleted object.
376      * @param id deleted object identifier.
377      */
378     public void removeRelationShipAndDelete(String id) {
379         GraphicObject killMe = getObjectFromId(id);
380         String parentUID = killMe.getParent();
381
382
383         /* Remove object from Parent's Children list */
384         if (parentUID != null && !parentUID.equals("")) {
385             getObjectFromId(parentUID).removeChild(id);
386             //setProperty(id, GraphicObjectProperties.__GO_PARENT__, "");
387
388             objectUpdate(parentUID, GraphicObjectProperties.__GO_CHILDREN__);
389             //objectUpdate(id, GraphicObjectProperties.__GO_PARENT__);
390         }
391
392         killMe.setValid(false);
393         recursiveDeleteChildren(killMe);
394
395         deleteObject(id);
396     }
397
398     private void recursiveDeleteChildren(GraphicObject killMe) {
399         String children[] = killMe.getChildren();
400
401         for (int i = 0 ; i < children.length ; ++i) {
402             GraphicObject killMeThisChild = getObjectFromId(children[i]);
403             killMeThisChild.setValid(false);
404             recursiveDeleteChildren(killMeThisChild);
405             deleteObject(children[i]);
406         }
407     }
408 }