Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
FigCompartmentBox |
|
| 3.0344827586206895;3.034 | ||||
FigCompartmentBox$1 |
|
| 3.0344827586206895;3.034 |
1 | /* $Id: FigCompartmentBox.java 17926 2010-01-28 10:36:20Z bobtarling $ | |
2 | ******************************************************************************* | |
3 | * Copyright (c) 2009-2010 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 | * Bob Tarling | |
11 | ******************************************************************************* | |
12 | * | |
13 | * Some portions of this file was previously release using the BSD License: | |
14 | */ | |
15 | ||
16 | // $Id: FigCompartmentBox.java 17926 2010-01-28 10:36:20Z bobtarling $ | |
17 | // Copyright (c) 1996-2009 The Regents of the University of California. All | |
18 | // Rights Reserved. Permission to use, copy, modify, and distribute this | |
19 | // software and its documentation without fee, and without a written | |
20 | // agreement is hereby granted, provided that the above copyright notice | |
21 | // and this paragraph appear in all copies. This software program and | |
22 | // documentation are copyrighted by The Regents of the University of | |
23 | // California. The software program and documentation are supplied "AS | |
24 | // IS", without any accompanying services from The Regents. The Regents | |
25 | // does not warrant that the operation of the program will be | |
26 | // uninterrupted or error-free. The end-user understands that the program | |
27 | // was developed for research purposes and is advised not to rely | |
28 | // exclusively on the program for any reason. IN NO EVENT SHALL THE | |
29 | // UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, | |
30 | // SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, | |
31 | // ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF | |
32 | // THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF | |
33 | // SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY | |
34 | // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
35 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE | |
36 | // PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF | |
37 | // CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, | |
38 | // UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | |
39 | ||
40 | package org.argouml.uml.diagram.ui; | |
41 | ||
42 | import java.awt.Color; | |
43 | import java.awt.Dimension; | |
44 | import java.awt.Rectangle; | |
45 | import java.awt.event.InputEvent; | |
46 | import java.awt.event.MouseEvent; | |
47 | import java.beans.PropertyChangeEvent; | |
48 | import java.util.ArrayList; | |
49 | import java.util.List; | |
50 | ||
51 | import javax.swing.SwingUtilities; | |
52 | ||
53 | import org.apache.log4j.Logger; | |
54 | import org.argouml.model.AssociationChangeEvent; | |
55 | import org.argouml.model.AttributeChangeEvent; | |
56 | import org.argouml.model.InvalidElementException; | |
57 | import org.argouml.ui.targetmanager.TargetManager; | |
58 | import org.argouml.uml.diagram.DiagramSettings; | |
59 | import org.tigris.gef.base.Editor; | |
60 | import org.tigris.gef.base.Globals; | |
61 | import org.tigris.gef.base.Selection; | |
62 | import org.tigris.gef.base.SelectionButtons; | |
63 | import org.tigris.gef.presentation.Fig; | |
64 | import org.tigris.gef.presentation.FigGroup; | |
65 | import org.tigris.gef.presentation.FigRect; | |
66 | ||
67 | /** | |
68 | * Class to display graphics for a node with compartments in a diagram. | |
69 | * <p> | |
70 | * | |
71 | * The leaf descendants of this class shall add the compartments in top to | |
72 | * bottom order. | |
73 | * <p> | |
74 | * | |
75 | * It deals with highlighting editable compartments. | |
76 | * <p> | |
77 | * | |
78 | * All descendants of this class have the bigPort filled with the main fig fill | |
79 | * color, with line border. | |
80 | * <p> | |
81 | * | |
82 | * The name, keyword and stereotype are shown in transparent figs without | |
83 | * border, but their size is reduced so that they fit within the border of the | |
84 | * borderFig. | |
85 | */ | |
86 | 0 | public abstract class FigCompartmentBox extends FigNodeModelElement { |
87 | ||
88 | 0 | private static final Logger LOG = Logger.getLogger( |
89 | FigCompartmentBox.class); | |
90 | ||
91 | /** | |
92 | * Default bounds for a compartment. | |
93 | */ | |
94 | 0 | protected static final Rectangle DEFAULT_COMPARTMENT_BOUNDS |
95 | = new Rectangle( | |
96 | X0, Y0 + 20 /* 20 = height of name fig ?*/, | |
97 | WIDTH, ROWHEIGHT + 2 /* 2*LINE_WIDTH? or extra padding? */ ); | |
98 | ||
99 | /** | |
100 | * Text highlighted by mouse actions on the diagram.<p> | |
101 | */ | |
102 | 0 | private static CompartmentFigText highlightedFigText = null; |
103 | ||
104 | 0 | private List<FigCompartment> compartments = |
105 | new ArrayList<FigCompartment>(); | |
106 | ||
107 | /** | |
108 | * Buffer the calculated dimensions of the compartments for later use. | |
109 | */ | |
110 | protected Dimension containerBox; | |
111 | ||
112 | /** | |
113 | * Initialization shared by all constructors. | |
114 | */ | |
115 | private void initialize() { | |
116 | // Set properties of the stereotype box. | |
117 | 0 | getStereotypeFig().setHeight(STEREOHEIGHT + LINE_WIDTH); |
118 | ||
119 | /* | |
120 | * The nameFig is transparent, since this is a box and the fill color is | |
121 | * drawn by the bigPort. | |
122 | */ | |
123 | 0 | getNameFig().setFillColor(null); |
124 | 0 | } |
125 | ||
126 | /** | |
127 | * Overrule this if a rectangle is not usable. | |
128 | * | |
129 | * @return the Fig to be used as bigPort | |
130 | */ | |
131 | protected Fig createBigPortFig() { | |
132 | 0 | Fig b = new FigRect(X0, Y0, 0, 0, LINE_COLOR, FILL_COLOR); |
133 | 0 | return b; |
134 | } | |
135 | ||
136 | /** | |
137 | * Construct a Fig with owner, bounds, and settings. | |
138 | * | |
139 | * @param owner the model element that owns this fig | |
140 | * @param bounds the rectangle defining the bounds | |
141 | * @param settings the rendering settings | |
142 | */ | |
143 | public FigCompartmentBox(Object owner, Rectangle bounds, | |
144 | DiagramSettings settings) { | |
145 | 0 | super(owner, bounds, settings); |
146 | 0 | initialize(); |
147 | 0 | } |
148 | ||
149 | /** | |
150 | * Get the compartment that lists model elements of the given type. | |
151 | * This can also be used to test if a Fig supports a particular type | |
152 | * of compartment by checking for a null return. | |
153 | * @param metaType the model element type for which the compartment is | |
154 | * required. | |
155 | * @return a compartment fig or null if the compartment is not contained. | |
156 | */ | |
157 | public FigCompartment getCompartment(Object metaType) { | |
158 | 0 | for (FigCompartment f : compartments) { |
159 | 0 | if (f.getCompartmentType() == metaType) { |
160 | 0 | return f; |
161 | } | |
162 | } | |
163 | 0 | return null; |
164 | } | |
165 | ||
166 | /** | |
167 | * Return true of a compartment exists and is visible | |
168 | * @param metaType the model element type for which the compartment is | |
169 | * required. | |
170 | * @return true if the compartment exists and is visible | |
171 | */ | |
172 | public boolean isCompartmentVisible(Object metaType) { | |
173 | 0 | FigCompartment f = getCompartment(metaType); |
174 | 0 | if (f == null) { |
175 | 0 | return false; |
176 | } | |
177 | 0 | return f.isVisible(); |
178 | } | |
179 | ||
180 | protected List<FigCompartment> getCompartments() { | |
181 | 0 | return compartments; |
182 | } | |
183 | ||
184 | @Override | |
185 | public void addFig(Fig fig) { | |
186 | 0 | if (fig instanceof FigCompartment) { |
187 | 0 | addCompartment((FigCompartment) fig); |
188 | } | |
189 | 0 | super.addFig(fig); |
190 | 0 | } |
191 | ||
192 | private void addCompartment(FigCompartment c) { | |
193 | 0 | assert !compartments.contains(c); |
194 | 0 | addFig(c.getSeparatorFig()); |
195 | 0 | compartments.add(c); |
196 | 0 | } |
197 | ||
198 | protected int getVisibleCompartmentCount() { | |
199 | 0 | int result = 0; |
200 | 0 | for (int i = 0; i < compartments.size(); i++) { |
201 | 0 | result += compartments.get(i).isVisible() ? 1 : 0; |
202 | } | |
203 | 0 | return result; |
204 | } | |
205 | ||
206 | @Override | |
207 | public Dimension getMinimumSize() { | |
208 | // Use "aSize" to build up the minimum size. Start with the size of the | |
209 | // name compartment and build up. | |
210 | 0 | Dimension aSize = getNameFig().getMinimumSize(); |
211 | ||
212 | /* | |
213 | * Only take into account the stereotype width, not the height, since | |
214 | * the height is included in the name fig: | |
215 | */ | |
216 | 0 | aSize = ArgoFigUtil.addChildWidth(aSize, getStereotypeFig()); |
217 | ||
218 | /* Add the height of all the compartments (if there are any), | |
219 | * and check their minimum width: */ | |
220 | 0 | for (FigCompartment c : compartments) { |
221 | 0 | aSize = ArgoFigUtil.addChildDimensions(aSize, c); |
222 | } | |
223 | ||
224 | /* We want to maintain a minimum width for the fig. Also, add the border | |
225 | * dimensions to the minimum space required for its contents: | |
226 | */ | |
227 | 0 | aSize.width = Math.max(WIDTH, aSize.width); |
228 | ||
229 | 0 | aSize = addCompartmentBoxSurroundings(aSize); |
230 | ||
231 | 0 | return aSize; |
232 | } | |
233 | ||
234 | /** | |
235 | * Increase the size of the given box with the area around the | |
236 | * compartments. | |
237 | * | |
238 | * @param box the minimum box size needed for the compartments | |
239 | * @return the dimensions of the complete fig | |
240 | */ | |
241 | protected Dimension addCompartmentBoxSurroundings(Dimension box) { | |
242 | 0 | containerBox = new Dimension(box); |
243 | 0 | box.width += 2 * getLineWidth(); |
244 | 0 | box.height += 2 * getLineWidth(); |
245 | 0 | return box; |
246 | } | |
247 | ||
248 | /** | |
249 | * Given the outside dimensions and location of the Fig, calculate | |
250 | * the position and size of the box for the compartments. | |
251 | * The compartments are located inside the complete fig. For a | |
252 | * rectangle (i.e. the default implementation), only the line-width | |
253 | * of the outside box needs to be added. | |
254 | * Other Figs may have other shapes, e.g. a Use Case has the | |
255 | * box located inside an ellipse. So, they need to overrule this method. | |
256 | * | |
257 | * @param x outside top left | |
258 | * @param y outside top left | |
259 | * @param w outside dimension, including line-width | |
260 | * @param h outside dimension, including line-width | |
261 | * @return the location and area to be used by the compartments | |
262 | */ | |
263 | protected Rectangle calculateCompartmentBoxDimensions( | |
264 | final int x, final int y, final int w, final int h) { | |
265 | 0 | return new Rectangle( |
266 | x + getLineWidth(), | |
267 | y + getLineWidth(), | |
268 | w - 2 * getLineWidth(), | |
269 | h - 2 * getLineWidth()); | |
270 | } | |
271 | ||
272 | /** | |
273 | * Sets the bounds, but the size will be at least the one returned by | |
274 | * {@link #getMinimumSize()}, unless checking of size is disabled. | |
275 | * <p> | |
276 | * | |
277 | * If the required height is bigger, then the additional height is equally | |
278 | * distributed among all compartments, such that the accumulated height of | |
279 | * all visible figs equals the demanded height. | |
280 | * | |
281 | * @param x Desired X coordinate of upper left corner | |
282 | * | |
283 | * @param y Desired Y coordinate of upper left corner | |
284 | * | |
285 | * @param width Desired width of the Fig | |
286 | * | |
287 | * @param height Desired height of the Fig | |
288 | * | |
289 | * @see org.tigris.gef.presentation.Fig#setBoundsImpl(int, int, int, int) | |
290 | */ | |
291 | @Override | |
292 | protected void setStandardBounds(final int x, final int y, final int w, | |
293 | final int h) { | |
294 | ||
295 | // Save our old boundaries so it can be used in property message later | |
296 | 0 | Rectangle oldBounds = getBounds(); |
297 | ||
298 | // Make sure we don't try to set things smaller than the minimum | |
299 | 0 | Dimension minimumSize = getMinimumSize(); |
300 | 0 | int newW = Math.max(w, minimumSize.width); |
301 | 0 | int newH = Math.max(h, minimumSize.height); |
302 | ||
303 | /* The box for the compartments is somewhere | |
304 | * inside the outside bounds: */ | |
305 | 0 | Rectangle box = calculateCompartmentBoxDimensions( |
306 | x, y, newW, newH); | |
307 | ||
308 | 0 | int currentHeight = 0; |
309 | ||
310 | 0 | if (getStereotypeFig().isVisible()) { |
311 | 0 | int stereotypeHeight = getStereotypeFig().getMinimumSize().height; |
312 | 0 | getNameFig().setTopMargin(stereotypeHeight); |
313 | 0 | getStereotypeFig().setBounds( |
314 | box.x, | |
315 | box.y, | |
316 | box.width, | |
317 | stereotypeHeight); | |
318 | 0 | } else { |
319 | 0 | getNameFig().setTopMargin(0); |
320 | } | |
321 | ||
322 | /* Now the new nameFig height will include the stereotype height: */ | |
323 | 0 | Dimension nameMin = getNameFig().getMinimumSize(); |
324 | 0 | int minNameHeight = Math.max(nameMin.height, NAME_FIG_HEIGHT); |
325 | ||
326 | 0 | getNameFig().setBounds(box.x, box.y, |
327 | box.width, minNameHeight); | |
328 | ||
329 | /* The new height can not be less than the name height: */ | |
330 | /* | |
331 | * TODO: Is this needed/correct? | |
332 | * For when all compartments are hidden? | |
333 | */ | |
334 | 0 | newH = Math.max(minNameHeight + 2 * getLineWidth(), newH); |
335 | ||
336 | 0 | currentHeight += minNameHeight; |
337 | ||
338 | 0 | int requestedHeight = box.height - currentHeight; |
339 | 0 | int neededHeight = 0; |
340 | /* Calculate the minimum needed height for all the compartments:*/ | |
341 | 0 | for (FigCompartment c : compartments) { |
342 | 0 | if (c.isVisible()) { |
343 | 0 | neededHeight += c.getMinimumSize().height; |
344 | } | |
345 | } | |
346 | ||
347 | 0 | for (FigCompartment c : compartments) { |
348 | 0 | if (c.isVisible()) { |
349 | 0 | int compartmentHeight = c.getMinimumSize().height; |
350 | 0 | if (requestedHeight > neededHeight) { |
351 | /* | |
352 | * Distribute the extra height over the visible | |
353 | * compartments: | |
354 | */ | |
355 | 0 | compartmentHeight += (requestedHeight - neededHeight) |
356 | / getVisibleCompartmentCount(); | |
357 | } | |
358 | 0 | setCompartmentBounds(c, |
359 | new Rectangle( | |
360 | box.x, | |
361 | box.y + currentHeight, | |
362 | box.width, | |
363 | compartmentHeight), | |
364 | new Rectangle(x, y, newW, newH)); | |
365 | 0 | currentHeight += compartmentHeight; |
366 | 0 | } |
367 | } | |
368 | 0 | if (requestedHeight < neededHeight) { |
369 | /* Increase the height of the fig: */ | |
370 | 0 | newH += neededHeight - requestedHeight; |
371 | } | |
372 | /* | |
373 | * If requested height equals needed height then do nothing; it fits | |
374 | * exactly. | |
375 | */ | |
376 | ||
377 | /* Finally set the bounds of the big box and the border fig: */ | |
378 | 0 | getBigPort().setBounds(x, y, newW, newH); |
379 | ||
380 | // Now force calculation of the bounds of the figure, update the edges | |
381 | // and trigger anyone who's listening to see if the "bounds" property | |
382 | // has changed. | |
383 | ||
384 | 0 | calcBounds(); |
385 | 0 | updateEdges(); |
386 | 0 | LOG.debug("Bounds change : old - " + oldBounds + ", new - " |
387 | + getBounds()); | |
388 | 0 | firePropChange("bounds", oldBounds, getBounds()); |
389 | 0 | } |
390 | ||
391 | /** | |
392 | * Set the bounds of the compartment. | |
393 | * | |
394 | * @param c the compartment | |
395 | * @param cb the new compartment bounds | |
396 | * @param ob the new outside fig bounds | |
397 | */ | |
398 | protected void setCompartmentBounds(FigCompartment c, | |
399 | Rectangle cb, Rectangle ob) { | |
400 | 0 | Rectangle r = new Rectangle(); |
401 | 0 | r.y = cb.y; |
402 | 0 | r.height = getLineWidth(); |
403 | 0 | r.width = ob.width; |
404 | 0 | r.x = ob.x; |
405 | 0 | c.setExternalSeparatorFigBounds(r); |
406 | 0 | c.setBounds(cb.x, cb.y + 1, cb.width, cb.height - 1); |
407 | 0 | } |
408 | ||
409 | /* | |
410 | * @see org.tigris.gef.presentation.Fig#translate(int, int) | |
411 | */ | |
412 | @Override | |
413 | public void translate(int dx, int dy) { | |
414 | 0 | super.translate(dx, dy); |
415 | 0 | Editor ce = Globals.curEditor(); |
416 | 0 | if (ce != null) { |
417 | 0 | Selection sel = ce.getSelectionManager().findSelectionFor(this); |
418 | 0 | if (sel instanceof SelectionButtons) { |
419 | 0 | ((SelectionButtons) sel).hideButtons(); |
420 | } | |
421 | } | |
422 | 0 | } |
423 | ||
424 | @Override | |
425 | protected void modelChanged(PropertyChangeEvent mee) { | |
426 | 0 | super.modelChanged(mee); |
427 | 0 | if (mee instanceof AssociationChangeEvent |
428 | || mee instanceof AttributeChangeEvent) { | |
429 | 0 | Runnable doWorkRunnable = new Runnable() { |
430 | public void run() { | |
431 | try { | |
432 | 0 | renderingChanged(); |
433 | 0 | updateListeners(getOwner(), getOwner()); |
434 | 0 | } catch (InvalidElementException e) { |
435 | 0 | if (LOG.isDebugEnabled()) { |
436 | 0 | LOG.debug("method accessed " |
437 | + "deleted element", e); | |
438 | } | |
439 | 0 | } |
440 | 0 | } |
441 | }; | |
442 | 0 | SwingUtilities.invokeLater(doWorkRunnable); |
443 | } | |
444 | 0 | } |
445 | ||
446 | /* | |
447 | * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent) | |
448 | */ | |
449 | @Override | |
450 | public void mouseClicked(MouseEvent mouseEvent) { | |
451 | ||
452 | 0 | if (mouseEvent.isConsumed()) { |
453 | 0 | return; |
454 | } | |
455 | 0 | super.mouseClicked(mouseEvent); |
456 | 0 | if (mouseEvent.isShiftDown() |
457 | && TargetManager.getInstance().getTargets().size() > 0) { | |
458 | 0 | return; |
459 | } | |
460 | ||
461 | 0 | Editor ce = Globals.curEditor(); |
462 | 0 | if (ce != null) { |
463 | 0 | Selection sel = ce.getSelectionManager().findSelectionFor(this); |
464 | 0 | if (sel instanceof SelectionButtons) { |
465 | 0 | ((SelectionButtons) sel).hideButtons(); |
466 | } | |
467 | } | |
468 | 0 | unhighlight(); |
469 | ||
470 | 0 | Rectangle r = |
471 | new Rectangle( | |
472 | mouseEvent.getX() - 1, | |
473 | mouseEvent.getY() - 1, | |
474 | 2, | |
475 | 2); | |
476 | ||
477 | 0 | Fig f = hitFig(r); |
478 | 0 | if (f instanceof FigCompartment) { |
479 | 0 | FigCompartment figCompartment = (FigCompartment) f; |
480 | 0 | f = figCompartment.hitFig(r); |
481 | 0 | if (f instanceof CompartmentFigText) { |
482 | 0 | if (highlightedFigText != null && highlightedFigText != f) { |
483 | 0 | highlightedFigText.setHighlighted(false); |
484 | 0 | if (highlightedFigText.getGroup() != null) { |
485 | /* Preventing NullPointerException. */ | |
486 | 0 | highlightedFigText.getGroup().damage(); |
487 | } | |
488 | } | |
489 | 0 | ((CompartmentFigText) f).setHighlighted(true); |
490 | 0 | highlightedFigText = (CompartmentFigText) f; |
491 | 0 | TargetManager.getInstance().setTarget(f); |
492 | } | |
493 | } | |
494 | 0 | } |
495 | ||
496 | /** | |
497 | * Remove the highlight from the currently highlit FigText. | |
498 | * | |
499 | * @return the FigText that had highlight removed | |
500 | */ | |
501 | protected CompartmentFigText unhighlight() { | |
502 | Fig fc; | |
503 | // Search all feature compartments for a text fig to unhighlight | |
504 | 0 | for (int i = 1; i < getFigs().size(); i++) { |
505 | 0 | fc = getFigAt(i); |
506 | 0 | if (fc instanceof FigCompartment) { |
507 | 0 | CompartmentFigText ft = |
508 | unhighlight((FigCompartment) fc); | |
509 | 0 | if (ft != null) { |
510 | 0 | return ft; |
511 | } | |
512 | } | |
513 | } | |
514 | 0 | return null; |
515 | } | |
516 | ||
517 | /** | |
518 | * Search the given compartment for a highlighted CompartmentFigText | |
519 | * and unhighlight it. | |
520 | * | |
521 | * @param fc compartment to search for highlight item | |
522 | * @return item that was unhighlighted or null if no action was taken | |
523 | */ | |
524 | protected final CompartmentFigText unhighlight( | |
525 | FigCompartment fc) { | |
526 | Fig ft; | |
527 | 0 | for (int i = 1; i < fc.getFigs().size(); i++) { |
528 | 0 | ft = fc.getFigAt(i); |
529 | 0 | if (ft instanceof CompartmentFigText |
530 | && ((CompartmentFigText) ft).isHighlighted()) { | |
531 | 0 | ((CompartmentFigText) ft).setHighlighted(false); |
532 | 0 | ft.getGroup().damage(); |
533 | 0 | return ((CompartmentFigText) ft); |
534 | } | |
535 | } | |
536 | 0 | return null; |
537 | } | |
538 | ||
539 | protected void createContainedModelElement(FigGroup fg, InputEvent ie) { | |
540 | 0 | if (!(fg instanceof FigCompartment)) { |
541 | 0 | return; |
542 | } | |
543 | 0 | ((FigCompartment) fg).createModelElement(); |
544 | /* Populate the compartment now, | |
545 | * so that we can put the last one in edit mode: | |
546 | * This fixes issue 5439. */ | |
547 | 0 | ((FigCompartment) fg).populate(); |
548 | // TODO: The above populate works but seems rather heavy here. | |
549 | // I can see something like this is needed though as events | |
550 | // won't manage this quick enough. Could we make | |
551 | // FigEditableCompartment.createModelElement() create | |
552 | // the new child Fig instance? It may also be useful | |
553 | // for it to return the new model element rather than | |
554 | // the current void return - Bob. | |
555 | 0 | List figList = fg.getFigs(); |
556 | 0 | if (figList.size() > 0) { |
557 | 0 | Fig fig = (Fig) figList.get(figList.size() - 1); |
558 | 0 | if (fig != null && fig instanceof CompartmentFigText) { |
559 | 0 | if (highlightedFigText != null) { |
560 | 0 | highlightedFigText.setHighlighted(false); |
561 | 0 | if (highlightedFigText.getGroup() != null) { |
562 | /* Preventing NullPointerException. */ | |
563 | 0 | highlightedFigText.getGroup().damage(); |
564 | } | |
565 | } | |
566 | 0 | CompartmentFigText ft = (CompartmentFigText) fig; |
567 | 0 | ft.startTextEditor(ie); |
568 | 0 | ft.setHighlighted(true); |
569 | 0 | highlightedFigText = ft; |
570 | } | |
571 | } | |
572 | 0 | ie.consume(); |
573 | 0 | } |
574 | ||
575 | /** | |
576 | * Show or hide a compartment based on the meta-type of its contents. | |
577 | * | |
578 | * @param metaType the compartment type to be shown | |
579 | * @param visible true if the compartment should be visible | |
580 | */ | |
581 | public void showCompartment(Object metaType, boolean visible) { | |
582 | 0 | FigCompartment fc = |
583 | getCompartment(metaType); | |
584 | 0 | if (fc == null) return; |
585 | 0 | assert fc != null; |
586 | 0 | setCompartmentVisible(fc, visible); |
587 | 0 | } |
588 | ||
589 | /** | |
590 | * TODO: This functionality is in the worn place. We should be able to | |
591 | * call setVisible on the compartment itself and then this class should | |
592 | * react to that event. | |
593 | * Improvements will follow in later releases. | |
594 | * Hence this method should not be considered stable for module developers. | |
595 | * @param compartment the compartment to be changed | |
596 | * @param isVisible true if the attribute compartment is visible | |
597 | */ | |
598 | public void setCompartmentVisible(FigCompartment compartment, | |
599 | boolean isVisible) { | |
600 | 0 | Rectangle rect = getBounds(); |
601 | 0 | if (compartment.isVisible()) { |
602 | 0 | if (!isVisible) { // hide compartment |
603 | 0 | damage(); |
604 | 0 | for (Object f : compartment.getFigs()) { |
605 | 0 | ((Fig) f).setVisible(false); |
606 | } | |
607 | 0 | compartment.setVisible(false); |
608 | /* | |
609 | * Hiding one compartment means that the Fig returns to minimal | |
610 | * dimensions: | |
611 | */ | |
612 | 0 | Dimension aSize = getMinimumSize(); |
613 | 0 | setBounds(rect.x, rect.y, (int) aSize.getWidth(), (int) aSize |
614 | .getHeight()); | |
615 | /* | |
616 | * Alternatively, we could reduce the height of the Fig by the | |
617 | * height of this one hidden compartment. But that would not be | |
618 | * possible for the width - so we better return to minimal | |
619 | * dimensions overall. | |
620 | */ | |
621 | 0 | } |
622 | } else { | |
623 | 0 | if (isVisible) { // show compartment |
624 | 0 | for (Object f : compartment.getFigs()) { |
625 | 0 | ((Fig) f).setVisible(true); |
626 | } | |
627 | 0 | compartment.setVisible(true); |
628 | 0 | Dimension aSize = this.getMinimumSize(); |
629 | 0 | setBounds(rect.x, rect.y, |
630 | (int) aSize.getWidth(), (int) aSize.getHeight()); | |
631 | 0 | damage(); |
632 | } | |
633 | } | |
634 | 0 | } |
635 | ||
636 | @Override | |
637 | public void setLineWidth(int w) { | |
638 | /* This sets the lineWidth of all in the group: */ | |
639 | 0 | super.setLineWidth(w); |
640 | /* NameFig and StereotypeFig are handled by parent. */ | |
641 | 0 | } |
642 | ||
643 | @Override | |
644 | public int getLineWidth() { | |
645 | 0 | return getBigPort().getLineWidth(); |
646 | } | |
647 | ||
648 | @Override | |
649 | public void setFillColor(Color col) { | |
650 | 0 | super.setFillColor(col); |
651 | 0 | getStereotypeFig().setFillColor(null); |
652 | 0 | getNameFig().setFillColor(null); |
653 | 0 | } |
654 | ||
655 | @Override | |
656 | public Color getFillColor() { | |
657 | 0 | return getBigPort().getFillColor(); |
658 | } | |
659 | ||
660 | @Override | |
661 | public void setFilled(boolean f) { | |
662 | 0 | super.setFilled(f); |
663 | 0 | getBigPort().setFilled(f); |
664 | 0 | getNameFig().setFilled(false); |
665 | 0 | getStereotypeFig().setFilled(false); |
666 | 0 | } |
667 | ||
668 | @Override | |
669 | protected void updateStereotypeText() { | |
670 | ||
671 | 0 | if (getOwner() == null) { |
672 | 0 | return; |
673 | } | |
674 | ||
675 | 0 | getStereotypeFig().setVisible( |
676 | getStereotypeFig().getStereotypeCount() > 0); | |
677 | ||
678 | 0 | super.updateStereotypeText(); |
679 | ||
680 | 0 | if (getStereotypeFig().isVisible()) { |
681 | 0 | getNameFig().setTopMargin( |
682 | getStereotypeFig().getMinimumSize().height); | |
683 | } else { | |
684 | 0 | getNameFig().setTopMargin(0); |
685 | } | |
686 | ||
687 | /* TODO: Is this needed? */ | |
688 | // forceRepaintShadow(); | |
689 | 0 | } |
690 | ||
691 | } |