001: package net.suberic.util.gui;
002:
003: import javax.swing.*;
004: import net.suberic.util.VariableBundle;
005: import java.util.Hashtable;
006: import java.util.StringTokenizer;
007: import java.util.MissingResourceException;
008: import javax.swing.Action;
009:
010: /**
011: * This is a JMenu which implements the ConfigurableUI interface, and
012: * therefore may be dynamically created using a VariableBundle and key,
013: * and updated using an array of Actions.
014: */
015:
016: public class ConfigurablePopupMenu extends JPopupMenu implements
017: ConfigurableUI {
018:
019: // the latest commands list. i'm storing this for now because i
020: // can't do a JButton.removeActionListeners().
021:
022: protected Hashtable commands = new Hashtable();
023:
024: public ConfigurablePopupMenu() {
025: super ();
026: }
027:
028: /**
029: * This creates a new ConfigurableMenu using the menuID as the
030: * configuration key, and vars as the source for the values of all the
031: * properties.
032: *
033: * If menuID doesn't exist in vars, then this returns an empty
034: * Menu.
035: */
036:
037: public ConfigurablePopupMenu(String menuID, VariableBundle vars) {
038: super ();
039:
040: configureComponent(menuID, vars);
041: }
042:
043: /**
044: * This configures the Menu using the given menuID and
045: * VariableBundle.
046: *
047: * As defined in interface net.suberic.util.gui.ConfigurableUI.
048: */
049:
050: public void configureComponent(String key, VariableBundle vars) {
051: StringTokenizer iKeys = null;
052: try {
053: iKeys = new StringTokenizer(vars.getProperty(key), ":");
054: } catch (MissingResourceException mre) {
055: try {
056: System.err.println(vars
057: .getProperty("error.NoSuchResource")
058: + " " + mre.getKey());
059: } catch (MissingResourceException mretwo) {
060: System.err.println("Unable to load resource "
061: + mre.getKey());
062: }
063:
064: return;
065:
066: }
067: String currentToken;
068:
069: try {
070: setLabel(vars.getProperty(key + ".Label"));
071: } catch (MissingResourceException mre) {
072: }
073:
074: while (iKeys.hasMoreTokens()) {
075: currentToken = iKeys.nextToken();
076: if (currentToken.equals("-")) {
077: this .addSeparator();
078: } else {
079: JMenuItem mi = createMenuItem(key, currentToken, vars);
080: this .add(mi);
081: }
082: }
083: }
084:
085: /**
086: * And this actually creates the menu items themselves.
087: */
088: protected JMenuItem createMenuItem(String menuID,
089: String menuItemID, VariableBundle vars) {
090: // TODO: should also make these undo-able.
091:
092: if (vars.getProperty(menuID + "." + menuItemID + ".class", "") == "") {
093:
094: if (vars.getProperty(menuID + "." + menuItemID, "") != "") {
095: return new ConfigurableMenu(menuID + "." + menuItemID,
096: vars);
097: }
098:
099: JMenuItem mi;
100: try {
101: mi = new JMenuItem(vars.getProperty(menuID + "."
102: + menuItemID + ".Label"));
103: } catch (MissingResourceException mre) {
104: mi = new JMenuItem(menuItemID);
105: }
106:
107: java.net.URL url = null;
108:
109: try {
110: url = this .getClass().getResource(
111: vars.getProperty(menuID + "." + menuItemID
112: + ".Image"));
113: } catch (MissingResourceException mre) {
114: }
115:
116: if (url != null) {
117: mi.setHorizontalTextPosition(JButton.RIGHT);
118: mi.setIcon(new ImageIcon(url));
119: }
120:
121: String cmd = vars.getProperty(menuID + "." + menuItemID
122: + ".Action", menuItemID);
123:
124: mi.setActionCommand(cmd);
125:
126: return mi;
127: } else {
128: // this means that we have a submenu.
129: ConfigurableMenu m;
130:
131: if (vars.getProperty(menuID + "." + menuItemID + ".class",
132: "").equals("")) {
133: m = new ConfigurableMenu(menuID + "." + menuItemID,
134: vars);
135:
136: } else {
137: // this means we're using a custom Menu.
138:
139: try {
140: Class menuClass = Class.forName(vars.getProperty(
141: menuID + "." + menuItemID + ".class",
142: "net.suberic.util.gui.ConfigurableMenu"));
143: m = (ConfigurableMenu) menuClass.newInstance();
144: m.configureComponent(menuID + "." + menuItemID,
145: vars);
146: } catch (Exception e) {
147: // if we get any errors, just create a plain
148: // ConfigurableMenu.
149: System.err
150: .println("Unable to create menu with class "
151: + vars
152: .getProperty(menuID + "."
153: + menuItemID
154: + ".class",
155: "net.suberic.util.gui.ConfigurableMenu")
156: + ": " + e.getMessage());
157: e.printStackTrace();
158: m = new ConfigurableMenu(menuID + "." + menuItemID,
159: vars);
160: }
161: }
162:
163: return m;
164:
165: }
166: }
167:
168: /**
169: * As defined in net.suberic.util.gui.ConfigurableUI
170: */
171: public void setActive(javax.swing.Action[] newActions) {
172: Hashtable tmpHash = new Hashtable();
173: if (newActions != null && newActions.length > 0) {
174: for (int i = 0; i < newActions.length; i++) {
175: String cmdName = (String) newActions[i]
176: .getValue(Action.NAME);
177: tmpHash.put(cmdName, newActions[i]);
178: }
179: }
180: setActive(tmpHash);
181: }
182:
183: /**
184: * As defined in net.suberic.util.gui.ConfigurableUI
185: */
186: public void setActive(Hashtable newCommands) {
187: clearListeners();
188: commands = newCommands;
189: setActiveMenuItems();
190: }
191:
192: protected void setActiveMenuItems() {
193: for (int j = 0; j < getSubElements().length; j++) {
194: if (getComponent(j) instanceof ConfigurableMenu) {
195: ((ConfigurableMenu) getComponent(j))
196: .setActive(commands);
197: } else {
198: JMenuItem mi = (JMenuItem) getComponent(j);
199: Action a = getAction(mi.getActionCommand());
200: if (a != null) {
201: //mi.removeActionListener(a);
202: mi.addActionListener(a);
203: mi.setEnabled(true);
204: } else {
205: mi.setEnabled(false);
206: }
207: }
208: }
209: }
210:
211: /**
212: * This clears all of the current listeners on the Menu.
213: */
214:
215: private void clearListeners() {
216: for (int j = 0; j < getSubElements().length; j++) {
217: if (getComponent(j) instanceof ConfigurableMenu) {
218: // we don't have to clear the listeners here because
219: // it will be done in setActive().
220: ;
221: } else {
222: JMenuItem mi = (JMenuItem) getComponent(j);
223: Action a = getAction(mi.getActionCommand());
224: if (a != null) {
225: mi.removeActionListener(a);
226: }
227: }
228: }
229: }
230:
231: /**
232: * This gets an action from the supported commands. If there is no
233: * supported action, it returns null
234: */
235:
236: public Action getAction(String command) {
237: return (Action) commands.get(command);
238: }
239:
240: }
|