001 /* 002 Copyright (C) 2002 Renaud Pawlak 003 004 This program is free software; you can redistribute it and/or modify 005 it under the terms of the GNU Lesser General Public License as 006 published by the Free Software Foundation; either version 2 of the 007 License, or (at your option) any later version. 008 009 This program is distributed in the hope that it will be useful, 010 but WITHOUT ANY WARRANTY; without even the implied warranty of 011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 GNU Lesser General Public License for more details. 013 014 You should have received a copy of the GNU Lesser General Public 015 License along with this program; if not, write to the Free Software 016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 017 USA. */ 018 019 package org.objectweb.jac.ide.diagrams; 020 021 import CH.ifa.draw.framework.DrawingEditor; 022 import CH.ifa.draw.framework.ConnectionFigure; 023 import CH.ifa.draw.framework.Connector; 024 import CH.ifa.draw.framework.Drawing; 025 import CH.ifa.draw.framework.Figure; 026 import CH.ifa.draw.framework.FigureEnumeration; 027 import CH.ifa.draw.standard.AbstractTool; 028 import CH.ifa.draw.util.Geom; 029 import org.objectweb.jac.core.Wrapping; 030 import org.objectweb.jac.core.Wrappee; 031 import org.objectweb.jac.ide.ModelElement; 032 import org.objectweb.jac.ide.PointcutLink; 033 import org.objectweb.jac.ide.Diagram; 034 import org.objectweb.jac.util.Log; 035 import java.awt.Point; 036 import java.awt.event.MouseEvent; 037 import java.util.Enumeration; 038 039 public class PointcutLinkCreationTool extends AbstractTool { 040 041 /** 042 * the anchor point of the interaction 043 */ 044 private Connector myStartConnector; 045 private Connector myEndConnector; 046 private Connector myTargetConnector; 047 048 private Figure myTarget; 049 050 /** 051 * the currently created figure 052 */ 053 private ConnectionFigure myConnection; 054 055 /** 056 * the figure that was actually added 057 * Note, this can be a different figure from the one which has been created. 058 */ 059 private Figure myAddedFigure; 060 061 /** 062 * the prototypical figure that is used to create new 063 * connections. 064 */ 065 private ConnectionFigure fPrototype; 066 067 068 public PointcutLinkCreationTool(DrawingEditor newDrawingEditor, ConnectionFigure newPrototype) { 069 super(newDrawingEditor); 070 fPrototype = newPrototype; 071 } 072 073 /** 074 * Handles mouse move events in the drawing view. 075 */ 076 public void mouseMove(MouseEvent e, int x, int y) { 077 trackConnectors(e, x, y); 078 } 079 080 /** 081 * Manipulates connections in a context dependent way. If the 082 * mouse down hits a figure start a new connection. If the mousedown 083 * hits a connection split a segment or join two segments. 084 */ 085 public void mouseDown(MouseEvent e, int x, int y) 086 { 087 int ex = e.getX(); 088 int ey = e.getY(); 089 setTargetFigure(findConnectionStart(ex, ey, drawing())); 090 if (getTargetFigure() != null 091 && getTargetFigure().getClass()==AspectFigure.class) { 092 setStartConnector(findConnector(ex, ey, getTargetFigure())); 093 if (getStartConnector() != null) { 094 Point p = new Point(ex, ey); 095 setConnection(createConnection()); 096 getConnection().startPoint(p.x, p.y); 097 getConnection().endPoint(p.x, p.y); 098 setAddedFigure(view().add(getConnection())); 099 } 100 } 101 } 102 103 /** 104 * Adjust the created connection or split segment. 105 */ 106 public void mouseDrag(MouseEvent e, int x, int y) { 107 Point p = new Point(e.getX(), e.getY()); 108 if (getConnection() != null) { 109 trackConnectors(e, x, y); 110 if (getTargetConnector() != null) { 111 p = Geom.center(getTargetConnector().displayBox()); 112 } 113 getConnection().endPoint(p.x, p.y); 114 } 115 } 116 117 /** 118 * Connects the figures if the mouse is released over another 119 * figure. 120 */ 121 public void mouseUp(MouseEvent e, int x, int y) { 122 Figure c = null; 123 if (getStartConnector() != null) { 124 c = findTarget(e.getX(), e.getY(), drawing()); 125 } 126 127 if (c != null && (c.getClass()==ClassFigure.class || 128 c.getClass()==InstanceFigure.class)) { 129 setEndConnector(findConnector(e.getX(), e.getY(), c)); 130 if (getEndConnector() != null) { 131 getConnection().connectStart(getStartConnector()); 132 getConnection().connectEnd(getEndConnector()); 133 getConnection().updateConnection(); 134 135 /* 136 setUndoActivity(createUndoActivity()); 137 getUndoActivity().setAffectedFigures( 138 new SingleFigureEnumerator(getAddedFigure())); 139 */ 140 AspectFigure source = (AspectFigure)getStartConnector().owner(); 141 ModelElementFigure target = (ModelElementFigure)c; 142 Log.trace("figures","creating a new poincut link between "+ 143 source.getSubstance()+" and "+target.getSubstance()); 144 145 createRelation(source.getClassElement(),target.getSubstance()); 146 147 } 148 } 149 else if (getConnection() != null) { 150 ((DiagramView)editor()).showStatus("Invalid or empty ending element for relation."); 151 view().remove(getConnection()); 152 } 153 154 setConnection(null); 155 setStartConnector(null); 156 setEndConnector(null); 157 setAddedFigure(null); 158 editor().toolDone(); 159 } 160 161 162 protected void createRelation(org.objectweb.jac.ide.Class source, ModelElement target) { 163 164 if(source != null && target != null ) { 165 PointcutLink rel = new PointcutLink(); 166 rel.setStart(source); 167 rel.setEnd(target); 168 // *** ((LinkFigure)getConnection()).setSubstance(rel); 169 LinkFigure linkFigure=(LinkFigure)getConnection(); 170 org.objectweb.jac.ide.LinkFigure linkFig = 171 new org.objectweb.jac.ide.LinkFigure(rel); 172 linkFigure.setLinkFigure(linkFig); 173 174 view().add(linkFigure.createName("newPointcut")); 175 view().add(linkFigure.createEndRole("ALL:ALL")); 176 view().add(linkFigure.createStartRole("?")); 177 //view().add(((LinkFigure)getConnection()).createStartCardinality("0-1")); 178 //view().add(((LinkFigure)getConnection()).createEndCardinality("0-1")); 179 ((org.objectweb.jac.ide.Aspect)source).addPointcutLink(rel); 180 181 Diagram diagram = (Diagram)((DiagramView)editor()).getSubstance(); 182 183 diagram.addFigure(linkFig); 184 185 Wrapping.invokeRoleMethod((Wrappee)rel,"registerObject", 186 new Object[]{getConnection(),null}); 187 } 188 } 189 190 public void deactivate() { 191 super.deactivate(); 192 if (getTargetFigure() != null) { 193 getTargetFigure().connectorVisibility(false); 194 } 195 } 196 197 /** 198 * Creates the ConnectionFigure. By default the figure prototype is 199 * cloned. 200 */ 201 protected ConnectionFigure createConnection() { 202 return (ConnectionFigure)fPrototype.clone(); 203 } 204 205 /** 206 * Finds a connectable figure target. 207 */ 208 protected Figure findSource(int x, int y, Drawing drawing) { 209 return findConnectableFigure(x, y, drawing); 210 } 211 212 /** 213 * Finds a connectable figure target. 214 */ 215 protected Figure findTarget(int x, int y, Drawing drawing) { 216 Figure target = findConnectableFigure(x, y, drawing); 217 Figure start = getStartConnector().owner(); 218 219 if (target != null 220 && getConnection() != null 221 && target.canConnect() 222 && !target.includes(start) 223 && getConnection().canConnect(start, target)) { 224 return target; 225 } 226 return null; 227 } 228 229 /** 230 * Finds an existing connection figure. 231 */ 232 protected ConnectionFigure findConnection(int x, int y, Drawing drawing) { 233 Enumeration k = drawing.figuresReverse(); 234 while (k.hasMoreElements()) { 235 Figure figure = (Figure) k.nextElement(); 236 figure = figure.findFigureInside(x, y); 237 if (figure != null && (figure instanceof ConnectionFigure)) { 238 return (ConnectionFigure)figure; 239 } 240 } 241 return null; 242 } 243 244 private void setConnection(ConnectionFigure newConnection) { 245 myConnection = newConnection; 246 } 247 248 /** 249 * Gets the connection which is created by this tool 250 */ 251 protected ConnectionFigure getConnection() { 252 return myConnection; 253 } 254 255 protected void trackConnectors(MouseEvent e, int x, int y) { 256 Figure c = null; 257 258 if (getStartConnector() == null) { 259 c = findSource(x, y, drawing()); 260 } 261 else { 262 c = findTarget(x, y, drawing()); 263 } 264 265 // track the figure containing the mouse 266 if (c != getTargetFigure()) { 267 if (getTargetFigure() != null) { 268 getTargetFigure().connectorVisibility(false); 269 } 270 setTargetFigure(c); 271 if (getTargetFigure() != null) { 272 getTargetFigure().connectorVisibility(true); 273 } 274 } 275 276 Connector cc = null; 277 if (c != null) { 278 cc = findConnector(e.getX(), e.getY(), c); 279 } 280 if (cc != getTargetConnector()) { 281 setTargetConnector(cc); 282 } 283 284 view().checkDamage(); 285 } 286 287 private Connector findConnector(int x, int y, Figure f) { 288 return f.connectorAt(x, y); 289 } 290 291 /** 292 * Finds a connection start figure. 293 */ 294 protected Figure findConnectionStart(int x, int y, Drawing drawing) { 295 Figure target = findConnectableFigure(x, y, drawing); 296 if ((target != null) && target.canConnect()) { 297 return target; 298 } 299 return null; 300 } 301 302 private Figure findConnectableFigure(int x, int y, Drawing drawing) { 303 FigureEnumeration k = drawing.figuresReverse(); 304 while (k.hasMoreElements()) { 305 Figure figure = k.nextFigure(); 306 if (!figure.includes(getConnection()) && figure.canConnect() 307 && figure.containsPoint(x, y)) { 308 return figure; 309 } 310 } 311 return null; 312 } 313 314 private void setStartConnector(Connector newStartConnector) { 315 myStartConnector = newStartConnector; 316 } 317 318 protected Connector getStartConnector() { 319 return myStartConnector; 320 } 321 322 private void setEndConnector(Connector newEndConnector) { 323 myEndConnector = newEndConnector; 324 } 325 326 protected Connector getEndConnector() { 327 return myEndConnector; 328 } 329 330 private void setTargetConnector(Connector newTargetConnector) { 331 myTargetConnector = newTargetConnector; 332 } 333 334 protected Connector getTargetConnector() { 335 return myTargetConnector; 336 } 337 338 private void setTargetFigure(Figure newTarget) { 339 myTarget = newTarget; 340 } 341 342 protected Figure getTargetFigure() { 343 return myTarget; 344 } 345 346 /** 347 * Gets the figure that was actually added 348 * Note, this can be a different figure from the one which has been created. 349 */ 350 protected Figure getAddedFigure() { 351 return myAddedFigure; 352 } 353 354 private void setAddedFigure(Figure newAddedFigure) { 355 myAddedFigure = newAddedFigure; 356 } 357 358 /** 359 * Factory method for undo activity 360 */ 361 /* 362 protected Undoable createUndoActivity() { 363 return new ConnectionTool.UndoActivity(view(), getConnection()); 364 } 365 366 public static class UndoActivity extends UndoableAdapter { 367 368 private ConnectionFigure myConnection; 369 private Connector myStartConnector; 370 private Connector myEndConnector; 371 372 public UndoActivity(DrawingView newDrawingView, ConnectionFigure newConnection) { 373 super(newDrawingView); 374 setConnection(newConnection); 375 myStartConnector = getConnection().getStartConnector(); 376 myEndConnector = getConnection().getEndConnector(); 377 setUndoable(true); 378 setRedoable(true); 379 } 380 public boolean undo() { 381 if (!super.undo()) { 382 return false; 383 } 384 385 getConnection().disconnectStart(); 386 getConnection().disconnectEnd(); 387 388 FigureEnumeration fe = getAffectedFigures(); 389 while (fe.hasMoreElements()) { 390 getDrawingView().drawing().orphan(fe.nextFigure()); 391 } 392 393 getDrawingView().clearSelection(); 394 395 return true; 396 } 397 398 public boolean redo() { 399 if (!super.redo()) { 400 return false; 401 } 402 403 getConnection().connectStart(myStartConnector); 404 getConnection().connectEnd(myEndConnector); 405 getConnection().updateConnection(); 406 407 getDrawingView().insertFigures(getAffectedFigures(), 0, 0, false); 408 409 return true; 410 } 411 412 private void setConnection(ConnectionFigure newConnection) { 413 myConnection = newConnection; 414 } 415 416 /** 417 * Gets the currently created figure 418 * / 419 protected ConnectionFigure getConnection() { 420 return myConnection; 421 } 422 } 423 */ 424 }