take care link in xcos diagram positionning
[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                         xx[0][i+1] = ((mxPoint)getGeometry().getPoints().get(i)).getX();
198                 }
199                 xx[0][1 + getPointCount()] = getTarget().getGeometry().getCenterX() + getTarget().getParent().getGeometry().getX();
200                 data.add(new ScilabDouble(xx));
201
202                 // yy
203                 double[][] yy = new double[1][2 + getPointCount()];
204                 yy[0][0] = -(getSource().getGeometry().getCenterY() + getSource().getParent().getGeometry().getY() - getSource().getParent().getGeometry().getHeight());
205                 for(int i = 0 ; i < getPointCount() ; i++){
206                         yy[0][i+1] = - ((mxPoint)getGeometry().getPoints().get(i)).getY() + getSource().getParent().getGeometry().getHeight();
207                 }
208                 yy[0][1 + getPointCount()] = -(getTarget().getGeometry().getCenterY() + getTarget().getParent().getGeometry().getY() - getSource().getParent().getGeometry().getHeight());
209                 data.add(new ScilabDouble(yy));
210                 
211                 data.add(new ScilabString("drawlink")); // id
212
213                 double[][] thick = {{0, 0}};
214                 data.add(new ScilabDouble(thick)); // thick
215
216                 data.add(new ScilabDouble(getColorAndType())); //ct
217
218                 double fromBlockID = ((BasicBlock) getSource().getParent()).getOrdering();
219                 double fromPortID = ((BasicPort) getSource()).getOrdering();
220                 double fromType = 0;
221                 
222                 if(getSource() instanceof InputPort || getSource() instanceof ControlPort){
223                         fromType = 1;
224                 }
225                 double[][] fromData = {{fromBlockID, fromPortID, fromType}};
226                 data.add(new ScilabDouble(fromData)); // from
227
228                 double toBlockID = ((BasicBlock) getTarget().getParent()).getOrdering();
229                 double toPortID = ((BasicPort) getTarget()).getOrdering();
230                 double toType = 0;
231                 if(getTarget() instanceof InputPort || getTarget() instanceof ControlPort){
232                         toType = 1;
233                 }
234                 double[][] toData = {{toBlockID, toPortID, toType}};
235                 data.add(new ScilabDouble(toData)); // to
236
237                 return data;
238         }
239
240         public abstract double[][] getColorAndType();
241
242         public void openContextMenu(ScilabGraph graph) {
243                 ContextMenu menu = ScilabContextMenu.createContextMenu();
244                 menu.add(DeleteAction.createMenu(graph));
245                 /*--- */
246                 menu.getAsSimpleContextMenu().addSeparator();
247                 /*--- */
248                 Menu format = ScilabMenu.createMenu();
249                 format.setText(XcosMessages.FORMAT);
250                 format.add(ColorAction.createMenu(graph, XcosMessages.BORDER_COLOR, mxConstants.STYLE_STROKECOLOR));
251                 menu.add(format);
252                 /*--- */
253                 menu.getAsSimpleContextMenu().addSeparator();
254                 /*--- */
255                 Menu linkStyle = ScilabMenu.createMenu();
256                 linkStyle.setText(XcosMessages.LINK_STYLE);
257                 linkStyle.add(LinkStyleAction.createMenu(graph, XcosMessages.LINK_STYLE_STRAIGHT, mxConstants.SHAPE_CONNECTOR));
258                 linkStyle.add(LinkStyleAction.createMenu(graph, XcosMessages.LINK_STYLE_HORIZONTAL, mxConstants.ELBOW_HORIZONTAL));
259                 linkStyle.add(LinkStyleAction.createMenu(graph, XcosMessages.LINK_STYLE_VERTICAL, mxConstants.ELBOW_VERTICAL));
260                 
261                 
262                 menu.add(linkStyle);
263                 
264                 ((SwingScilabContextMenu) menu.getAsSimpleContextMenu()).setLocation(MouseInfo.getPointerInfo().getLocation().x, MouseInfo.getPointerInfo().getLocation().y);           
265
266                 menu.setVisible(true);
267         }
268
269     public static BasicLink createLinkFromPorts(BasicPort from, BasicPort to) {
270         if (from instanceof ExplicitOutputPort && to instanceof ExplicitInputPort) {
271             return new ExplicitLink();
272         }
273         if (from instanceof ImplicitOutputPort && to instanceof ImplicitInputPort) {
274             return new ImplicitLink();
275         }
276
277         if (from instanceof ImplicitOutputPort && to instanceof ImplicitOutputPort) {
278             return new ImplicitLink();
279         }
280
281         if (from instanceof ImplicitInputPort && to instanceof ImplicitInputPort) {
282             return new ImplicitLink();
283         }
284
285         if (from instanceof CommandPort && to instanceof ControlPort) {
286             return new CommandControlLink();
287         }
288         if (to instanceof ExplicitOutputPort && from instanceof ExplicitInputPort) {
289             return new ExplicitLink();
290         }
291         if (to instanceof ImplicitOutputPort && from instanceof ImplicitInputPort) {
292             return new ImplicitLink();
293         }
294         if (to instanceof CommandPort && from instanceof ControlPort) {
295             return new CommandControlLink();
296         }
297         return new ExplicitLink();
298         }
299
300 }