Author: penyaskito
Date: 2008-04-23 16:45:11-0700
New Revision: 14449

Modified:
   trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigNodeModelElement.java

Log:
Update the UI of the FigNodes in the Swing/AWT thread. Related to issue 5016.

Modified: 
trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigNodeModelElement.java
Url: 
http://argouml.tigris.org/source/browse/argouml/trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigNodeModelElement.java?view=diff&rev=14449&p1=trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigNodeModelElement.java&p2=trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigNodeModelElement.java&r1=14448&r2=14449
==============================================================================
--- 
trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigNodeModelElement.java   
    (original)
+++ 
trunk/src/argouml-app/src/org/argouml/uml/diagram/ui/FigNodeModelElement.java   
    2008-04-23 16:45:11-0700
@@ -78,6 +78,7 @@
 import org.argouml.model.DiElement;
 import org.argouml.model.InvalidElementException;
 import org.argouml.model.Model;
+import org.argouml.model.UmlChangeEvent;
 import org.argouml.notation.NotationProvider;
 import org.argouml.notation.NotationProviderFactory2;
 import org.argouml.ui.ArgoJMenu;
@@ -912,9 +913,9 @@
     /*
      * @see 
java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
      */
-    public void propertyChange(PropertyChangeEvent pve) {
-        Object src = pve.getSource();
-        String pName = pve.getPropertyName();
+    public void propertyChange(final PropertyChangeEvent pve) {
+        final Object src = pve.getSource();
+        final String pName = pve.getPropertyName();
         if (pve instanceof DeleteInstanceEvent && src == getOwner()) {
             removeFromDiagram();
             return;
@@ -926,35 +927,87 @@
                 //parse the text that was edited
                 textEdited((FigText) src);
                 // resize the FigNode to accomodate the new text
-                Rectangle bbox = getBounds();
-                Dimension minSize = getMinimumSize();
+                final Rectangle bbox = getBounds();
+                final Dimension minSize = getMinimumSize();
                 bbox.width = Math.max(bbox.width, minSize.width);
                 bbox.height = Math.max(bbox.height, minSize.height);
                 setBounds(bbox.x, bbox.y, bbox.width, bbox.height);
                 endTrans();
             } catch (PropertyVetoException ex) {
                 LOG.error("could not parse the text entered. "
-                         + "PropertyVetoException",
-                         ex);
+                        + "PropertyVetoException",
+                        ex);
             }
         } else if (pName.equals("editing")
-                        && Boolean.TRUE.equals(pve.getNewValue())) {
+                && Boolean.TRUE.equals(pve.getNewValue())) {
             textEditStarted((FigText) src);
         } else {
             super.propertyChange(pve);
         }
         if (Model.getFacade().isAUMLElement(src)) {
+            final UmlChangeEvent event = (UmlChangeEvent) pve;
             /* If the source of the event is an UML object,
              * e.g. the owner of this Fig (but not always only the owner
              * is shown, e.g. for a class, also its attributes are shown),
              * then the UML model has been changed.
              */
-            // We catch the exception here so it is handled for all subclasses
+            final Object owner = getOwner();
+            if (owner == null) {
+                // TODO: Should this not be an assert?
+                return;
+            }
             try {
-                modelChanged(pve);
-            } catch (InvalidElementException e) {
-                LOG.debug("modelChanged method accessed deleted element ", e);
+                modelChanged(event);
             }
+            catch (InvalidElementException e) {
+                LOG.debug("modelChanged method accessed deleted element ", e); 
           
+            }
+            if (event.getSource() == owner 
+                    && "stereotype".equals(event.getPropertyName())) {
+                stereotypeChanged(event);            
+            }
+            Runnable doWorkRunnable = new Runnable() {
+                public void run() {
+                    try {
+                        updateLayout(event);
+                    }
+                    catch (InvalidElementException e) {
+                        LOG.debug("modelChanged method accessed deleted 
element ", e);
+                    }
+                }  
+            };
+            SwingUtilities.invokeLater(doWorkRunnable);
+        }
+    }
+
+    /**
+     * Called by propertyChanged when it detects that a stereotype
+     * has been added or removed. On removal the FigNode removes its
+     * listener to that stereotype. When a new stereotype is detected
+     * we add a listener.
+     * TODO: Bob says: In my opinion we shouldn't be doing this here.
+     * FigStereotype should always be listening to change of its
+     * owners name.
+     * FigStereotypesCompartment should always be listening for add
+     * or remove of Stereotypes to its owner.
+     * Those classes will need to pass some event to the FigNode on
+     * the AWT thread only if a change results in a change of size
+     * that requires a redraw.
+     * <p>NOTE: Runs at the Model (MDR) Thread </p>
+     * @param event the UmlChangeEvent that caused the change
+     */
+    private void stereotypeChanged(final UmlChangeEvent event) {
+        final Object owner = getOwner();
+        assert owner != null;
+        try {          
+            if (event.getOldValue() != null) {
+                removeElementListener(event.getOldValue());
+            }
+            if (event.getNewValue() != null) {
+                addElementListener(event.getNewValue(), "name");
+            }
+        } catch (InvalidElementException e) {
+            LOG.debug("stereotypeChanged method accessed deleted element ", e);
         }
     }
 
@@ -1103,59 +1156,74 @@
         nameFig.keyTyped(ke);
     }
 
+    /**
+     * This is a template method called by the ArgoUML framework as the result
+     * of a change to a model element. Do not call this method directly
+     * yourself.
+     * <p>Override this in any subclasses in order to change what model
+     * elements the FigNode is listening to as a result of change to the 
model.</p>
+     * <p>This method is guaranteed by the framework to be running on the same
+     * thread as the model subsystem.</p>
+     * TODO: Lets refactor this at some time to take UmlChangeEvent argument
+     *
+     * @param event the UmlChangeEvent that caused the change
+     */
+    protected void modelChanged(PropertyChangeEvent event) {
+        if (event instanceof AssociationChangeEvent 
+                || event instanceof AttributeChangeEvent) {
+            if (notationProviderName != null) {
+                notationProviderName.updateListener(this, getOwner(), event);
+            }
+            updateListeners(getOwner(), getOwner());
+        }
+    }    
+    
     ////////////////////////////////////////////////////////////////
     // internal methods
-
+    
     /**
-      * This is called after any part of the UML ModelElement has
-     * changed. This method automatically updates the stereotype rendering, 
-     * and updates all listeners for the stereotypes.
-     * Updating the listeners for the name notation is delegated 
-     * to the notation provider for the name.
-     * Subclasses should override and update other parts. <p>
-     *
-     * For e.g. a Package, if the visibility is changed 
+     * This is a template method called by the ArgoUML framework as the result
+     * of a change to a model element. Do not call this method directly
+     * yourself.
+     * <p>Override this in any subclasses in order to restructure the FigNode
+     * due to change of any model element that this FigNode is listening 
to.</p>
+     * <p>This method automatically updates the stereotype rendering.</p>
+     * <p>The default behavior is to update the name and stereotype text.</p>
+     * <p>For e.g. a Package, if the visibility is changed 
      * via the properties panel, then
      * the display of it on the diagram has to follow the change.
-     * This is not handled here, but by the notationProviderName.
+     * This is not handled here, but by the notationProviderName.</p>
+     * <p>This method is guaranteed by the framework to be running on the 
+     * Swing/AWT thread.</p>
      *
-     * @param mee the ModelElementEvent that caused the change
+     * @param event the UmlChangeEvent that caused the change
      */
-    protected void modelChanged(PropertyChangeEvent mee) {
-        if (mee == null) {
-            throw new IllegalArgumentException("event may never be null "
-                           + "with modelchanged");
-        }
-        Object owner = getOwner();
-        // If the element has been deleted, the caller will
-        // receive an InvalidElementException that it must handle.
+    protected void updateLayout(UmlChangeEvent event) {
+        assert event != null;
+        final Object owner = getOwner();
+        assert owner != null;
         if (owner == null) {
             return;
         }
-        if (mee instanceof AssociationChangeEvent 
-                || mee instanceof AttributeChangeEvent) {
+        boolean needDamage = false;
+        if (event instanceof AssociationChangeEvent 
+                || event instanceof AttributeChangeEvent) {
             if (notationProviderName != null) {
-                notationProviderName.updateListener(this, getOwner(), mee);
                 updateNameText();
             }
-            updateListeners(getOwner(), getOwner());
-            damage();
+            needDamage = true;
         }
-        if ((mee.getSource() == owner
-                && mee.getPropertyName().equals("stereotype"))) {
-            if (mee.getOldValue() != null) {
-                removeElementListener(mee.getOldValue());
-            }
-            if (mee.getNewValue() != null) {
-                addElementListener(mee.getNewValue(), "name");
-            }
+        if (event.getSource() == owner
+                && "stereotype".equals(event.getPropertyName())) {
             updateStereotypeText();
             updateStereotypeIcon();
+            needDamage = true;
+        }
+        if (needDamage) {
             damage();
         }
     }
 
-
     /**
      * Create a new model element contained in the fig owner.
      * Used by subclasses to, for example, create an attribute

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to