Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
ModeCreateGraphEdge |
|
| 8.2;8.2 |
1 | /* $Id: ModeCreateGraphEdge.java 17865 2010-01-12 20:45:26Z linus $ | |
2 | ***************************************************************************** | |
3 | * Copyright (c) 2009 Contributors - see below | |
4 | * All rights reserved. This program and the accompanying materials | |
5 | * are made available under the terms of the Eclipse Public License v1.0 | |
6 | * which accompanies this distribution, and is available at | |
7 | * http://www.eclipse.org/legal/epl-v10.html | |
8 | * | |
9 | * Contributors: | |
10 | * tfmorris | |
11 | ***************************************************************************** | |
12 | * | |
13 | * Some portions of this file was previously release using the BSD License: | |
14 | */ | |
15 | ||
16 | // Copyright (c) 2005-2008 The Regents of the University of California. All | |
17 | // Rights Reserved. Permission to use, copy, modify, and distribute this | |
18 | // software and its documentation without fee, and without a written | |
19 | // agreement is hereby granted, provided that the above copyright notice | |
20 | // and this paragraph appear in all copies. This software program and | |
21 | // documentation are copyrighted by The Regents of the University of | |
22 | // California. The software program and documentation are supplied "AS | |
23 | // IS", without any accompanying services from The Regents. The Regents | |
24 | // does not warrant that the operation of the program will be | |
25 | // uninterrupted or error-free. The end-user understands that the program | |
26 | // was developed for research purposes and is advised not to rely | |
27 | // exclusively on the program for any reason. IN NO EVENT SHALL THE | |
28 | // UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, | |
29 | // SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, | |
30 | // ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF | |
31 | // THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF | |
32 | // SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY | |
33 | // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
34 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE | |
35 | // PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF | |
36 | // CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, | |
37 | // UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | |
38 | ||
39 | package org.argouml.uml.diagram.ui; | |
40 | ||
41 | import java.awt.Color; | |
42 | import java.awt.Point; | |
43 | import java.awt.event.MouseEvent; | |
44 | import java.awt.event.MouseListener; | |
45 | ||
46 | import org.apache.log4j.Logger; | |
47 | import org.argouml.model.Model; | |
48 | import org.argouml.uml.diagram.static_structure.ui.FigEdgeNote; | |
49 | import org.tigris.gef.base.Layer; | |
50 | import org.tigris.gef.base.ModeCreatePolyEdge; | |
51 | import org.tigris.gef.graph.MutableGraphModel; | |
52 | import org.tigris.gef.presentation.Fig; | |
53 | import org.tigris.gef.presentation.FigEdge; | |
54 | import org.tigris.gef.presentation.FigNode; | |
55 | import org.tigris.gef.presentation.FigPoly; | |
56 | ||
57 | /** | |
58 | * A Mode to interpret user input while creating an edge. | |
59 | * The edge can connect any two model element prooviding isConnectionValid | |
60 | * return true. | |
61 | */ | |
62 | 0 | public abstract class ModeCreateGraphEdge extends ModeCreatePolyEdge { |
63 | ||
64 | 0 | private static final Logger LOG = |
65 | Logger.getLogger(ModeCreateGraphEdge.class); | |
66 | ||
67 | /** | |
68 | * The Fig from which drawing starts, either a FigNode or a FigEdge | |
69 | */ | |
70 | private Fig sourceFig; | |
71 | ||
72 | /* | |
73 | * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent) | |
74 | */ | |
75 | @Override | |
76 | public void mousePressed(MouseEvent me) { | |
77 | 0 | int x = me.getX(), y = me.getY(); |
78 | 0 | Fig underMouse = editor.hit(x, y); |
79 | 0 | if (underMouse == null) { |
80 | 0 | underMouse = editor.hit(x - 16, y - 16, 32, 32); |
81 | } | |
82 | ||
83 | 0 | if (underMouse == null && _npoints == 0) { |
84 | 0 | done(); |
85 | 0 | me.consume(); |
86 | 0 | return; |
87 | } | |
88 | ||
89 | 0 | if (_npoints > 0) { |
90 | 0 | me.consume(); |
91 | 0 | return; |
92 | } | |
93 | ||
94 | 0 | sourceFig = underMouse; |
95 | ||
96 | 0 | if (underMouse instanceof FigEdgeModelElement |
97 | && !(underMouse instanceof FigEdgeNote)) { | |
98 | // If we're drawing from an edge | |
99 | ||
100 | 0 | FigEdgeModelElement sourceEdge = (FigEdgeModelElement) underMouse; |
101 | 0 | sourceEdge.makeEdgePort(); |
102 | 0 | FigEdgePort edgePort = sourceEdge.getEdgePort(); |
103 | 0 | sourceEdge.computeRoute(); |
104 | ||
105 | 0 | underMouse = edgePort; |
106 | 0 | setSourceFigNode(edgePort); |
107 | 0 | setStartPort(sourceFig.getOwner()); |
108 | 0 | setStartPortFig(edgePort); |
109 | ||
110 | 0 | } else if (underMouse instanceof FigNodeModelElement) { |
111 | 0 | if (getSourceFigNode() == null) { |
112 | 0 | setSourceFigNode((FigNode) underMouse); |
113 | 0 | setStartPort(getSourceFigNode().deepHitPort(x, y)); |
114 | } | |
115 | 0 | if (getStartPort() == null) { |
116 | 0 | done(); |
117 | 0 | me.consume(); |
118 | 0 | return; |
119 | } | |
120 | 0 | setStartPortFig( |
121 | getSourceFigNode().getPortFig(getStartPort())); | |
122 | } else { | |
123 | 0 | done(); |
124 | 0 | me.consume(); |
125 | 0 | return; |
126 | } | |
127 | ||
128 | 0 | createFig(me); |
129 | 0 | me.consume(); |
130 | 0 | } |
131 | ||
132 | /* | |
133 | * @see org.tigris.gef.base.ModeCreatePolyEdge#mouseReleased(java.awt.event.MouseEvent) | |
134 | */ | |
135 | @Override | |
136 | public void mouseReleased(MouseEvent me) { | |
137 | 0 | if (me.isConsumed()) { |
138 | 0 | return; |
139 | } | |
140 | 0 | if (getSourceFigNode() == null) { |
141 | 0 | done(); |
142 | 0 | me.consume(); |
143 | 0 | return; |
144 | } | |
145 | 0 | int x = me.getX(), y = me.getY(); |
146 | 0 | Fig destFig = editor.hit(x, y); |
147 | 0 | if (destFig == null) { |
148 | 0 | destFig = editor.hit(x - 16, y - 16, 32, 32); |
149 | } | |
150 | 0 | MutableGraphModel graphModel = |
151 | (MutableGraphModel) editor.getGraphModel(); | |
152 | ||
153 | 0 | if (!isConnectionValid(sourceFig, destFig)) { |
154 | 0 | destFig = null; |
155 | } else { | |
156 | 0 | LOG.info("Connection valid"); |
157 | } | |
158 | ||
159 | 0 | if (destFig instanceof FigEdgeModelElement |
160 | && !(destFig instanceof FigEdgeNote)) { | |
161 | 0 | FigEdgeModelElement destEdge = (FigEdgeModelElement) destFig; |
162 | 0 | destEdge.makeEdgePort(); |
163 | 0 | destFig = destEdge.getEdgePort(); |
164 | 0 | destEdge.computeRoute(); |
165 | } | |
166 | ||
167 | 0 | if (destFig instanceof FigNodeModelElement) { |
168 | 0 | FigNode destFigNode = (FigNode) destFig; |
169 | 0 | Object foundPort = destFigNode.getOwner(); |
170 | ||
171 | 0 | if (foundPort == getStartPort() && _npoints < 4) { |
172 | // user made a false start | |
173 | 0 | done(); |
174 | 0 | me.consume(); |
175 | 0 | return; |
176 | } | |
177 | 0 | if (foundPort != null) { |
178 | 0 | FigPoly p = (FigPoly) _newItem; |
179 | 0 | if (foundPort == getStartPort() && _npoints >= 4) { |
180 | 0 | p.setSelfLoop(true); |
181 | } | |
182 | 0 | editor.damageAll(); |
183 | 0 | p.setComplete(true); |
184 | ||
185 | 0 | LOG.info("Connecting"); |
186 | 0 | FigEdge fe = buildConnection( |
187 | graphModel, | |
188 | getMetaType(), | |
189 | sourceFig, | |
190 | destFig); | |
191 | ||
192 | 0 | if (fe != null) { |
193 | 0 | editor.getSelectionManager().select(fe); |
194 | } | |
195 | 0 | editor.damageAll(); |
196 | ||
197 | // if the new edge implements the MouseListener | |
198 | // interface it has to receive the mouseReleased() event | |
199 | 0 | if (fe instanceof MouseListener) { |
200 | 0 | ((MouseListener) fe).mouseReleased(me); |
201 | } | |
202 | ||
203 | 0 | endAttached(fe); |
204 | ||
205 | 0 | done(); |
206 | 0 | me.consume(); |
207 | 0 | return; |
208 | } | |
209 | } | |
210 | 0 | if (!nearLast(x, y)) { |
211 | 0 | editor.damageAll(); |
212 | 0 | Point snapPt = new Point(x, y); |
213 | 0 | editor.snap(snapPt); |
214 | 0 | ((FigPoly) _newItem).addPoint(snapPt.x, snapPt.y); |
215 | 0 | _npoints++; |
216 | 0 | editor.damageAll(); |
217 | } | |
218 | 0 | _lastX = x; |
219 | 0 | _lastY = y; |
220 | 0 | me.consume(); |
221 | 0 | } |
222 | ||
223 | /** | |
224 | * Return the meta type of the element that this mode is designed to | |
225 | * create. | |
226 | * @return the meta type of the connection required. | |
227 | */ | |
228 | protected abstract Object getMetaType(); | |
229 | ||
230 | /** | |
231 | * Called after the edge has been drawn from a source and dropped to a | |
232 | * destination. Return true if this drop is valid. | |
233 | * The default is true, subclasses should override this with their own | |
234 | * logic. | |
235 | * @param source the source fig | |
236 | * @param dest the dest fig | |
237 | * @return true if drop on an edge is valid. | |
238 | */ | |
239 | protected boolean isConnectionValid(Fig source, Fig dest) { | |
240 | 0 | return Model.getUmlFactory().isConnectionValid( |
241 | getMetaType(), | |
242 | source == null ? null : source.getOwner(), | |
243 | dest == null ? null : dest.getOwner(), | |
244 | true); | |
245 | } | |
246 | ||
247 | /** | |
248 | * Create an edge of the given type and connect it to the | |
249 | * given nodes. | |
250 | * | |
251 | * @param graphModel the GraphModel containing the objects | |
252 | * @param edgeType the UML object type of the connection | |
253 | * @param fromElement the Fig for the "from" element | |
254 | * @param destFigNode the Fig for the "to" element | |
255 | * @return a newly created FigEdge | |
256 | */ | |
257 | protected FigEdge buildConnection( | |
258 | MutableGraphModel graphModel, | |
259 | Object edgeType, | |
260 | Fig fromElement, | |
261 | Fig destFigNode) { | |
262 | 0 | Object modelElement = graphModel.connect( |
263 | fromElement.getOwner(), | |
264 | destFigNode.getOwner(), | |
265 | edgeType); | |
266 | ||
267 | 0 | setNewEdge(modelElement); |
268 | ||
269 | // Calling connect() will add the edge to the GraphModel and | |
270 | // any LayerPersectives on that GraphModel will get a | |
271 | // edgeAdded event and will add an appropriate FigEdge | |
272 | // (determined by the GraphEdgeRenderer). | |
273 | ||
274 | 0 | if (getNewEdge() != null) { |
275 | 0 | getSourceFigNode().damage(); |
276 | 0 | destFigNode.damage(); |
277 | 0 | Layer lay = editor.getLayerManager().getActiveLayer(); |
278 | 0 | FigEdge fe = (FigEdge) lay.presentationFor(getNewEdge()); |
279 | 0 | _newItem.setLineColor(Color.black); |
280 | 0 | fe.setFig(_newItem); |
281 | 0 | fe.setSourcePortFig(getStartPortFig()); |
282 | 0 | fe.setSourceFigNode(getSourceFigNode()); |
283 | 0 | fe.setDestPortFig(destFigNode); |
284 | 0 | fe.setDestFigNode((FigNode) destFigNode); |
285 | 0 | return fe; |
286 | ||
287 | } else { | |
288 | 0 | return null; |
289 | } | |
290 | ||
291 | } | |
292 | } |