Coverage Report - org.argouml.uml.diagram.ui.FigNodeAssociation
 
Classes in this File Line Coverage Branch Coverage Complexity
FigNodeAssociation
0%
0/111
0%
0/40
2
 
 1  
 /* $Id: FigNodeAssociation.java 18775 2010-09-23 16:39:06Z bobtarling $
 2  
  *****************************************************************************
 3  
  * Copyright (c) 2009-2010 Contributors - see below
 4  
  * All rights reserved. This program and the accompanying materials
 5  
  * are made available under the terms of the Eclipse Public License v1.0
 6  
  * which accompanies this distribution, and is available at
 7  
  * http://www.eclipse.org/legal/epl-v10.html
 8  
  *
 9  
  * Contributors:
 10  
  *    bobtarling
 11  
  *    Michiel van der Wulp
 12  
  *****************************************************************************
 13  
  *
 14  
  * Some portions of this file was previously release using the BSD License:
 15  
  */
 16  
 
 17  
 // Copyright (c) 2005-2009 The Regents of the University of California. All
 18  
 // Rights Reserved. Permission to use, copy, modify, and distribute this
 19  
 // software and its documentation without fee, and without a written
 20  
 // agreement is hereby granted, provided that the above copyright notice
 21  
 // and this paragraph appear in all copies.  This software program and
 22  
 // documentation are copyrighted by The Regents of the University of
 23  
 // California. The software program and documentation are supplied "AS
 24  
 // IS", without any accompanying services from The Regents. The Regents
 25  
 // does not warrant that the operation of the program will be
 26  
 // uninterrupted or error-free. The end-user understands that the program
 27  
 // was developed for research purposes and is advised not to rely
 28  
 // exclusively on the program for any reason.  IN NO EVENT SHALL THE
 29  
 // UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
 30  
 // SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
 31  
 // ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
 32  
 // THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
 33  
 // SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
 34  
 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 35  
 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
 36  
 // PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
 37  
 // CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
 38  
 // UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 39  
 
 40  
 package org.argouml.uml.diagram.ui;
 41  
 
 42  
 import java.awt.Color;
 43  
 import java.awt.Dimension;
 44  
 import java.awt.Rectangle;
 45  
 import java.util.Collection;
 46  
 import java.util.Iterator;
 47  
 import java.util.List;
 48  
 
 49  
 import org.argouml.model.Model;
 50  
 import org.argouml.model.RemoveAssociationEvent;
 51  
 import org.argouml.model.UmlChangeEvent;
 52  
 import org.argouml.uml.diagram.DiagramSettings;
 53  
 import org.tigris.gef.base.LayerPerspective;
 54  
 import org.tigris.gef.graph.GraphEdgeRenderer;
 55  
 import org.tigris.gef.graph.MutableGraphModel;
 56  
 import org.tigris.gef.presentation.Fig;
 57  
 import org.tigris.gef.presentation.FigDiamond;
 58  
 import org.tigris.gef.presentation.FigEdge;
 59  
 import org.tigris.gef.presentation.FigNode;
 60  
 import org.tigris.gef.presentation.FigText;
 61  
 
 62  
 /**
 63  
  * Class to display graphics for N-ary association (association node),
 64  
  * i.e. the diamond. <p>
 65  
  * 
 66  
  * TODO: Improve the location of the stereotypes!
 67  
  *
 68  
  * @author pepargouml@yahoo.es
 69  
  */
 70  0
 public class FigNodeAssociation extends FigNodeModelElement {
 71  
     
 72  
     private static final int X = 0;
 73  
     private static final int Y = 0;
 74  
 
 75  
     private FigDiamond head;
 76  
 
 77  
     @Override
 78  
     protected Fig createBigPortFig() {
 79  0
         return new FigDiamond(0, 0, 70, 70, DEBUG_COLOR, DEBUG_COLOR);
 80  
     }
 81  
 
 82  
     private void initFigs() {
 83  0
         setEditable(false);
 84  0
         head = new FigDiamond(0, 0, 70, 70, LINE_COLOR, FILL_COLOR);
 85  
 
 86  0
         getNameFig().setFilled(false);
 87  0
         getNameFig().setLineWidth(0);
 88  
 //      The following does not seem to work - centered the Fig instead.
 89  
 //        getNameFig().setJustificationByName("center");
 90  
 
 91  0
         getStereotypeFig().setBounds(X + 10, Y + NAME_FIG_HEIGHT + 1, 
 92  
                 0, NAME_FIG_HEIGHT);
 93  0
         getStereotypeFig().setFilled(false);
 94  0
         getStereotypeFig().setLineWidth(0);
 95  
 
 96  
         // add Figs to the FigNode in back-to-front order
 97  0
         addFig(getBigPort());
 98  0
         addFig(head);
 99  0
         if (!Model.getFacade().isAAssociationClass(getOwner())) {
 100  0
             addFig(getNameFig());
 101  0
             addFig(getStereotypeFig());
 102  
         }
 103  
 
 104  0
         setBlinkPorts(false); //make port invisible unless mouse enters
 105  0
         Rectangle r = getBounds();
 106  0
         setBounds(r);
 107  0
         setResizable(true);
 108  0
     }
 109  
     
 110  
     /**
 111  
      * Construct a new FigNodeAssociation.
 112  
      * 
 113  
      * @param owner owning UML element
 114  
      * @param bounds position and size
 115  
      * @param settings render settings
 116  
      */
 117  
     public FigNodeAssociation(Object owner, Rectangle bounds,
 118  
             DiagramSettings settings) {
 119  0
         super(owner, bounds, settings);
 120  0
         initFigs();
 121  0
     }
 122  
 
 123  
     /*
 124  
      * @see java.lang.Object#clone()
 125  
      */
 126  
     @Override
 127  
     public Object clone() {
 128  0
         FigNodeAssociation figClone = (FigNodeAssociation) super.clone();
 129  0
         Iterator it = figClone.getFigs().iterator();
 130  0
         figClone.setBigPort((FigDiamond) it.next());
 131  0
         figClone.head = (FigDiamond) it.next();
 132  0
         figClone.setNameFig((FigText) it.next());
 133  0
         return figClone;
 134  
     }
 135  
 
 136  
 
 137  
     /**
 138  
      * Called when a model event is received from model subsystem.
 139  
      * handles when a n-ary association becomes a binary association.
 140  
      *
 141  
      * @param mee the event
 142  
      */
 143  
     @Override
 144  
     protected void updateLayout(UmlChangeEvent mee) {
 145  0
         super.updateLayout(mee);
 146  0
         if (mee.getSource() == getOwner()
 147  
                 && mee instanceof RemoveAssociationEvent
 148  
                 && "connection".equals(mee.getPropertyName())
 149  
                 && Model.getFacade().getConnections(getOwner()).size() == 2) {
 150  0
             reduceToBinary();
 151  
         }
 152  0
     }
 153  
 
 154  
     /**
 155  
      * Called when deletion of an association end reduces the number of ends
 156  
      * of an association down to only two. This Fig which represent the diamond
 157  
      * node of a n-ary association needs to be replaced by a FigAssociation
 158  
      * representing the binary relationship.
 159  
      */
 160  
     private void reduceToBinary() {
 161  0
         final Object association = getOwner();
 162  0
         assert (Model.getFacade().getConnections(association).size() == 2);
 163  
         
 164  
         // Detach any non-associationend edges (such as comment edges) already
 165  
         // attached before this association node is removed.
 166  
         // They'll later be re-attached to the new FigAssociation
 167  0
         final Collection<FigEdge> existingEdges = getFigEdges();
 168  0
         for (Iterator<FigEdge> it = existingEdges.iterator(); it.hasNext(); ) {
 169  0
             FigEdge edge = it.next();
 170  0
             if (edge instanceof FigAssociationEnd) {
 171  0
                 it.remove();
 172  
             } else {
 173  0
                 removeFigEdge(edge);
 174  
             }
 175  0
         }
 176  
         
 177  
         // Now we can remove ourself (which will also remove the
 178  
         // attached association ends edges)
 179  0
         final LayerPerspective lay = (LayerPerspective) getLayer();
 180  0
         final MutableGraphModel gm = (MutableGraphModel) lay.getGraphModel();
 181  0
         gm.removeNode(association);
 182  0
         removeFromDiagram();
 183  
         
 184  
         // Create the new FigAssociation edge to replace the node
 185  0
         final GraphEdgeRenderer renderer =
 186  
             lay.getGraphEdgeRenderer();
 187  0
         final FigEdgeModelElement figEdge =
 188  
             (FigEdgeModelElement) renderer.getFigEdgeFor(
 189  
                 gm, lay, association, null);
 190  0
         lay.add(figEdge);
 191  0
         gm.addEdge(association);
 192  
         
 193  
         // Add the non-associationend edges (such as comment edges) that were
 194  
         // originally attached to this and attach them to the new
 195  
         // FigAssociation and make sure they are positioned correctly.
 196  0
         for (FigEdge edge : existingEdges) {
 197  0
             figEdge.makeEdgePort();
 198  0
             if (edge.getDestFigNode() == this) {
 199  0
                 edge.setDestFigNode(figEdge.getEdgePort());
 200  0
                 edge.setDestPortFig(figEdge.getEdgePort());
 201  
             }
 202  0
             if (edge.getSourceFigNode() == this) {
 203  0
                 edge.setSourceFigNode(figEdge.getEdgePort());
 204  0
                 edge.setSourcePortFig(figEdge.getEdgePort());
 205  
             }
 206  
         }
 207  0
         figEdge.computeRoute();
 208  0
     }
 209  
     
 210  
     /*
 211  
      * Makes sure that the edges stick to the outline of the fig.
 212  
      * @see org.tigris.gef.presentation.Fig#getGravityPoints()
 213  
      */
 214  
     @Override
 215  
     public List getGravityPoints() {
 216  0
         return getBigPort().getGravityPoints();
 217  
     }
 218  
 
 219  
     /*
 220  
      * @see org.tigris.gef.presentation.Fig#setLineColor(java.awt.Color)
 221  
      */
 222  
     @Override
 223  
     public void setLineColor(Color col) {
 224  0
         head.setLineColor(col);
 225  0
     }
 226  
 
 227  
     /*
 228  
      * @see org.tigris.gef.presentation.Fig#getLineColor()
 229  
      */
 230  
     @Override
 231  
     public Color getLineColor() {
 232  0
         return head.getLineColor();
 233  
     }
 234  
 
 235  
     /*
 236  
      * @see org.tigris.gef.presentation.Fig#setFillColor(java.awt.Color)
 237  
      */
 238  
     @Override
 239  
     public void setFillColor(Color col) {
 240  0
         head.setFillColor(col);
 241  0
     }
 242  
 
 243  
     /*
 244  
      * @see org.tigris.gef.presentation.Fig#getFillColor()
 245  
      */
 246  
     @Override
 247  
     public Color getFillColor() {
 248  0
         return head.getFillColor();
 249  
     }
 250  
 
 251  
     /*
 252  
      * @see org.tigris.gef.presentation.Fig#setFilled(boolean)
 253  
      */
 254  
     @Override
 255  
     public void setFilled(boolean f) {
 256  0
     }
 257  
 
 258  
     @Override
 259  
     public boolean isFilled() {
 260  0
         return true;
 261  
     }
 262  
 
 263  
     /*
 264  
      * @see org.tigris.gef.presentation.Fig#setLineWidth(int)
 265  
      */
 266  
     @Override
 267  
     public void setLineWidth(int w) {
 268  0
         head.setLineWidth(w);
 269  0
     }
 270  
 
 271  
     /*
 272  
      * @see org.tigris.gef.presentation.Fig#getLineWidth()
 273  
      */
 274  
     @Override
 275  
     public int getLineWidth() {
 276  0
         return head.getLineWidth();
 277  
     }
 278  
 
 279  
     @Override
 280  
     protected void setStandardBounds(int x, int y, int w, int h) {
 281  0
         Rectangle oldBounds = getBounds();
 282  
 
 283  0
         Rectangle nm = getNameFig().getBounds();
 284  
         /* Center the NameFig, since center justification 
 285  
          * does not seem to work. */
 286  0
         getNameFig().setBounds(x + (w - nm.width) / 2, 
 287  
                 y + h / 2 - nm.height / 2, 
 288  
                 nm.width, nm.height);
 289  
         // TODO: Replace magic numbers with constants
 290  0
         if (getStereotypeFig().isVisible()) {
 291  
             /* TODO: Test this. */
 292  0
             getStereotypeFig().setBounds(x, y + h / 2 - 20, w, 15);
 293  0
             int stereotypeHeight = getStereotypeFig().getMinimumSize().height;
 294  0
             getStereotypeFig().setBounds(
 295  
                     x,
 296  
                     y,
 297  
                     w,
 298  
                     stereotypeHeight);
 299  
         }
 300  
         
 301  0
         head.setBounds(x, y, w, h);
 302  0
         getBigPort().setBounds(x, y, w, h);
 303  
 
 304  0
         calcBounds(); //_x = x; _y = y; _w = w; _h = h;
 305  0
         firePropChange("bounds", oldBounds, getBounds());
 306  0
         updateEdges();
 307  0
     }
 308  
 
 309  
     @Override
 310  
     public Dimension getMinimumSize() {
 311  0
         Dimension aSize = getNameFig().getMinimumSize();
 312  0
         if (getStereotypeFig().isVisible()) {
 313  0
             Dimension stereoMin = getStereotypeFig().getMinimumSize();
 314  0
             aSize.width = Math.max(aSize.width, stereoMin.width);
 315  0
             aSize.height += stereoMin.height;
 316  
         }
 317  0
         aSize.width = Math.max(70, aSize.width);
 318  0
         int size = Math.max(aSize.width, aSize.height);
 319  0
         aSize.width = size;
 320  0
         aSize.height = size;
 321  
         
 322  0
         return aSize;
 323  
     }
 324  
     
 325  
     
 326  
     /**
 327  
      * Remove entire composite Fig from Diagram. Discover the attached
 328  
      * FigEdgeAssociationClass and the FigClassAssociationClass attached to
 329  
      * that. Remove them from the diagram before removing this.
 330  
      */
 331  
     @Override
 332  
     protected void removeFromDiagramImpl() {
 333  0
         FigEdgeAssociationClass figEdgeLink = null;
 334  0
         final List edges = getFigEdges();
 335  
 
 336  0
         if (edges != null) {
 337  0
             for (Iterator it = edges.iterator(); it.hasNext()
 338  0
                     && figEdgeLink == null;) {
 339  0
                 Object o = it.next();
 340  0
                 if (o instanceof FigEdgeAssociationClass) {
 341  0
                     figEdgeLink = (FigEdgeAssociationClass) o;
 342  
                 }
 343  0
             }
 344  
         }
 345  
 
 346  0
         if (figEdgeLink != null) {
 347  0
             FigNode figClassBox = figEdgeLink.getDestFigNode();
 348  0
             if (!(figClassBox instanceof FigClassAssociationClass)) {
 349  0
                 figClassBox = figEdgeLink.getSourceFigNode();
 350  
             }
 351  0
             figEdgeLink.removeFromDiagramImpl();
 352  0
             ((FigClassAssociationClass) figClassBox).removeFromDiagramImpl();
 353  
         }
 354  
 
 355  0
         super.removeFromDiagramImpl();
 356  0
     }
 357  
 
 358  
 }
 359