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