Coverage Report - org.argouml.uml.diagram.ui.FigCompartmentBox
 
Classes in this File Line Coverage Branch Coverage Complexity
FigCompartmentBox
0%
0/205
0%
0/106
3.034
FigCompartmentBox$1
0%
0/8
0%
0/2
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  
 }