Coverage Report - org.openpermis.editor.policy.gui.SelectableAction
 
Classes in this File Line Coverage Branch Coverage Complexity
SelectableAction
0%
0/33
0%
0/16
2.067
SelectableAction$1
0%
0/9
0%
0/6
2.067
 
 1  
 /*
 2  
  * Copyright (c) 2009, Swiss Federal Department of Defence Civil Protection and Sport
 3  
  *                     (http://www.vbs.admin.ch)
 4  
  * Copyright (c) 2009, Ergon Informatik AG (http://www.ergon.ch)
 5  
  * All rights reserved.
 6  
  *
 7  
  * Licensed under the Open Permis License which accompanies this distribution,
 8  
  * and is available at http://www.openpermis.org/BSDlicenceKent.txt
 9  
  */
 10  
 package org.openpermis.editor.policy.gui;
 11  
 
 12  
 import java.awt.event.ActionEvent;
 13  
 import java.awt.event.ItemEvent;
 14  
 import java.awt.event.ItemListener;
 15  
 import java.beans.PropertyChangeEvent;
 16  
 import java.beans.PropertyChangeListener;
 17  
 
 18  
 import javax.swing.AbstractAction;
 19  
 import javax.swing.AbstractButton;
 20  
 import javax.swing.Action;
 21  
 import javax.swing.Icon;
 22  
 import javax.swing.JCheckBox;
 23  
 import javax.swing.JCheckBoxMenuItem;
 24  
 import javax.swing.JToggleButton;
 25  
 
 26  
 
 27  
 /**
 28  
  * Extended swing {@link Action} that provides selection support.
 29  
  * @note Selection support is built-in in JSE6, this class is for backward compatibility 
 30  
  * of JSE5 only.
 31  
  * @since 0.1.0
 32  
  */
 33  
 public abstract class SelectableAction
 34  
         extends AbstractAction
 35  
         implements ItemListener
 36  
 {
 37  
 
 38  
         //---- Static
 39  
         
 40  
         /**
 41  
          * @since 0.1.0
 42  
          */
 43  
         private static final long serialVersionUID = -7232379579443222905L;
 44  
         
 45  
         /**
 46  
          * The property key used to indicate that an action is selected.
 47  
          * <p>The value of this property is of type {@link Boolean}.</p>
 48  
          * @since 0.1.0
 49  
          */
 50  
         private static final String SELECTED_KEY = "_selected";
 51  
         
 52  
         /**
 53  
          * Configures the specified button for use with the given action.
 54  
          * <p>If the action is a selectable action then selection support will be added.</p>
 55  
          * @param <T> the type of button to configure.
 56  
          * @param button the button to configure.
 57  
          * @param action the action to configure to button from.
 58  
          * @return the button passed in for fluent style use.
 59  
          * @since 0.1.0
 60  
          */
 61  
         private static <T extends AbstractButton> T configure (final T button, Action action) {
 62  0
                 if (!(action instanceof SelectableAction)) {
 63  0
                         return button;
 64  
                 }
 65  0
                 final SelectableAction selectableAction = (SelectableAction) action;
 66  0
                 button.addItemListener(selectableAction);
 67  0
                 selectableAction.addPropertyChangeListener(
 68  
                         new PropertyChangeListener() {
 69  0
                                 public void propertyChange (PropertyChangeEvent event) {
 70  0
                                         if (selectableAction.isSelectionEvent(event)) {
 71  0
                                                 if (button.getAction() != selectableAction) {
 72  
                                                         // Button has a new action, detach.
 73  0
                                                         selectableAction.removePropertyChangeListener(this);
 74  0
                                                         return;
 75  
                                                 }
 76  0
                                                 final boolean selected = selectableAction.isSelected();
 77  0
                                                 if (button.isSelected() != selected) {
 78  0
                                                         button.setSelected(selected);
 79  
                                                 }
 80  
                                         }
 81  0
                                 }
 82  
                         }
 83  
                 );
 84  0
                 return button;
 85  
         }
 86  
         
 87  
         /**
 88  
          * Creates a check box where properties are taken from the Action supplied.
 89  
          * <p>Also provides selection support if the action specified is a selectable action.</p>
 90  
          * @param action the action to create the check box.
 91  
          * @return the check box requested.
 92  
          * @since 0.1.0
 93  
          */
 94  
         public static JCheckBox createCheckBox (Action action) {
 95  0
                 return configure(new JCheckBox(action), action);
 96  
         }
 97  
         
 98  
         /**
 99  
          * Creates a toggle button where properties are taken from the Action supplied.
 100  
          * <p>Also provides selection support if the action specified is a selectable action.</p>
 101  
          * @param action the action to create the toggle button.
 102  
          * @return the toggle button requested.
 103  
          * @since 0.1.0
 104  
          */
 105  
         public static JToggleButton createToggleButton (Action action) {
 106  0
                 return configure(new JToggleButton(action), action);
 107  
         }
 108  
         
 109  
         /**
 110  
          * Creates a check box menu item where properties are taken from the Action supplied.
 111  
          * <p>Also provides selection support if the action specified is a selectable action.</p>
 112  
          * @param action the action to create the check box menu item.
 113  
          * @return the check box menu item requested.
 114  
          * @since 0.1.0
 115  
          */
 116  
         public static JCheckBoxMenuItem createCheckBoxMenuItem (Action action) {
 117  0
                 return configure(new JCheckBoxMenuItem(action), action);
 118  
         }
 119  
         
 120  
         /**
 121  
          * Check if the specified action is selected.
 122  
          * <p>Only selectable actions can have the selected state, all others return {@code false}.</p>
 123  
          * @param action the action to check.
 124  
          * @return {@code true} if it is selected, {@code false} otherwise.
 125  
          * @since 0.1.0
 126  
          */
 127  
         public boolean isSelected (Action action) {
 128  0
                 if (action instanceof SelectableAction) {
 129  0
                         return ((SelectableAction) action).isSelected();
 130  
                 }
 131  0
                 return false;
 132  
         }
 133  
         
 134  
         //---- Constructors
 135  
         
 136  
         /**
 137  
          * Defines an <code>Action</code> with the specified name and small icon.
 138  
          * @param name the description of the action.
 139  
          * @param icon the small icon of the action.
 140  
          * @since 0.1.0
 141  
          */
 142  
         public SelectableAction (String name, Icon icon) {
 143  0
                 super(name, icon);
 144  0
         }
 145  
         
 146  
         //---- Methods
 147  
         
 148  
         /**
 149  
          * Convenience factory method to create a check box that is bound to this action.
 150  
          * @return the check box requested.
 151  
          * @since 0.1.0
 152  
          */
 153  
         public JCheckBox createCheckBox () {
 154  0
                 return createCheckBox(this);
 155  
         }
 156  
         
 157  
         /**
 158  
          * Convenience factory method to create a toggle button that is bound to this action.
 159  
          * @return the toggle button requested.
 160  
          * @since 0.1.0
 161  
          */
 162  
         public JToggleButton createToggleButton () {
 163  0
                 return createToggleButton(this);
 164  
         }
 165  
         
 166  
         /**
 167  
          * Convenience factory method to create a check box menu item that is bound to this action.
 168  
          * @return the check box menu item requested.
 169  
          * @since 0.1.0
 170  
          */
 171  
         public JCheckBoxMenuItem createCheckBoxMenuItem () {
 172  0
                 return createCheckBoxMenuItem(this);
 173  
         }
 174  
         
 175  
         /**
 176  
          * Checks if the event is a selection change event fired by this action.
 177  
          * <p>Use {@link #isSelected()} to check the value or inspect the event values
 178  
          * which are of type {@link Boolean}.</p>
 179  
          * @param event the event to check, may be {@code null}.
 180  
          * @return {@code true} if the event is a selection change event on this action.
 181  
          * @since 0.1.0
 182  
          */
 183  
         public boolean isSelectionEvent (PropertyChangeEvent event) {
 184  0
                 if (event == null || event.getSource() != this) {
 185  0
                         return false;
 186  
                 }
 187  0
                 return SELECTED_KEY.equals(event.getPropertyName());
 188  
         }
 189  
         
 190  
         /**
 191  
          * Check if the specified action is selected.
 192  
          * @return {@code true} if it is selected, {@code false} otherwise.
 193  
          * @since 0.1.0
 194  
          */
 195  
         public boolean isSelected () {
 196  0
                 return Boolean.TRUE.equals(getValue(SELECTED_KEY));
 197  
         }
 198  
         
 199  
         /**
 200  
          * Sets the selection state of this action.
 201  
          * @param selected the new selection state of this action.
 202  
          * @since 0.1.0
 203  
          */
 204  
         public void setSelected (boolean selected) {
 205  0
                 putValue(SELECTED_KEY, Boolean.valueOf(selected));
 206  0
         }
 207  
         
 208  
         //---- Action
 209  
         
 210  
         /**
 211  
          * @since 0.1.0
 212  
          */
 213  
         public abstract void actionPerformed (ActionEvent e);
 214  
 
 215  
         //---- ItemListener
 216  
         
 217  
         /**
 218  
          * Synchronizes the selection state of this action with the one of the button.
 219  
          * <p>If the button changes, the action will change as well.</p>
 220  
          * @param e the item state change event.
 221  
          * @since 0.1.0
 222  
          */
 223  
         public void itemStateChanged (ItemEvent e) {
 224  0
                 if (!(e.getItemSelectable() instanceof AbstractButton)) {
 225  
                         // Only use this item listener for buttons the action is attached to!
 226  0
                         return;
 227  
                 }
 228  0
                 final AbstractButton button = (AbstractButton) e.getItemSelectable();
 229  0
                 if (button.getAction() != this) {
 230  
                         // The action of the button has changed, we are no longer tracking
 231  
                         // this button in this case.
 232  0
                         button.removeItemListener(this);
 233  0
                         return;
 234  
                 }
 235  0
                 final boolean selected = e.getStateChange() == ItemEvent.SELECTED;
 236  0
                 if (isSelected() != selected) {
 237  0
                         setSelected(selected);
 238  
                 }
 239  0
         }
 240  
 
 241  
 }