Coverage Report - org.dishevelled.identify.IdLabel
 
Classes in this File Line Coverage Branch Coverage Complexity
IdLabel
96%
125/129
91%
57/62
2.097
IdLabel$1
11%
1/9
0%
0/4
2.097
 
 1  
 /*
 2  
 
 3  
     dsh-identify  Lightweight components for identifiable beans.
 4  
     Copyright (c) 2003-2019 held jointly by the individual authors.
 5  
 
 6  
     This library is free software; you can redistribute it and/or modify it
 7  
     under the terms of the GNU Lesser General Public License as published
 8  
     by the Free Software Foundation; either version 3 of the License, or (at
 9  
     your option) any later version.
 10  
 
 11  
     This library is distributed in the hope that it will be useful, but WITHOUT
 12  
     ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
 13  
     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 14  
     License for more details.
 15  
 
 16  
     You should have received a copy of the GNU Lesser General Public License
 17  
     along with this library;  if not, write to the Free Software Foundation,
 18  
     Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA.
 19  
 
 20  
     > http://www.fsf.org/licensing/licenses/lgpl.html
 21  
     > http://www.opensource.org/licenses/lgpl-license.php
 22  
 
 23  
 */
 24  
 package org.dishevelled.identify;
 25  
 
 26  
 import java.awt.Image;
 27  
 import java.awt.Dimension;
 28  
 import java.awt.Rectangle;
 29  
 import java.awt.Graphics;
 30  
 import java.awt.ComponentOrientation;
 31  
 
 32  
 import java.awt.event.MouseEvent;
 33  
 import java.awt.event.MouseAdapter;
 34  
 import java.awt.event.MouseListener;
 35  
 
 36  
 import javax.swing.Icon;
 37  
 import javax.swing.JLabel;
 38  
 import javax.swing.ImageIcon;
 39  
 
 40  
 import org.dishevelled.iconbundle.IconSize;
 41  
 import org.dishevelled.iconbundle.IconState;
 42  
 import org.dishevelled.iconbundle.IconBundle;
 43  
 import org.dishevelled.iconbundle.IconTextDirection;
 44  
 
 45  
 /**
 46  
  * An extension of JLabel that displays the name property value
 47  
  * and appropriate icon from an icon bundle for a given bean.
 48  
  *
 49  
  * @author  Michael Heuer
 50  
  */
 51  
 public final class IdLabel
 52  
     extends JLabel
 53  
 {
 54  
     /** Default icon size. */
 55  2
     public static final IconSize DEFAULT_ICON_SIZE = IconSize.DEFAULT_32X32;
 56  
 
 57  
     /** Default icon state. */
 58  2
     public static final IconState DEFAULT_ICON_STATE = IconState.NORMAL;
 59  
 
 60  
     /** Default icon text direction. */
 61  2
     private static final IconTextDirection DEFAULT_ICON_TEXT_DIRECTION = IconTextDirection.LEFT_TO_RIGHT;
 62  
 
 63  
     /** Bound value property. */
 64  
     private Object value;
 65  
 
 66  
     /** Icon size. */
 67  410
     private IconSize iconSize = DEFAULT_ICON_SIZE;
 68  
 
 69  
     /** Icon state. */
 70  410
     private IconState iconState = DEFAULT_ICON_STATE;
 71  
 
 72  
     /** Icon text direction. */
 73  410
     private IconTextDirection iconTextDirection = DEFAULT_ICON_TEXT_DIRECTION;
 74  
 
 75  
     /** ImageIcon wrapper for image from icon bundle. */
 76  
     private transient ImageIcon imageIcon;
 77  
 
 78  
     /** Dirty flag. */
 79  410
     private transient boolean dirty = false;
 80  
 
 81  
     /** Mouseover mouse listener. */
 82  410
     private MouseListener mouseoverListener = new MouseAdapter()
 83  410
         {
 84  
             @Override
 85  
             public void mouseEntered(final MouseEvent e)
 86  
             {
 87  0
                 if (getIconState().equals(IconState.NORMAL))
 88  
                 {
 89  0
                     setIconState(IconState.MOUSEOVER);
 90  0
                     repaint();
 91  
                 }
 92  0
             }
 93  
 
 94  
             @Override
 95  
             public void mouseExited(final MouseEvent e)
 96  
             {
 97  0
                 if (getIconState().equals(IconState.MOUSEOVER))
 98  
                 {
 99  0
                     setIconState(IconState.NORMAL);
 100  0
                     repaint();
 101  
                 }
 102  0
             }
 103  
         };
 104  
 
 105  
     /**
 106  
      * Cache of the previous state, for use in returning to the
 107  
      * proper state following a call of <code>setEnabled(true)</code>.
 108  
      */
 109  410
     private transient IconState previousState = DEFAULT_ICON_STATE;
 110  
 
 111  
 
 112  
     /**
 113  
      * Create a new label with a null value.
 114  
      */
 115  
     public IdLabel()
 116  
     {
 117  68
         super();
 118  
 
 119  68
         addMouseListener(mouseoverListener);
 120  
 
 121  68
         setValue(null);
 122  68
         rebuild();
 123  68
     }
 124  
 
 125  
     /**
 126  
      * Create a new label for the specified value.
 127  
      *
 128  
      * @param value value
 129  
      */
 130  
     public IdLabel(final Object value)
 131  
     {
 132  186
         super();
 133  
 
 134  186
         addMouseListener(mouseoverListener);
 135  
 
 136  186
         setValue(value);
 137  186
         rebuild();
 138  186
     }
 139  
 
 140  
     /**
 141  
      * Create a new label for the specified value with the specified icon size.
 142  
      *
 143  
      * @param value value
 144  
      * @param iconSize icon size, must not be null
 145  
      */
 146  
     public IdLabel(final Object value, final IconSize iconSize)
 147  
     {
 148  156
         super();
 149  
 
 150  156
         addMouseListener(mouseoverListener);
 151  
 
 152  156
         setValue(value);
 153  156
         setIconSize(iconSize);
 154  154
         rebuild();
 155  154
     }
 156  
 
 157  
 
 158  
     /**
 159  
      * Return the value for this label.
 160  
      *
 161  
      * @return the value for this label
 162  
      */
 163  
     public Object getValue()
 164  
     {
 165  18
         return value;
 166  
     }
 167  
 
 168  
     /**
 169  
      * Set the value for this label to <code>value</code>.
 170  
      *
 171  
      * <p>This is a bound property.</p>
 172  
      *
 173  
      * @param value value for this label
 174  
      */
 175  
     public void setValue(final Object value)
 176  
     {
 177  450
         Object oldValue = this.value;
 178  450
         this.value = value;
 179  450
         firePropertyChange("value", oldValue, this.value);
 180  
 
 181  450
         setDirty(true);
 182  450
     }
 183  
 
 184  
     /**
 185  
      * Return the icon size for this label.
 186  
      *
 187  
      * @return the icon size for this label
 188  
      */
 189  
     public IconSize getIconSize()
 190  
     {
 191  332
         return iconSize;
 192  
     }
 193  
 
 194  
     /**
 195  
      * Set the icon size for this label to <code>iconSize</code>.
 196  
      *
 197  
      * <p>This is a bound property.</p>
 198  
      *
 199  
      * @param iconSize icon size, must not be null
 200  
      */
 201  
     public void setIconSize(final IconSize iconSize)
 202  
     {
 203  486
         if (iconSize == null)
 204  
         {
 205  4
             throw new IllegalArgumentException("iconSize must not be null");
 206  
         }
 207  
 
 208  482
         IconSize oldIconSize = this.iconSize;
 209  482
         this.iconSize = iconSize;
 210  
 
 211  482
         if (!oldIconSize.equals(this.iconSize))
 212  
         {
 213  330
             setDirty(true);
 214  330
             firePropertyChange("iconSize", oldIconSize, iconSize);
 215  
         }
 216  482
     }
 217  
 
 218  
     /**
 219  
      * Return the icon state for this label.
 220  
      *
 221  
      * @return the icon state for this label
 222  
      */
 223  
     public IconState getIconState()
 224  
     {
 225  110
         return iconState;
 226  
     }
 227  
 
 228  
     /**
 229  
      * Set the icon state for this label to <code>iconState</code>.
 230  
      *
 231  
      * <p>This is a bound property.</p>
 232  
      *
 233  
      * @param iconState icon state, must not be null
 234  
      */
 235  
     public void setIconState(final IconState iconState)
 236  
     {
 237  76
         if (iconState == null)
 238  
         {
 239  2
             throw new IllegalArgumentException("iconState must not be null");
 240  
         }
 241  
 
 242  74
         IconState oldIconState = this.iconState;
 243  74
         this.iconState = iconState;
 244  
 
 245  74
         if (!oldIconState.equals(this.iconState))
 246  
         {
 247  62
             setDirty(true);
 248  62
             firePropertyChange("iconState", oldIconState, this.iconState);
 249  
         }
 250  74
     }
 251  
 
 252  
     /**
 253  
      * Return the icon text direction for this label.
 254  
      *
 255  
      * @return the icon text direction for this label
 256  
      */
 257  
     IconTextDirection getIconTextDirection()
 258  
     {
 259  10
         return iconTextDirection;
 260  
     }
 261  
 
 262  
     @Override
 263  
     public void setComponentOrientation(final ComponentOrientation orientation)
 264  
     {
 265  10
         ComponentOrientation oldOrientation = getComponentOrientation();
 266  
 
 267  10
         if (!oldOrientation.equals(orientation))
 268  
         {
 269  10
             if (orientation != null)
 270  
             {
 271  8
                 iconTextDirection = orientation.isLeftToRight()
 272  
                     ? IconTextDirection.LEFT_TO_RIGHT : IconTextDirection.RIGHT_TO_LEFT;
 273  
 
 274  8
                 setDirty(true);
 275  
             }
 276  
         }
 277  
 
 278  10
         super.setComponentOrientation(orientation);
 279  10
     }
 280  
 
 281  
     @Override
 282  
     public void applyComponentOrientation(final ComponentOrientation orientation)
 283  
     {
 284  6
         ComponentOrientation oldOrientation = getComponentOrientation();
 285  
 
 286  6
         if (!oldOrientation.equals(orientation))
 287  
         {
 288  6
             if (orientation != null)
 289  
             {
 290  4
                 iconTextDirection = orientation.isLeftToRight()
 291  
                     ? IconTextDirection.LEFT_TO_RIGHT : IconTextDirection.RIGHT_TO_LEFT;
 292  
 
 293  4
                 setDirty(true);
 294  
             }
 295  
         }
 296  
 
 297  6
         super.applyComponentOrientation(orientation);
 298  4
     }
 299  
 
 300  
     @Override
 301  
     public void setEnabled(final boolean enabled)
 302  
     {
 303  28
         boolean previousEnabled = isEnabled();
 304  
 
 305  28
         if (enabled && !previousEnabled)
 306  
         {
 307  12
             setIconState(previousState);
 308  
         }
 309  16
         else if (!enabled && previousEnabled)
 310  
         {
 311  12
             previousState = getIconState();
 312  12
             setIconState(IconState.DISABLED);
 313  
         }
 314  
 
 315  28
         super.setEnabled(enabled);
 316  
 
 317  28
         setDirty(true);
 318  28
     }
 319  
 
 320  
     /**
 321  
      * Set the dirty flag to the logical OR of <code>dirty</code>
 322  
      * and the previous dirty state.
 323  
      *
 324  
      * @param dirty dirty flag
 325  
      */
 326  
     private void setDirty(final boolean dirty)
 327  
     {
 328  882
         this.dirty = (this.dirty || dirty);
 329  882
     }
 330  
 
 331  
     /**
 332  
      * Return true if a rebuild of the text and icon properties
 333  
      * is necessary.
 334  
      *
 335  
      * @return true if a rebuild of the text and icon properties
 336  
      *    is necessary
 337  
      */
 338  
     private boolean isDirty()
 339  
     {
 340  2190
         return dirty;
 341  
     }
 342  
 
 343  
     /**
 344  
      * Rebuild the text and icon properties of this label
 345  
      * with the name property and icon bundle image of
 346  
      * <code>getValue()</code>, respectively.
 347  
      */
 348  
     private void rebuild()
 349  
     {
 350  1180
         String name = IdentifyUtils.getNameFor(value);
 351  1180
         setText(name);
 352  
 
 353  1180
         IconBundle iconBundle = IdentifyUtils.getIconBundleFor(value);
 354  
 
 355  1180
         if (iconBundle == null)
 356  
         {
 357  432
             super.setIcon(null);
 358  432
             imageIcon = null;
 359  
         }
 360  
         else
 361  
         {
 362  748
             Image image = iconBundle.getImage(this, iconTextDirection, iconState, iconSize);
 363  
 
 364  748
             if (imageIcon == null)
 365  
             {
 366  258
                 imageIcon = new ImageIcon(image);
 367  
             }
 368  
             else
 369  
             {
 370  490
                 imageIcon.setImage(image);
 371  
             }
 372  
 
 373  748
             super.setIcon(imageIcon);
 374  
         }
 375  
 
 376  1180
         dirty = false;
 377  1180
     }
 378  
 
 379  
     @Override
 380  
     public String getText()
 381  
     {
 382  1070
         if (isDirty())
 383  
         {
 384  432
             rebuild();
 385  
         }
 386  1070
         return super.getText();
 387  
     }
 388  
 
 389  
     @Override
 390  
     public Icon getIcon()
 391  
     {
 392  236
         if (isDirty())
 393  
         {
 394  8
             rebuild();
 395  
         }
 396  236
         return imageIcon;
 397  
     }
 398  
 
 399  
     @Override
 400  
     public Icon getDisabledIcon()
 401  
     {
 402  20
         if (isDirty())
 403  
         {
 404  8
             rebuild();
 405  
         }
 406  20
         return imageIcon;
 407  
     }
 408  
 
 409  
     @Override
 410  
     public Rectangle getBounds()
 411  
     {
 412  144
         if (isDirty())
 413  
         {
 414  36
             rebuild();
 415  
         }
 416  144
         return super.getBounds();
 417  
     }
 418  
 
 419  
     @Override
 420  
     public Rectangle getBounds(final Rectangle rv)
 421  
     {
 422  72
         if (isDirty())
 423  
         {
 424  36
             rebuild();
 425  
         }
 426  72
         return super.getBounds(rv);
 427  
     }
 428  
 
 429  
     @Override
 430  
     public Dimension getMaximumSize()
 431  
     {
 432  72
         if (isDirty())
 433  
         {
 434  36
             rebuild();
 435  
         }
 436  72
         return super.getMaximumSize();
 437  
     }
 438  
 
 439  
     @Override
 440  
     public Dimension getMinimumSize()
 441  
     {
 442  72
         if (isDirty())
 443  
         {
 444  36
             rebuild();
 445  
         }
 446  72
         return super.getMinimumSize();
 447  
     }
 448  
 
 449  
     @Override
 450  
     public Dimension getPreferredSize()
 451  
     {
 452  72
         if (isDirty())
 453  
         {
 454  36
             rebuild();
 455  
         }
 456  72
         return super.getPreferredSize();
 457  
     }
 458  
 
 459  
     @Override
 460  
     public Dimension getSize()
 461  
     {
 462  72
         if (isDirty())
 463  
         {
 464  36
             rebuild();
 465  
         }
 466  72
         return super.getSize();
 467  
     }
 468  
 
 469  
     @Override
 470  
     public Rectangle getVisibleRect()
 471  
     {
 472  72
         if (isDirty())
 473  
         {
 474  36
             rebuild();
 475  
         }
 476  72
         return super.getVisibleRect();
 477  
     }
 478  
 
 479  
     @Override
 480  
     public int getHeight()
 481  
     {
 482  144
         if (isDirty())
 483  
         {
 484  36
             rebuild();
 485  
         }
 486  144
         return super.getHeight();
 487  
     }
 488  
 
 489  
     @Override
 490  
     public int getWidth()
 491  
     {
 492  144
         if (isDirty())
 493  
         {
 494  36
             rebuild();
 495  
         }
 496  144
         return super.getWidth();
 497  
     }
 498  
 
 499  
     @Override
 500  
     public void paintComponent(final Graphics g)
 501  
     {
 502  0
         if (isDirty())
 503  
         {
 504  0
             rebuild();
 505  
         }
 506  0
         super.paintComponent(g);
 507  0
     }
 508  
 }