001 /* 002 * $Id: AbstractActionExt.java,v 1.7 2006/03/29 03:37:47 rbair Exp $ 003 * 004 * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle, 005 * Santa Clara, California 95054, U.S.A. All rights reserved. 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public 018 * License along with this library; if not, write to the Free Software 019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 020 */ 021 022 package org.jdesktop.swingx.action; 023 024 import java.awt.event.ItemEvent; 025 import java.awt.event.ItemListener; 026 import java.beans.PropertyChangeListener; 027 028 import javax.swing.AbstractAction; 029 import javax.swing.Action; 030 import javax.swing.Icon; 031 import javax.swing.KeyStroke; 032 033 /** 034 * Extends the concept of the Action to include toggle or group states. 035 * 036 */ 037 public abstract class AbstractActionExt extends AbstractAction 038 implements ItemListener { 039 040 /** 041 * The key for the large icon 042 */ 043 public static final String LARGE_ICON = "__LargeIcon__"; 044 045 /** 046 * The key for the button group 047 */ 048 public static final String GROUP = "__Group__"; 049 050 /** 051 * The key for the flag which indicates that this is a state type. 052 */ 053 public static final String IS_STATE = "__State__"; 054 055 /** 056 * Specified whether the action is selected; the default is false 057 */ 058 private boolean selected = false; 059 060 /** 061 * Default constructor, does nothing. 062 * 063 */ 064 public AbstractActionExt() { 065 // default constructor 066 } 067 /** 068 * Copy constuctor copies the state. 069 */ 070 public AbstractActionExt(AbstractActionExt action) { 071 Object[] keys = action.getKeys(); 072 for (int i = 0; i < keys.length; i++) { 073 putValue((String)keys[i], action.getValue((String)keys[i])); 074 } 075 this.selected = action.selected; 076 this.enabled = action.enabled; 077 078 // Copy change listeners. 079 PropertyChangeListener[] listeners = action.getPropertyChangeListeners(); 080 for (int i = 0; i < listeners.length; i++) { 081 addPropertyChangeListener(listeners[i]); 082 } 083 } 084 085 public AbstractActionExt(String name) { 086 super(name); 087 } 088 089 public AbstractActionExt(String name, Icon icon) { 090 super(name, icon); 091 } 092 093 /** 094 * Constructs an Action with the label and command 095 * 096 * @param name name of the action usually used as a label 097 * @param command command key of the action 098 */ 099 public AbstractActionExt(String name, String command) { 100 this(name); 101 setActionCommand(command); 102 } 103 104 /** 105 * @param name display name of the action 106 * @param command the value of the action command key 107 * @param icon icon to display 108 */ 109 public AbstractActionExt(String name, String command, Icon icon) { 110 super(name, icon); 111 setActionCommand(command); 112 } 113 /** 114 * Returns a short desciption of the action. 115 * 116 * @return the short description or null 117 */ 118 public String getShortDescription() { 119 return (String)getValue(Action.SHORT_DESCRIPTION); 120 } 121 122 /** 123 * Sets the short desciption of the action. This will also 124 * set the long description value is it is null. 125 * <p> 126 * This is a convenience method for <code>putValue</code> with the 127 * <code>Action.SHORT_DESCRIPTION</code> key. 128 * 129 * @param desc the short description; can be <code>null</code>w 130 * @see Action#SHORT_DESCRIPTION 131 * @see Action#putValue 132 */ 133 public void setShortDescription(String desc) { 134 putValue(Action.SHORT_DESCRIPTION, desc); 135 if (desc != null && getLongDescription() == null) { 136 setLongDescription(desc); 137 } 138 } 139 140 /** 141 * Returns a long desciption of the action. 142 * 143 * @return the long description or null 144 */ 145 public String getLongDescription() { 146 return (String)getValue(Action.LONG_DESCRIPTION); 147 } 148 149 /** 150 * Sets the long desciption of the action. This will also set the 151 * value of the short description if that value is null. 152 * <p> 153 * This is a convenience method for <code>putValue</code> with the 154 * <code>Action.LONG_DESCRIPTION</code> key. 155 * 156 * @param desc the long description; can be <code>null</code> 157 * @see Action#LONG_DESCRIPTION 158 * @see Action#putValue 159 */ 160 public void setLongDescription(String desc) { 161 putValue(Action.LONG_DESCRIPTION, desc); 162 if (desc != null && getShortDescription() == null) { 163 setShortDescription(desc); 164 } 165 } 166 167 /** 168 * Returns a small icon which represents the action. 169 * 170 * @return the small icon or null 171 */ 172 public Icon getSmallIcon() { 173 return (Icon)getValue(SMALL_ICON); 174 } 175 176 /** 177 * Sets the small icon which represents the action. 178 * <p> 179 * This is a convenience method for <code>putValue</code> with the 180 * <code>Action.SMALL_ICON</code> key. 181 * 182 * @param icon the small icon; can be <code>null</code> 183 * @see Action#SMALL_ICON 184 * @see Action#putValue 185 */ 186 public void setSmallIcon(Icon icon) { 187 putValue(SMALL_ICON, icon); 188 } 189 190 /** 191 * Returns a large icon which represents the action. 192 * 193 * @return the large icon or null 194 */ 195 public Icon getLargeIcon() { 196 return (Icon)getValue(LARGE_ICON); 197 } 198 199 /** 200 * Sets the large icon which represents the action. 201 * <p> 202 * This is a convenience method for <code>putValue</code> with the 203 * <code>LARGE_ICON</code> key. 204 * 205 * @param icon the large icon; can be <code>null</code> 206 * @see #LARGE_ICON 207 * @see Action#putValue 208 */ 209 public void setLargeIcon(Icon icon) { 210 putValue(LARGE_ICON, icon); 211 } 212 213 /** 214 * Sets the name of the action. 215 * <p> 216 * This is a convenience method for <code>putValue</code> with the 217 * <code>Action.NAME</code> key. 218 * 219 * @param name the name of the action; can be <code>null</code> 220 * @see Action#NAME 221 * @see Action#putValue 222 */ 223 public void setName(String name) { 224 putValue(Action.NAME, name); 225 } 226 227 /** 228 * Returns the name of the action. 229 * 230 * @return the name of the action or null 231 */ 232 public String getName() { 233 return (String)getValue(Action.NAME); 234 } 235 236 public void setMnemonic(String mnemonic) { 237 if (mnemonic != null && mnemonic.length() > 0) { 238 putValue(Action.MNEMONIC_KEY, new Integer(mnemonic.charAt(0))); 239 } 240 } 241 242 /** 243 * Sets the mnemonic key code for the action. 244 * <p> 245 * This is a convenience method for <code>putValue</code> with the 246 * <code>Action.MNEMONIC_KEY</code> key. 247 * <p> 248 * This method does not validate the value. Please see 249 * {@link javax.swing.AbstractButton#setMnemonic(int)} for details 250 * concerning the value of the mnemonic. 251 * 252 * @param mnemonic an int key code mnemonic or 0 253 * @see javax.swing.AbstractButton#setMnemonic(int) 254 * @see Action#MNEMONIC_KEY 255 * @see Action#putValue 256 */ 257 public void setMnemonic(int mnemonic) { 258 putValue(Action.MNEMONIC_KEY, new Integer(mnemonic)); 259 } 260 261 /** 262 * Return the mnemonic key code for the action. 263 * 264 * @return the mnemonic or 0 265 */ 266 public int getMnemonic() { 267 Integer value = (Integer)getValue(Action.MNEMONIC_KEY); 268 if (value != null) { 269 return value.intValue(); 270 } 271 return '\0'; 272 } 273 274 /** 275 * Sets the action command key. The action command key 276 * is used to identify the action. 277 * <p> 278 * This is a convenience method for <code>putValue</code> with the 279 * <code>Action.ACTION_COMMAND_KEY</code> key. 280 * 281 * @param key the action command 282 * @see Action#ACTION_COMMAND_KEY 283 * @see Action#putValue 284 */ 285 public void setActionCommand(Object key) { 286 putValue(Action.ACTION_COMMAND_KEY, key); 287 } 288 289 /** 290 * Returns the action command. 291 * 292 * @return the action command or null 293 */ 294 public Object getActionCommand() { 295 return getValue(Action.ACTION_COMMAND_KEY); 296 } 297 298 /** 299 * Returns the key stroke which represents an accelerator 300 * for the action. 301 * 302 * @return the key stroke or null 303 */ 304 public KeyStroke getAccelerator() { 305 return (KeyStroke)getValue(Action.ACCELERATOR_KEY); 306 } 307 308 /** 309 * Sets the key stroke which represents an accelerator 310 * for the action. 311 * <p> 312 * This is a convenience method for <code>putValue</code> with the 313 * <code>Action.ACCELERATOR_KEY</code> key. 314 * 315 * @param key the key stroke; can be <code>null</code> 316 * @see Action#ACCELERATOR_KEY 317 * @see Action#putValue 318 */ 319 public void setAccelerator(KeyStroke key) { 320 putValue(Action.ACCELERATOR_KEY, key); 321 } 322 323 /** 324 * Sets the group identity of the state action. This is used to 325 * identify the action as part of a button group. 326 */ 327 public void setGroup(Object group) { 328 putValue(GROUP, group); 329 } 330 331 public Object getGroup() { 332 return getValue(GROUP); 333 } 334 335 /** 336 * Will perform cleanup on the object. 337 * Should be called when finished with the Action. This should be used if 338 * a new action is constructed from the properties of an old action. 339 * The old action properties should be disposed. 340 */ 341 public void dispose() { 342 PropertyChangeListener[] listeners = getPropertyChangeListeners(); 343 for (int i = 0; i < listeners.length; i++) { 344 removePropertyChangeListener(listeners[i]); 345 } 346 } 347 348 // Properties etc.... 349 350 /** 351 * Inicates if this action has states. If this method returns 352 * true then the this will send ItemEvents to ItemListeners 353 * when the control constructed with this action in invoked. 354 * 355 * @return true if this can handle states 356 */ 357 public boolean isStateAction() { 358 Boolean state = (Boolean)getValue(IS_STATE); 359 if (state != null) { 360 return state.booleanValue(); 361 } 362 return false; 363 } 364 365 /** 366 * Set the state property to true. 367 */ 368 public void setStateAction() { 369 setStateAction(true); 370 } 371 372 /** 373 * Set the state property. 374 * 375 * @param state if true then this action will fire ItemEvents 376 */ 377 public void setStateAction(boolean state) { 378 putValue(IS_STATE, Boolean.valueOf(state)); 379 } 380 381 /** 382 * @return true if the action is in the selected state 383 */ 384 public boolean isSelected() { 385 return selected; 386 } 387 388 /** 389 * Changes the state of the action 390 * @param newValue true to set the action as selected of the action. 391 */ 392 public synchronized void setSelected(boolean newValue) { 393 boolean oldValue = this.selected; 394 if (oldValue != newValue) { 395 this.selected = newValue; 396 firePropertyChange("selected", Boolean.valueOf(oldValue), 397 Boolean.valueOf(newValue)); 398 } 399 } 400 401 public String toString() { 402 StringBuffer buffer = new StringBuffer("["); 403 // RG: Fix for J2SE 5.0; Can't cascade append() calls because 404 // return type in StringBuffer and AbstractStringBuilder are different 405 buffer.append(this.getClass().toString()); 406 buffer.append(":"); 407 try { 408 Object[] keys = getKeys(); 409 for (int i = 0; i < keys.length; i++) { 410 buffer.append(keys[i]); 411 buffer.append('='); 412 buffer.append(getValue( (String) keys[i]).toString()); 413 if (i < keys.length - 1) { 414 buffer.append(','); 415 } 416 } 417 buffer.append(']'); 418 } 419 catch (Exception ex) { // RG: append(char) throws IOException in J2SE 5.0 420 /** @todo Log it */ 421 } 422 return buffer.toString(); 423 } 424 425 /** 426 * @inheritDoc 427 * Default to no-op 428 */ 429 public void itemStateChanged(ItemEvent e) { 430 } 431 }