29b69a05fa5d55db99fadcfba0caf2a4e1e23b0b
[scilab.git] / scilab / modules / xcos / src / java / org / scilab / modules / xcos / graph / model / XcosCell.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2015-2015 - Scilab Enterprises - Clement DAVID
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.xcos.graph.model;
14
15 import java.util.Collections;
16 import java.util.List;
17
18 import org.scilab.modules.graph.ScilabGraphUniqueObject;
19 import org.scilab.modules.xcos.JavaController;
20 import org.scilab.modules.xcos.Kind;
21 import org.scilab.modules.xcos.ObjectProperties;
22 import org.scilab.modules.xcos.PortKind;
23 import org.scilab.modules.xcos.VectorOfDouble;
24 import org.scilab.modules.xcos.VectorOfScicosID;
25
26 import com.mxgraph.model.mxGeometry;
27 import com.mxgraph.model.mxICell;
28 import com.mxgraph.util.mxPoint;
29
30
31 public class XcosCell extends ScilabGraphUniqueObject {
32     private static final long serialVersionUID = 1L;
33
34     private transient ScicosObjectOwner owner;
35
36     /**
37      * Construct an Xcos graphical object.
38      *
39      * This Java object owns the corresponding MVC object and thus will unrefererence it on GC.
40      *
41      * @param uid the associated MVC identifier
42      * @param kind the associated MVC kind
43      */
44     public XcosCell(long uid, Kind kind) {
45         owner = new ScicosObjectOwner(uid, kind);
46
47         // defensive programming
48         if (uid == 0l) {
49             throw new IllegalArgumentException();
50         }
51
52         JavaController controller = new JavaController();
53         controller.referenceObject(uid);
54     }
55
56     /**
57      * @return the MVC unique identifier
58      */
59     public long getUID() {
60         return owner.getUID();
61     }
62
63     /**
64      * @return the MVC kind of object
65      */
66     public Kind getKind() {
67         return owner.getKind();
68     }
69
70     /*
71      * Override setters and hierarchy modifiers to propagate changes to the model
72      */
73
74     /* (non-Javadoc)
75      * @see com.mxgraph.model.mxCell#setValue(java.lang.Object)
76      */
77     @Override
78     public void setValue(Object value) {
79         super.setValue(value);
80         if (owner == null) {
81             return;
82         }
83
84         JavaController controller = new JavaController();
85         switch (getKind()) {
86             case ANNOTATION:
87                 controller.setObjectProperty(getUID(), getKind(), ObjectProperties.DESCRIPTION, String.valueOf(value));
88                 break;
89             case BLOCK:
90             case LINK:
91             case PORT:
92                 controller.setObjectProperty(getUID(), getKind(), ObjectProperties.LABEL, String.valueOf(value));
93                 break;
94             default:
95                 break;
96         }
97     }
98
99     /* (non-Javadoc)
100      * @see com.mxgraph.model.mxCell#setId(java.lang.String)
101      */
102     @Override
103     public void setId(String id) {
104         super.setId(id);
105
106         JavaController controller = new JavaController();
107         switch (getKind()) {
108             case ANNOTATION:
109                 controller.setObjectProperty(getUID(), getKind(), ObjectProperties.UID, id);
110                 break;
111             case BLOCK:
112                 controller.setObjectProperty(getUID(), getKind(), ObjectProperties.UID, id);
113                 break;
114             case LINK:
115                 controller.setObjectProperty(getUID(), getKind(), ObjectProperties.UID, id);
116                 break;
117             case PORT:
118                 controller.setObjectProperty(getUID(), getKind(), ObjectProperties.UID, id);
119                 break;
120             default:
121                 break;
122         }
123     }
124
125     /* (non-Javadoc)
126      * @see com.mxgraph.model.mxCell#setGeometry(com.mxgraph.model.mxGeometry)
127      */
128     @Override
129     public void setGeometry(mxGeometry geometry) {
130         super.setGeometry(geometry);
131         if (owner == null) {
132             return;
133         }
134
135         JavaController controller = new JavaController();
136         switch (getKind()) {
137             case ANNOTATION:
138             case BLOCK: {
139                 VectorOfDouble v = new VectorOfDouble(4);
140                 v.set(0, geometry.getX());
141                 v.set(1, geometry.getY());
142                 v.set(2, geometry.getWidth());
143                 v.set(3, geometry.getHeight());
144                 controller.setObjectProperty(getUID(), getKind(), ObjectProperties.GEOMETRY, v);
145                 break;
146             }
147             case LINK: {
148                 /*
149                  * try to find the origin of the source and target accordingly to the JGraphX implementation
150                  */
151                 mxPoint sourcePoint = null;
152                 mxPoint targetPoint = null;
153
154                 mxICell sourceCell = getSource();
155                 mxICell targetCell = getTarget();
156                 if (sourceCell != null && sourceCell.getGeometry() != null) {
157                     sourcePoint = new mxPoint(sourceCell.getGeometry().getCenterX(), sourceCell.getGeometry().getCenterY());
158                 }
159                 if (targetCell != null && targetCell.getGeometry() != null) {
160                     targetPoint = new mxPoint(targetCell.getGeometry().getCenterX(), targetCell.getGeometry().getCenterY());
161                 }
162
163                 if (sourcePoint == null) {
164                     sourcePoint = geometry.getSourcePoint();
165                 }
166                 if (targetPoint == null) {
167                     targetPoint = geometry.getTargetPoint();
168                 }
169
170                 if (sourcePoint == null) {
171                     sourcePoint = new mxPoint();
172                 }
173                 if (targetPoint == null) {
174                     targetPoint = new mxPoint();
175                 }
176
177                 List<mxPoint> points = geometry.getPoints();
178                 if (points == null) {
179                     points = Collections.emptyList();
180                 }
181
182                 /*
183                  * At that point, the sourcePoint, targetPoint and points are valid values (but may be unknown)
184                  * encode them to the the CONTROL_POINTS
185                  */
186
187                 // Allocate some space to contains them all
188                 int nbOfPoints = 2 + points.size();
189                 VectorOfDouble v = new VectorOfDouble(2 * nbOfPoints);
190                 int i = 0;
191
192                 // then fill the allocation space
193                 v.set(2 * i, sourcePoint.getX());
194                 v.set(2 * i + 1, sourcePoint.getY());
195                 i++;
196
197                 for (; i < nbOfPoints - 1 ; i++) {
198                     v.set(2 * i, points.get(i - 1).getX());
199                     v.set(2 * i + 1, points.get(i - 1).getY());
200                 }
201
202                 v.set(2 * i, targetPoint.getX());
203                 v.set(2 * i + 1, targetPoint.getY());
204                 i++;
205
206                 /*
207                  * Finally push the values to the model
208                  */
209                 controller.setObjectProperty(getUID(), getKind(), ObjectProperties.CONTROL_POINTS, v);
210                 break;
211             }
212             default:
213                 break;
214         }
215     }
216
217     /* (non-Javadoc)
218      * @see com.mxgraph.model.mxCell#setStyle(java.lang.String)
219      */
220     @Override
221     public void setStyle(String style) {
222         super.setStyle(style);
223         if (owner == null) {
224             return;
225         }
226
227         JavaController controller = new JavaController();
228         switch (getKind()) {
229             case ANNOTATION:
230             case BLOCK:
231             case PORT:
232                 controller.setObjectProperty(getUID(), getKind(), ObjectProperties.STYLE, String.valueOf(style));
233                 break;
234             default:
235                 break;
236         }
237
238     }
239
240     /* (non-Javadoc)
241      * @see com.mxgraph.model.mxCell#setParent(com.mxgraph.model.mxICell)
242      */
243     @Override
244     public void setParent(mxICell parent) {
245         super.setParent(parent);
246
247         if (parent instanceof XcosCell) {
248             XcosCell p = (XcosCell) parent;
249             JavaController controller = new JavaController();
250             switch (getKind()) {
251                 case ANNOTATION:
252                 case BLOCK:
253                 case LINK:
254                     if (p.getKind() == Kind.DIAGRAM) {
255                         controller.setObjectProperty(getUID(), getKind(), ObjectProperties.PARENT_DIAGRAM, p.getUID());
256                     } else {
257                         controller.setObjectProperty(getUID(), getKind(), ObjectProperties.PARENT_BLOCK, p.getUID());
258
259                         long[] root = new long[1];
260                         controller.getObjectProperty(p.getUID(), p.getKind(), ObjectProperties.PARENT_DIAGRAM, root);
261                         controller.setObjectProperty(getUID(), getKind(), ObjectProperties.PARENT_DIAGRAM, root[0]);
262                     }
263                     break;
264                 case PORT:
265                     controller.setObjectProperty(getUID(), getKind(), ObjectProperties.SOURCE_BLOCK, p.getUID());
266                     break;
267                 default:
268                     break;
269             }
270         }
271     }
272
273     @Override
274     public mxICell setTerminal(mxICell terminal, boolean isSource) {
275         mxICell cell = super.setTerminal(terminal, isSource);
276
277         if (cell == null) {
278             return cell;
279         }
280
281         // a terminal of an XcosCell is always another XcosCell
282         XcosCell t = (XcosCell) cell;
283         JavaController controller = new JavaController();
284         switch (getKind()) {
285             case LINK:
286                 if (isSource) {
287                     controller.setObjectProperty(getUID(), getKind(), ObjectProperties.SOURCE_PORT, t.getUID());
288                 } else {
289                     controller.setObjectProperty(getUID(), getKind(), ObjectProperties.DESTINATION_PORT, t.getUID());
290                 }
291                 break;
292             default:
293                 break;
294         }
295
296         return cell;
297     }
298
299     /* (non-Javadoc)
300      * @see com.mxgraph.model.mxCell#insert(com.mxgraph.model.mxICell, int)
301      */
302     @Override
303     public mxICell insert(mxICell child, int index) {
304         mxICell inserted = super.insert(child, index);
305
306         // the child might not be an XcosCell but just an mxCell label
307         if (child instanceof XcosCell) {
308             XcosCell c = (XcosCell) child;
309             switch (getKind()) {
310                 case BLOCK:
311                     if (c.getKind() == Kind.PORT) {
312                         insertPort(c, index);
313                     } else {
314                         insertChild(c, index);
315                     }
316                     break;
317                 case DIAGRAM:
318                     insertChild(c, index);
319                     break;
320                 default:
321                     break;
322             }
323
324             JavaController controller = new JavaController();
325             controller.referenceObject(c.getUID());
326         }
327
328         return inserted;
329     }
330
331     private void insertPort(XcosCell c, int index) {
332         JavaController controller = new JavaController();
333         int[] v = new int[1];
334         controller.getObjectProperty(c.getUID(), c.getKind(), ObjectProperties.PORT_KIND, v);
335
336         VectorOfScicosID children = new VectorOfScicosID();
337         final ObjectProperties property;
338         switch (PortKind.values()[v[0]]) {
339             case PORT_IN:
340                 property = ObjectProperties.INPUTS;
341                 break;
342             case PORT_OUT:
343                 property = ObjectProperties.OUTPUTS;
344                 break;
345             case PORT_EIN:
346                 property = ObjectProperties.EVENT_INPUTS;
347                 break;
348             case PORT_EOUT:
349                 property = ObjectProperties.EVENT_OUTPUTS;
350                 break;
351             default:
352                 property = null;
353                 break;
354         }
355
356         // FIXME manage the index argument
357         if (property != null) {
358             controller.getObjectProperty(getUID(), getKind(), property, children);
359             children.add(c.getUID());
360             controller.setObjectProperty(getUID(), getKind(), property, children);
361         }
362     }
363
364     private void insertChild(XcosCell c, int index) {
365         JavaController controller = new JavaController();
366         VectorOfScicosID children = new VectorOfScicosID();
367
368         controller.getObjectProperty(getUID(), getKind(), ObjectProperties.CHILDREN, children);
369         children.add(index, c.getUID());
370         controller.setObjectProperty(getUID(), getKind(), ObjectProperties.CHILDREN, children);
371     }
372
373     /* (non-Javadoc)
374      * @see com.mxgraph.model.mxCell#remove(com.mxgraph.model.mxICell)
375      */
376     @Override
377     public mxICell remove(mxICell child) {
378         mxICell removed = super.remove(child);
379
380         // the child might not be an XcosCell but just an mxCell label
381         if (child instanceof XcosCell) {
382             XcosCell c = (XcosCell) child;
383             switch (getKind()) {
384                 case BLOCK:
385                     if (c.getKind() == Kind.PORT) {
386                         removePort(c);
387                     } else {
388                         removeChild(c);
389                     }
390                     break;
391                 case DIAGRAM:
392                     removeChild(c);
393                     break;
394                 default:
395                     break;
396             }
397
398             JavaController controller = new JavaController();
399             controller.deleteObject(c.getUID());
400         }
401         return removed;
402     }
403
404     private void removePort(XcosCell c) {
405         JavaController controller = new JavaController();
406         int[] v = new int[1];
407         controller.getObjectProperty(c.getUID(), c.getKind(), ObjectProperties.PORT_KIND, v);
408
409         VectorOfScicosID children = new VectorOfScicosID();
410         final ObjectProperties property;
411         switch (PortKind.values()[v[0]]) {
412             case PORT_IN:
413                 property = ObjectProperties.INPUTS;
414                 break;
415             case PORT_OUT:
416                 property = ObjectProperties.OUTPUTS;
417                 break;
418             case PORT_EIN:
419                 property = ObjectProperties.EVENT_INPUTS;
420                 break;
421             case PORT_EOUT:
422                 property = ObjectProperties.EVENT_OUTPUTS;
423                 break;
424             default:
425                 property = null;
426                 break;
427         }
428
429         controller.getObjectProperty(getUID(), getKind(), property, children);
430         children.remove(c.getUID());
431         controller.setObjectProperty(getUID(), getKind(), property, children);
432     }
433
434     private void removeChild(XcosCell c) {
435         JavaController controller = new JavaController();
436         VectorOfScicosID children = new VectorOfScicosID();
437
438         controller.getObjectProperty(getUID(), getKind(), ObjectProperties.CHILDREN, children);
439         children.remove(c.getUID());
440         controller.setObjectProperty(getUID(), getKind(), ObjectProperties.CHILDREN, children);
441
442     }
443
444     /*
445      * Override methods from Object
446      */
447
448     @Override
449     public Object clone() throws CloneNotSupportedException {
450         JavaController controller = new JavaController();
451         XcosCell c = (XcosCell) super.clone();
452         c.owner = new ScicosObjectOwner(controller.cloneObject(getUID(), false), getKind());
453         return c;
454     }
455
456     @Override
457     protected void finalize() throws Throwable {
458         JavaController controller = new JavaController();
459         controller.deleteObject(getUID());
460     }
461 }