Xcos: propagate ports style updates as mxUndoableEdit changes
[scilab.git] / scilab / modules / xcos / src / java / org / scilab / modules / xcos / port / BasicPort.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2009 - DIGITEO - Bruno JOFRET
4  * Copyright (C) 2011-2015 - Scilab Enterprises - Clement DAVID
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16
17 package org.scilab.modules.xcos.port;
18
19 import org.scilab.modules.graph.utils.StyleMap;
20 import org.scilab.modules.types.ScilabType;
21 import org.scilab.modules.xcos.JavaController;
22 import org.scilab.modules.xcos.Kind;
23 import org.scilab.modules.xcos.ObjectProperties;
24 import org.scilab.modules.xcos.PortKind;
25 import org.scilab.modules.xcos.block.BasicBlock;
26 import org.scilab.modules.xcos.graph.model.XcosCell;
27
28 import com.mxgraph.model.mxGeometry;
29 import com.mxgraph.model.mxICell;
30 import com.mxgraph.util.mxConstants;
31
32 /**
33  * Common implementation of any Port.
34  */
35 public abstract class BasicPort extends XcosCell {
36     private static final long serialVersionUID = 0L;
37
38     /**
39      * The side-size of any port. All ports must have the same size.
40      */
41     public static final double DEFAULT_PORTSIZE = 8;
42
43     private Orientation orientation;
44
45     /** Type of any dataport */
46     public enum Type {
47         /** The link direction as no impact on simulation */
48         IMPLICIT,
49         /** The link keep its direction on simulation */
50         EXPLICIT;
51
52         /**
53          * @return A scicos compatible representation
54          */
55         public String getAsString() {
56             switch (this) {
57                 case IMPLICIT:
58                     return "I";
59                 case EXPLICIT:
60                     return "E";
61                 default:
62                     return "";
63             }
64         }
65     };
66
67     /** Type of any data on any dataport */
68     public enum DataType {
69         /** A not specific type */
70         UNKNOW_TYPE,
71         /** Data is real (double) numbers */
72         REAL_MATRIX,
73         /** Data is complex (double + i * double) numbers */
74         COMPLEX_MATRIX,
75         /** Data is int32 (32 bits) numbers */
76         INT32_MATRIX,
77         /** Data is int16 (16 bits) numbers */
78         INT16_MATRIX,
79         /** Data is int8 (8bits) numbers */
80         INT8_MATRIX,
81         /** Data is uint32 (unsigned 32 bits) numbers */
82         UINT32_MATRIX,
83         /** Data is uint16 (unsigned 16 bits) numbers */
84         UINT16_MATRIX,
85         /** Data is uint8 (unsigned 8 bits) numbers */
86         UINT8_MATRIX;
87
88         /**
89          * @return A scicos compatible representation
90          */
91         public int asScilabValue() {
92             if (this.equals(UNKNOW_TYPE)) {
93                 return -1;
94             }
95
96             // We assume that the types are sorted well on the enum definition
97             return this.ordinal();
98         }
99
100         /**
101          * @param val
102          *            A scicos representation
103          * @return The java compatible representation
104          */
105         public static DataType convertScilabValue(int val) {
106             if (val <= 0 || val > DataType.values().length - 1) {
107                 return DataType.UNKNOW_TYPE;
108             }
109
110             // We assume that the types are sorted well on the enum definition
111             return DataType.values()[val];
112         }
113
114         public static DataType convertScilabValue(double val) {
115             return convertScilabValue((int) val);
116         }
117     }
118
119     /**
120      * Instantiate a port with a style (or typename).
121      *
122      * @param style
123      *            Value to be set as a Style and as TypeName
124      */
125     public BasicPort(final JavaController controller, long uid, Kind kind, Object value, String style, String id, Orientation orientation, boolean isImplicit, PortKind portKind) {
126         super(controller, uid, kind, value, new mxGeometry(0, 0, DEFAULT_PORTSIZE, DEFAULT_PORTSIZE), style, id);
127
128         this.vertex = true;
129
130         controller.setObjectProperty(uid, Kind.PORT, ObjectProperties.IMPLICIT, isImplicit);
131         controller.setObjectProperty(uid, Kind.PORT, ObjectProperties.PORT_KIND, portKind.ordinal());
132
133         this.orientation = orientation;
134         setStyle(computeLabelPosition(orientation));
135     }
136
137     /**
138      * @return the type of the port (Explicit or Implicit)
139      */
140     public abstract Type getType();
141
142     public abstract PortKind getPortKind();
143
144     /** @return The default orientation of this port */
145     public final Orientation getOrientation() {
146         return orientation;
147     }
148
149     /**
150      * @param defaultOrientation
151      *            The default orientation of this port
152      */
153     public final void setOrientation(Orientation defaultOrientation) {
154         if (orientation != defaultOrientation) {
155             orientation = defaultOrientation;
156             setStyle(computeLabelPosition(orientation));
157         }
158     }
159
160     /**
161      * Set the label position of the current port according to the orientation.
162      *
163      * @param current
164      *            the port orientation, if null, does nothing.
165      * @return an updated style for the orientation
166      */
167     public final String computeLabelPosition(final Orientation current) {
168         if (current != null) {
169             StyleMap style = new StyleMap(getStyle());
170
171             // clean up any previously set spacing values
172             style.remove(mxConstants.STYLE_LABEL_POSITION);
173             style.remove(mxConstants.STYLE_VERTICAL_LABEL_POSITION);
174             style.remove(mxConstants.STYLE_SPACING_BOTTOM);
175             style.remove(mxConstants.STYLE_SPACING_LEFT);
176             style.remove(mxConstants.STYLE_SPACING_RIGHT);
177             style.remove(mxConstants.STYLE_SPACING_TOP);
178
179             // set up the port position
180             style.put(mxConstants.STYLE_ALIGN, current.getLabelPosition());
181             style.put(mxConstants.STYLE_VERTICAL_ALIGN, current.getVerticalLabelPosition());
182             style.put(mxConstants.STYLE_SPACING, Double.toString(BasicPort.DEFAULT_PORTSIZE + 2.0));
183
184             return style.toString();
185         }
186
187         return getStyle();
188     }
189
190     /**
191      * Hook to update the port label from the associated block expression.
192      *
193      * The current port index may be found in the ordering data.
194      *
195      * @param exprs
196      *            the associated block expression.
197      */
198     public void updateLabel(ScilabType exprs) {
199     }
200
201     /*
202      * Overriden methods from jgraphx
203      */
204
205     /**
206      * {@inheritDoc}
207      */
208     @Override
209     public String toString() {
210         final StringBuilder str = new StringBuilder();
211
212         final mxICell parent = getParent();
213         if (parent != null) {
214             if (parent instanceof BasicBlock) {
215                 JavaController controller = new JavaController();
216                 String[] interfaceFunctionName = new String[1];
217                 controller.getObjectProperty(((BasicBlock) parent).getUID(), Kind.BLOCK, ObjectProperties.INTERFACE_FUNCTION, interfaceFunctionName);
218                 str.append(interfaceFunctionName[0]).append('.');
219             } else {
220                 str.append(parent.getClass().getSimpleName()).append('.');
221             }
222         }
223
224         if (getChildCount() > 0) {
225             // append the label
226             str.append(getChildAt(0).getValue());
227         } else {
228             str.append(getClass().getSimpleName());
229         }
230         if (parent != null) {
231             str.append('[').append(getParent().getIndex(this)).append(']');
232         }
233         if (getEdgeCount() == 1) {
234             str.append(" (connected)");
235         } else if (getEdgeCount() > 1) {
236             str.append(" - multiple links (");
237             str.append(getEdgeCount());
238             str.append(')');
239         }
240
241         return str.toString();
242     }
243 }