4 * Created on 10 October 2001, 01:59
\r
9 package org.tjworld.components;
\r
11 import javax.swing.Icon;
\r
12 import javax.swing.Action;
\r
13 import java.io.Serializable;
\r
14 import java.lang.Cloneable;
\r
15 import java.util.Locale;
\r
16 import java.util.ResourceBundle;
\r
17 import javax.swing.event.SwingPropertyChangeSupport;
\r
20 * <code>PowerAction</code> enhances <code>AbstractAction</code> by addding support for
\r
21 * additional properties of components, such as alternate icons
\r
22 * (dimmed, rollover, selected, pressed).
\r
24 * It is used with Power implementations of several swing components such as
\r
25 * <code>PowerButton, PowerMenuItem, PowerLabel, PowerTextField</code>.
\r
27 * It can be used with <code>JButton, JMenuItem, JLabel, JTextField</code> directly
\r
28 * to support more properties than just <code>name</code> and <code>icon</code> that
\r
29 * <code>AbstractAction</code> supports.
\r
31 * These new components are named <code>PowerButton, PowerMenuItem,</code> and so on.
\r
33 * They provide additional methods for setting and getting a PowerAction on the
\r
36 * Implementations of PowerAction need only subclass this abstract class and
\r
37 * define the <code>actionPerformed</code> method.
\r
40 * @version 1.0 10 Oct 2001
\r
42 * @see Action, AbstractAction
\r
44 public abstract class PowerAction extends javax.swing.AbstractAction {
\r
45 /** Useful constants supporting Locale-sensitive values */
\r
46 public static final String LOC_KEY_NAME = " LOC_KEY_NAME";
\r
47 public static final String LOC_KEY_SHORT_DESCRIPTION = "LOC_KEY_SD";
\r
48 public static final String LOC_KEY_LONG_DESCRIPTION = "LOC_KEY_LD";
\r
49 public static final String LOC_KEY_ACTION_COMMAND_KEY = "LOC_KEY_AC";
\r
50 public static final String LOC_KEY_MNEMONIC_KEY = "LOC_KEY_MNEM";
\r
51 public static final String LOC_KEY_ACCELERATOR_KEY = "LOC_KEY_ACCEL";
\r
53 /** Flag masks for blocking selected PropertyChangeEvents */
\r
54 public static final long MASK_NAME = 0x80000000;
\r
55 public static final long MASK_ICON = 0x40000000;
\r
56 public static final long MASK_SHORT_DESCRIPTION = 0x20000000;
\r
57 public static final long MASK_LONG_DESCRIPTION = 0x10000000;
\r
58 public static final long MASK_ACTION_COMMAND_KEY = 0x08000000;
\r
59 public static final long MASK_MNEMONIC_KEY = 0x04000000;
\r
60 public static final long MASK_ACCELERATOR_KEY = 0x02000000;
\r
62 public static final long MASK_LOC_NAME = 0x00008000;
\r
63 public static final long MASK_LOC_ICON = 0x00004000;
\r
64 public static final long MASK_LOC_SHORT_DESCRIPTION = 0x00002000;
\r
65 public static final long MASK_LOC_LONG_DESCRIPTION = 0x00001000;
\r
66 public static final long MASK_LOC_ACTION_COMMAND_KEY = 0x00000800;
\r
67 public static final long MASK_LOC_MNEMONIC = 0x00000400;
\r
68 public static final long MASK_LOC_ACCELERATOR_KEY = 0x00000200;
\r
70 /** frequently used masks */
\r
71 public static final long MASK_ALL = 0xFFFFFFFF; // everything enabled
\r
72 public static final long MASK_JMENUITEM = 0xFFFFFFFF; // everything enabled
\r
73 public static final long MASK_JBUTTON = 0xFDFFFFFF; // no accelerator
\r
74 public static final long MASK_JTOOLBAR_BUTTON = 0x75FFFFFF; // no name, action command, accelerator
\r
75 public static final long MASK_NONE = 0x00000000; // nothing enabled
\r
77 /** current mask flags */
\r
78 protected long maskFlags = 0xFFFFFFFF;
\r
80 /** Keep track of the state of the Property Change Listener interface */
\r
81 protected boolean firePropertyChangeEnabled = true;
\r
83 /** A copy of the original change support object */
\r
84 protected SwingPropertyChangeSupport oldChangeSupport;
\r
86 /** make the action Locale-sensitive */
\r
87 protected Locale currentLocale = null;
\r
89 /** Creates new default PowerAction */
\r
90 public PowerAction() {
\r
91 super(); // nothing special for the default constructor to do, so let super class do it's thing
\r
94 /** Create a new PowerAction that supports just the properties that <code>javax.swing.AbstractButton</code> uses.
\r
96 * @param name The Text or Title of a component using this action
\r
97 * @param icon The Icon associated with this action
\r
98 * @param tooltip The popup tooltip associated with <code>JComponent</code>
\r
99 * @param longDesc The longer description associated with this action (for use in help services, etc.)
\r
100 * @param actionCommand The action command name (e.g: New, Save, Delete. etc.)
\r
101 * @param mnemonic The character in <code>name</code> used as a quick-key (gets underlined in menu's and buttons)
\r
102 * @param accelerator The key-combination required to activate this action from the parent window or frame
\r
104 * @see AbstractButton#configurePropertiesFromAction
\r
106 public PowerAction(String name, Icon icon, String tooltip, String longDesc, String actionCommand, int mnemonic, javax.swing.KeyStroke accelerator) {
\r
107 super(name, icon); // let super add these, don't duplicate code
\r
109 // add key-value pairs ONLY if the received value is not 'empty'
\r
110 if(tooltip != null) putValue(Action.SHORT_DESCRIPTION, tooltip);
\r
111 if(longDesc != null) putValue(Action.LONG_DESCRIPTION, longDesc);
\r
112 if(actionCommand != null) putValue(Action.ACTION_COMMAND_KEY, actionCommand);
\r
113 if(mnemonic > 0) putValue(Action.MNEMONIC_KEY, new Integer(mnemonic));
\r
114 if(accelerator != null) putValue(Action.ACCELERATOR_KEY, accelerator);
\r
117 /** Create a new PowerAction that supports locale-sensitive values
\r
119 * The <code>ResourceBundle</code> keys that indentify the values used by the action
\r
120 * are stored as Key/Values along with the standard <code>Action</code> key/value pairs.
\r
122 * Hereafter, a simple call to <code>setLocale(loc, res)</code> allows the action to update
\r
123 * itself with locale-sensitive values.
\r
125 * @param name The Text or Title of a component using this action
\r
126 * @param icon The Icon associated with this action
\r
127 * @param tooltip The popup tooltip associated with <code>JComponent</code>
\r
128 * @param longDesc The longer description associated with this action (for use in help services, etc.)
\r
129 * @param actionCommand The action command name (e.g: New, Save, Delete. etc.)
\r
130 * @param mnemonic The character in <code>name</code> used as a quick-key (gets underlined in menu's and buttons)
\r
131 * @param accelerator The key-combination required to activate this action from the parent window or frame
\r
132 * @param loc The Locale currently assigned to this action
\r
133 * @param locName The <code>ResourceBundle</code> key used to identify the NAME value
\r
134 * @param locTooltip The <code>ResourceBundle</code> key used to identify the SHORT_DESCRIPTION value
\r
135 * @param locLongDesc The <code>ResourceBundle</code> key used to identify the LONG_DESCRIPTION value
\r
136 * @param locActionCommand The <code>ResourceBundle</code> key used to identify the ACTION_COMMAND value
\r
137 * @param locMnemonic The <code>ResourceBundle</code> key used to identify the MNEMONIC value
\r
138 * @param locAccelerator The <code>ResourceBundle</code> key used to identify the ACCELERATOR value
\r
140 * @see ResourceBundle
\r
142 * @see PowerAction#setLocale
\r
144 public PowerAction(String name, Icon icon, String tooltip, String longDesc, String actionCommand, int mnemonic, javax.swing.KeyStroke accelerator,
\r
145 java.util.Locale loc, String locName, String locTooltip, String locLongDesc, String locActionCommand, String locMnemonic, String locAccelerator) {
\r
146 this(name, icon, tooltip, longDesc, actionCommand, mnemonic, accelerator); // don't duplicate code
\r
148 // add Locale-sensitve key-value pairs ONLY if the received value is not 'empty'
\r
149 if(locName != null) putValue(LOC_KEY_NAME, locName);
\r
150 if(locTooltip != null) putValue(LOC_KEY_SHORT_DESCRIPTION, locTooltip);
\r
151 if(locLongDesc != null) putValue(LOC_KEY_LONG_DESCRIPTION, locLongDesc);
\r
152 if(locActionCommand != null) putValue(LOC_KEY_ACTION_COMMAND_KEY, locActionCommand);
\r
153 if(locMnemonic != null) putValue(LOC_KEY_MNEMONIC_KEY, locMnemonic);
\r
154 if(locAccelerator != null) putValue(LOC_KEY_ACCELERATOR_KEY, locAccelerator);
\r
156 if(loc != null) // set the Locale
\r
157 currentLocale = loc;
\r
159 currentLocale = Locale.getDefault();
\r
162 /** Are PropertyChangeEvents enabled?
\r
164 * @returns true is they are, false otherwise
\r
166 public boolean isFirePropertyChangeEnabled() {
\r
167 return firePropertyChangeEnabled;
\r
170 public void setPropertyChangeMask(long mask) {
\r
171 maskFlags = mask; // update the enabled PropertyChange events
\r
174 public long getPropertyChangeMask() {
\r
178 /** Enable or Disable PropertyChangeEvent notifications
\r
180 * @param enabled true to enable, false to disable
\r
182 public void setFirePropertyChangeEnabled(boolean enabled) {
\r
183 if(enabled) { // return the underlying AbstractAction.changeSupport to it's original state
\r
184 if(changeSupport == null && oldChangeSupport != null) // don't mes it up if it's not null
\r
185 changeSupport = oldChangeSupport; // allow AbstractAction.firePropertyChange() to work again
\r
186 } else { // disable AbstractAction.firePropertyChange()
\r
187 oldChangeSupport = changeSupport; // keep a copy, ready for re-enabling
\r
188 changeSupport = null; // clear the change support
\r
191 firePropertyChangeEnabled = enabled; // update the flag
\r
194 /** Update the locale, alter strings if necessary
\r
196 * For each <code>Action</code> key/value pair that has an associated <code>ResourceBundle</code>
\r
197 * key specified, the value will be updated from the specified <code>ResourceBundle</code>
\r
199 * @param loc The new locale
\r
200 * @param res The resource bundle to get new strings from
\r
202 public void setLocale(Locale loc, ResourceBundle res) {
\r
203 // make sure locale is valid, in use, and not already changed; otherwise ignore it
\r
204 if(loc != null && currentLocale != null && loc != currentLocale) {
\r
205 currentLocale = loc; // update locale
\r
206 if(res != null) { // make sure the resource bundle is good too
\r
208 /* for each potential Action key/value pair, only update if the Locale-Key
\r
209 * is in the collection of key/value pairs
\r
211 * would be cleaner source to do this in an iteration - maybe need to create
\r
212 * an array to store the static constant key names from Action and PowerAction??
\r
214 String locKeyName = null;
\r
215 Object actValue = null;
\r
216 Object locValue = null;
\r
218 if((actValue = getValue(Action.NAME)) != null) { // there is a key/value pair that might need updating
\r
219 if((locKeyName = (String)getValue(LOC_KEY_NAME)) != null) { // a locale-sensitive resource key has been stored...
\r
220 locValue = res.getObject(locKeyName); // ...so request it's value from the resource bundle
\r
221 if(locValue != null) { // don't try to replace a good value with an empty one
\r
222 if((maskFlags & MASK_NAME) == MASK_NAME) // disable PropertyChangeEvents if mask is set
\r
223 setFirePropertyChangeEnabled(false);
\r
225 putValue(Action.NAME, locValue); // change the value
\r
226 setFirePropertyChangeEnabled(true); // ensure PropertyChangeEvents are enabled
\r
231 if((actValue = getValue(Action.SHORT_DESCRIPTION)) != null) { // there is a key/value pair that might need updating
\r
232 if((locKeyName = (String)getValue(LOC_KEY_SHORT_DESCRIPTION)) != null) { // a locale-sensitive resource key has been stored...
\r
233 locValue = res.getObject(locKeyName); // ...so request it's value from the resource bundle
\r
234 if(locValue != null) { // don't try to replace a good value with an empty one
\r
235 if((maskFlags & MASK_SHORT_DESCRIPTION) == MASK_SHORT_DESCRIPTION) // disable PropertyChangeEvents if mask is set
\r
236 setFirePropertyChangeEnabled(false);
\r
238 putValue(Action.SHORT_DESCRIPTION, locValue);
\r
239 setFirePropertyChangeEnabled(true); // ensure PropertyChangeEvents are enabled
\r
244 if((actValue = getValue(Action.LONG_DESCRIPTION)) != null) { // there is a key/value pair that might need updating
\r
245 if((locKeyName = (String)getValue(LOC_KEY_LONG_DESCRIPTION)) != null) { // a locale-sensitive resource key has been stored...
\r
246 locValue = res.getObject(locKeyName); // ...so request it's value from the resource bundle
\r
247 if(locValue != null) { // don't try to replace a good value with an empty one
\r
248 if((maskFlags & MASK_LONG_DESCRIPTION) == MASK_LONG_DESCRIPTION) // disable PropertyChangeEvents if mask is set
\r
249 setFirePropertyChangeEnabled(false);
\r
251 putValue(Action.LONG_DESCRIPTION, locValue);
\r
252 setFirePropertyChangeEnabled(true); // ensure PropertyChangeEvents are enabled
\r
257 if((actValue = getValue(Action.ACTION_COMMAND_KEY)) != null) { // there is a key/value pair that might need updating
\r
258 if((locKeyName = (String)getValue(LOC_KEY_ACTION_COMMAND_KEY)) != null) { // a locale-sensitive resource key has been stored...
\r
259 locValue = res.getObject(locKeyName); // ...so request it's value from the resource bundle
\r
260 if(locValue != null) { // don't try to replace a good value with an empty one
\r
261 if((maskFlags & MASK_ACTION_COMMAND_KEY) == MASK_ACTION_COMMAND_KEY) // disable PropertyChangeEvents if mask is set
\r
262 setFirePropertyChangeEnabled(false);
\r
263 putValue(Action.ACTION_COMMAND_KEY, locValue);
\r
264 setFirePropertyChangeEnabled(true); // ensure PropertyChangeEvents are enabled
\r
269 if((actValue = getValue(Action.MNEMONIC_KEY)) != null) { // there is a key/value pair that might need updating
\r
270 if((locKeyName = (String)getValue(LOC_KEY_MNEMONIC_KEY)) != null) { // a locale-sensitive resource key has been stored...
\r
271 locValue = res.getObject(locKeyName); // ...so request it's value from the resource bundle
\r
272 if(locValue != null) { // don't try to replace a good value with an empty one
\r
273 if((maskFlags & MASK_MNEMONIC_KEY) == MASK_MNEMONIC_KEY) // disable PropertyChangeEvents if mask is set
\r
274 setFirePropertyChangeEnabled(false); // ensure PropertyChangeEvents are enabled
\r
276 putValue(Action.MNEMONIC_KEY, locValue);
\r
277 setFirePropertyChangeEnabled(true); // ensure PropertyChangeEvents are enabled
\r
282 if((actValue = getValue(Action.ACCELERATOR_KEY)) != null) { // there is a key/value pair that might need updating
\r
283 if((locKeyName = (String)getValue(LOC_KEY_ACCELERATOR_KEY)) != null) { // a locale-sensitive resource key has been stored...
\r
284 locValue = res.getObject(locKeyName); // ...so request it's value from the resource bundle
\r
285 if(locValue != null) { // don't try to replace a good value with an empty one
\r
286 if((maskFlags & MASK_ACCELERATOR_KEY) == MASK_ACCELERATOR_KEY) // disable PropertyChangeEvents if mask is set
\r
287 setFirePropertyChangeEnabled(false);
\r
289 putValue(Action.ACCELERATOR_KEY, locValue);
\r
290 setFirePropertyChangeEnabled(true); // ensure PropertyChangeEvents are enabled
\r
298 /** Get the current Locale of the Action
\r
300 * @returns The current locale
\r
302 public Locale getLocale() {
\r
303 return currentLocale;
\r