001/* A menu item factory that creates actions for firing actions 002 003 Copyright (c) 2000-2016 The Regents of the University of California. 004 All rights reserved. 005 Permission is hereby granted, without written agreement and without 006 license or royalty fees, to use, copy, modify, and distribute this 007 software and its documentation for any purpose, provided that the above 008 copyright notice and the following two paragraphs appear in all copies 009 of this software. 010 011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 015 SUCH DAMAGE. 016 017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 022 ENHANCEMENTS, OR MODIFICATIONS. 023 024 PT_COPYRIGHT_VERSION_2 025 COPYRIGHTENDKEY 026 027 */ 028package ptolemy.vergil.toolbox; 029 030import java.lang.ref.WeakReference; 031import java.util.Iterator; 032import java.util.LinkedList; 033import java.util.List; 034 035import javax.swing.Action; 036import javax.swing.JMenu; 037import javax.swing.JMenuItem; 038 039import diva.gui.toolbox.JContextMenu; 040import ptolemy.kernel.util.NamedObj; 041 042/////////////////////////////////////////////////////////////////// 043//// MenuActionFactory 044 045/** 046 A factory that adds a given action or set of actions 047 to a context menu. If an array of actions is given to 048 the constructor, then the actions will be put in a submenu 049 with the specified label. 050 051 @author Steve Neuendorffer 052 @version $Id$ 053 @since Ptolemy II 1.0 054 @Pt.ProposedRating Red (eal) 055 @Pt.AcceptedRating Red (johnr) 056 */ 057public class MenuActionFactory implements MenuItemFactory { 058 /** Construct a factory that adds a given action to a given context menu. 059 * @param action The action to be associated with the context menu. 060 */ 061 public MenuActionFactory(Action action) { 062 _action = action; 063 } 064 065 /** Construct a factory that adds a given group of actions 066 * to a given context menu in a submenu with the specified label. 067 * @param actions The actions to be in the submenu. 068 * @param label The label for the submenu. 069 */ 070 public MenuActionFactory(Action[] actions, String label) { 071 _actions = actions; 072 _label = label; 073 } 074 075 /** Add an action to the pre-existing group of actions. 076 * @param action The action to add. 077 */ 078 public void addAction(Action action) { 079 addAction(action, null); 080 } 081 082 /** Add an action to the pre-existing group of actions. 083 * If this was constructed with the single argument, then this 084 * converts the menu action into a submenu with the specified label. 085 * @param action The action to add. 086 * @param label The label to give to the menu group. 087 */ 088 public void addAction(Action action, String label) { 089 if (_action != null) { 090 // Previously, there was only one action. 091 // Convert to a subaction. 092 _actions = new Action[2]; 093 _actions[0] = _action; 094 _actions[1] = action; 095 _action = null; 096 } else { 097 // Create a new actions array. 098 Action[] newActions = new Action[_actions.length + 1]; 099 System.arraycopy(_actions, 0, newActions, 0, _actions.length); 100 newActions[_actions.length] = action; 101 _actions = newActions; 102 } 103 if (label != null) { 104 _label = label; 105 } 106 } 107 108 /** Add a set of action to the pre-existing group of actions. 109 * If this was constructed with the single argument, then this 110 * converts the menu action into a submenu with the specified label. 111 * @param actions The actions to add. 112 * @param label The label to give to the menu group if it 113 * previously not a menu group. 114 */ 115 public void addActions(Action[] actions, String label) { 116 int start = 0; 117 if (_action != null) { 118 // Previously, there was only one action. 119 // Convert to a subaction. 120 _actions = new Action[actions.length + 1]; 121 _actions[0] = _action; 122 start = 1; 123 _action = null; 124 } else { 125 Action[] newActions = new Action[_actions.length + actions.length]; 126 System.arraycopy(_actions, 0, newActions, 0, _actions.length); 127 start = _actions.length; 128 _actions = newActions; 129 } 130 System.arraycopy(actions, 0, _actions, start, actions.length); 131 _label = label; 132 } 133 134 /** Add a menu item listener to the list of menu item listeners. 135 * 136 * @param listener The menu item listener. 137 */ 138 public void addMenuItemListener(MenuItemListener listener) { 139 if (_menuItemListeners == null) { 140 _menuItemListeners = new LinkedList(); 141 } 142 _menuItemListeners.add(new WeakReference(listener)); 143 } 144 145 /** Add an item to the given context menu that will configure the 146 * parameters on the given target. 147 * @param menu The context menu to add to. 148 * @param object The object that the menu item command will operate on. 149 * @return A menu item, or null to decline to provide a menu item. 150 */ 151 @Override 152 public JMenuItem create(JContextMenu menu, NamedObj object) { 153 JMenuItem menuItem; 154 if (_action != null) { 155 // Single action as a simple menu entry. 156 menuItem = _add(menu, _action, 157 (String) _action.getValue(Action.NAME)); 158 } else { 159 // Requested a submenu with a group of actions. 160 final JMenu submenu = new JMenu(_label); 161 menu.add(submenu, _label); 162 for (Action _action2 : _actions) { 163 _add(submenu, _action2); 164 } 165 menuItem = submenu; 166 } 167 if (_menuItemListeners != null) { 168 Iterator listeners = _menuItemListeners.iterator(); 169 while (listeners.hasNext()) { 170 WeakReference reference = (WeakReference) listeners.next(); 171 Object contents = reference.get(); 172 if (contents instanceof MenuItemListener) { 173 ((MenuItemListener) contents).menuItemCreated(menu, object, 174 menuItem); 175 } 176 } 177 } 178 return menuItem; 179 } 180 181 /** Substitute the old action with the new action, if the old action is 182 * added to this factory. 183 * @param oldAction The old action. 184 * @param newAction The new action. 185 * @return true if the old action is found and is substituted; false if the 186 * old action is not added to this factory. 187 */ 188 public boolean substitute(Action oldAction, Action newAction) { 189 if (_action != null) { 190 if (_action == oldAction) { 191 _action = newAction; 192 return true; 193 } else { 194 return false; 195 } 196 } else { 197 for (int i = 0; i < _actions.length; i++) { 198 if (_actions[i] == oldAction) { 199 _actions[i] = newAction; 200 return true; 201 } 202 } 203 return false; 204 } 205 } 206 207 /** Add an action to the context menu. 208 * @param menu The context menu. 209 * @param action The action to be added to the context menu. 210 * @param tooltip The tooltip for the action. 211 * @return The added menu item. 212 */ 213 protected JMenuItem _add(JContextMenu menu, Action action, String tooltip) { 214 return menu.add(action, tooltip); 215 } 216 217 /** Add an action to the submenu. 218 * @param submenu The submenu. 219 * @param action The action to be added to the submenu. 220 * @return The added menu item. 221 */ 222 protected JMenuItem _add(JMenu submenu, Action action) { 223 return submenu.add(action); 224 } 225 226 /////////////////////////////////////////////////////////////////// 227 //// private variables //// 228 229 /** The action that will be added to the context menu. */ 230 private Action _action; 231 232 /** The group of actions that will be added in a submenu. */ 233 private Action[] _actions; 234 235 /** The submenu label, if one was given. */ 236 private String _label; 237 238 /** the list of menu item listeners. */ 239 private List _menuItemListeners; 240}