Coverage Report - org.argouml.uml.diagram.ui.FigSingleLineText
 
Classes in this File Line Coverage Branch Coverage Complexity
FigSingleLineText
30%
19/62
3%
1/32
2.2
FigSingleLineText$1
0%
0/11
0%
0/2
2.2
 
 1  
 /* $Id: FigSingleLineText.java 17865 2010-01-12 20:45:26Z linus $
 2  
  *****************************************************************************
 3  
  * Copyright (c) 2009 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  
  *    mvw
 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.ui;
 40  
 
 41  
 import java.awt.Dimension;
 42  
 import java.awt.Font;
 43  
 import java.awt.Rectangle;
 44  
 import java.awt.event.KeyEvent;
 45  
 import java.beans.PropertyChangeEvent;
 46  
 import java.util.Arrays;
 47  
 
 48  
 import javax.swing.SwingUtilities;
 49  
 
 50  
 import org.apache.log4j.Logger;
 51  
 import org.argouml.model.AttributeChangeEvent;
 52  
 import org.argouml.model.InvalidElementException;
 53  
 import org.argouml.model.Model;
 54  
 import org.argouml.model.UmlChangeEvent;
 55  
 import org.argouml.uml.diagram.DiagramSettings;
 56  
 import org.tigris.gef.presentation.FigText;
 57  
 
 58  
 /**
 59  
  * A SingleLine FigText to provide consistency across Figs displaying single
 60  
  * lines of text.<ul>
 61  
  * <li>The display area is transparent
 62  
  * <li>Text is center justified
 63  
  * <li>There is no line border
 64  
  * <li>There is space below the line for a "Clarifier",
 65  
  * i.e. a red squiggly line.
 66  
  * </ul><p>
 67  
  * 
 68  
  * Some of these have an UML object as owner, others do not.
 69  
  *
 70  
  * @author Bob Tarling
 71  
  */
 72  119
 public class FigSingleLineText extends ArgoFigText  {
 73  
 
 74  119
     private static final Logger LOG =
 75  
         Logger.getLogger(FigSingleLineText.class);
 76  
 
 77  
     /**
 78  
      * The properties of 'owner' that this is interested in
 79  
      */
 80  
     private String[] properties;
 81  
 
 82  
     private void initialize() {
 83  1071
         setFillColor(FILL_COLOR); // in case someone turns it on
 84  1071
         super.setFilled(false);
 85  1071
         setTabAction(FigText.END_EDITING);
 86  1071
         setReturnAction(FigText.END_EDITING);
 87  1071
         setLineWidth(0);
 88  1071
         setTextColor(TEXT_COLOR);
 89  1071
     }
 90  
     
 91  
     public void setFilled(boolean filled) {
 92  
         // Do not allow fill to change. We should see through
 93  
         // the text to the color of the main FIg background.
 94  1071
     }
 95  
 
 96  
     /**
 97  
      * Construct text fig
 98  
      * 
 99  
      * @param owner owning UML element
 100  
      * @param bounds position and size
 101  
      * @param settings rendering settings
 102  
      * @param expandOnly true if the Fig should only expand and never contract
 103  
      */
 104  
     public FigSingleLineText(Object owner, Rectangle bounds,
 105  
             DiagramSettings settings, boolean expandOnly) {
 106  
 
 107  1071
         this(owner, bounds, settings, expandOnly, (String[]) null);
 108  1071
     }
 109  
 
 110  
     /**
 111  
      * Construct text fig
 112  
      * 
 113  
      * @param owner owning UML element
 114  
      * @param bounds position and size
 115  
      * @param settings rendering settings
 116  
      * @param expandOnly true if the Fig should only expand and never contract
 117  
      * @param property name of property to listen to
 118  
      */
 119  
     public FigSingleLineText(Object owner, Rectangle bounds,
 120  
             DiagramSettings settings, boolean expandOnly, String property) {
 121  
 
 122  0
         this(owner, bounds, settings, expandOnly, new String[] {property});
 123  0
     }
 124  
 
 125  
     /**
 126  
      * Constructor for text fig without owner. 
 127  
      * Using this constructor shall mean 
 128  
      * that this fig will never have an owner.
 129  
      * 
 130  
      * @param bounds position and size
 131  
      * @param settings rendering settings
 132  
      * @param expandOnly true if the Fig should only expand and never contract
 133  
      */
 134  
     public FigSingleLineText(Rectangle bounds,
 135  
             DiagramSettings settings, boolean expandOnly) {
 136  
 
 137  0
         this(null, bounds, settings, expandOnly);
 138  0
     }
 139  
     
 140  
     /**
 141  
      * Construct text fig
 142  
      * 
 143  
      * @param owner owning UML element
 144  
      * @param bounds position and size
 145  
      * @param settings rendering settings
 146  
      * @param expandOnly true if the Fig should only expand and never contract
 147  
      * @param allProperties names of properties to listen to
 148  
      */
 149  
     public FigSingleLineText(Object owner, Rectangle bounds,
 150  
             DiagramSettings settings, boolean expandOnly, 
 151  
             String[] allProperties) {
 152  1071
         super(owner, bounds, settings, expandOnly);
 153  1071
         initialize();
 154  1071
         this.properties = allProperties;
 155  1071
         addModelListener();
 156  1071
     }
 157  
     
 158  
     /**
 159  
      * TODO: This function attempts to optimize the more generic 
 160  
      * code in the parent, which also works correctly in this case. 
 161  
      * Is this a good idea?
 162  
      */
 163  
     @Override
 164  
     public Dimension getMinimumSize() {
 165  0
         Dimension d = new Dimension();
 166  
 
 167  0
         Font font = getFont();
 168  
 
 169  0
         if (font == null) {
 170  0
             return d;
 171  
         }
 172  0
         int maxW = 0;
 173  0
         int maxH = 0;
 174  0
         if (getFontMetrics() == null) {
 175  0
             maxH = font.getSize();
 176  
         } else {
 177  0
             maxH = getFontMetrics().getHeight();
 178  0
             maxW = getFontMetrics().stringWidth(getText());
 179  
         }
 180  
 
 181  
         /* Now force minimum dimensions for the text: */
 182  0
         maxW = Math.max(maxW, MIN_TEXT_WIDTH);
 183  
 
 184  
         /* Now add the areas around the text to return the complete size: */
 185  0
         int overallH = maxH + getTopMargin() + getBotMargin()
 186  
             + 2 * getLineWidth();
 187  0
         int overallW = maxW + getLeftMargin() + getRightMargin()
 188  
             + 2 * getLineWidth();
 189  0
         d.width = overallW;
 190  0
         d.height = overallH;
 191  0
         return d;
 192  
     }
 193  
 
 194  
     @Override
 195  
     protected boolean isStartEditingKey(KeyEvent ke) {
 196  0
         if ((ke.getModifiers()
 197  
              & (KeyEvent.META_MASK | KeyEvent.ALT_MASK)) == 0) {
 198  0
             return super.isStartEditingKey(ke);
 199  
         } else {
 200  0
             return false;
 201  
         }
 202  
     }
 203  
 
 204  
     private void addModelListener() {
 205  1071
         if (properties != null && getOwner() != null) {
 206  0
             Model.getPump().addModelEventListener(this, getOwner(), properties);
 207  
         }
 208  1071
     }
 209  
     
 210  
     @Override
 211  
     public void removeFromDiagram() {
 212  0
         if (getOwner() != null && properties != null) {
 213  0
             Model.getPump().removeModelEventListener(
 214  
                     this, 
 215  
                     getOwner(), 
 216  
                     properties);
 217  
         }
 218  0
         super.removeFromDiagram();
 219  0
     }
 220  
     
 221  
     @Override
 222  
     public void propertyChange(PropertyChangeEvent pce) {
 223  0
         if ("remove".equals(pce.getPropertyName()) 
 224  
                 && (pce.getSource() == getOwner())) {
 225  0
             deleteFromModel();
 226  
         }
 227  
 
 228  0
         if (pce instanceof UmlChangeEvent) {
 229  0
             final UmlChangeEvent event = (UmlChangeEvent) pce;
 230  0
             Runnable doWorkRunnable = new Runnable() {
 231  
                 public void run() {
 232  
                     try {
 233  0
                         updateLayout(event);
 234  0
                     } catch (InvalidElementException e) {
 235  0
                         if (LOG.isDebugEnabled()) {
 236  0
                             LOG.debug("event = "
 237  
                                     + event.getClass().getName());
 238  0
                             LOG.debug("source = " + event.getSource());
 239  0
                             LOG.debug("old = " + event.getOldValue());
 240  0
                             LOG.debug("name = " + event.getPropertyName());
 241  0
                             LOG.debug("updateLayout method accessed "
 242  
                                     + "deleted element ", e);
 243  
                         }
 244  0
                     }
 245  0
                 }  
 246  
             };
 247  0
             SwingUtilities.invokeLater(doWorkRunnable);
 248  
         }
 249  0
     }
 250  
     
 251  
     /**
 252  
      * This is a template method called by the ArgoUML framework as the result
 253  
      * of a change to a model element. Do not call this method directly
 254  
      * yourself.
 255  
      * <p>Override this in any subclasses in order to redisplay the Fig
 256  
      * due to change of any model element that this Fig is listening to.</p>
 257  
      * <p>This method is guaranteed by the framework to be running on the 
 258  
      * Swing/AWT thread.</p>
 259  
      *
 260  
      * @param event the UmlChangeEvent that caused the change
 261  
      */
 262  
     protected void updateLayout(UmlChangeEvent event) {
 263  0
         assert event != null;
 264  0
         if (getOwner() == event.getSource()
 265  
                 && properties != null
 266  
                 && Arrays.asList(properties).contains(event.getPropertyName())
 267  
                 && event instanceof AttributeChangeEvent) {
 268  
             /* TODO: Why does it fail for changing 
 269  
              * the name of an associationend?
 270  
              *  Why should it pass? */
 271  
             //assert Arrays.asList(properties).contains(
 272  
             //    event.getPropertyName()) 
 273  
             //  : event.getPropertyName(); 
 274  
             // TODO: Do we really always need to do this or only if
 275  
             // notationProvider is null?
 276  0
             setText();
 277  
         }
 278  0
     }
 279  
     
 280  
     /**
 281  
      * This function without parameter shall
 282  
      * determine the text of the Fig taking values from the owner,
 283  
      * and then call {@link #setText(String)}.
 284  
      * To be implemented as required by sub classes.
 285  
      */
 286  
     protected void setText() {
 287  0
     }
 288  
 
 289  
     public void renderingChanged() {
 290  0
         super.renderingChanged();
 291  
         /* This is needed for e.g. 
 292  
          * guillemet notation change on a class name, 
 293  
          * see issue 5419. */
 294  0
         setText();
 295  0
     }
 296  
 }