001 /* 002 Copyright (C) 2002-2003 Renaud Pawlak <renaud@aopsys.com> 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 */ 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.Figure; 024 import CH.ifa.draw.framework.FigureEnumeration; 025 import CH.ifa.draw.framework.Connector; 026 import CH.ifa.draw.framework.Drawing; 027 028 import CH.ifa.draw.util.Geom; 029 030 import org.objectweb.jac.ide.Class; 031 import org.objectweb.jac.util.Log; 032 033 import java.awt.Point; 034 import java.awt.event.MouseEvent; 035 import java.util.Enumeration; 036 037 public class RelationLinkCreationTool extends AbstractTool { 038 039 /** the anchor point of the interaction */ 040 Connector myStartConnector; 041 Connector myEndConnector; 042 Connector myTargetConnector; 043 044 Figure myTarget; 045 046 /** the currently created figure */ 047 LinkFigure myConnection; 048 049 public RelationLinkCreationTool(DrawingEditor newDrawingEditor) { 050 super(newDrawingEditor); 051 } 052 053 /** 054 * Handles mouse move events in the drawing view. 055 */ 056 public void mouseMove(MouseEvent e, int x, int y) { 057 trackConnectors(e, x, y); 058 } 059 060 /** 061 * Manipulates connections in a context dependent way. If the 062 * mouse down hits a figure start a new connection. If the mousedown 063 * hits a connection split a segment or join two segments. 064 */ 065 public void mouseDown(MouseEvent e, int x, int y) 066 { 067 Log.trace("diagram","mouseDown"); 068 int ex = e.getX(); 069 int ey = e.getY(); 070 myTarget = findConnectionStart(ex, ey, drawing()); 071 Log.trace("diagram","target figure = "+myTarget); 072 if (myTarget != null 073 && (myTarget.getClass()==ClassFigure.class || 074 myTarget.getClass()==AspectFigure.class)) { 075 myStartConnector = findConnector(ex, ey, myTarget); 076 if (myStartConnector != null) { 077 Point p = new Point(ex, ey); 078 myConnection = createLinkFigure(); 079 myConnection.startPoint(p.x, p.y); 080 myConnection.endPoint(p.x, p.y); 081 view().add(myConnection); 082 } 083 } 084 } 085 086 protected LinkFigure createLinkFigure() { 087 return new RelationLinkFigure(); 088 } 089 090 /** 091 * Adjust the created connection or split segment. 092 */ 093 public void mouseDrag(MouseEvent e, int x, int y) { 094 Log.trace("diagram",2,"mouseDrag "+x+","+y); 095 Point p = new Point(e.getX(), e.getY()); 096 if (myConnection != null) { 097 trackConnectors(e, x, y); 098 if (myTargetConnector != null) { 099 p = Geom.center(myTargetConnector.displayBox()); 100 } 101 myConnection.endPoint(p.x, p.y); 102 } 103 } 104 105 /** 106 * Connects the figures if the mouse is released over another 107 * figure. 108 */ 109 public void mouseUp(MouseEvent e, int x, int y) { 110 Log.trace("diagram","mouseUp "+x+","+y); 111 Log.trace("diagram"," myStartConnector="+myStartConnector); 112 ModelElementFigure dest = null; 113 if (myStartConnector != null) { 114 dest = findTarget(e.getX(), e.getY(), drawing()); 115 Log.trace("diagram"," dest="+dest); 116 } 117 118 if (dest instanceof ClassFigure) { 119 myEndConnector = findConnector(e.getX(), e.getY(), dest); 120 Log.trace("diagram"," myEndConnector="+myEndConnector); 121 if (myEndConnector != null) { 122 myConnection.connectStart(myStartConnector); 123 myConnection.connectEnd(myEndConnector); 124 myConnection.updateConnection(); 125 ClassFigure source = (ClassFigure)myStartConnector.owner(); 126 createRelation(source.getClassElement(), 127 ((ClassFigure)dest).getClassElement()); 128 } 129 } 130 else if (myConnection != null) { 131 ((DiagramView)editor()).showStatus( 132 "Invalid or empty ending element for relation."); 133 view().remove(myConnection); 134 } 135 136 myConnection = null; 137 myStartConnector = null; 138 myEndConnector = null; 139 editor().toolDone(); 140 } 141 142 /** 143 * Create a RelationLink between two classes. 144 * @param source start class of the link 145 * @param target end class of the link 146 */ 147 protected void createRelation(Class source, Class target) { 148 if (source != null && target != null) { 149 diagramView().createRelation(source,target,(RelationLinkFigure)myConnection,false); 150 view().clearSelection(); 151 view().addToSelection(myConnection); 152 } 153 } 154 155 public void deactivate() { 156 super.deactivate(); 157 if (myTarget != null) { 158 myTarget.connectorVisibility(false); 159 } 160 } 161 162 163 /** 164 * Finds a connectable figure target. 165 */ 166 protected Figure findSource(int x, int y, Drawing drawing) { 167 return findConnectableFigure(x, y, drawing); 168 } 169 170 /** 171 * Finds a connectable figure target. 172 */ 173 protected ModelElementFigure findTarget(int x, int y, Drawing drawing) { 174 ModelElementFigure target = findConnectableFigure(x, y, drawing); 175 Figure start = myStartConnector.owner(); 176 177 if (target != null 178 && myConnection != null 179 && target.canConnect() 180 && myConnection.canConnect(start, target)) { 181 return target; 182 } 183 return null; 184 } 185 186 /** 187 * Finds an existing connection figure. 188 */ 189 protected ConnectionFigure findConnection(int x, int y, Drawing drawing) { 190 Enumeration k = drawing.figuresReverse(); 191 while (k.hasMoreElements()) { 192 Figure figure = (Figure) k.nextElement(); 193 figure = figure.findFigureInside(x, y); 194 if (figure != null && (figure instanceof ConnectionFigure)) { 195 return (ConnectionFigure)figure; 196 } 197 } 198 return null; 199 } 200 201 protected void trackConnectors(MouseEvent e, int x, int y) { 202 Figure c = null; 203 204 if (myStartConnector == null) { 205 c = findSource(x, y, drawing()); 206 } 207 else { 208 c = findTarget(x, y, drawing()); 209 } 210 211 // track the figure containing the mouse 212 if (c != myTarget) { 213 if (myTarget != null) { 214 myTarget.connectorVisibility(false); 215 } 216 myTarget = c; 217 if (myTarget != null) { 218 myTarget.connectorVisibility(true); 219 } 220 } 221 222 Connector cc = null; 223 if (c != null) { 224 cc = findConnector(e.getX(), e.getY(), c); 225 } 226 if (cc != myTargetConnector) { 227 myTargetConnector = cc; 228 } 229 230 view().checkDamage(); 231 } 232 233 private Connector findConnector(int x, int y, Figure f) { 234 return f.connectorAt(x, y); 235 } 236 237 /** 238 * Finds a connection start figure. 239 */ 240 protected Figure findConnectionStart(int x, int y, Drawing drawing) { 241 Figure target = findConnectableFigure(x, y, drawing); 242 if ((target != null) && target.canConnect()) { 243 return target; 244 } 245 return null; 246 } 247 248 private ModelElementFigure findConnectableFigure( 249 int x, int y, Drawing drawing) 250 { 251 FigureEnumeration k = drawing.figuresReverse(); 252 while (k.hasMoreElements()) { 253 Figure figure = k.nextFigure(); 254 if (!figure.includes(myConnection) && figure.canConnect() 255 && figure.containsPoint(x, y)) { 256 return (ModelElementFigure)figure; 257 } 258 } 259 return null; 260 } 261 262 }