920f423c0eb10cd39712f96df282fb58127470fe
[scilab.git] / scilab / modules / xcos / src / java / org / scilab / modules / xcos / link / BasicLink.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2009 - 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.xcos.link;
14
15 import java.awt.MouseInfo;
16 import java.awt.geom.Line2D;
17 import java.awt.geom.Point2D;
18 import java.util.ArrayList;
19
20 import org.scilab.modules.graph.ScilabGraph;
21 import org.scilab.modules.graph.actions.DeleteAction;
22 import org.scilab.modules.gui.bridge.contextmenu.SwingScilabContextMenu;
23 import org.scilab.modules.gui.contextmenu.ContextMenu;
24 import org.scilab.modules.gui.contextmenu.ScilabContextMenu;
25 import org.scilab.modules.gui.menu.Menu;
26 import org.scilab.modules.gui.menu.ScilabMenu;
27 import org.scilab.modules.hdf5.scilabTypes.ScilabDouble;
28 import org.scilab.modules.hdf5.scilabTypes.ScilabMList;
29 import org.scilab.modules.hdf5.scilabTypes.ScilabString;
30 import org.scilab.modules.xcos.XcosUIDObject;
31 import org.scilab.modules.xcos.actions.ColorAction;
32 import org.scilab.modules.xcos.actions.LinkStyleAction;
33 import org.scilab.modules.xcos.block.BasicBlock;
34 import org.scilab.modules.xcos.link.commandcontrol.CommandControlLink;
35 import org.scilab.modules.xcos.link.explicit.ExplicitLink;
36 import org.scilab.modules.xcos.link.implicit.ImplicitLink;
37 import org.scilab.modules.xcos.port.BasicPort;
38 import org.scilab.modules.xcos.port.command.CommandPort;
39 import org.scilab.modules.xcos.port.control.ControlPort;
40 import org.scilab.modules.xcos.port.input.ExplicitInputPort;
41 import org.scilab.modules.xcos.port.input.ImplicitInputPort;
42 import org.scilab.modules.xcos.port.input.InputPort;
43 import org.scilab.modules.xcos.port.output.ExplicitOutputPort;
44 import org.scilab.modules.xcos.port.output.ImplicitOutputPort;
45 import org.scilab.modules.xcos.utils.XcosMessages;
46
47 import com.mxgraph.util.mxConstants;
48 import com.mxgraph.util.mxPoint;
49 import com.mxgraph.util.mxRectangle;
50
51 public abstract class BasicLink extends XcosUIDObject {
52
53         public BasicLink(String style) {
54                 super();
55                 setVertex(false);
56                 setEdge(true);
57                 setStyle(style);
58         }
59
60         public void setOrdering(int ordering) {
61                 ((BasicPort) this.getSource()).setConnectedLinkId(ordering);
62                 ((BasicPort) this.getTarget()).setConnectedLinkId(ordering);
63         }
64
65         public void removePoint(int index){
66                 if(getGeometry() == null || getGeometry().getPoints() == null){
67                         return;
68                 }
69                 if(index < getGeometry().getPoints().size()){
70                         getGeometry().getPoints().remove(index);
71                 }
72         }
73         
74         public mxPoint[] getPoints(int index, boolean fromStart){
75                 
76                 if(getGeometry() == null || getGeometry().getPoints() == null){
77                         return new mxPoint[0];
78                 }
79                 
80                 int start = 0;
81                 int size = 0;
82                 if(fromStart){
83                         size = Math.min(getGeometry().getPoints().size(), index);
84                         start = 0;
85                 }else{
86                         start = index;
87                         size = getGeometry().getPoints().size() - index;
88                 }
89                 
90                 if(size > 0)
91                 {       
92                         mxPoint points[] = new mxPoint[size];
93                         for(int i = 0 ; i < size ; i++){
94                                 points[i] = (mxPoint)getGeometry().getPoints().get(start + i);
95                         }
96                         return points;
97                 }
98                 return null;
99         }
100         
101         public int getPointCount(){
102                 if(getGeometry() == null || getGeometry().getPoints() == null){
103                         return 0;
104                 }
105                 return getGeometry().getPoints().size();
106         }
107
108         public int findNearestSegment(mxPoint point){
109
110                 if(getGeometry() == null || getGeometry().getPoints() == null){
111                         return 0;
112                 }
113                 
114                 double startX = (getSource().getParent().getGeometry().getX() + getSource().getGeometry().getX());
115                 double startY = (getSource().getParent().getGeometry().getY() + getSource().getGeometry().getY());
116
117                 double endX = (getTarget().getParent().getGeometry().getX() + getTarget().getGeometry().getX());
118                 double endY = (getTarget().getParent().getGeometry().getY() + getTarget().getGeometry().getY());
119
120                 double saveDist = -1;
121                 int findPos = 0;
122
123                 for(int i = 0 ; i < getGeometry().getPoints().size() + 1; i++){
124                         Point2D.Double point1 = null;
125                         Point2D.Double point2 = null;
126
127                         if(i == 0){//first block
128                                 point1 = new Point2D.Double(startX, startY);
129                         }else{
130                                 point1 = new Point2D.Double((int) ((mxPoint)getGeometry().getPoints().get(i-1)).getX(), (int) ((mxPoint)getGeometry().getPoints().get(i-1)).getY());
131                         }
132
133                         if(i == getGeometry().getPoints().size()){
134                                 point2 = new Point2D.Double(endX, endY);
135                         }else{
136                                 point2 = new Point2D.Double((int)((mxPoint)getGeometry().getPoints().get(i)).getX(), (int)((mxPoint)getGeometry().getPoints().get(i)).getY());
137                         }
138
139                         Point2D.Double addPoint = new Point2D.Double(point.getX(),point.getY());
140                         Line2D.Double line = new Line2D.Double(point1, point2);
141
142                         if(saveDist == -1){
143                                 saveDist = line.ptSegDist(addPoint);
144                                 findPos = i;
145                         }
146                         else{
147                                 double dist = line.ptSegDist(addPoint);
148                                 if(dist < saveDist){
149                                         saveDist = dist;
150                                         findPos = i;
151                                 }
152                         }
153                 }
154                 return findPos;
155         }
156         
157         public void addPoint(double x, double y) {
158                 mxPoint point = new mxPoint(x, y);
159                 if (getGeometry().getPoints() == null) {
160                         getGeometry().setPoints(new ArrayList());
161                 }
162                 getGeometry().getPoints().add(point);
163         }
164
165         public void insertPoint(double x, double y) {
166                 mxPoint point = new mxPoint(x, y);
167                 if (getGeometry().getPoints() == null) {
168                         getGeometry().setPoints(new ArrayList());
169                         getGeometry().getPoints().add(point);
170                 }
171                 else {
172                         //check to delete an old point before try to insert
173                         for(int i = 0 ; i < getGeometry().getPoints().size(); i++){
174                                 mxPoint oldPoint = (mxPoint)getGeometry().getPoints().get(i);
175                                 mxRectangle rect = new mxRectangle(oldPoint.getX() - 5, oldPoint.getY() - 5, 10, 10);
176                                 if(rect.contains(x, y)){
177                                         getGeometry().getPoints().remove(i);
178                                         return;
179                                 }else{
180                                 }
181                         }                       
182
183                         int insertPos = findNearestSegment(point);
184                         getGeometry().getPoints().add(insertPos, point);
185                 }
186         }
187
188         public ScilabMList getAsScilabObj() {
189                 String[] fields = {"Link", "xx", "yy", "id", "thick", "ct", "from", "to"};
190                 ScilabMList data = new ScilabMList(fields);
191
192                 double[][] xx = new double[1][2 + getPointCount()];
193
194                 // xx
195                 xx[0][0] = getSource().getGeometry().getCenterX() + getSource().getParent().getGeometry().getX();
196                 for(int i = 0 ; i < getPointCount() ; i++){
197                         System.err.println("Point : " + ((mxPoint)getGeometry().getPoints().get(i)).getX());
198                         xx[0][i+1] = ((mxPoint)getGeometry().getPoints().get(i)).getX();
199                 }
200                 xx[0][1 + getPointCount()] = getTarget().getGeometry().getCenterX() + getTarget().getParent().getGeometry().getX();
201                 data.add(new ScilabDouble(xx));
202
203                 // yy
204                 double[][] yy = new double[1][2 + getPointCount()];
205                 yy[0][0] = -(getSource().getGeometry().getCenterY() + getSource().getParent().getGeometry().getY() - getSource().getParent().getGeometry().getHeight());
206                 for(int i = 0 ; i < getPointCount() ; i++){
207                         System.err.println("Point : " + - ((mxPoint)getGeometry().getPoints().get(i)).getY());
208                         yy[0][i+1] = - ((mxPoint)getGeometry().getPoints().get(i)).getY() + getSource().getParent().getGeometry().getHeight();
209                 }
210                 yy[0][1 + getPointCount()] = -(getTarget().getGeometry().getCenterY() + getTarget().getParent().getGeometry().getY() - getSource().getParent().getGeometry().getHeight());
211                 data.add(new ScilabDouble(yy));
212                 
213                 data.add(new ScilabString("drawlink")); // id
214
215                 double[][] thick = {{0, 0}};
216                 data.add(new ScilabDouble(thick)); // thick
217
218                 data.add(new ScilabDouble(getColorAndType())); //ct
219
220                 double fromBlockID = ((BasicBlock) getSource().getParent()).getOrdering();
221                 double fromPortID = ((BasicPort) getSource()).getOrdering();
222                 double fromType = 0;
223                 
224                 if(getSource() instanceof InputPort || getSource() instanceof ControlPort){
225                         fromType = 1;
226                 }
227                 double[][] fromData = {{fromBlockID, fromPortID, fromType}};
228                 data.add(new ScilabDouble(fromData)); // from
229
230                 double toBlockID = ((BasicBlock) getTarget().getParent()).getOrdering();
231                 double toPortID = ((BasicPort) getTarget()).getOrdering();
232                 double toType = 0;
233                 if(getTarget() instanceof InputPort || getTarget() instanceof ControlPort){
234                         toType = 1;
235                 }
236                 double[][] toData = {{toBlockID, toPortID, toType}};
237                 data.add(new ScilabDouble(toData)); // to
238
239                 return data;
240         }
241
242         public abstract double[][] getColorAndType();
243
244         public void openContextMenu(ScilabGraph graph) {
245                 ContextMenu menu = ScilabContextMenu.createContextMenu();
246                 menu.add(DeleteAction.createMenu(graph));
247                 /*--- */
248                 menu.getAsSimpleContextMenu().addSeparator();
249                 /*--- */
250                 Menu format = ScilabMenu.createMenu();
251                 format.setText(XcosMessages.FORMAT);
252                 format.add(ColorAction.createMenu(graph, XcosMessages.BORDER_COLOR, mxConstants.STYLE_STROKECOLOR));
253                 menu.add(format);
254                 /*--- */
255                 menu.getAsSimpleContextMenu().addSeparator();
256                 /*--- */
257                 Menu linkStyle = ScilabMenu.createMenu();
258                 linkStyle.setText(XcosMessages.LINK_STYLE);
259                 linkStyle.add(LinkStyleAction.createMenu(graph, XcosMessages.LINK_STYLE_STRAIGHT, mxConstants.SHAPE_CONNECTOR));
260                 linkStyle.add(LinkStyleAction.createMenu(graph, XcosMessages.LINK_STYLE_HORIZONTAL, mxConstants.ELBOW_HORIZONTAL));
261                 linkStyle.add(LinkStyleAction.createMenu(graph, XcosMessages.LINK_STYLE_VERTICAL, mxConstants.ELBOW_VERTICAL));
262                 
263                 
264                 menu.add(linkStyle);
265                 
266                 ((SwingScilabContextMenu) menu.getAsSimpleContextMenu()).setLocation(MouseInfo.getPointerInfo().getLocation().x, MouseInfo.getPointerInfo().getLocation().y);           
267
268                 menu.setVisible(true);
269         }
270
271     public static BasicLink createLinkFromPorts(BasicPort from, BasicPort to) {
272         if (from instanceof ExplicitOutputPort && to instanceof ExplicitInputPort) {
273             return new ExplicitLink();
274         }
275         if (from instanceof ImplicitOutputPort && to instanceof ImplicitInputPort) {
276             return new ImplicitLink();
277         }
278
279         if (from instanceof ImplicitOutputPort && to instanceof ImplicitOutputPort) {
280             return new ImplicitLink();
281         }
282
283         if (from instanceof ImplicitInputPort && to instanceof ImplicitInputPort) {
284             return new ImplicitLink();
285         }
286
287         if (from instanceof CommandPort && to instanceof ControlPort) {
288             return new CommandControlLink();
289         }
290         if (to instanceof ExplicitOutputPort && from instanceof ExplicitInputPort) {
291             return new ExplicitLink();
292         }
293         if (to instanceof ImplicitOutputPort && from instanceof ImplicitInputPort) {
294             return new ImplicitLink();
295         }
296         if (to instanceof CommandPort && from instanceof ControlPort) {
297             return new CommandControlLink();
298         }
299         return new ExplicitLink();
300         }
301
302 }