Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
ActionAddNote |
|
| 8.0;8 |
1 | /* $Id: ActionAddNote.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 | * bobtarling | |
11 | ***************************************************************************** | |
12 | * | |
13 | * Some portions of this file was previously release using the BSD License: | |
14 | */ | |
15 | ||
16 | // Copyright (c) 1996-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.Point; | |
42 | import java.awt.Rectangle; | |
43 | import java.awt.event.ActionEvent; | |
44 | import java.util.Collection; | |
45 | import java.util.Iterator; | |
46 | ||
47 | import javax.swing.Action; | |
48 | ||
49 | import org.argouml.application.helpers.ResourceLoaderWrapper; | |
50 | import org.argouml.i18n.Translator; | |
51 | import org.argouml.kernel.UmlModelMutator; | |
52 | import org.argouml.model.Model; | |
53 | import org.argouml.ui.ProjectBrowser; | |
54 | import org.argouml.ui.targetmanager.TargetManager; | |
55 | import org.argouml.uml.CommentEdge; | |
56 | import org.argouml.uml.diagram.ArgoDiagram; | |
57 | import org.argouml.uml.diagram.DiagramUtils; | |
58 | import org.tigris.gef.graph.MutableGraphModel; | |
59 | import org.tigris.gef.presentation.Fig; | |
60 | import org.tigris.gef.presentation.FigEdge; | |
61 | import org.tigris.gef.presentation.FigNode; | |
62 | import org.tigris.gef.presentation.FigPoly; | |
63 | import org.argouml.ui.UndoableAction; | |
64 | ||
65 | /** | |
66 | * Action to add a note aka comment. This action adds a Comment to 0..* | |
67 | * modelelements. <p> | |
68 | * | |
69 | * The modelelements that are present on the current diagram, are connected | |
70 | * graphically. All others are only annotated in the model. | |
71 | */ | |
72 | @UmlModelMutator | |
73 | public class ActionAddNote extends UndoableAction { | |
74 | ||
75 | /** | |
76 | * The default position (x and y) of the new fig. | |
77 | */ | |
78 | private static final int DEFAULT_POS = 20; | |
79 | ||
80 | /** | |
81 | * The distance (x and y) from other figs where we place this. | |
82 | */ | |
83 | private static final int DISTANCE = 80; | |
84 | ||
85 | /** | |
86 | * The constructor. This action is not global, since it is never disabled. | |
87 | */ | |
88 | public ActionAddNote() { | |
89 | 900 | super(Translator.localize("action.new-comment"), |
90 | ResourceLoaderWrapper.lookupIcon("action.new-comment")); | |
91 | // Set the tooltip string: | |
92 | 900 | putValue(Action.SHORT_DESCRIPTION, |
93 | Translator.localize("action.new-comment")); | |
94 | 900 | putValue(Action.SMALL_ICON, ResourceLoaderWrapper |
95 | .lookupIconResource("New Note")); | |
96 | 900 | } |
97 | ||
98 | ||
99 | /* | |
100 | * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) | |
101 | */ | |
102 | @Override | |
103 | public void actionPerformed(ActionEvent ae) { | |
104 | 0 | super.actionPerformed(ae); //update all tools' enabled status |
105 | 0 | Collection targets = TargetManager.getInstance().getModelTargets(); |
106 | ||
107 | //Let's build the comment first, unlinked. | |
108 | 0 | ArgoDiagram diagram = DiagramUtils.getActiveDiagram(); |
109 | 0 | Object comment = |
110 | Model.getCoreFactory().buildComment(null, | |
111 | diagram.getNamespace()); | |
112 | 0 | MutableGraphModel mgm = (MutableGraphModel) diagram.getGraphModel(); |
113 | ||
114 | //Now, we link it to the modelelements which are represented by FigNode | |
115 | 0 | Object firstTarget = null; |
116 | 0 | Iterator i = targets.iterator(); |
117 | 0 | while (i.hasNext()) { |
118 | 0 | Object obj = i.next(); |
119 | 0 | Fig destFig = diagram.presentationFor(obj); |
120 | 0 | if (destFig instanceof FigEdgeModelElement) { |
121 | 0 | FigEdgeModelElement destEdge = (FigEdgeModelElement) destFig; |
122 | 0 | destEdge.makeEdgePort(); |
123 | 0 | destFig = destEdge.getEdgePort(); |
124 | 0 | destEdge.calcBounds(); |
125 | } | |
126 | 0 | if (Model.getFacade().isAModelElement(obj) |
127 | && (!(Model.getFacade().isAComment(obj)))) { | |
128 | 0 | if (firstTarget == null) { |
129 | 0 | firstTarget = obj; |
130 | } | |
131 | /* Prevent e.g. AssociationClasses from being added trice: */ | |
132 | 0 | if (!Model.getFacade().getAnnotatedElements(comment) |
133 | .contains(obj)) { | |
134 | 0 | Model.getCoreHelper().addAnnotatedElement(comment, obj); |
135 | } | |
136 | } | |
137 | 0 | } |
138 | ||
139 | //Create the Node Fig for the comment itself and draw it | |
140 | 0 | mgm.addNode(comment); |
141 | // remember the fig for later | |
142 | 0 | Fig noteFig = diagram.presentationFor(comment); |
143 | ||
144 | //Create the comment links and draw them | |
145 | 0 | i = Model.getFacade().getAnnotatedElements(comment).iterator(); |
146 | 0 | while (i.hasNext()) { |
147 | 0 | Object obj = i.next(); |
148 | 0 | if (diagram.presentationFor(obj) != null) { |
149 | 0 | CommentEdge commentEdge = new CommentEdge(comment, obj); |
150 | 0 | mgm.addEdge(commentEdge); |
151 | 0 | FigEdge fe = (FigEdge) diagram.presentationFor(commentEdge); |
152 | 0 | FigPoly fp = (FigPoly) fe.getFig(); |
153 | 0 | fp.setComplete(true); |
154 | } | |
155 | 0 | } |
156 | ||
157 | //Place the comment Fig on the nicest spot on the diagram | |
158 | 0 | noteFig.setLocation(calculateLocation(diagram, firstTarget, noteFig)); |
159 | ||
160 | //Select the new comment as target | |
161 | 0 | TargetManager.getInstance().setTarget(noteFig.getOwner()); |
162 | 0 | } |
163 | ||
164 | /** | |
165 | * Calculate the position of the comment, based on the 1st target only. | |
166 | * | |
167 | * @param diagram The Diagram that we are working in. | |
168 | * @param firstTarget The object element of the first found comment. | |
169 | * @param noteFig The Fig for the comment. | |
170 | * @return The position where it should be placed. | |
171 | */ | |
172 | private Point calculateLocation( | |
173 | ArgoDiagram diagram, Object firstTarget, Fig noteFig) { | |
174 | 0 | Point point = new Point(DEFAULT_POS, DEFAULT_POS); |
175 | ||
176 | 0 | if (firstTarget == null) { |
177 | 0 | return point; |
178 | } | |
179 | ||
180 | 0 | Fig elemFig = diagram.presentationFor(firstTarget); |
181 | 0 | if (elemFig == null) { |
182 | 0 | return point; |
183 | } | |
184 | ||
185 | 0 | if (elemFig instanceof FigEdgeModelElement) { |
186 | 0 | elemFig = ((FigEdgeModelElement) elemFig).getEdgePort(); |
187 | } | |
188 | ||
189 | 0 | if (elemFig instanceof FigNode) { |
190 | // TODO: We need a better algorithm. | |
191 | 0 | point.x = elemFig.getX() + elemFig.getWidth() + DISTANCE; |
192 | 0 | point.y = elemFig.getY(); |
193 | // TODO: This can't depend on ProjectBrowser. Alternate below | |
194 | 0 | Rectangle drawingArea = |
195 | ProjectBrowser.getInstance().getEditorPane().getBounds(); | |
196 | // Perhaps something like the following would work instead | |
197 | // Rectangle drawingArea = | |
198 | // Globals.curEditor().getJComponent().getVisibleRect(); | |
199 | ||
200 | 0 | if (point.x + noteFig.getWidth() > drawingArea.getX()) { |
201 | 0 | point.x = elemFig.getX() - noteFig.getWidth() - DISTANCE; |
202 | ||
203 | 0 | if (point.x >= 0) { |
204 | 0 | return point; |
205 | } | |
206 | ||
207 | 0 | point.x = elemFig.getX(); |
208 | 0 | point.y = elemFig.getY() - noteFig.getHeight() - DISTANCE; |
209 | 0 | if (point.y >= 0) { |
210 | 0 | return point; |
211 | } | |
212 | ||
213 | 0 | point.y = elemFig.getY() + elemFig.getHeight() + DISTANCE; |
214 | 0 | if (point.y + noteFig.getHeight() > drawingArea.getHeight()) { |
215 | 0 | return new Point(0, 0); |
216 | } | |
217 | } | |
218 | } | |
219 | ||
220 | 0 | return point; |
221 | } | |
222 | ||
223 | /** | |
224 | * The UID. | |
225 | */ | |
226 | private static final long serialVersionUID = 6502515091619480472L; | |
227 | } |