1 /* 2 * @(#)LineConnection.java 5.1 3 * 4 */ 5 6 package CH.ifa.draw.figures; 7 8 import java.awt.*; 9 import java.util.*; 10 import java.io.*; 11 import CH.ifa.draw.framework.*; 12 import CH.ifa.draw.standard.*; 13 import CH.ifa.draw.util.*; 14 15 /** 16 * A LineConnection is a standard implementation of the 17 * ConnectionFigure interface. The interface is implemented with PolyLineFigure. 18 * @see ConnectionFigure 19 */ 20 public class LineConnection extends PolyLineFigure implements ConnectionFigure { 21 22 protected Connector fStart = null; 23 protected Connector fEnd = null; 24 25 /* 26 * Serialization support. 27 */ 28 private static final long serialVersionUID = 6883731614578414801L; 29 private int lineConnectionSerializedDataVersion = 1; 30 31 /** 32 * Constructs a LineConnection. A connection figure has 33 * an arrow decoration at the start and end. 34 */ LineConnection()35 public LineConnection() { 36 super(4); 37 setStartDecoration(new ArrowTip()); 38 setEndDecoration(new ArrowTip()); 39 } 40 41 /** 42 * Tests whether a figure can be a connection target. 43 * ConnectionFigures cannot be connected and return false. 44 */ canConnect()45 public boolean canConnect() { 46 return false; 47 } 48 49 /** 50 * Ensures that a connection is updated if the connection 51 * was moved. 52 */ basicMoveBy(int dx, int dy)53 protected void basicMoveBy(int dx, int dy) { 54 // don't move the start and end point since they are connected 55 for (int i = 1; i < fPoints.size()-1; i++) 56 ((Point) fPoints.elementAt(i)).translate(dx, dy); 57 58 updateConnection(); // make sure that we are still connected 59 } 60 61 /** 62 * Sets the start figure of the connection. 63 */ connectStart(Connector start)64 public void connectStart(Connector start) { 65 fStart = start; 66 startFigure().addFigureChangeListener(this); 67 } 68 69 /** 70 * Sets the end figure of the connection. 71 */ connectEnd(Connector end)72 public void connectEnd(Connector end) { 73 fEnd = end; 74 endFigure().addFigureChangeListener(this); 75 handleConnect(startFigure(), endFigure()); 76 } 77 78 /** 79 * Disconnects the start figure. 80 */ disconnectStart()81 public void disconnectStart() { 82 startFigure().removeFigureChangeListener(this); 83 fStart = null; 84 } 85 86 /** 87 * Disconnects the end figure. 88 */ disconnectEnd()89 public void disconnectEnd() { 90 handleDisconnect(startFigure(), endFigure()); 91 endFigure().removeFigureChangeListener(this); 92 fEnd = null; 93 } 94 95 /** 96 * Tests whether a connection connects the same figures 97 * as another ConnectionFigure. 98 */ connectsSame(ConnectionFigure other)99 public boolean connectsSame(ConnectionFigure other) { 100 return other.start() == start() && other.end() == end(); 101 } 102 103 /** 104 * Handles the disconnection of a connection. 105 * Override this method to handle this event. 106 */ handleDisconnect(Figure start, Figure end)107 protected void handleDisconnect(Figure start, Figure end) {} 108 109 /** 110 * Handles the connection of a connection. 111 * Override this method to handle this event. 112 */ handleConnect(Figure start, Figure end)113 protected void handleConnect(Figure start, Figure end) {} 114 115 /** 116 * Gets the start figure of the connection. 117 */ startFigure()118 public Figure startFigure() { 119 if (start() != null) 120 return start().owner(); 121 return null; 122 } 123 124 /** 125 * Gets the end figure of the connection. 126 */ endFigure()127 public Figure endFigure() { 128 if (end() != null) 129 return end().owner(); 130 return null; 131 } 132 133 /** 134 * Gets the start figure of the connection. 135 */ start()136 public Connector start() { 137 return fStart; 138 } 139 140 /** 141 * Gets the end figure of the connection. 142 */ end()143 public Connector end() { 144 return fEnd; 145 } 146 147 /** 148 * Tests whether two figures can be connected. 149 */ canConnect(Figure start, Figure end)150 public boolean canConnect(Figure start, Figure end) { 151 return true; 152 } 153 154 /** 155 * Sets the start point. 156 */ startPoint(int x, int y)157 public void startPoint(int x, int y) { 158 willChange(); 159 if (fPoints.size() == 0) 160 fPoints.addElement(new Point(x, y)); 161 else 162 fPoints.setElementAt(new Point(x, y), 0); 163 changed(); 164 } 165 166 /** 167 * Sets the end point. 168 */ endPoint(int x, int y)169 public void endPoint(int x, int y) { 170 willChange(); 171 if (fPoints.size() < 2) 172 fPoints.addElement(new Point(x, y)); 173 else 174 fPoints.setElementAt(new Point(x, y), fPoints.size()-1); 175 changed(); 176 } 177 178 /** 179 * Gets the start point. 180 */ startPoint()181 public Point startPoint(){ 182 Point p = (Point)fPoints.firstElement(); 183 return new Point(p.x, p.y); 184 } 185 186 /** 187 * Gets the end point. 188 */ endPoint()189 public Point endPoint() { 190 Point p = (Point)fPoints.lastElement(); 191 return new Point(p.x, p.y); 192 } 193 194 /** 195 * Gets the handles of the figure. It returns the normal 196 * PolyLineHandles but adds ChangeConnectionHandles at the 197 * start and end. 198 */ handles()199 public Vector handles() { 200 Vector handles = new Vector(fPoints.size()); 201 handles.addElement(new ChangeConnectionStartHandle(this)); 202 for (int i = 1; i < fPoints.size()-1; i++) 203 handles.addElement(new PolyLineHandle(this, locator(i), i)); 204 handles.addElement(new ChangeConnectionEndHandle(this)); 205 return handles; 206 } 207 208 /** 209 * Sets the point and updates the connection. 210 */ setPointAt(Point p, int i)211 public void setPointAt(Point p, int i) { 212 super.setPointAt(p, i); 213 layoutConnection(); 214 } 215 216 /** 217 * Inserts the point and updates the connection. 218 */ insertPointAt(Point p, int i)219 public void insertPointAt(Point p, int i) { 220 super.insertPointAt(p, i); 221 layoutConnection(); 222 } 223 224 /** 225 * Removes the point and updates the connection. 226 */ removePointAt(int i)227 public void removePointAt(int i) { 228 super.removePointAt(i); 229 layoutConnection(); 230 } 231 232 /** 233 * Updates the connection. 234 */ updateConnection()235 public void updateConnection() { 236 if (fStart != null) { 237 Point start = fStart.findStart(this); 238 startPoint(start.x, start.y); 239 } 240 if (fEnd != null) { 241 Point end = fEnd.findEnd(this); 242 endPoint(end.x, end.y); 243 } 244 } 245 246 /** 247 * Lays out the connection. This is called when the connection 248 * itself changes. By default the connection is recalculated 249 */ layoutConnection()250 public void layoutConnection() { 251 updateConnection(); 252 } 253 figureChanged(FigureChangeEvent e)254 public void figureChanged(FigureChangeEvent e) { 255 updateConnection(); 256 } 257 figureRemoved(FigureChangeEvent e)258 public void figureRemoved(FigureChangeEvent e) { 259 if (listener() != null) 260 listener().figureRequestRemove(new FigureChangeEvent(this)); 261 } 262 figureRequestRemove(FigureChangeEvent e)263 public void figureRequestRemove(FigureChangeEvent e) {} figureInvalidated(FigureChangeEvent e)264 public void figureInvalidated(FigureChangeEvent e) {} figureRequestUpdate(FigureChangeEvent e)265 public void figureRequestUpdate(FigureChangeEvent e) {} 266 release()267 public void release() { 268 super.release(); 269 handleDisconnect(startFigure(), endFigure()); 270 if (fStart != null) startFigure().removeFigureChangeListener(this); 271 if (fEnd != null) endFigure().removeFigureChangeListener(this); 272 } 273 write(StorableOutput dw)274 public void write(StorableOutput dw) { 275 super.write(dw); 276 dw.writeStorable(fStart); 277 dw.writeStorable(fEnd); 278 } 279 read(StorableInput dr)280 public void read(StorableInput dr) throws IOException { 281 super.read(dr); 282 Connector start = (Connector)dr.readStorable(); 283 if (start != null) 284 connectStart(start); 285 Connector end = (Connector)dr.readStorable(); 286 if (end != null) 287 connectEnd(end); 288 if (start != null && end != null) 289 updateConnection(); 290 } 291 readObject(ObjectInputStream s)292 private void readObject(ObjectInputStream s) 293 throws ClassNotFoundException, IOException { 294 295 s.defaultReadObject(); 296 297 if (fStart != null) 298 connectStart(fStart); 299 if (fEnd != null) 300 connectEnd(fEnd); 301 } 302 } 303