svn commit: r17338 - trunk/src/argouml-app/src/org/argouml/uml/diagram: static_structure/ui ui

Michiel van der Wulp <[email protected]>
Newsgroups gmane.comp.lang.uml.argouml.cvs
Message-ID <[email protected]>
Author: mvw
Date: 2009-09-22 01:39:41-0700
New Revision: 17338

Modified:
   trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigClass.java
   trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigClassifierBoxWithAttributes.java
   trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigDataType.java
   trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigEnumeration.java
   trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigInterface.java
   trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigSignal.java
   trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigStereotypeDeclaration.java
   trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigCompartment.java
   trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigCompartmentBox.java
   trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigEditableCompartment.java
   trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigStereotypesGroup.java

Log:
ArgoUML: Moved size calculations from its specializations to FigCompartment. 
The FigCompartment now maintains a list of compartments.
Changed the separator line in each compartment from a line into a rectangle, so that it also supports line width, and is positioned correctly.
GEF: Changed FigLine to support line width.


Modified: trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigClass.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigClass.java?view=diff&pathrev=17338&r1=17337&r2=17338
==============================================================================
--- trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigClass.java	(original)
+++ trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigClass.java	2009-09-22 01:39:41-0700
@@ -55,7 +55,8 @@
      *
      * The properties of all these graphic elements are adjusted
      * appropriately. The main boxes are all filled and have
-     * outlines. TODO: which is wrong, since the bigPort is filled, too.
+     * outlines. 
+     * TODO: which is wrong, since the bigPort is filled, too.
      * 
      * @param element model element to be represented by this fig.
      * @param bounds rectangle describing bounds
@@ -75,11 +76,17 @@
         addFig(getNameFig());
         /* Stereotype covers NameFig: */
         addFig(getStereotypeFig());
-        addFig(getOperationsFig());
+        /* Compartments from top to bottom: */
         addFig(getAttributesCompartment());
+        addFig(getOperationsFig());
         addFig(getBorderFig());
         
-
+        // Make all the parts match the main fig
+        setFilled(true);
+        setFillColor(FILL_COLOR);
+        setLineColor(LINE_COLOR);
+        setLineWidth(LINE_WIDTH);
+        
         /* Set the drop location in the case of D&D: */
         if (bounds != null) {
             setLocation(bounds.x, bounds.y);
@@ -90,9 +97,6 @@
         enableSizeChecking(true);
     }
 
-    /*
-     * @see java.lang.Object#clone()
-     */
     @Override
     public Object clone() {
         FigClass figClone = (FigClass) super.clone();
@@ -109,9 +113,6 @@
         return figClone;
     }
 
-    /*
-     * @see org.tigris.gef.presentation.Fig#makeSelection()
-     */
     public Selection makeSelection() {
         return new SelectionClass(this);
     }
@@ -120,13 +121,6 @@
         return buildModifierPopUp(ABSTRACT | LEAF | ROOT | ACTIVE);
     }
 
-    /*
-     * @see org.tigris.gef.presentation.Fig#getLineWidth()
-     */
-    public int getLineWidth() {
-        return getBorderFig().getLineWidth();
-    }
-
     /**
      * @param fgVec the FigGroup
      * @param ft    the Figtext
@@ -146,10 +140,10 @@
         do {
             i--;
             while (i < 1) {
-                if (fgVec == getAttributesFig()) {
+                if (fgVec == getAttributesCompartment()) {
                     fgVec = getOperationsFig();
                 } else {
-                    fgVec = getAttributesFig();
+                    fgVec = getAttributesCompartment();
                 }
                 figs = fgVec.getFigs();
                 i = figs.size() - 1;
@@ -164,7 +158,7 @@
 
     /**
      * @param fgVec the FigGroup
-     * @param ft    the Figtext
+     * @param ft    the FigText
      * @param i     get the fig after fig i
      * @return the FigText
      */
@@ -180,10 +174,10 @@
         do {
             i++;
             while (i >= v.size()) {
-                if (fgVec == getAttributesFig()) {
+                if (fgVec == getAttributesCompartment()) {
                     fgVec = getOperationsFig();
                 } else {
-                    fgVec = getAttributesFig();
+                    fgVec = getAttributesCompartment();
                 }
                 v = new ArrayList(fgVec.getFigs());
                 i = 1;
@@ -216,9 +210,6 @@
 
     }
 
-    /*
-     * @see org.argouml.uml.diagram.ui.FigNodeModelElement#updateNameText()
-     */
     @Override
     protected void updateNameText() {
         super.updateNameText();

Modified: trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigClassifierBoxWithAttributes.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigClassifierBoxWithAttributes.java?view=diff&pathrev=17338&r1=17337&r2=17338
==============================================================================
--- trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigClassifierBoxWithAttributes.java	(original)
+++ trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigClassifierBoxWithAttributes.java	2009-09-22 01:39:41-0700
@@ -24,14 +24,12 @@
 
 package org.argouml.uml.diagram.static_structure.ui;
 
-import java.awt.Dimension;
 import java.awt.Rectangle;
 import java.util.HashSet;
 import java.util.Set;
 
 import javax.swing.Action;
 
-import org.apache.log4j.Logger;
 import org.argouml.model.AddAssociationEvent;
 import org.argouml.model.AssociationChangeEvent;
 import org.argouml.model.AttributeChangeEvent;
@@ -49,11 +47,8 @@
  *
  * @author Michiel
  */
-public class FigClassifierBoxWithAttributes extends FigClassifierBox 
+public abstract class FigClassifierBoxWithAttributes extends FigClassifierBox 
     implements AttributesCompartmentContainer {
-
-    private static final Logger LOG = 
-        Logger.getLogger(FigClassifierBoxWithAttributes.class);
     
     private FigAttributesCompartment attributesFigCompartment;
     
@@ -204,7 +199,7 @@
 
     /**
      * Updates the attributes in the fig. Called from modelchanged if there is
-     * a modelevent effecting the attributes and from renderingChanged in all
+     * a modelEvent effecting the attributes and from renderingChanged in all
      * cases.
      * TODO: Looks like this should be private - Bob.
      */
@@ -226,150 +221,6 @@
     public void setAttributesVisible(boolean isVisible) {
         setCompartmentVisible(attributesFigCompartment, isVisible);
     }
-    @Override
-    public Dimension getMinimumSize() {
-        // Use "aSize" to build up the minimum size. Start with the size of the
-        // name compartment and build up.
-        Dimension aSize = getNameFig().getMinimumSize();
-
-        /* Only take into account the stereotype width, not the height, 
-         * since the height is included in the name fig: */
-        aSize = addChildWidth(aSize, getStereotypeFig());
-        aSize = addChildDimensions(aSize, getAttributesCompartment());
-        aSize = addChildDimensions(aSize, getOperationsFig());
-
-        /* We want to maintain a minimum width for the 
-         * fig. Also, add the border dimensions 
-         * to the minimum space required for its contents: */
-        aSize.width = Math.max(WIDTH, aSize.width);
-        aSize.width += 2 * getLineWidth();
-        aSize.height += 2 * getLineWidth();
-    
-        return aSize;
-    }
-
-    /**
-     * Sets the bounds, but the size will be at least the one returned by
-     * {@link #getMinimumSize()}, unless checking of size is disabled.<p>
-     *
-     * If the required height is bigger, then the additional height is
-     * equally distributed among all compartments, such that the
-     * accumulated height of all visible figs equals the demanded height.
-     *
-     * @param x  Desired X coordinate of upper left corner
-     *
-     * @param y  Desired Y coordinate of upper left corner
-     *
-     * @param width  Desired width of the Fig
-     *
-     * @param height  Desired height of the Fig
-     * 
-     * @see org.tigris.gef.presentation.Fig#setBoundsImpl(int, int, int, int)
-     */
-    @Override
-    protected void setStandardBounds(final int x, final int y, final int w,
-            final int h) {
-
-        // Save our old boundaries so it can be used in property message later
-        Rectangle oldBounds = getBounds();
-
-        // Make sure we don't try to set things smaller than the minimum
-        Dimension minimumSize = getMinimumSize();
-        int newW = Math.max(w, minimumSize.width);
-        int newH = Math.max(h, minimumSize.height);
-        
-        int currentHeight = 0;
-
-        if (getStereotypeFig().isVisible()) {
-            int stereotypeHeight = getStereotypeFig().getMinimumSize().height;
-            getNameFig().setTopMargin(stereotypeHeight);
-            getStereotypeFig().setBounds(
-                    x + getLineWidth(),
-                    y + getLineWidth(),
-                    newW - 2 * getLineWidth(),
-                    stereotypeHeight);
-        } else {
-            getNameFig().setTopMargin(0);
-        }
-
-        /* Now the new nameFig height will include the stereotype height: */
-        Dimension nameMin = getNameFig().getMinimumSize();
-        int minNameHeight = Math.max(nameMin.height, NAME_FIG_HEIGHT);
-        
-        getNameFig().setBounds(
-                x + getLineWidth(), 
-                y + getLineWidth(), 
-                newW - 2 * getLineWidth(), 
-                minNameHeight);
-        
-        /* The new height can not be less than the name height: */
-        /* TODO: Is this needed/correct? 
-         * For when all compartments are hidden? */
-        newH = Math.max(minNameHeight + 2 * getLineWidth(), newH);
-        
-        currentHeight += minNameHeight;
-
-        int attributesHeight = 0;
-        int operationsHeight = 0;
-        int visibleCompartments = 0;
-
-        if (getAttributesCompartment().isVisible()) {
-            visibleCompartments++;
-            attributesHeight = 
-                getAttributesCompartment().getMinimumSize().height;
-        }
-        if (getOperationsFig().isVisible()) {
-            visibleCompartments++;
-            operationsHeight = getOperationsFig().getMinimumSize().height;
-        }
-        
-        int requestedHeight = newH - currentHeight - 2 * getLineWidth();
-        int neededHeight = attributesHeight + operationsHeight;
-        
-        if (requestedHeight > neededHeight) {
-            /* Distribute the extra height over the visible compartments: */
-            if (getAttributesCompartment().isVisible()) {
-                attributesHeight += (requestedHeight - neededHeight) / visibleCompartments;
-            }
-            if (getOperationsFig().isVisible()) {
-                operationsHeight += (requestedHeight - neededHeight) / visibleCompartments;
-            }
-        } else if (requestedHeight < neededHeight) {
-            /* Increase the height of the fig: */
-            newH += neededHeight - requestedHeight;
-        }
-
-        if (getAttributesCompartment().isVisible()) {
-            getAttributesCompartment().setBounds(
-                    x + getLineWidth(),
-                    y + currentHeight + getLineWidth(),
-                    newW - 2 * getLineWidth(),
-                    attributesHeight);
-            currentHeight += attributesHeight;
-        }
-        
-        if (getOperationsFig().isVisible()) {
-            getOperationsFig().setBounds(
-                    x + getLineWidth(),
-                    y + currentHeight + getLineWidth(),
-                    newW - 2 * getLineWidth(),
-                    operationsHeight);
-        }
-        
-        // set bounds of big box
-        getBigPort().setBounds(x, y, newW, newH);
-        getBorderFig().setBounds(x, y, newW, newH);
-
-        // Now force calculation of the bounds of the figure, update the edges
-        // and trigger anyone who's listening to see if the "bounds" property
-        // has changed.
-
-        calcBounds();
-        updateEdges();
-        LOG.debug("Bounds change : old - " + oldBounds + ", new - " 
-                + getBounds());
-        firePropChange("bounds", oldBounds, getBounds());
-    }
 
     /**
      * @return the Fig for the EnumerationLiterals compartment

Modified: trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigDataType.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigDataType.java?view=diff&pathrev=17338&r1=17337&r2=17338
==============================================================================
--- trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigDataType.java	(original)
+++ trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigDataType.java	2009-09-22 01:39:41-0700
@@ -24,7 +24,6 @@
 
 package org.argouml.uml.diagram.static_structure.ui;
 
-import java.awt.Dimension;
 import java.awt.Rectangle;
 
 import org.apache.log4j.Logger;
@@ -48,7 +47,11 @@
  * always <<datatype>>, e.g. for an Enumeration. <p>
  * 
  * There is no need for a specific minimal width for this Fig, 
- * since its width will most of the time be determined by the keyword.
+ * since its width will most of the time be determined by the keyword.<p>
+ * 
+ * This Fig supports a compartment for operations at the bottom. 
+ * Other compartments may be added above it by specializations 
+ * of the DataType Fig by overriding the addExtraCompartments() method.
  */
 public class FigDataType extends FigClassifierBox {
 
@@ -69,9 +72,16 @@
         addFig(getBigPort());
         addFig(getNameFig());
         addFig(getStereotypeFig());
+        addExtraCompartments();
         addFig(getOperationsFig());
         addFig(getBorderFig());
-
+        
+        // Make all the parts match the main fig
+        setFilled(true);
+        setFillColor(FILL_COLOR);
+        setLineColor(LINE_COLOR);
+        setLineWidth(LINE_WIDTH);
+        
         /* Set the drop location in the case of D&D: */
         if (bounds != null) {
             setLocation(bounds.x, bounds.y);
@@ -83,6 +93,10 @@
         enableSizeChecking(true);
     }
 
+    protected  void addExtraCompartments() {
+        /* Do nothing by default. */
+    }
+
     /**
      * Primary constructor for a {@link FigDataType}.
      *
@@ -117,42 +131,11 @@
         return "datatype";
     }
 
-    /*
-     * @see org.tigris.gef.presentation.Fig#makeSelection()
-     */
     @Override
     public Selection makeSelection() {
         return new SelectionDataType(this);
     }
 
-    /**
-     * Gets the minimum size permitted for a datatype on the diagram.
-     *
-     * @return  the size of the minimum bounding box.
-     */
-    @Override
-    public Dimension getMinimumSize() {
-        // Use "aSize" to build up the minimum size. Start with the size of the
-        // name compartment and build up.
-
-        Dimension aSize = getNameFig().getMinimumSize();
-
-        /* Only take into account the stereotype width, not the height, 
-         * since the height is included in the name fig: */
-        addChildWidth(aSize, getStereotypeFig());
-        
-        aSize = addChildDimensions(aSize, getOperationsFig());
-
-        /* We want to maintain a minimum width for the 
-         * interface fig. Also, add the border dimensions 
-         * to the minimum space required for its contents: */
-        aSize.width = Math.max(WIDTH, aSize.width);
-        aSize.width += 2 * getLineWidth();
-        aSize.height += 2 * getLineWidth();
-
-        return aSize;
-    }
-
     @Override
     public void setEnclosingFig(Fig encloser) {
         Fig oldEncloser = getEnclosingFig();
@@ -198,94 +181,4 @@
 
     }
 
-    /**
-     * Sets the bounds, but the size will be at least the one returned by
-     * {@link #getMinimumSize()}, unless checking of size is disabled.<p>
-     *
-     * If the required height is bigger, then the additional height is
-     * equally distributed among all figs (i.e. compartments), such that the
-     * accumulated height of all visible figs equals the demanded height<p>.
-     *
-     * @param x  Desired X coordinate of upper left corner
-     *
-     * @param y  Desired Y coordinate of upper left corner
-     *
-     * @param w  Desired width of the figure
-     *
-     * @param h  Desired height of the figure
-     * @see org.tigris.gef.presentation.Fig#setBoundsImpl(int, int, int, int)
-     */
-    @Override
-    protected void setStandardBounds(final int x, final int y, final int w,
-            final int h) {
-        /* Save our old boundaries (needed later), and get minimum size
-         * info.*/ 
-        Rectangle oldBounds = getBounds();
-
-        /* The new size can not be smaller than the minimum. */
-        Dimension minimumSize = getMinimumSize();
-        int newW = Math.max(w, minimumSize.width);
-        int newH = Math.max(h, minimumSize.height);
-        
-        int currentHeight = 0;
-
-        if (getStereotypeFig().isVisible()) {
-            int stereotypeHeight = getStereotypeFig().getMinimumSize().height;
-            getNameFig().setTopMargin(stereotypeHeight);
-            getStereotypeFig().setBounds(
-                    x + getLineWidth(),
-                    y + getLineWidth(),
-                    newW - 2 * getLineWidth(),
-                    stereotypeHeight);
-        } else {
-            getNameFig().setTopMargin(0);
-        }
-        
-        /* Now the new nameFig height will include the stereotype height: */
-        Dimension nameMin = getNameFig().getMinimumSize();
-        int minNameHeight = Math.max(nameMin.height, NAME_FIG_HEIGHT);
-        
-        getNameFig().setBounds(
-                x + getLineWidth(), 
-                y + getLineWidth(), 
-                newW - 2 * getLineWidth(), 
-                minNameHeight);
-        
-        /* The new height can not be less than the name height: */
-        /* TODO: Is this needed/correct? */
-        newH = Math.max(minNameHeight, newH);
-        
-        currentHeight += minNameHeight;
-
-        /* And the operations compartment takes the remainder 
-         * of the requested height: */
-        if (getOperationsFig().isVisible()) {
-            int operationsHeight = newH - currentHeight - 2 * getLineWidth();
-            /* If the requested height is smaller than the minimum required, ... */
-            if ( operationsHeight < getOperationsFig().getMinimumSize().height) {
-                /* ... then we use the minimum ... */
-                operationsHeight = getOperationsFig().getMinimumSize().height;
-                /* ... and make the Fig bigger: */
-                newH += getOperationsFig().getMinimumSize().height - operationsHeight;
-            }
-            getOperationsFig().setBounds(
-                    x + getLineWidth(),
-                    y + currentHeight + getLineWidth(),
-                    newW - 2 * getLineWidth(),
-                    operationsHeight);
-        }
-        
-        // set bounds of big box
-        getBigPort().setBounds(x, y, newW, newH);
-        getBorderFig().setBounds(x, y, newW, newH);
-
-        // Now force calculation of the bounds of the figure, update the edges
-        // and trigger anyone who's listening to see if the "bounds" property
-        // has changed.
-
-        calcBounds();
-        updateEdges();
-        firePropChange("bounds", oldBounds, getBounds());
-    }
-
 }

Modified: trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigEnumeration.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigEnumeration.java?view=diff&pathrev=17338&r1=17337&r2=17338
==============================================================================
--- trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigEnumeration.java	(original)
+++ trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigEnumeration.java	2009-09-22 01:39:41-0700
@@ -24,7 +24,6 @@
 
 package org.argouml.uml.diagram.static_structure.ui;
 
-import java.awt.Dimension;
 import java.awt.Rectangle;
 import java.beans.PropertyChangeEvent;
 import java.util.HashSet;
@@ -68,14 +67,6 @@
             DiagramSettings settings) {
         super(owner, bounds, settings);
 
-        enableSizeChecking(true);
-        setSuppressCalcBounds(false);
-
-        addFig(getLiteralsCompartment()); // This creates the compartment.
-        setEnumLiteralsVisible(true);
-        literalsCompartment.populate();
-
-        setBounds(getBounds());
     }
 
     @Override
@@ -83,9 +74,14 @@
         return "enumeration";
     }
     
-    /*
-     * @see org.argouml.uml.diagram.static_structure.ui.FigDataType#makeSelection()
-     */
+    @Override
+    protected void addExtraCompartments() {
+        // This creates the compartment.
+        addFig(getLiteralsCompartment());
+        setEnumLiteralsVisible(true);
+        literalsCompartment.populate();
+    }
+
     @Override
     public Selection makeSelection() {
         return new SelectionEnumeration(this);
@@ -99,9 +95,6 @@
         return clone;
     }
 
-    /*
-     * @see org.argouml.uml.diagram.static_structure.ui.FigClassifierBox#buildAddMenu()
-     */
     @Override
     protected ArgoJMenu buildAddMenu() {
         ArgoJMenu addMenu = super.buildAddMenu();
@@ -112,9 +105,6 @@
         return addMenu;
     }
 
-    /*
-     * @see org.argouml.uml.diagram.ui.FigNodeModelElement#modelChanged(java.beans.PropertyChangeEvent)
-     */
     @Override
     protected void modelChanged(PropertyChangeEvent mee) {
         super.modelChanged(mee);
@@ -125,9 +115,6 @@
         }
     }
 
-    /*
-     * @see org.argouml.uml.diagram.ui.FigNodeModelElement#renderingChanged()
-     */
     @Override
     public void renderingChanged() {
         super.renderingChanged();
@@ -135,10 +122,7 @@
             updateEnumLiterals();
         }
     }
-    
-    /*
-     * @see org.argouml.uml.diagram.ui.FigNodeModelElement#updateListeners(java.lang.Object)
-     */
+
     @Override
     protected void updateListeners(Object oldOwner, Object newOwner) {
         Set<Object[]> l = new HashSet<Object[]>();
@@ -181,131 +165,6 @@
         setBounds(getBounds());
     }
 
-    @Override
-    public Dimension getMinimumSize() {
-        // Use "aSize" to build up the minimum size. Start with the size of the
-        // name compartment and build up.
-
-        Dimension aSize = getNameFig().getMinimumSize();
-
-        /* Only take into account the stereotype width, not the height, 
-         * since the height is included in the name fig: */
-        addChildWidth(aSize, getStereotypeFig());
-        aSize = addChildDimensions(aSize, literalsCompartment);
-        aSize = addChildDimensions(aSize, getOperationsFig());
-
-        /* We want to maintain a minimum width for the 
-         * interface fig. Also, add the border dimensions 
-         * to the minimum space required for its contents: */
-        aSize.width = Math.max(WIDTH, aSize.width);
-        aSize.width += 2 * getLineWidth();
-        aSize.height += 2 * getLineWidth();
-        
-        return aSize;
-    }
-    
-    @Override
-    protected void setStandardBounds(final int x, final int y, final int w,
-            final int h) {
-        // Save our old boundaries so it can be used in property message later
-        Rectangle oldBounds = getBounds();
-        
-        /* The new size can not be smaller than the minimum. */
-        Dimension minimumSize = getMinimumSize();
-        int newW = Math.max(w, minimumSize.width);
-        int newH = Math.max(h, minimumSize.height);
-        
-        int currentHeight = 0;
-
-        if (getStereotypeFig().isVisible()) {
-            int stereotypeHeight = getStereotypeFig().getMinimumSize().height;
-            getNameFig().setTopMargin(stereotypeHeight);
-            getStereotypeFig().setBounds(
-                    x + getLineWidth(),
-                    y + getLineWidth(),
-                    newW - 2 * getLineWidth(),
-                    stereotypeHeight);
-        } else {
-            getNameFig().setTopMargin(0);
-        }
-        
-        /* Now the new nameFig height will include the stereotype height: */
-        Dimension nameMin = getNameFig().getMinimumSize();
-        int minNameHeight = Math.max(nameMin.height, NAME_FIG_HEIGHT);
-        
-        getNameFig().setBounds(
-                x + getLineWidth(), 
-                y + getLineWidth(), 
-                newW - 2 * getLineWidth(), 
-                minNameHeight);
-        
-        /* The new height can not be less than the name height: */
-        /* TODO: Is this needed/correct? 
-         * For when all compartments are hidden? */
-        newH = Math.max(minNameHeight + 2 * getLineWidth(), newH);
-        
-        currentHeight += minNameHeight;
-
-        int literalsHeight = 0;
-        int operationsHeight = 0;
-        int visibleCompartments = 0;
-
-        if (getLiteralsCompartment().isVisible()) {
-            visibleCompartments++;
-            literalsHeight = 
-                getLiteralsCompartment().getMinimumSize().height;
-        }
-        if (getOperationsFig().isVisible()) {
-            visibleCompartments++;
-            operationsHeight = getOperationsFig().getMinimumSize().height;
-        }
-        
-        int requestedHeight = newH - currentHeight - 2 * getLineWidth();
-        int neededHeight = literalsHeight + operationsHeight;
-        
-        if (requestedHeight > neededHeight) {
-            /* Distribute the extra height over the visible compartments: */
-            if (getLiteralsCompartment().isVisible()) {
-                literalsHeight += (requestedHeight - neededHeight) / visibleCompartments;
-            }
-            if (getOperationsFig().isVisible()) {
-                operationsHeight += (requestedHeight - neededHeight) / visibleCompartments;
-            }
-        } else if (requestedHeight < neededHeight) {
-            /* Increase the height of the fig: */
-            newH += neededHeight - requestedHeight;
-        }
-
-        if (getLiteralsCompartment().isVisible()) {
-            getLiteralsCompartment().setBounds(
-                    x + getLineWidth(),
-                    y + currentHeight + getLineWidth(),
-                    newW - 2 * getLineWidth(),
-                    literalsHeight);
-            currentHeight += literalsHeight;
-        }
-        
-        if (getOperationsFig().isVisible()) {
-            getOperationsFig().setBounds(
-                    x + getLineWidth(),
-                    y + currentHeight + getLineWidth(),
-                    newW - 2 * getLineWidth(),
-                    operationsHeight);
-        }
-        
-        // set bounds of big box
-        getBigPort().setBounds(x, y, newW, newH);
-        getBorderFig().setBounds(x, y, newW, newH);
-        
-        // Now force calculation of the bounds of the figure, update the edges
-        // and trigger anyone who's listening to see if the "bounds" property
-        // has changed.
-
-        calcBounds();
-        updateEdges();
-        firePropChange("bounds", oldBounds, getBounds());
-    }
-
     /**
      * @return the Fig for the EnumerationLiterals compartment
      */

Modified: trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigInterface.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigInterface.java?view=diff&pathrev=17338&r1=17337&r2=17338
==============================================================================
--- trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigInterface.java	(original)
+++ trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigInterface.java	2009-09-22 01:39:41-0700
@@ -24,8 +24,9 @@
 
 package org.argouml.uml.diagram.static_structure.ui;
 
-import java.awt.Dimension;
 import java.awt.Rectangle;
+import java.util.HashSet;
+import java.util.Set;
 
 import org.apache.log4j.Logger;
 import org.argouml.model.Model;
@@ -66,9 +67,16 @@
         addFig(getNameFig());
         // stereotype fig covers the name fig:
         addFig(getStereotypeFig());
+        /* Only one compartment: */
         addFig(getOperationsFig());
         addFig(getBorderFig());
 
+        // Make all the parts match the main fig
+        setFilled(true);
+        setFillColor(FILL_COLOR);
+        setLineColor(LINE_COLOR);
+        setLineWidth(LINE_WIDTH);
+
         /* Set the drop location in the case of D&D: */
         if (bounds != null) {
             setLocation(bounds.x, bounds.y);
@@ -94,48 +102,11 @@
         initialize(bounds);
     }
     
-    /*
-     * @see org.tigris.gef.presentation.Fig#makeSelection()
-     */
     @Override
     public Selection makeSelection() {
         return new SelectionInterface(this);
     }
 
-
-    /**
-     * Gets the minimum size permitted for an interface on the diagram.<p>
-     *
-     * Parts of this are hardcoded.<p>
-     *
-     * @return  the size of the minimum bounding box.
-     */
-    @Override
-    public Dimension getMinimumSize() {
-        // Use "aSize" to build up the minimum size. Start with the size of the
-        // name compartment and build up.
-        Dimension aSize = getNameFig().getMinimumSize();
-
-        /* Only take into account the stereotype width, not the height, 
-         * since the height is included in the name fig: */
-        addChildWidth(aSize, getStereotypeFig());
-
-        addChildDimensions(aSize, getOperationsFig());
-
-        /* We want to maintain a minimum width for the 
-         * interface fig. Also, add the border dimensions 
-         * to the minimum space required for its contents: */
-        aSize.width = Math.max(WIDTH, aSize.width);
-        aSize.width += 2 * getLineWidth();
-        aSize.height += 2 * getLineWidth();
-
-        return aSize;
-    }
-
-
-    /*
-     * @see org.tigris.gef.presentation.Fig#setEnclosingFig(org.tigris.gef.presentation.Fig)
-     */
     @Override
     public void setEnclosingFig(Fig encloser) {
         Fig oldEncloser = getEnclosingFig();
@@ -201,93 +172,51 @@
                 + "operationsVisible=" + isOperationsVisible();
     }
 
-    /**
-     * Sets the bounds, but the size will be at least the one returned by
-     * {@link #getMinimumSize()}, unless checking of size is disabled.<p>
-     *
-     * If the required height is bigger, then the additional height is
-     * equally distributed among all figs (i.e. compartments), such that the
-     * accumulated height of all visible figs equals the demanded height.
-     *
-     * @param x  Desired X coordinate of upper left corner
-     *
-     * @param y  Desired Y coordinate of upper left corner
-     *
-     * @param w  Desired width of the FigInterface
-     *
-     * @param h  Desired height of the FigInterface
-     */
     @Override
-    protected void setStandardBounds(final int x, final int y, final int w,
-            final int h) {
-        /* Save our old boundaries (needed later), and get minimum size
-         * info.*/ 
-        Rectangle oldBounds = getBounds();
-
-        /* The new size can not be smaller than the minimum. */
-        Dimension minimumSize = getMinimumSize();
-        int newW = Math.max(w, minimumSize.width);
-        int newH = Math.max(h, minimumSize.height);
-
-        int currentHeight = 0;
-
-        if (getStereotypeFig().isVisible()) {
-            int stereotypeHeight = getStereotypeFig().getMinimumSize().height;
-            getNameFig().setTopMargin(stereotypeHeight);
-            getStereotypeFig().setBounds(
-                    x + getLineWidth(),
-                    y + getLineWidth(),
-                    newW - 2 * getLineWidth(),
-                    stereotypeHeight);
-        } else {
-            getNameFig().setTopMargin(0);
-        }
-        
-        /* Now the new nameFig height will include the stereotype height: */
-        Dimension nameMin = getNameFig().getMinimumSize();
-        int minNameHeight = Math.max(nameMin.height, NAME_FIG_HEIGHT);
-        
-        getNameFig().setBounds(
-                x + getLineWidth(), 
-                y + getLineWidth(), 
-                newW - 2 * getLineWidth(), 
-                minNameHeight);
-        
-        /* The new height can not be less than the name height: */
-        /* TODO: Is this needed/correct? */
-        newH = Math.max(minNameHeight, newH);
-        
-        currentHeight += minNameHeight;
+    protected void updateListeners(Object oldOwner, Object newOwner) {
+        Set<Object[]> listeners = new HashSet<Object[]>();
+
+        // Collect the set of model elements that we want to listen to
+        if (newOwner != null) {
+            // TODO: Because we get called on each and every change event, when
+            // the model is in a state of flux, we'll often get an
+            // InvalidElementException before we finish this collection. The
+            // only saving grace is that we're called SO many times that on the
+            // last time, things should be stable again and we'll get a good set
+            // of elements for the final update.  We need a better mechanism.
+            
+            // add the listeners to the newOwner
+            listeners.add(new Object[] {newOwner, null});
+            
+            // and its stereotypes
+            // TODO: Aren't stereotypes handled elsewhere?
+            for (Object stereotype 
+                    : Model.getFacade().getStereotypes(newOwner)) {
+                listeners.add(new Object[] {stereotype, null});
+            }
 
-        /* And the operations compartment takes the remainder 
-         * of the requested height: */
-        if (getOperationsFig().isVisible()) {
-            int operationsHeight = newH - currentHeight - 2 * getLineWidth();
-            /* If the requested height is smaller than the minimum required, ... */
-            if ( operationsHeight < getOperationsFig().getMinimumSize().height) {
-                /* ... then we use the minimum ... */
-                operationsHeight = getOperationsFig().getMinimumSize().height;
-                /* ... and make the Fig bigger: */
-                newH += getOperationsFig().getMinimumSize().height - operationsHeight;
+            // and its features
+            for (Object feat : Model.getFacade().getFeatures(newOwner)) {
+                listeners.add(new Object[] {feat, null});
+                // and the stereotypes of its features
+                for (Object stereotype 
+                        : Model.getFacade().getStereotypes(feat)) {
+                    listeners.add(new Object[] {stereotype, null});
+                }
+                // and the parameter of its operations
+                if (Model.getFacade().isAOperation(feat)) {
+                    for (Object param : Model.getFacade().getParameters(feat)) {
+                        listeners.add(new Object[] {param, null});
+                        /* Testing: Add a parameter to an operation on an Interface.
+                         * Does the Interface Fig adapt its width? */
+                    }
+                }
             }
-            getOperationsFig().setBounds(
-                    x + getLineWidth(),
-                    y + currentHeight + getLineWidth(),
-                    newW - 2 * getLineWidth(),
-                    operationsHeight);
         }
         
-        // set bounds of big box
-        getBigPort().setBounds(x, y, newW, newH);
-        getBorderFig().setBounds(x, y, newW, newH);
-
-        // Now force calculation of the bounds of the figure, update the edges
-        // and trigger anyone who's listening to see if the "bounds" property
-        // has changed.
-
-        calcBounds();
-        updateEdges();
-        firePropChange("bounds", oldBounds, getBounds());
+        // Update the listeners to match the desired set using the minimal
+        // update facility
+        updateElementListeners(listeners);
     }
 
 }
\ No newline at end of file

Modified: trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigSignal.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigSignal.java?view=diff&pathrev=17338&r1=17337&r2=17338
==============================================================================
--- trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigSignal.java	(original)
+++ trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigSignal.java	2009-09-22 01:39:41-0700
@@ -74,10 +74,17 @@
         addFig(getNameFig());
         /* Stereotype covers NameFig: */
         addFig(getStereotypeFig());
-        addFig(getOperationsFig());
+        /* Compartments from top to bottom: */
         addFig(getAttributesCompartment());
+        addFig(getOperationsFig());
         addFig(getBorderFig());
 
+        // Make all the parts match the main fig
+        setFilled(true);
+        setFillColor(FILL_COLOR);
+        setLineColor(LINE_COLOR);
+        setLineWidth(LINE_WIDTH);
+        
         // by default, do not show operations nor attributes:
         setOperationsVisible(false);
         setAttributesVisible(false);
@@ -92,17 +99,11 @@
         enableSizeChecking(true);
     }
     
-    /*
-     * @see org.argouml.uml.diagram.static_structure.ui.FigDataType#makeSelection()
-     */
     @Override
     public Selection makeSelection() {
         return new SelectionSignal(this);
     }
 
-    /*
-     * @see org.argouml.uml.diagram.static_structure.ui.FigClassifierBox#getPopUpActions(java.awt.event.MouseEvent)
-     */
     @Override
     public Vector getPopUpActions(MouseEvent me) {
         Vector popUpActions = super.getPopUpActions(me);
@@ -112,9 +113,6 @@
         return popUpActions;
     }
 
-    /*
-     * @see org.argouml.uml.diagram.ui.FigNodeModelElement#modelChanged(java.beans.PropertyChangeEvent)
-     */
     @Override
     protected void modelChanged(PropertyChangeEvent mee) {
         super.modelChanged(mee);

Modified: trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigStereotypeDeclaration.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigStereotypeDeclaration.java?view=diff&pathrev=17338&r1=17337&r2=17338
==============================================================================
--- trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigStereotypeDeclaration.java	(original)
+++ trunk/src/argouml-app/src/org/argouml/uml/diagram/static_structure/ui/FigStereotypeDeclaration.java	2009-09-22 01:39:41-0700
@@ -24,7 +24,6 @@
 
 package org.argouml.uml.diagram.static_structure.ui;
 
-import java.awt.Dimension;
 import java.awt.Rectangle;
 import java.awt.event.MouseEvent;
 import java.beans.PropertyChangeEvent;
@@ -51,7 +50,7 @@
  * Class to display a Stereotype declaration figure using
  * Classifier box notation.<p>
  *
- * TODO: This is just a placeholder right now! - tfm
+ * TODO: This is just a place-holder right now! - tfm
  * This needs to show tags and constraints.
  */
 public class FigStereotypeDeclaration extends FigCompartmentBox {
@@ -80,6 +79,12 @@
 //        addFig(constraintsFig);
 
         addFig(getBorderFig());
+        
+        // Make all the parts match the main fig
+        setFilled(true);
+        setFillColor(FILL_COLOR);
+        setLineColor(LINE_COLOR);
+        setLineWidth(LINE_WIDTH);
 
         /* Set the drop location in the case of D&D: */
         if (bounds != null) {
@@ -104,9 +109,6 @@
         enableSizeChecking(true);
     }
     
-    /*
-     * @see org.tigris.gef.presentation.Fig#makeSelection()
-     */
     @Override
     public Selection makeSelection() {
         return new SelectionStereotype(this);
@@ -114,7 +116,7 @@
 
     /**
      * Build a collection of menu items relevant for a right-click
-     * popup menu on a Stereotype.
+     * pop-up menu on a Stereotype.
      * {@inheritDoc}
      */
     @Override
@@ -153,101 +155,6 @@
         return popUpActions;
     }
 
-    /**
-     * Gets the minimum size permitted for a class on the diagram.
-     *
-     * @return  the size of the minimum bounding box.
-     */
-    @Override
-    public Dimension getMinimumSize() {
-        /* Use "aSize" to build up the minimum size. Start with the size of the
-         * name compartment and build up. */
-        Dimension aSize = getNameFig().getMinimumSize();
-
-        /* Only take into account the stereotype width, not the height, 
-         * since the height is included in the name fig: */
-        addChildWidth(aSize, getStereotypeFig());
-
-        // TODO: Allow space for each of the Tags & Constraints we have
-
-        /* We want to maintain a minimum width for the 
-         * stereotypeDeclaration. Also, add the border dimensions 
-         * to the minimum space required for its contents: */
-        aSize.width = Math.max(WIDTH, aSize.width);
-        aSize.width += 2 * getLineWidth();
-        aSize.height += 2 * getLineWidth();
-        
-        return aSize;
-    }
-
-    /**
-     * Sets the bounds, but the size will be at least the one returned by
-     * {@link #getMinimumSize()}, unless checking of size is disabled.<p>
-     *
-     * @param x  Desired X coordinate of upper left corner
-     *
-     * @param y  Desired Y coordinate of upper left corner
-     *
-     * @param w  Desired width of the fig
-     *
-     * @param h  Desired height of the fig
-     *
-     * @see org.tigris.gef.presentation.Fig#setBoundsImpl(int, int, int, int)
-     */
-    @Override
-    protected void setStandardBounds(final int x, final int y,
-            final int w, final int h) {
-        /* Save our old boundaries (needed later): */
-        Rectangle oldBounds = getBounds();
-
-        /* The new size can not be smaller than the minimum. */
-        Dimension minimumSize = getMinimumSize();
-        int newW = Math.max(w, minimumSize.width);
-        int newH = Math.max(h, minimumSize.height);
-
-        if (getStereotypeFig().isVisible()) {
-            int stereotypeHeight = getStereotypeFig().getMinimumSize().height;
-            getNameFig().setTopMargin(stereotypeHeight);
-            getStereotypeFig().setBounds(
-                    x + getLineWidth(),
-                    y + getLineWidth(),
-                    newW - 2 * getLineWidth(),
-                    stereotypeHeight);
-        } else {
-            getNameFig().setTopMargin(0);
-        }
-        
-        /* Now the new nameFig height will include the stereotype height: */
-        Dimension nameMin = getNameFig().getMinimumSize();
-        int minNameHeight = Math.max(nameMin.height, NAME_FIG_HEIGHT);
-        
-        getNameFig().setBounds(
-                x + getLineWidth(), 
-                y + getLineWidth(), 
-                newW - 2 * getLineWidth(), 
-                minNameHeight);
-
-        /* The new height can not be less than the name height: */
-        newH = Math.max(minNameHeight, newH);
-
-        // TODO: Compute size of Tags and Constraints
-
-        // set bounds of big box
-        getBigPort().setBounds(x, y, newW, newH);
-        getBorderFig().setBounds(x, y, newW, newH);
-        
-        // Now force calculation of the bounds of the figure, update the edges
-        // and trigger anyone who's listening to see if the "bounds" property
-        // has changed.
-
-        calcBounds();
-        updateEdges();
-        firePropChange("bounds", oldBounds, getBounds());
-    }
-
-    /*
-     * @see org.argouml.uml.diagram.static_structure.ui.FigCompartmentBox#unhighlight()
-     */
     @Override
     protected CompartmentFigText unhighlight() {
         CompartmentFigText fc = super.unhighlight();
@@ -276,16 +183,13 @@
         }
     }
 
-    /*
-     * @see org.argouml.uml.diagram.ui.FigNodeModelElement#updateListeners(java.lang.Object)
-     */
     @Override
     protected void updateListeners(Object oldOwner, Object newOwner) {
         
         Set<Object[]> listeners = new HashSet<Object[]>();
         if (newOwner != null) {
             listeners.add(new Object[] {newOwner, null});
-            // register for tagdefinitions:
+            // register for tagDefinitions:
             for (Object td : Model.getFacade().getTagDefinitions(newOwner)) {
                 listeners.add(new Object[] {td,
                     new String[] {"name", "tagType", "multiplicity"}});

Modified: trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigCompartment.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigCompartment.java?view=diff&pathrev=17338&r1=17337&r2=17338
==============================================================================
--- trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigCompartment.java	(original)
+++ trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigCompartment.java	2009-09-22 01:39:41-0700
@@ -27,12 +27,25 @@
 import java.awt.Dimension;
 import java.awt.Rectangle;
 import java.util.Collection;
+import java.util.List;
 
 import org.argouml.uml.diagram.DiagramSettings;
 import org.tigris.gef.presentation.Fig;
 import org.tigris.gef.presentation.FigRect;
 
 /**
+ * Presentation logic for a boxed compartment,
+ * containing vertically stacked figs,
+ * which is common to e.g. an operations
+ * compartment and an attributes compartment.<p>
+ * 
+ * The bigPort is filled, but has no border. All other figs contained 
+ * in this group may not be filled, but can have a border. <p>
+ * 
+ * The size calculation done here supports vertically 
+ * stacked sub-figs of this group and supports all 
+ * compartment specializations.
+ * 
  * @author Bob Tarling
  */
 public abstract class FigCompartment extends ArgoFigGroup {
@@ -58,10 +71,8 @@
     private void constructFigs(int x, int y, int w, int h) {
         bigPort = new FigRect(x, y, w, h, LINE_COLOR, FILL_COLOR);
         bigPort.setFilled(true);
-        setFilled(true);
-
         bigPort.setLineWidth(0);
-        setLineWidth(0);
+
         addFig(bigPort);
     }
     
@@ -79,7 +90,7 @@
     }
 
     /**
-     * @return the bigport
+     * @return the bigPort
      */
     public Fig getBigPort() {
         return bigPort;
@@ -87,7 +98,7 @@
 
     /**
      * The minimum width is the minimum width of the child with the widest
-     * miniumum width.
+     * minimum width.
      * The minimum height is the total minimum height of all child figs plus a
      * 2 pixel padding.
      * @return the minimum width
@@ -110,34 +121,56 @@
         return new Dimension(minWidth, minHeight);
     }
 
-    /*
-     * @see org.tigris.gef.presentation.Fig#setBoundsImpl(int, int, int, int)
-     */
     @Override
     protected void setBoundsImpl(int x, int y, int w, int h) {
-        int newW = w;
-        int newH = h;
+        Rectangle oldBounds = getBounds();
 
-        int fw;
-        int yy = y;
-        for  (Fig fig : (Collection<Fig>) getFigs()) {
+        Dimension minimumSize = getMinimumSize();
+        int newW = Math.max(w, minimumSize.width);
+        int newH = Math.max(h, minimumSize.height);
+
+        int currentHeight = 0;
+
+        for  (Fig fig : (List<Fig>) getFigs()) {
             if (fig.isVisible() && fig != getBigPort()) {
-                fw = fig.getMinimumSize().width;
-                //set new bounds for all included figs
-                fig.setBounds(x + 1, yy + 1, fw, fig.getMinimumSize().height);
-                if (newW < fw + 2) {
-                    newW = fw + 2;
-                }
-                yy += fig.getMinimumSize().height;
+                int fh = fig.getMinimumSize().height;
+
+                fig.setBounds(x, y + currentHeight, newW, fh);
+                currentHeight += fh;
             }
         }
         getBigPort().setBounds(x, y, newW, newH);
         calcBounds();
+        firePropChange("bounds", oldBounds, getBounds());
     }
     
     /**
      * Create a new model element for the compartment.
      */
     protected abstract void createModelElement();
-    
+
+    @Override
+    public void setLineWidth(int w) {
+        super.setLineWidth(w);
+        bigPort.setLineWidth(0);
+    }
+
+    @Override
+    public void setFilled(boolean f) {
+        // Only the bigPort may be filled
+        super.setFilled(false);
+        bigPort.setFilled(f);
+    }
+
+    @Deprecated //see parent
+    @Override
+    public boolean getFilled() {
+        return isFilled();
+    }
+
+    @Override
+    public boolean isFilled() {
+        return bigPort.isFilled();
+    }
+
 }

Modified: trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigCompartmentBox.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigCompartmentBox.java?view=diff&pathrev=17338&r1=17337&r2=17338
==============================================================================
--- trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigCompartmentBox.java	(original)
+++ trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigCompartmentBox.java	2009-09-22 01:39:41-0700
@@ -29,8 +29,10 @@
 import java.awt.Rectangle;
 import java.awt.event.InputEvent;
 import java.awt.event.MouseEvent;
+import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.log4j.Logger;
 import org.argouml.ui.targetmanager.TargetManager;
 import org.argouml.uml.diagram.DiagramSettings;
 import org.argouml.uml.diagram.static_structure.ui.SelectionClass;
@@ -41,36 +43,44 @@
 import org.tigris.gef.presentation.FigGroup;
 
 /**
- * Class to display graphics for a node with compartments in a diagram.<p>
+ * Class to display graphics for a node with compartments in a diagram.
+ * <p>
  * 
- * It adds a border around the box, 
- * and deals with highlighting editable compartments.<p>
+ * The leaf descendants of this class shall add the compartments in top to
+ * bottom order.
+ * <p>
  * 
- * All descendants of this class have the bigPort filled with the main fig 
- * fill color, without border. The borderFig has a transparent fill, 
- * and a visible border. <p>
+ * It adds a border around the box, and deals with highlighting editable
+ * compartments.
+ * <p>
+ * 
+ * All descendants of this class have the bigPort filled with the main fig fill
+ * color, without border. The borderFig has a transparent fill, and a visible
+ * border.
+ * <p>
  * 
  * Why do we need a separate border fig: I (MVW) think because 
- * some figs may have parts protruding outside the box like a UML Package 
- * or like a  UML Component. 
+ * some figs may have parts protruding outside the box like a 
+ * UML Package or like a UML Component.
  * 
- * TODO: Why is the fill not drawn by the borderFig? 
- * In the current situation, the border is drawn OVER 
- * the background fill (which won't work if colors have alpha 
- * channels). But the fill should only be drawn WITHIN 
- * the border. 
- * MVW: I propose to have the borderFig show the fill color 
- * and have the bigPort be transparent and without border.
- * Then we would need a drawing sequence change, too.
- * Or maybe the compartments should draw the fill color instead?
+ * TODO: Why is the fill not drawn by the borderFig? In the current 
+ * situation, the border is drawn OVER the background fill (which 
+ * won't work if colors have alpha channels). But the fill should only 
+ * be drawn WITHIN the border. MVW: I propose to have the borderFig
+ * show the fill color and have the bigPort be transparent and 
+ * without border. Then we would need a drawing sequence change,
+ * too. Or maybe the compartments should draw the fill color instead?
  * <p>
  * 
- * The name, keyword and stereotype are shown in 
- * transparent figs without border, but their size is reduced so that they 
- * fit within the border of the borderFig.
+ * The name, keyword and stereotype are shown in transparent figs without
+ * border, but their size is reduced so that they fit within the border of the
+ * borderFig.
  */
 public abstract class FigCompartmentBox extends FigNodeModelElement {
 
+    private static final Logger LOG = Logger.getLogger(
+            FigCompartmentBox.class);
+
     /**
      * Default bounds for a compartment.
      */
@@ -86,6 +96,9 @@
 
     private Fig borderFig;
 
+    private List<FigCompartment> compartments = 
+        new ArrayList<FigCompartment>();
+
     /**
      * Initialization shared by all constructors.
      */
@@ -95,13 +108,17 @@
         // when we try to render it, if we find we have a stereotype.
         getStereotypeFig().setVisible(false);
 
-        /* The nameFig is transparent, since this is a box and
-         * the fill color is drawn by the bigPort. */
+        /*
+         * The nameFig is transparent, since this is a box and the fill color is
+         * drawn by the bigPort.
+         */
         getNameFig().setFillColor(null);
-        
-        /* The borderFig shows the outside border of the box 
-         * around all compartments. Its size always equals the bigPort.
-         * Its body is transparent. */
+
+        /*
+         * The borderFig shows the outside border of the box around all
+         * compartments. Its size always equals the bigPort. Its body is
+         * transparent.
+         */
         borderFig = new FigEmptyRect(X0, Y0, 0, 0);
         borderFig.setLineColor(LINE_COLOR);
         borderFig.setLineWidth(LINE_WIDTH);
@@ -109,14 +126,15 @@
         getBigPort().setLineWidth(0);
         /* The bigPort draws the background color: */
         getBigPort().setFillColor(FILL_COLOR);
-        
-        /* TODO: The above means that the border is drawn OVER 
-         * the background fill (which won't work if colors have alpha 
-         * channels). But the fill should only be drawn WITHIN 
-         * the border. 
-         * MVW: I propose to have the borderFig show the fill color 
-         * and have the bigPort be transparent and without border. 
-         * */
+
+        /*
+         * TODO: The above means that the border is drawn OVER 
+         * the background fill (which won't work if colors have 
+         * alpha channels). But the fill should only be drawn WITHIN 
+         * the border. MVW: I propose to have the borderFig show 
+         * the fill color and have the bigPort be transparent and
+         * without border.
+         */
     }
 
     /**
@@ -131,7 +149,166 @@
         super(owner, bounds, settings);
         initialize();
     }
-    
+
+    @Override
+    public void addFig(Fig fig) {
+        if (fig instanceof FigCompartment) {
+            addCompartment((FigCompartment) fig);
+        }
+        super.addFig(fig);
+    }
+
+    private void addCompartment(FigCompartment c) {
+        assert !compartments.contains(c);
+        compartments.add(c);
+    }
+
+    protected int getVisibleCompartmentCount() {
+        int result = 0;
+        for (int i = 0; i < compartments.size(); i++) {
+            result += compartments.get(i).isVisible() ? 1 : 0;
+        }
+        return result;
+    }
+
+    @Override
+    public Dimension getMinimumSize() {
+        // Use "aSize" to build up the minimum size. Start with the size of the
+        // name compartment and build up.
+        Dimension aSize = getNameFig().getMinimumSize();
+
+        /*
+         * Only take into account the stereotype width, not the height, since
+         * the height is included in the name fig:
+         */
+        aSize = addChildWidth(aSize, getStereotypeFig());
+
+        /* Add the height of all the compartments (if there are any),
+         * and check their minimum width: */
+        for (FigCompartment c : compartments) {
+            aSize = addChildDimensions(aSize, c);
+        }
+
+        /* We want to maintain a minimum width for the fig. Also, add the border
+         * dimensions to the minimum space required for its contents:
+         */
+        aSize.width = Math.max(WIDTH, aSize.width);
+        aSize.width += 2 * getLineWidth();
+        aSize.height += 2 * getLineWidth();
+
+        return aSize;
+    }
+
+    /**
+     * Sets the bounds, but the size will be at least the one returned by
+     * {@link #getMinimumSize()}, unless checking of size is disabled.
+     * <p>
+     * 
+     * If the required height is bigger, then the additional height is equally
+     * distributed among all compartments, such that the accumulated height of
+     * all visible figs equals the demanded height.
+     * 
+     * @param x Desired X coordinate of upper left corner
+     * 
+     * @param y Desired Y coordinate of upper left corner
+     * 
+     * @param width Desired width of the Fig
+     * 
+     * @param height Desired height of the Fig
+     * 
+     * @see org.tigris.gef.presentation.Fig#setBoundsImpl(int, int, int, int)
+     */
+    @Override
+    protected void setStandardBounds(final int x, final int y, final int w,
+            final int h) {
+
+        // Save our old boundaries so it can be used in property message later
+        Rectangle oldBounds = getBounds();
+
+        // Make sure we don't try to set things smaller than the minimum
+        Dimension minimumSize = getMinimumSize();
+        int newW = Math.max(w, minimumSize.width);
+        int newH = Math.max(h, minimumSize.height);
+
+        int currentHeight = 0;
+
+        if (getStereotypeFig().isVisible()) {
+            int stereotypeHeight = getStereotypeFig().getMinimumSize().height;
+            getNameFig().setTopMargin(stereotypeHeight);
+            getStereotypeFig().setBounds(x + getLineWidth(),
+                    y + getLineWidth(), newW - 2 * getLineWidth(),
+                    stereotypeHeight);
+        } else {
+            getNameFig().setTopMargin(0);
+        }
+
+        /* Now the new nameFig height will include the stereotype height: */
+        Dimension nameMin = getNameFig().getMinimumSize();
+        int minNameHeight = Math.max(nameMin.height, NAME_FIG_HEIGHT);
+
+        getNameFig().setBounds(x + getLineWidth(), y + getLineWidth(),
+                newW - 2 * getLineWidth(), minNameHeight);
+
+        /* The new height can not be less than the name height: */
+        /*
+         * TODO: Is this needed/correct? 
+         * For when all compartments are hidden?
+         */
+        newH = Math.max(minNameHeight + 2 * getLineWidth(), newH);
+
+        currentHeight += minNameHeight;
+
+        int requestedHeight = newH - currentHeight - 2 * getLineWidth();
+        int neededHeight = 0;
+        /* Calculate the minimum needed height for all the compartments:*/
+        for (FigCompartment c : compartments) {
+            if (c.isVisible()) {
+                neededHeight += c.getMinimumSize().height;
+            }
+        }
+
+        for (FigCompartment c : compartments) {
+            if (c.isVisible()) {
+                int compartmentHeight = c.getMinimumSize().height;
+                if (requestedHeight > neededHeight) {
+                    /*
+                     * Distribute the extra height over the visible
+                     * compartments:
+                     */
+                    compartmentHeight += (requestedHeight - neededHeight)
+                            / getVisibleCompartmentCount();
+                }
+                c.setBounds(x + getLineWidth(), 
+                        y + currentHeight + getLineWidth(), 
+                        newW - 2 * getLineWidth(),
+                        compartmentHeight);
+                currentHeight += compartmentHeight;
+            }
+        }
+        if (requestedHeight < neededHeight) {
+            /* Increase the height of the fig: */
+            newH += neededHeight - requestedHeight;
+        }
+        /*
+         * If requested height equals needed height then do nothing; it fits
+         * exactly.
+         */
+
+        /* Finally set the bounds of the big box and the border fig: */
+        getBigPort().setBounds(x, y, newW, newH);
+        getBorderFig().setBounds(x, y, newW, newH);
+
+        // Now force calculation of the bounds of the figure, update the edges
+        // and trigger anyone who's listening to see if the "bounds" property
+        // has changed.
+
+        calcBounds();
+        updateEdges();
+        LOG.debug("Bounds change : old - " + oldBounds + ", new - "
+                + getBounds());
+        firePropChange("bounds", oldBounds, getBounds());
+    }
+
     /*
      * @see org.tigris.gef.presentation.Fig#translate(int, int)
      */
@@ -239,11 +416,6 @@
         return null;
     }
 
-    /*
-     * @see org.argouml.uml.diagram.ui.FigNodeModelElement#createContainedModelElement(
-     *         org.tigris.gef.presentation.FigGroup,
-     *         java.awt.event.InputEvent)
-     */
     protected void createContainedModelElement(FigGroup fg, InputEvent ie) {
         if (!(fg instanceof FigEditableCompartment)) {
             return;
@@ -279,16 +451,16 @@
         }
         ie.consume();
     }
-    
+
     protected Fig getBorderFig() {
-	return borderFig;
+        return borderFig;
     }
 
     /**
-     * This utility adds the size of a child component to an overall size. 
-     * The width is maximized with child's width and the
-     * child's height is added to the overall height.
-     * If the child figure is not visible or not yet created, it's size is not added.
+     * This utility adds the size of a child component to an overall size. The
+     * width is maximized with child's width and the child's height is added to
+     * the overall height. If the child figure is not visible or not yet
+     * created, it's size is not added.
      * 
      * @param size current dimensions - modified with the result
      * @param child child figure
@@ -305,16 +477,16 @@
     }
 
     /**
-     * This utility adds the width of a child component to an overall size. 
-     * The width is maximized with child's width and the
-     * child's height is ignored.
+     * This utility adds the width of a child component to an overall size. The
+     * width is maximized with child's width and the child's height is ignored.
      * If the child figure is not visible, it's size is not added.
      * 
      * @param size current dimensions - modified with the result
      * @param child child figure
      * @return new Dimension with child width added
      */
-    protected static Dimension addChildWidth(Dimension size, Fig child) {
+    protected static Dimension addChildWidth(Dimension size, 
+            Fig child) {
         if (child.isVisible()) {
             Dimension childSize = child.getMinimumSize();
             size.width = Math.max(size.width, childSize.width);
@@ -328,19 +500,29 @@
      *
      * @see org.argouml.uml.diagram.AttributesCompartmentContainer#setAttributesVisible(boolean)
      */
-    protected void setCompartmentVisible(FigCompartment compartment, 
+    protected void setCompartmentVisible(FigCompartment compartment,
             boolean isVisible) {
         Rectangle rect = getBounds();
         if (compartment.isVisible()) {
-            if (!isVisible) {  // hide compartment
+            if (!isVisible) { // hide compartment
                 damage();
                 for (Object f : compartment.getFigs()) {
                     ((Fig) f).setVisible(false);
                 }
                 compartment.setVisible(false);
-                Dimension aSize = this.getMinimumSize();
-                setBounds(rect.x, rect.y,
-                          (int) aSize.getWidth(), (int) aSize.getHeight());
+                /*
+                 * Hiding one compartment means that the Fig returns to minimal
+                 * dimensions:
+                 */
+                Dimension aSize = getMinimumSize();
+                setBounds(rect.x, rect.y, (int) aSize.getWidth(), (int) aSize
+                        .getHeight());
+                /*
+                 * Alternatively, we could reduce the height of the Fig by the
+                 * height of this one hidden compartment. But that would not be
+                 * possible for the width - so we better return to minimal
+                 * dimensions overall.
+                 */
             }
         } else {
             if (isVisible) { // show compartment
@@ -355,10 +537,12 @@
             }
         }
     }
-    
+
     @Override
     public void setLineWidth(int w) {
-        borderFig.setLineWidth(w);
+        /* This sets the lineWidth of all in the group: */
+        super.setLineWidth(w);
+        /* NameFig and StereotypeFig are handled by parent. */
     }
 
     @Override
@@ -367,14 +551,8 @@
     }
 
     @Override
-    public void setLineColor(Color col) {
-        getStereotypeFig().setLineColor(null);
-        borderFig.setLineColor(col);
-    }
-
-    @Override
     public void setFillColor(Color col) {
-        getBigPort().setFillColor(col);
+        super.setFillColor(col);
         getStereotypeFig().setFillColor(null);
         getNameFig().setFillColor(null);
     }
@@ -383,23 +561,25 @@
     public Color getFillColor() {
         return getBigPort().getFillColor();
     }
-    
+
     @Override
     public void setFilled(boolean f) {
+        super.setFilled(f);
         getBigPort().setFilled(f);
+        getNameFig().setFilled(false);
         getStereotypeFig().setFilled(false);
     }
-    
+
     @Override
     protected void updateStereotypeText() {
 
         if (getOwner() == null) {
             return;
         }
-        
+
         getStereotypeFig().setVisible(
                 getStereotypeFig().getStereotypeCount() > 0);
-        
+
         super.updateStereotypeText();
 
         if (getStereotypeFig().isVisible()) {
@@ -410,7 +590,7 @@
         }
 
         /* TODO: Is this needed? */
-//        forceRepaintShadow();
+        // forceRepaintShadow();
     }
 
 }

Modified: trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigEditableCompartment.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigEditableCompartment.java?view=diff&pathrev=17338&r1=17337&r2=17338
==============================================================================
--- trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigEditableCompartment.java	(original)
+++ trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigEditableCompartment.java	2009-09-22 01:39:41-0700
@@ -24,6 +24,7 @@
 
 package org.argouml.uml.diagram.ui;
 
+import java.awt.Color;
 import java.awt.Dimension;
 import java.awt.Rectangle;
 import java.util.ArrayList;
@@ -35,14 +36,17 @@
 import org.argouml.notation.NotationProvider;
 import org.argouml.uml.diagram.DiagramSettings;
 import org.tigris.gef.presentation.Fig;
-import org.tigris.gef.presentation.FigLine;
+import org.tigris.gef.presentation.FigRect;
 
 /**
  * Presentation logic for a boxed compartment,
  * which is common to e.g. an operations
  * compartment and an attributes compartment.<p>
  * 
- * This class is adds the possibility to 
+ * It adds a separator line at the top of the compartment, 
+ * which follows the line width and color of the parent. <p>
+ * 
+ * This class adds the possibility to 
  * make the whole compartment invisible, and
  * a NotationProvider is used to handle (generate and parse) 
  * the texts shown in the compartment, i.e. 
@@ -57,7 +61,7 @@
 
     private static final int MIN_HEIGHT = FigNodeModelElement.NAME_FIG_HEIGHT;
 
-    private FigSeperator compartmentSeperator;
+    private FigSeparator compartmentSeperator;
 
     /**
      * The constructor. <p>
@@ -81,7 +85,8 @@
     }
 
     private void constructFigs() {
-        compartmentSeperator = new FigSeperator(X0, Y0, 11);
+        compartmentSeperator = 
+            new FigSeparator(X0, Y0, 11, LINE_WIDTH);
         addFig(compartmentSeperator); // number 2
     }
     
@@ -90,7 +95,8 @@
      * encloses the entire group for use in attaching edges, etc and a
      * separator.
      * <p>
-     * NOTE: Subclasses should call populate() when they are fully constructed.
+     * NOTE: Subclasses should call populate() when 
+     * they are fully constructed.
      * 
      * @param owner owning UML element
      * @param bounds bounding rectangle of fig
@@ -107,7 +113,7 @@
     /**
      * @return separator figure
      */
-    protected FigSeperator getSeperatorFig() {
+    protected FigSeparator getSeperatorFig() {
         return compartmentSeperator;
     }
 
@@ -138,14 +144,11 @@
         }
     }
 
-    /*
-     * @see org.tigris.gef.presentation.FigGroup#addFig(org.tigris.gef.presentation.Fig)
-     */
     @Override
     public void addFig(Fig fig) {
         if (fig != getBigPort()
                 && !(fig instanceof CompartmentFigText)
-                && !(fig instanceof FigSeperator)) {
+                && !(fig instanceof FigSeparator)) {
             LOG.error("Illegal Fig added to a FigEditableCompartment");
             throw new IllegalArgumentException(
                     "A FigEditableCompartment can only "
@@ -330,7 +333,7 @@
             DiagramSettings settings);
     
     /**
-     * Returns the new size of the FigGroup (either attributes or
+     * Returns the new size of the FigGroup (e.g. attributes or
      * operations) after calculation new bounds for all sub-figs,
      * considering their minimal sizes; FigGroup need not be
      * displayed; no update event is fired.<p>
@@ -362,94 +365,63 @@
     @Override
     public Dimension getMinimumSize() {
         Dimension d = super.getMinimumSize();
-        if (d.height < MIN_HEIGHT) {
-            d.height = MIN_HEIGHT;
-        }
+        d.height = Math.max(d.height, 
+                MIN_HEIGHT + compartmentSeperator.getHeight());
         return d;
     }
 
-    /*
-     * @see org.tigris.gef.presentation.Fig#setBoundsImpl(int, int, int, int)
-     */
     @Override
-    protected void setBoundsImpl(int x, int y, int w, int h) {
-        int newW = w;
-        int newH = h;
-
-        int fw;
-        int yy = y;
-        int lineWidth = getLineWidth();
-        for (Fig fig : (List<Fig>) getFigs()) {
-            if (fig.isVisible() && fig != getBigPort()) {
-                if (fig instanceof FigSeperator) {
-                    fw = w;
-                } else {
-                    fw = fig.getMinimumSize().width;
-                }
-
-                fig.setBounds(x + lineWidth, yy + lineWidth, fw, 
-                        fig.getMinimumSize().height);
-                if (newW < fw + 2 * lineWidth) {
-                    newW = fw + 2 * lineWidth;
-                }
-                yy += fig.getMinimumSize().height;
-            }
+    public void setLineColor(Color col) {
+        super.setLineColor(col);
+        if (col != null) {
+            compartmentSeperator.setFillColor(col);
+            compartmentSeperator.setFilled(true);
         }
-        getBigPort().setBounds(x + lineWidth, y + lineWidth, 
-                newW - 2 * lineWidth, newH - 2 * lineWidth);
-        calcBounds();
+    }
+
+    @Override
+    public void setLineWidth(int w) {
+        super.setLineWidth(0);
+    }
+
+    @Override
+    public void setFillColor(Color col) {
+        super.setFillColor(col);
+        compartmentSeperator.setFillColor(getLineColor());
+        compartmentSeperator.setFilled(true);
+    }
+
+    @Override
+    public void setFilled(boolean f) {
+        super.setFilled(f);
+        compartmentSeperator.setFilled(true);
     }
 
     /**
-     * Fig representing separator for compartment.
-     * This is a horizontal line.
+     * Fig representing a horizontal line separator for compartment. <p>
+     * 
+     * This is a horizontal line, but implemented as a rectangle 
+     * filled with the line color, since using a FigLine would draw the line 
+     * around the start and end coordinates with a line width > 1.
      */
-    protected static class FigSeperator extends FigLine {
+    protected static class FigSeparator extends FigRect {
         /**
          * Constructor.
-         * TODO: The line-width is set by the containing group - so
-         * no need to do that here also.
          *
          * @param x coordinate
          * @param y coordinate
          * @param len length of the line
          */
-        FigSeperator(int x, int y, int len) {
-            super(x, y, (x + len) - 1, y, LINE_COLOR);
-            setLineWidth(LINE_WIDTH);
-        }
-
-        /*
-         * @see org.tigris.gef.presentation.Fig#getSize()
-         */
-        @Override
-        public Dimension getSize() {
-            return new Dimension((_x2 - _x1) + 1, getLineWidth());
+        FigSeparator(int x, int y, int len, int lineWidth) {
+            super(x, y, len, lineWidth);
+            setLineWidth(0);
+            setFilled(true);
         }
 
-        /*
-         * @see org.tigris.gef.presentation.Fig#getMinimumSize()
-         */
         @Override
         public Dimension getMinimumSize() {
-            return new Dimension(0, getLineWidth());
-        }
-
-        /*
-         * @see org.tigris.gef.presentation.Fig#setBoundsImpl(
-         *         int, int, int, int)
-         */
-        @Override
-        public void setBoundsImpl(int x, int y, int w, int h) {
-            setX1(x);
-            setY1(y);
-            setX2((x + w) - 1);
-            setY2(y);
-        }
-
-        /**
-         * The UID.
-         */
-        private static final long serialVersionUID = -2222511596507221760L;
+            return new Dimension(MIN_SIZE, getHeight());
+        }        
+        
     }
 }

Modified: trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigStereotypesGroup.java
Url: http://argouml.tigris.org/source/browse/argouml/trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigStereotypesGroup.java?view=diff&pathrev=17338&r1=17337&r2=17338
==============================================================================
--- trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigStereotypesGroup.java	(original)
+++ trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigStereotypesGroup.java	2009-09-22 01:39:41-0700
@@ -389,15 +389,19 @@
     protected void setBoundsImpl(int x, int y, int w, int h) {
         Rectangle oldBounds = getBounds();
 
+        Dimension minimumSize = getMinimumSize();
+        int newW = Math.max(w, minimumSize.width);
+        int newH = Math.max(h, minimumSize.height);
+        
         int yy = y;
         for  (Fig fig : (Collection<Fig>) getFigs()) {
             if (fig != bigPort) {
-                fig.setBounds(x + 1, yy + 1, w - 2,
+                fig.setBounds(x, yy, newW,
                               fig.getMinimumSize().height);
                 yy += fig.getMinimumSize().height;
             }
         }
-        bigPort.setBounds(x, y, w, h);
+        bigPort.setBounds(x, y, newW, newH);
         calcBounds();
         firePropChange("bounds", oldBounds, getBounds());
     }


------------------------------------------------------
http://argouml.tigris.org/ds/viewMessage.do?dsForumId=5905&dsMessageId=2397702

To unsubscribe from this discussion, e-mail: [[email protected]].
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.