Coverage Report - org.argouml.uml.diagram.static_structure.ui.FigComment
 
Classes in this File Line Coverage Branch Coverage Complexity
FigComment
0%
0/242
0%
0/90
2.459
 
 1  
 /* $Id: FigComment.java 18728 2010-09-10 09:29:47Z mvw $
 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  
  *    Michiel van der Wulp
 11  
  *****************************************************************************
 12  
  *
 13  
  * Some portions of this file was previously release using the BSD License:
 14  
  */
 15  
 
 16  
 // Copyright (c) 1996-2009 The Regents of the University of California. All
 17  
 // Rights Reserved. Permission to use, copy, modify, and distribute this
 18  
 // software and its documentation without fee, and without a written
 19  
 // agreement is hereby granted, provided that the above copyright notice
 20  
 // and this paragraph appear in all copies.  This software program and
 21  
 // documentation are copyrighted by The Regents of the University of
 22  
 // California. The software program and documentation are supplied "AS
 23  
 // IS", without any accompanying services from The Regents. The Regents
 24  
 // does not warrant that the operation of the program will be
 25  
 // uninterrupted or error-free. The end-user understands that the program
 26  
 // was developed for research purposes and is advised not to rely
 27  
 // exclusively on the program for any reason.  IN NO EVENT SHALL THE
 28  
 // UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
 29  
 // SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
 30  
 // ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
 31  
 // THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
 32  
 // SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
 33  
 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 34  
 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
 35  
 // PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
 36  
 // CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
 37  
 // UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 38  
 
 39  
 package org.argouml.uml.diagram.static_structure.ui;
 40  
 
 41  
 import java.awt.Color;
 42  
 import java.awt.Dimension;
 43  
 import java.awt.Point;
 44  
 import java.awt.Polygon;
 45  
 import java.awt.Rectangle;
 46  
 import java.awt.event.InputEvent;
 47  
 import java.awt.event.KeyEvent;
 48  
 import java.awt.event.KeyListener;
 49  
 import java.awt.event.MouseEvent;
 50  
 import java.awt.event.MouseListener;
 51  
 import java.beans.PropertyChangeEvent;
 52  
 import java.beans.PropertyChangeListener;
 53  
 import java.beans.VetoableChangeListener;
 54  
 import java.util.ArrayList;
 55  
 import java.util.Collection;
 56  
 import java.util.Iterator;
 57  
 
 58  
 import javax.swing.SwingUtilities;
 59  
 
 60  
 import org.apache.log4j.Logger;
 61  
 import org.argouml.kernel.DelayedChangeNotify;
 62  
 import org.argouml.kernel.DelayedVChangeListener;
 63  
 import org.argouml.model.AttributeChangeEvent;
 64  
 import org.argouml.model.Model;
 65  
 import org.argouml.model.RemoveAssociationEvent;
 66  
 import org.argouml.model.UmlChangeEvent;
 67  
 import org.argouml.ui.ArgoJMenu;
 68  
 import org.argouml.uml.diagram.DiagramSettings;
 69  
 import org.argouml.uml.diagram.ui.FigMultiLineText;
 70  
 import org.argouml.uml.diagram.ui.FigNodeModelElement;
 71  
 import org.tigris.gef.base.Geometry;
 72  
 import org.tigris.gef.base.Selection;
 73  
 import org.tigris.gef.presentation.Fig;
 74  
 import org.tigris.gef.presentation.FigPoly;
 75  
 import org.tigris.gef.presentation.FigRect;
 76  
 import org.tigris.gef.presentation.FigText;
 77  
 
 78  
 /**
 79  
  * Class to display a UML comment in a diagram.
 80  
  *
 81  
  * @author Andreas Rueckert
 82  
  */
 83  
 public class FigComment
 84  
     extends FigNodeModelElement
 85  
     implements VetoableChangeListener,
 86  
                DelayedVChangeListener,
 87  
                MouseListener,
 88  
                KeyListener,
 89  
                PropertyChangeListener {
 90  
     /**
 91  
      * Logger.
 92  
      */
 93  0
     private static final Logger LOG = Logger.getLogger(FigComment.class);
 94  
 
 95  
     ////////////////////////////////////////////////////////////////
 96  
     // constants
 97  
 
 98  0
     private int width = 80;
 99  0
     private int height = 60;
 100  
 
 101  
     /**
 102  
      * A dog-ear is a bent corner in a book.
 103  
      */
 104  0
     private int dogear = 10;
 105  
 
 106  0
     private boolean readyToEdit = true;
 107  
 
 108  
     // The figure that holds the text of the note.
 109  
     private FigText bodyTextFig;
 110  
 
 111  
     private FigPoly outlineFig;
 112  
 
 113  
     /**
 114  
      * The upper right corner.
 115  
      */
 116  
     private FigPoly urCorner;
 117  
 
 118  
     /**
 119  
      * Flag to indicate that we have just been created. This is to fix the
 120  
      * problem with loading comments that have stereotypes already
 121  
      * defined.<p>
 122  
      */
 123  
     private boolean newlyCreated;
 124  
 
 125  
     @Override
 126  
     protected Fig createBigPortFig() {
 127  0
         FigRect fr = new FigRect(0, 0, width, height, null, null);
 128  0
         fr.setFilled(false);
 129  0
         fr.setLineWidth(0);
 130  0
         return fr;
 131  
     }
 132  
 
 133  
     private void initialize() {
 134  0
         Color fg = super.getLineColor(); // Use super because not fully init'd
 135  0
         Color fill = super.getFillColor();
 136  
         
 137  0
         outlineFig = new FigPoly(fg, fill);
 138  0
         outlineFig.addPoint(0, 0);
 139  0
         outlineFig.addPoint(width - 1 - dogear, 0);
 140  0
         outlineFig.addPoint(width - 1, dogear);
 141  0
         outlineFig.addPoint(width - 1, height - 1);
 142  0
         outlineFig.addPoint(0, height - 1);
 143  0
         outlineFig.addPoint(0, 0);
 144  0
         outlineFig.setFilled(true);
 145  0
         outlineFig.setLineWidth(LINE_WIDTH);
 146  
 
 147  0
         urCorner = new FigPoly(fg, fill);
 148  0
         urCorner.addPoint(width - 1 - dogear, 0);
 149  0
         urCorner.addPoint(width - 1, dogear);
 150  0
         urCorner.addPoint(width - 1 - dogear, dogear);
 151  0
         urCorner.addPoint(width - 1 - dogear, 0);
 152  0
         urCorner.setFilled(true);
 153  0
         Color col = outlineFig.getFillColor();
 154  0
         urCorner.setFillColor(col.darker());
 155  0
         urCorner.setLineWidth(LINE_WIDTH);
 156  
 
 157  
         // add Figs to the FigNode in back-to-front order
 158  0
         addFig(getBigPort());
 159  0
         addFig(outlineFig);
 160  0
         addFig(urCorner);
 161  0
         addFig(getStereotypeFig());
 162  0
         addFig(bodyTextFig);
 163  
         
 164  0
         col = outlineFig.getFillColor();
 165  0
         urCorner.setFillColor(col.darker());
 166  
 
 167  0
         setBlinkPorts(false); //make port invisible unless mouse enters
 168  0
         Rectangle r = getBounds();
 169  0
         setBounds(r.x, r.y, r.width, r.height);
 170  0
         updateEdges();
 171  
 
 172  0
         readyToEdit = false;
 173  
         // Mark this as newly created. This is to get round the problem with
 174  
         // creating figs for loaded comments that had stereotypes. They are
 175  
         // saved with their dimensions INCLUDING the stereotype, but since we
 176  
         // pretend the stereotype is not visible, we add height the first time
 177  
         // we render such a comment. This is a complete fudge, and really we
 178  
         // ought to address how comment objects with stereotypes are saved. But
 179  
         // that will be hard work.
 180  0
         newlyCreated = true;
 181  0
     }
 182  
 
 183  
     /**
 184  
      * Construct a comment figure with the given model element, bounds, and
 185  
      * settings. This constructor is used by the PGML parser.
 186  
      * 
 187  
      * @param owner owning Comments
 188  
      * @param bounds position and size
 189  
      * @param settings rendering settings
 190  
      */
 191  
     public FigComment(Object owner, Rectangle bounds, 
 192  
             DiagramSettings settings) {
 193  0
         super(owner, bounds, settings);
 194  
         
 195  0
         bodyTextFig = new FigMultiLineText(getOwner(), 
 196  
                 new Rectangle(2, 2, width - 2 - dogear, height - 4), 
 197  
                 getSettings(), true);
 198  
         
 199  0
         initialize();
 200  0
         updateBody();
 201  0
         if (bounds != null) {
 202  0
             setLocation(bounds.x, bounds.y);
 203  
         }
 204  0
     }
 205  
 
 206  
     /**
 207  
      * Get the default text for this figure.
 208  
      *
 209  
      * @return The default text for this figure.
 210  
      */
 211  
     @Override
 212  
     public String placeString() {
 213  0
         String placeString = retrieveBody();
 214  0
         if (placeString == null) {
 215  
             // TODO: I18N
 216  0
             placeString = "new note";
 217  
         }
 218  0
         return placeString;
 219  
     }
 220  
 
 221  
     /**
 222  
      * Clone this figure.
 223  
      *
 224  
      * @return The cloned figure.
 225  
      */
 226  
     @Override
 227  
     public Object clone() {
 228  0
         FigComment figClone = (FigComment) super.clone();
 229  0
         Iterator thisIter = this.getFigs().iterator();
 230  0
         while (thisIter.hasNext()) {
 231  0
             Object thisFig = thisIter.next();
 232  0
             if (thisFig == outlineFig) {
 233  0
                 figClone.outlineFig = (FigPoly) thisFig;
 234  
             }
 235  0
             if (thisFig == urCorner) {
 236  0
                 figClone.urCorner = (FigPoly) thisFig;
 237  
             }
 238  0
             if (thisFig == bodyTextFig) {
 239  0
                 figClone.bodyTextFig = (FigText) thisFig;
 240  
             }
 241  0
         }
 242  0
         return figClone;
 243  
     }
 244  
 
 245  
     private void updateBody() {
 246  0
         if (getOwner() != null) {
 247  0
             String body = (String) Model.getFacade().getBody(getOwner());
 248  0
             if (body != null) {
 249  0
                 bodyTextFig.setText(body);
 250  
             }
 251  
         }
 252  0
     }
 253  
 
 254  
 
 255  
     /**
 256  
      * See FigNodeModelElement.java for more info on these methods.
 257  
      */
 258  
 
 259  
     /**
 260  
      * If the user double clicks on any part of this FigNode, pass it
 261  
      * down to one of the internal Figs.  This allows the user to
 262  
      * initiate direct text editing.
 263  
      *
 264  
      * {@inheritDoc}
 265  
      */
 266  
     @Override
 267  
     public void mouseClicked(MouseEvent me) {
 268  0
         if (!readyToEdit) {
 269  0
             Object owner = getOwner();
 270  0
             if (Model.getFacade().isAModelElement(owner) 
 271  
                     && !Model.getModelManagementHelper().isReadOnly(owner)) {
 272  0
                 readyToEdit = true;
 273  
             } else {
 274  0
                 LOG.debug("not ready to edit note");
 275  0
                 return;
 276  
             }
 277  
         }
 278  0
         if (me.isConsumed()) {
 279  0
             return;
 280  
         }
 281  0
         if (me.getClickCount() >= 2
 282  
             && !(me.isPopupTrigger()
 283  
                  || me.getModifiers() == InputEvent.BUTTON3_MASK)) {
 284  0
             if (getOwner() == null) {
 285  0
                 return;
 286  
             }
 287  0
             Fig f = hitFig(new Rectangle(me.getX() - 2, me.getY() - 2, 4, 4));
 288  0
             if (f instanceof MouseListener) {
 289  0
                 ((MouseListener) f).mouseClicked(me);
 290  
             }
 291  
         }
 292  0
         me.consume();
 293  0
     }
 294  
 
 295  
     /*
 296  
      * @see java.beans.VetoableChangeListener#vetoableChange(java.beans.PropertyChangeEvent)
 297  
      */
 298  
     @Override
 299  
     public void vetoableChange(PropertyChangeEvent pce) {
 300  0
         Object src = pce.getSource();
 301  0
         if (src == getOwner()) {
 302  0
             DelayedChangeNotify delayedNotify =
 303  
                 new DelayedChangeNotify(this, pce);
 304  0
             SwingUtilities.invokeLater(delayedNotify);
 305  0
         } else {
 306  0
             LOG.debug("FigNodeModelElement got vetoableChange"
 307  
                       + " from non-owner:" + src);
 308  
         }
 309  0
     }
 310  
 
 311  
     /*
 312  
      * @see org.argouml.kernel.DelayedVChangeListener#delayedVetoableChange(java.beans.PropertyChangeEvent)
 313  
      */
 314  
     @Override
 315  
     public void delayedVetoableChange(PropertyChangeEvent pce) {
 316  
         // update any text, colors, fonts, etc.
 317  0
         renderingChanged();
 318  
         // update the relative sizes and positions of internel Figs
 319  0
         endTrans();
 320  0
     }
 321  
 
 322  
     /*
 323  
      * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
 324  
      */
 325  
     @Override
 326  
     public void propertyChange(PropertyChangeEvent pve) {
 327  0
         Object src = pve.getSource();
 328  0
         String pName = pve.getPropertyName();
 329  0
         if (pName.equals("editing")
 330  
             && Boolean.FALSE.equals(pve.getNewValue())) {
 331  
             //parse the text that was edited
 332  0
             textEdited((FigText) src);
 333  
             // resize the FigNode to accomodate the new text
 334  0
             Rectangle bbox = getBounds();
 335  0
             Dimension minSize = getMinimumSize();
 336  0
             bbox.width = Math.max(bbox.width, minSize.width);
 337  0
             bbox.height = Math.max(bbox.height, minSize.height);
 338  0
             setBounds(bbox.x, bbox.y, bbox.width, bbox.height);
 339  0
             endTrans();
 340  0
         } else {
 341  0
             super.propertyChange(pve);
 342  
         }
 343  0
     }
 344  
 
 345  
     /*
 346  
      * @see java.awt.event.KeyListener#keyPressed(java.awt.event.KeyEvent)
 347  
      */
 348  
     @Override
 349  
     public void keyPressed(KeyEvent ke) {
 350  
         // Not used, do nothing.
 351  0
     }
 352  
 
 353  
     /*
 354  
      * @see java.awt.event.KeyListener#keyReleased(java.awt.event.KeyEvent)
 355  
      */
 356  
     @Override
 357  
     public void keyReleased(KeyEvent ke) {
 358  
         // Not used, do nothing.
 359  0
     }
 360  
 
 361  
     /*
 362  
      * @see java.awt.event.KeyListener#keyTyped(java.awt.event.KeyEvent)
 363  
      */
 364  
     @Override
 365  
     public void keyTyped(KeyEvent ke) {
 366  0
         if (Character.isISOControl(ke.getKeyChar())) {
 367  0
             return;
 368  
         }
 369  0
         if (!readyToEdit) {
 370  0
             Object owner = getOwner();
 371  0
             if (Model.getFacade().isAModelElement(owner)
 372  
                     && !Model.getModelManagementHelper().isReadOnly(owner)) {
 373  0
                 storeBody("");
 374  0
                 readyToEdit = true;
 375  
             } else {
 376  0
                 LOG.debug("not ready to edit note");
 377  0
                 return;
 378  
             }
 379  
         }
 380  0
         if (ke.isConsumed()) {
 381  0
             return;
 382  
         }
 383  0
         if (getOwner() == null) {
 384  0
             return;
 385  
         }
 386  0
         bodyTextFig.keyTyped(ke);
 387  0
     }
 388  
 
 389  
     ////////////////////////////////////////////////////////////////
 390  
     // Fig accessors
 391  
 
 392  
     /**
 393  
      * @return an empty menu
 394  
      * @see org.argouml.uml.diagram.ui.FigNodeModelElement#buildShowPopUp()
 395  
      */
 396  
     @Override
 397  
     protected ArgoJMenu buildShowPopUp() {
 398  0
         return new ArgoJMenu("menu.popup.show");
 399  
     }
 400  
 
 401  
     /*
 402  
      * @see org.tigris.gef.presentation.Fig#makeSelection()
 403  
      */
 404  
     @Override
 405  
     public Selection makeSelection() {
 406  0
         return new SelectionComment(this);
 407  
     }
 408  
 
 409  
     /*
 410  
      * @see org.tigris.gef.presentation.Fig#setLineColor(java.awt.Color)
 411  
      */
 412  
     @Override
 413  
     public void setLineColor(Color col) {
 414  
         // The text element has no border, so the line color doesn't matter.
 415  0
         outlineFig.setLineColor(col);
 416  0
         urCorner.setLineColor(col);
 417  0
     }
 418  
 
 419  
     /*
 420  
      * @see org.tigris.gef.presentation.Fig#getLineColor()
 421  
      */
 422  
     @Override
 423  
     public Color getLineColor() {
 424  0
         return outlineFig.getLineColor();
 425  
     }
 426  
 
 427  
     /*
 428  
      * @see org.tigris.gef.presentation.Fig#setFillColor(java.awt.Color)
 429  
      */
 430  
     @Override
 431  
     public void setFillColor(Color col) {
 432  0
         outlineFig.setFillColor(col);
 433  0
         urCorner.setFillColor(col);
 434  0
     }
 435  
 
 436  
     /*
 437  
      * @see org.tigris.gef.presentation.Fig#getFillColor()
 438  
      */
 439  
     @Override
 440  
     public Color getFillColor() {
 441  0
         return outlineFig.getFillColor();
 442  
     }
 443  
 
 444  
     /*
 445  
      * @see org.tigris.gef.presentation.Fig#setFilled(boolean)
 446  
      */
 447  
     @Override
 448  
     public void setFilled(boolean f) {
 449  0
         bodyTextFig.setFilled(false); // The text is always opaque.
 450  0
         outlineFig.setFilled(f);
 451  0
         urCorner.setFilled(f);
 452  0
     }
 453  
 
 454  
     @Override
 455  
     public boolean isFilled() {
 456  0
         return outlineFig.isFilled();
 457  
     }
 458  
 
 459  
     /*
 460  
      * @see org.tigris.gef.presentation.Fig#setLineWidth(int)
 461  
      */
 462  
     @Override
 463  
     public void setLineWidth(int w) {
 464  0
         bodyTextFig.setLineWidth(0); // Make a seamless integration of the text
 465  
         // in the note figure.
 466  0
         outlineFig.setLineWidth(w);
 467  0
         urCorner.setLineWidth(w);
 468  0
     }
 469  
 
 470  
     /*
 471  
      * @see org.tigris.gef.presentation.Fig#getLineWidth()
 472  
      */
 473  
     @Override
 474  
     public int getLineWidth() {
 475  0
         return outlineFig.getLineWidth();
 476  
     }
 477  
 
 478  
     ////////////////////////////////////////////////////////////////
 479  
     // user interaction methods
 480  
 
 481  
     /*
 482  
      * @see org.argouml.uml.diagram.ui.FigNodeModelElement#textEdited(org.tigris.gef.presentation.FigText)
 483  
      */
 484  
     @Override
 485  
     protected void textEdited(FigText ft) {
 486  0
         if (ft == bodyTextFig) {
 487  0
             storeBody(ft.getText());
 488  
         }
 489  0
     }
 490  
 
 491  
     /*
 492  
      * @see org.argouml.uml.diagram.ui.FigNodeModelElement#textEditStarted(org.tigris.gef.presentation.FigText)
 493  
      */
 494  
     @Override
 495  
     protected void textEditStarted(FigText ft) {
 496  0
         showHelp("parsing.help.comment");
 497  0
     }
 498  
 
 499  
     /*
 500  
      * @see org.tigris.gef.presentation.Fig#setEnclosingFig(org.tigris.gef.presentation.Fig)
 501  
      */
 502  
     @Override
 503  
     public void setEnclosingFig(Fig encloser) {
 504  0
         super.setEnclosingFig(encloser);
 505  0
     }
 506  
 
 507  
     ////////////////////////////////////////////////////////////////
 508  
     // accessor methods
 509  
 
 510  
     /**
 511  
      * Stores the body text in the associated model element.
 512  
      *
 513  
      * @param body The body text to store.
 514  
      */
 515  
     public final void storeBody(String body) {
 516  0
         if (getOwner() != null) {
 517  0
             Model.getCoreHelper().setBody(getOwner(), body);
 518  
         }
 519  0
     }
 520  
 
 521  
     /**
 522  
      * Retrieve the body text from the associated model element.
 523  
      *
 524  
      * @return The body from the associated model element.
 525  
      */
 526  
     private String retrieveBody() {
 527  0
         return (getOwner() != null)
 528  
             ? (String) Model.getFacade().getBody(getOwner())
 529  
             : null;
 530  
     }
 531  
 
 532  
     /*
 533  
      * @see org.tigris.gef.presentation.Fig#getUseTrapRect()
 534  
      */
 535  
     @Override
 536  
     public boolean getUseTrapRect() {
 537  0
         return true;
 538  
     }
 539  
     
 540  
     /**
 541  
      * Always returns null as the FigComment does not display its name.
 542  
      * @return null
 543  
      */
 544  
     @Override
 545  
     public Rectangle getNameBounds() {
 546  0
         return null;
 547  
     }
 548  
 
 549  
     /**
 550  
      * Get the minimum size for the note figure.
 551  
      *
 552  
      * @return The minimum size for the note figure.
 553  
      */
 554  
     @Override
 555  
     public Dimension getMinimumSize() {
 556  
 
 557  
         // Get the size of the text field.
 558  0
         Dimension aSize = bodyTextFig.getMinimumSize();
 559  
 
 560  
         // If we have a stereotype displayed, then allow some space for that
 561  
         // (width and height)
 562  
 
 563  0
         if (getStereotypeFig().isVisible()) {
 564  0
             Dimension stereoMin = getStereotypeFig().getMinimumSize();
 565  0
             aSize.width =
 566  
                 Math.max(aSize.width,
 567  
                          stereoMin.width);
 568  0
             aSize.height += stereoMin.height;
 569  
         }
 570  
 
 571  
         // And add the gaps around the textfield to get the minimum
 572  
         // size of the note.
 573  0
         return new Dimension(aSize.width + 4 + dogear,
 574  
                              aSize.height + 4);
 575  
     }
 576  
 
 577  
     /*
 578  
      * @see org.tigris.gef.presentation.Fig#setBounds(int, int, int, int)
 579  
      */
 580  
     @Override
 581  
     protected void setStandardBounds(int px, int py, int w, int h) {
 582  0
         if (bodyTextFig == null) {
 583  0
             return;
 584  
         }
 585  
 
 586  0
         Dimension stereoMin = getStereotypeFig().getMinimumSize();
 587  
 
 588  0
         int stereotypeHeight = 0;
 589  0
         if (getStereotypeFig().isVisible()) {
 590  0
             stereotypeHeight = stereoMin.height;
 591  
         }
 592  
 
 593  0
         Rectangle oldBounds = getBounds();
 594  
 
 595  
         // Resize the text figure
 596  0
         bodyTextFig.setBounds(px + 2, py + 2 + stereotypeHeight,
 597  
                 w - 4 - dogear, h - 4 - stereotypeHeight);
 598  
 
 599  0
         getStereotypeFig().setBounds(px + 2, py + 2,
 600  
                 w - 4 - dogear, stereoMin.height);
 601  
 
 602  
         // Resize the big port around the figure
 603  0
         getBigPort().setBounds(px, py, w, h);
 604  
 
 605  
         // Since this is a complex polygon, there's no easy way to resize it.
 606  0
         Polygon newPoly = new Polygon();
 607  0
         newPoly.addPoint(px, py);
 608  0
         newPoly.addPoint(px + w - 1 - dogear, py);
 609  0
         newPoly.addPoint(px + w - 1, py + dogear);
 610  0
         newPoly.addPoint(px + w - 1, py + h - 1);
 611  0
         newPoly.addPoint(px, py + h - 1);
 612  0
         newPoly.addPoint(px, py);
 613  0
         outlineFig.setPolygon(newPoly);
 614  
 
 615  
         // Just move the corner to it's new position.
 616  0
         urCorner.setBounds(px + w - 1 - dogear, py, dogear, dogear);
 617  
 
 618  0
         calcBounds(); //_x = x; _y = y; _w = w; _h = h;
 619  0
         firePropChange("bounds", oldBounds, getBounds());
 620  0
     }
 621  
 
 622  
     /*
 623  
      * TODO: This is the same as in parent - remove?
 624  
      * @see org.argouml.uml.diagram.ui.FigNodeModelElement#updateBounds()
 625  
      */
 626  
     @Override
 627  
     protected void updateBounds() {
 628  0
         Rectangle bbox = getBounds();
 629  0
         Dimension minSize = getMinimumSize();
 630  0
         bbox.width = Math.max(bbox.width, minSize.width);
 631  0
         bbox.height = Math.max(bbox.height, minSize.height);
 632  0
         setBounds(bbox.x, bbox.y, bbox.width, bbox.height);
 633  0
     }
 634  
 
 635  
     ///////////////////////////////////////////////////////////////////
 636  
     // Internal methods
 637  
 
 638  
     @Override
 639  
     protected final void updateLayout(UmlChangeEvent mee) {
 640  0
         super.updateLayout(mee);
 641  
 
 642  0
         if (mee instanceof AttributeChangeEvent
 643  
                 && mee.getPropertyName().equals("body")) {
 644  
 
 645  0
             bodyTextFig.setText(mee.getNewValue().toString());
 646  0
             calcBounds();
 647  0
             setBounds(getBounds());
 648  0
             damage();
 649  0
         } else if (mee instanceof RemoveAssociationEvent
 650  
                 && mee.getPropertyName().equals("annotatedElement")) {
 651  
             /* Remove the commentedge.
 652  
              * If there are more then one comment-edges between 
 653  
              * the 2 objects, then delete them all. */
 654  0
             Collection<FigEdgeNote> toRemove = new ArrayList<FigEdgeNote>();
 655  0
             Collection c = getFigEdges(); // all connected edges
 656  0
             for (Iterator i = c.iterator(); i.hasNext(); ) {
 657  0
                 FigEdgeNote fen = (FigEdgeNote) i.next();
 658  0
                 Object otherEnd = fen.getDestination(); // the UML object
 659  0
                 if (otherEnd == getOwner()) { // wrong end of the edge
 660  0
                     otherEnd = fen.getSource();
 661  
                 }
 662  0
                 if (otherEnd == mee.getOldValue())  {
 663  0
                     toRemove.add(fen);
 664  
                 }
 665  0
             }
 666  
             
 667  0
             for (FigEdgeNote fen : toRemove) {
 668  0
                 fen.removeFromDiagram();
 669  
             }
 670  
         }
 671  0
     }
 672  
 
 673  
     /*
 674  
      * @see org.argouml.uml.diagram.ui.FigNodeModelElement#updateStereotypeText()
 675  
      */
 676  
     @Override
 677  
     protected void updateStereotypeText() {
 678  0
         Object me = getOwner();
 679  
 
 680  0
         if (me == null) {
 681  0
             return;
 682  
         }
 683  
 
 684  0
         Rectangle rect = getBounds();
 685  
 
 686  0
         Dimension stereoMin = getStereotypeFig().getMinimumSize();
 687  
 
 688  0
         if (Model.getFacade().getStereotypes(me).isEmpty()) {
 689  
 
 690  0
             if (getStereotypeFig().isVisible()) {
 691  0
                 getStereotypeFig().setVisible(false);
 692  0
                 rect.y += stereoMin.height;
 693  0
                 rect.height -= stereoMin.height;
 694  0
                 setBounds(rect.x, rect.y, rect.width, rect.height);
 695  0
                 calcBounds();
 696  
             }
 697  
         } else {
 698  0
             if (!getStereotypeFig().isVisible()) {
 699  0
                 getStereotypeFig().setVisible(true);
 700  
 
 701  
                 // Only adjust the stereotype height if we are not newly
 702  
                 // created. This gets round the problem of loading classes with
 703  
                 // stereotypes defined, which have the height already including
 704  
                 // the stereotype.
 705  
 
 706  0
                 if (!newlyCreated) {
 707  0
                     rect.y -= stereoMin.height;
 708  0
                     rect.height += stereoMin.height;
 709  0
                     rect.width =
 710  
                         Math.max(getMinimumSize().width, rect.width);
 711  0
                     setBounds(rect.x, rect.y, rect.width, rect.height);
 712  0
                     calcBounds();
 713  
                 }
 714  
             }
 715  
         }
 716  
         // Whatever happened we are no longer newly created, so clear the
 717  
         // flag. Then set the bounds for the rectangle we have defined.
 718  0
         newlyCreated = false;
 719  0
     }
 720  
     
 721  
     /**
 722  
      * Get the text body of the comment.
 723  
      * @return the body of the comment
 724  
      */
 725  
     public String getBody() {
 726  0
         return bodyTextFig.getText();
 727  
     }
 728  
 
 729  
     /*
 730  
      * @see org.tigris.gef.presentation.Fig#getClosestPoint(java.awt.Point)
 731  
      */
 732  
     @Override
 733  
     public Point getClosestPoint(Point anotherPt) {
 734  0
         Rectangle r = getBounds();
 735  0
         int[] xs = {
 736  
             r.x, r.x + r.width - dogear, r.x + r.width,
 737  
             r.x + r.width,  r.x,            r.x,
 738  
         };
 739  0
         int[] ys = {
 740  
             r.y, r.y,                    r.y + dogear,
 741  
             r.y + r.height, r.y + r.height, r.y,
 742  
         };
 743  0
         Point p =
 744  
             Geometry.ptClosestTo(
 745  
                 xs,
 746  
                 ys,
 747  
                 6,
 748  
                 anotherPt);
 749  0
         return p;
 750  
     }
 751  
 
 752  
     /**
 753  
      * The UID.
 754  
      */
 755  
     private static final long serialVersionUID = 7242542877839921267L;
 756  
 }