Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
ModeCreateAssociationEnd |
|
| 5.0;5 |
1 | /* $Id: ModeCreateAssociationEnd.java 18775 2010-09-23 16:39:06Z bobtarling $ | |
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 | * bobtarling | |
11 | ***************************************************************************** | |
12 | * | |
13 | * Some portions of this file was previously release using the BSD License: | |
14 | */ | |
15 | ||
16 | // Copyright (c) 2005-2007 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.util.Collection; | |
43 | import java.util.List; | |
44 | ||
45 | import org.argouml.model.IllegalModelElementConnectionException; | |
46 | import org.argouml.model.Model; | |
47 | import org.argouml.uml.diagram.static_structure.ui.FigClass; | |
48 | import org.argouml.uml.diagram.static_structure.ui.FigClassifierBox; | |
49 | import org.tigris.gef.base.Layer; | |
50 | import org.tigris.gef.base.LayerPerspective; | |
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 | ||
56 | /** | |
57 | * A Mode to interpret user input while creating an association end. | |
58 | * The association end can connect an existing association to an existing | |
59 | * classifier. | |
60 | * If the association is an n-ary association (diamond shape node) then | |
61 | * the edge is simply added. | |
62 | * If the association is a binary association edge then that edge is | |
63 | * transformed into a n-ary association. | |
64 | * | |
65 | * @author Bob Tarling | |
66 | */ | |
67 | 0 | public class ModeCreateAssociationEnd extends ModeCreateGraphEdge { |
68 | ||
69 | /** | |
70 | * The UID. | |
71 | */ | |
72 | private static final long serialVersionUID = -7249069222789301797L; | |
73 | ||
74 | public Object getMetaType() { | |
75 | 0 | return Model.getMetaTypes().getAssociationEnd(); |
76 | } | |
77 | ||
78 | /** | |
79 | * Create an edge of the given type and connect it to the | |
80 | * given nodes. | |
81 | * | |
82 | * @param graphModel the graph model in which to create the connection | |
83 | * element | |
84 | * @param edgeType the UML object type of the connection | |
85 | * @param sourceFig the FigNode for the source element | |
86 | * @param destFig the FigNode for the destination element | |
87 | * @return The FigEdge representing the newly created model element | |
88 | */ | |
89 | @Override | |
90 | protected FigEdge buildConnection( | |
91 | MutableGraphModel graphModel, | |
92 | Object edgeType, | |
93 | Fig sourceFig, | |
94 | Fig destFig) { | |
95 | try { | |
96 | // The source of an association end should not | |
97 | // be the classifier. If it is the user has drawn the wrong way | |
98 | // round so we swap here. | |
99 | 0 | if (sourceFig instanceof FigClassifierBox) { |
100 | 0 | final Fig tempFig = sourceFig; |
101 | 0 | sourceFig = destFig; |
102 | 0 | destFig = tempFig; |
103 | } | |
104 | ||
105 | 0 | Object associationEnd = |
106 | Model.getUmlFactory().buildConnection( | |
107 | edgeType, | |
108 | sourceFig.getOwner(), | |
109 | null, | |
110 | destFig.getOwner(), | |
111 | null, | |
112 | null, | |
113 | null); | |
114 | ||
115 | 0 | final FigNode sourceFigNode = convertToFigNode(sourceFig); |
116 | 0 | final FigNode destFigNode = convertToFigNode(destFig); |
117 | ||
118 | 0 | graphModel.addEdge(associationEnd); |
119 | ||
120 | 0 | setNewEdge(associationEnd); |
121 | ||
122 | // Calling connect() will add the edge to the GraphModel and | |
123 | // any LayerPersectives on that GraphModel will get a | |
124 | // edgeAdded event and will add an appropriate FigEdge | |
125 | // (determined by the GraphEdgeRenderer). | |
126 | ||
127 | 0 | if (getNewEdge() != null) { |
128 | 0 | sourceFigNode.damage(); |
129 | 0 | destFigNode.damage(); |
130 | 0 | Layer lay = editor.getLayerManager().getActiveLayer(); |
131 | 0 | FigEdge fe = (FigEdge) lay.presentationFor(getNewEdge()); |
132 | 0 | _newItem.setLineColor(Color.black); |
133 | 0 | fe.setFig(_newItem); |
134 | 0 | fe.setSourcePortFig(sourceFigNode); |
135 | 0 | fe.setSourceFigNode(sourceFigNode); |
136 | 0 | fe.setDestPortFig(destFigNode); |
137 | 0 | fe.setDestFigNode(destFigNode); |
138 | ||
139 | 0 | fe.computeRoute(); |
140 | ||
141 | 0 | return fe; |
142 | } else { | |
143 | 0 | return null; |
144 | } | |
145 | 0 | } catch (IllegalModelElementConnectionException e) { |
146 | // We have already confirmed the connection is valid | |
147 | 0 | return null; |
148 | } | |
149 | } | |
150 | ||
151 | /** | |
152 | * If the selected Fig is a FigAssociation (an edge) then | |
153 | * convert it to a FigNodeAssociation. | |
154 | * @param fig the select end Fig | |
155 | * @return the fig converted to a FigNode | |
156 | */ | |
157 | private FigNode convertToFigNode(Fig fig) { | |
158 | 0 | if (fig instanceof FigEdgePort) { |
159 | 0 | fig = fig.getGroup(); |
160 | } | |
161 | 0 | if (!(fig instanceof FigAssociation)) { |
162 | 0 | return (FigNode) fig; |
163 | } | |
164 | 0 | final FigAssociation figAssociation = (FigAssociation) fig; |
165 | 0 | final int x = figAssociation.getEdgePort().getX(); |
166 | 0 | final int y = figAssociation.getEdgePort().getY(); |
167 | 0 | final Object association = fig.getOwner(); |
168 | 0 | final FigNode originalEdgePort = figAssociation.getEdgePort(); |
169 | ||
170 | 0 | FigClassAssociationClass associationClassBox = null; |
171 | 0 | FigEdgeAssociationClass associationClassLink = null; |
172 | ||
173 | 0 | final LayerPerspective lay = |
174 | (LayerPerspective) editor.getLayerManager().getActiveLayer(); | |
175 | ||
176 | // Detach any edges (such as comment edges) already attached | |
177 | // to the FigAssociation before the FigAssociation is removed. | |
178 | // They'll later be re-attached to the new FigNodeAssociation | |
179 | 0 | final Collection<FigEdge> existingEdges = originalEdgePort.getFigEdges(); |
180 | 0 | for (FigEdge edge : existingEdges) { |
181 | 0 | if (edge instanceof FigEdgeAssociationClass) { |
182 | // If there are bits of an association class then | |
183 | // remember their location and path. | |
184 | 0 | associationClassLink = (FigEdgeAssociationClass) edge; |
185 | 0 | FigNode figNode = edge.getSourceFigNode(); |
186 | 0 | if (figNode instanceof FigEdgePort) { |
187 | 0 | figNode = edge.getDestFigNode(); |
188 | } | |
189 | 0 | associationClassBox = (FigClassAssociationClass) figNode; |
190 | 0 | originalEdgePort.removeFigEdge(edge); |
191 | 0 | lay.remove(edge); |
192 | 0 | lay.remove(associationClassBox); |
193 | 0 | } else { |
194 | 0 | originalEdgePort.removeFigEdge(edge); |
195 | } | |
196 | } | |
197 | ||
198 | 0 | List associationFigs = lay.presentationsFor(association); |
199 | ||
200 | 0 | figAssociation.removeFromDiagram(); |
201 | 0 | associationFigs = lay.presentationsFor(association); |
202 | ||
203 | // Create the new FigNodeAssociation and locate it. | |
204 | 0 | final MutableGraphModel gm = |
205 | (MutableGraphModel) editor.getGraphModel(); | |
206 | 0 | gm.addNode(association); |
207 | 0 | associationFigs = lay.presentationsFor(association); |
208 | 0 | associationFigs.remove(figAssociation); |
209 | 0 | associationFigs = lay.presentationsFor(association); |
210 | ||
211 | 0 | final FigNodeAssociation figNode = |
212 | (FigNodeAssociation) associationFigs.get(0); | |
213 | ||
214 | 0 | figNode.setLocation( |
215 | x - figNode.getWidth() / 2, | |
216 | y - figNode.getHeight() / 2); | |
217 | 0 | editor.add(figNode); |
218 | 0 | editor.getSelectionManager().deselectAll(); |
219 | ||
220 | // Add the association ends to the graph model | |
221 | 0 | final Collection<Object> associationEnds = |
222 | Model.getFacade().getConnections(association); | |
223 | ||
224 | 0 | for (Object associationEnd : associationEnds) { |
225 | 0 | gm.addEdge(associationEnd); |
226 | } | |
227 | ||
228 | // Add the edges (such as comment edges) that were on the old | |
229 | // FigAssociation to our new FigNodeAssociation and make sure they are | |
230 | // positioned correctly. | |
231 | 0 | for (FigEdge edge : existingEdges) { |
232 | 0 | if (edge.getDestFigNode() == originalEdgePort) { |
233 | 0 | edge.setDestFigNode(figNode); |
234 | 0 | edge.setDestPortFig(figNode); |
235 | } | |
236 | 0 | if (edge.getSourceFigNode() == originalEdgePort) { |
237 | 0 | edge.setSourceFigNode(figNode); |
238 | 0 | edge.setSourcePortFig(figNode); |
239 | } | |
240 | } | |
241 | 0 | figNode.updateEdges(); |
242 | ||
243 | 0 | if (associationClassBox != null) { |
244 | 0 | associationFigs = lay.presentationsFor(association); |
245 | ||
246 | 0 | lay.add(associationClassBox); |
247 | 0 | associationClassLink.setSourceFigNode(figNode); |
248 | 0 | lay.add(associationClassLink); |
249 | ||
250 | 0 | associationFigs = lay.presentationsFor(association); |
251 | } | |
252 | ||
253 | 0 | return figNode; |
254 | } | |
255 | ||
256 | /* | |
257 | * If we're drawing to an edge then only allow if the start is a comment | |
258 | * @see org.argouml.uml.diagram.ui.ModeCreateGraphEdge#isConnectionValid(org.tigris.gef.presentation.Fig, org.tigris.gef.presentation.Fig) | |
259 | */ | |
260 | @Override | |
261 | protected final boolean isConnectionValid(Fig source, Fig dest) { | |
262 | 0 | return super.isConnectionValid(source, dest); |
263 | } | |
264 | ||
265 | ||
266 | } /* end class ModeCreateAssociation */ |