001    /* ========================================================================
002     * JCommon : a free general purpose class library for the Java(tm) platform
003     * ========================================================================
004     *
005     * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
006     * 
007     * Project Info:  http://www.jfree.org/jcommon/index.html
008     *
009     * This library is free software; you can redistribute it and/or modify it 
010     * under the terms of the GNU Lesser General Public License as published by 
011     * the Free Software Foundation; either version 2.1 of the License, or 
012     * (at your option) any later version.
013     *
014     * This library is distributed in the hope that it will be useful, but 
015     * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
016     * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
017     * License for more details.
018     *
019     * You should have received a copy of the GNU Lesser General Public
020     * License along with this library; if not, write to the Free Software
021     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
022     * USA.  
023     *
024     * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
025     * in the United States and other countries.]
026     * 
027     * -------------------
028     * ActionMenuItem.java
029     * -------------------
030     * (C)opyright 2002-2004, by Thomas Morgner and Contributors.
031     *
032     * Original Author:  Thomas Morgner;
033     * Contributor(s):   David Gilbert (for Object Refinery Limited);
034     *
035     * $Id: ActionMenuItem.java,v 1.5 2007/11/02 17:50:36 taqua Exp $
036     *
037     * ChangeLog
038     * ---------
039     * 30-Aug-2002 : Initial version
040     * 01-Aug-2002 : Documentation
041     * 10-Dec-2002 : Minor Javadoc updates (DG);
042     *
043     */
044    
045    package org.jfree.ui.action;
046    
047    import java.awt.event.KeyEvent;
048    import java.beans.PropertyChangeEvent;
049    import java.beans.PropertyChangeListener;
050    import javax.swing.Action;
051    import javax.swing.Icon;
052    import javax.swing.JMenuItem;
053    import javax.swing.KeyStroke;
054    
055    import org.jfree.util.Log;
056    
057    /**
058     * The ActionMenuItem is used to connect an Action and its properties to an
059     * MenuItem.
060     * <p/>
061     * This functionality is already implemented in JDK 1.3 but needed for JDK 1.2.2
062     * compatibility.
063     *
064     * @author Thomas Morgner
065     */
066    public class ActionMenuItem extends JMenuItem
067    {
068    
069      /** The action. */
070      private Action action;
071    
072      /** The property change handler. */
073      private ActionEnablePropertyChangeHandler propertyChangeHandler;
074    
075      /**
076       * Helperclass to handle the property change event raised by the action.
077       * Changed properties in the action will affect the button.
078       */
079      private class ActionEnablePropertyChangeHandler
080              implements PropertyChangeListener
081      {
082        public ActionEnablePropertyChangeHandler()
083        {
084        }
085    
086        /**
087         * Receives notification of a property change event.
088         *
089         * @param event the property change event.
090         */
091        public void propertyChange(final PropertyChangeEvent event)
092        {
093          try
094          {
095            if (event.getPropertyName().equals("enabled"))
096            {
097              setEnabled(getAction().isEnabled());
098            }
099            else if (event.getPropertyName().equals(Action.SMALL_ICON))
100            {
101              setIcon((Icon) getAction().getValue(Action.SMALL_ICON));
102            }
103            else if (event.getPropertyName().equals(Action.NAME))
104            {
105              setText((String) getAction().getValue(Action.NAME));
106            }
107            else if (event.getPropertyName().equals(Action.SHORT_DESCRIPTION))
108            {
109              ActionMenuItem.this.setToolTipText((String)
110                      getAction().getValue(Action.SHORT_DESCRIPTION));
111            }
112    
113            final Action ac = getAction();
114            if (event.getPropertyName().equals(ActionDowngrade.ACCELERATOR_KEY))
115            {
116              setAccelerator((KeyStroke) ac.getValue(ActionDowngrade.ACCELERATOR_KEY));
117            }
118            else if (event.getPropertyName().equals(ActionDowngrade.MNEMONIC_KEY))
119            {
120              final Object o = ac.getValue(ActionDowngrade.MNEMONIC_KEY);
121              if (o != null)
122              {
123                if (o instanceof Character)
124                {
125                  final Character c = (Character) o;
126                  setMnemonic(c.charValue());
127                }
128                else if (o instanceof Integer)
129                {
130                  final Integer c = (Integer) o;
131                  setMnemonic(c.intValue());
132                }
133              }
134              else
135              {
136                setMnemonic(KeyEvent.VK_UNDEFINED);
137              }
138            }
139          }
140          catch (Exception e)
141          {
142            Log.warn("Error on PropertyChange in ActionButton: ", e);
143          }
144        }
145      }
146    
147      /** Default constructor. */
148      public ActionMenuItem()
149      {
150        // nothing required
151      }
152    
153      /**
154       * Creates a menu item with the specified icon.
155       *
156       * @param icon the icon.
157       */
158      public ActionMenuItem(final Icon icon)
159      {
160        super(icon);
161      }
162    
163      /**
164       * Creates a menu item with the specified label.
165       *
166       * @param text the label.
167       */
168      public ActionMenuItem(final String text)
169      {
170        super(text);
171      }
172    
173      /**
174       * Creates a menu item with the specified label and icon.
175       *
176       * @param text the label.
177       * @param icon the icon.
178       */
179      public ActionMenuItem(final String text, final Icon icon)
180      {
181        super(text, icon);
182      }
183    
184      /**
185       * Creates a new menu item with the specified label and mnemonic.
186       *
187       * @param text the label.
188       * @param i    the mnemonic.
189       */
190      public ActionMenuItem(final String text, final int i)
191      {
192        super(text, i);
193      }
194    
195      /**
196       * Creates a new menu item based on the specified action.
197       *
198       * @param action the action.
199       */
200      public ActionMenuItem(final Action action)
201      {
202        setAction(action);
203      }
204    
205      /**
206       * Returns the assigned action or null if no action has been assigned.
207       *
208       * @return the action.
209       */
210      public Action getAction()
211      {
212        return this.action;
213      }
214    
215      /**
216       * Returns and initializes the PropertyChangehandler for this ActionMenuItem.
217       * The PropertyChangeHandler monitors the action and updates the menuitem if
218       * necessary.
219       *
220       * @return the property change handler.
221       */
222      private ActionEnablePropertyChangeHandler getPropertyChangeHandler()
223      {
224        if (this.propertyChangeHandler == null)
225        {
226          this.propertyChangeHandler = new ActionEnablePropertyChangeHandler();
227        }
228        return this.propertyChangeHandler;
229      }
230    
231      /**
232       * Enables and disables this button and if an action is assigned to this
233       * menuitem the propertychange is forwarded to the assigned action.
234       *
235       * @param b the new enable-state of this menuitem
236       */
237      public void setEnabled(final boolean b)
238      {
239        super.setEnabled(b);
240        if (getAction() != null)
241        {
242          getAction().setEnabled(b);
243        }
244      }
245    
246      /**
247       * Assigns the given action to this menuitem. The properties of the action
248       * will be assigned to the menuitem. If an previous action was set, the old
249       * action is unregistered.
250       * <p/>
251       * <ul> <li>NAME - specifies the menuitem text <li>SMALL_ICON - specifies the
252       * menuitems icon <li>MNEMONIC_KEY - specifies the menuitems mnemonic key
253       * <li>ACCELERATOR_KEY - specifies the menuitems accelerator </ul>
254       *
255       * @param newAction the new action
256       */
257      public void setAction(final Action newAction)
258      {
259        final Action oldAction = getAction();
260        if (oldAction != null)
261        {
262          removeActionListener(oldAction);
263          oldAction.removePropertyChangeListener(getPropertyChangeHandler());
264          setAccelerator(null);
265        }
266        this.action = newAction;
267        if (this.action != null)
268        {
269          addActionListener(newAction);
270          newAction.addPropertyChangeListener(getPropertyChangeHandler());
271    
272          setText((String) (newAction.getValue(Action.NAME)));
273          setToolTipText((String) (newAction.getValue(Action.SHORT_DESCRIPTION)));
274          setIcon((Icon) newAction.getValue(Action.SMALL_ICON));
275          setEnabled(this.action.isEnabled());
276    
277          Object o = newAction.getValue(ActionDowngrade.MNEMONIC_KEY);
278          if (o != null)
279          {
280            if (o instanceof Character)
281            {
282              final Character c = (Character) o;
283              setMnemonic(c.charValue());
284            }
285            else if (o instanceof Integer)
286            {
287              final Integer c = (Integer) o;
288              setMnemonic(c.intValue());
289            }
290          }
291          else
292          {
293            setMnemonic(KeyEvent.VK_UNDEFINED);
294          }
295    
296    
297          o = newAction.getValue(ActionDowngrade.ACCELERATOR_KEY);
298          if (o instanceof KeyStroke)
299          {
300            setAccelerator((KeyStroke) o);
301          }
302        }
303      }
304    }