001: /*
002: * EnhancedMenu.java - jEdit menu
003: * :tabSize=8:indentSize=8:noTabs=false:
004: * :folding=explicit:collapseFolds=1:
005: *
006: * Copyright (C) 2001, 2003 Slava Pestov
007: *
008: * This program is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU General Public License
010: * as published by the Free Software Foundation; either version 2
011: * of the License, or any later version.
012: *
013: * This program is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: * GNU General Public License for more details.
017: *
018: * You should have received a copy of the GNU General Public License
019: * along with this program; if not, write to the Free Software
020: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
021: */
022:
023: package org.gjt.sp.jedit.menu;
024:
025: //{{{ Imports
026: import javax.swing.event.*;
027: import javax.swing.*;
028: import java.util.StringTokenizer;
029: import org.gjt.sp.jedit.msg.*;
030: import org.gjt.sp.jedit.*;
031:
032: //}}}
033:
034: public class EnhancedMenu extends JMenu implements MenuListener {
035: //{{{ EnhancedMenu constructor
036: public EnhancedMenu(String name) {
037: this (name, jEdit.getProperty(name.concat(".label")), jEdit
038: .getActionContext());
039: } //}}}
040:
041: //{{{ EnhancedMenu constructor
042: public EnhancedMenu(String name, String label) {
043: this (name, label, jEdit.getActionContext());
044: } //}}}
045:
046: //{{{ EnhancedMenu constructor
047: public EnhancedMenu(String name, String label, ActionContext context) {
048: this .context = context;
049: if (label == null)
050: label = name;
051:
052: char mnemonic;
053: int index = label.indexOf('$');
054: if (index != -1 && label.length() - index > 1) {
055: mnemonic = Character.toLowerCase(label.charAt(index + 1));
056: label = label.substring(0, index).concat(
057: label.substring(++index));
058: } else
059: mnemonic = '\0';
060:
061: setText(label);
062: if (!OperatingSystem.isMacOS())
063: setMnemonic(mnemonic);
064:
065: String menuItems = jEdit.getProperty(name);
066: if (menuItems != null) {
067: StringTokenizer st = new StringTokenizer(menuItems);
068: while (st.hasMoreTokens()) {
069: String menuItemName = st.nextToken();
070: if (menuItemName.equals("-"))
071: addSeparator();
072: else
073: add(GUIUtilities.loadMenuItem(context,
074: menuItemName, true));
075: }
076: }
077:
078: initialComponentCount = getMenuComponentCount();
079:
080: providerCode = jEdit.getProperty(name + ".code");
081:
082: ebStub = new EditBusStub(name);
083: ebStub.menuOutOfDate = true;
084:
085: addMenuListener(this );
086:
087: if (providerCode != null)
088: EditBus.addToBus(ebStub);
089: } //}}}
090:
091: //{{{ menuSelected() method
092: public void menuSelected(MenuEvent evt) {
093: init();
094: } //}}}
095:
096: public void menuDeselected(MenuEvent e) {
097: }
098:
099: public void menuCanceled(MenuEvent e) {
100: }
101:
102: //{{{ init() method
103: public void init() {
104: if (providerCode == null)
105: return;
106:
107: if (provider == null) {
108: Object obj = BeanShell.eval(null, BeanShell.getNameSpace(),
109: providerCode);
110: provider = (DynamicMenuProvider) obj;
111: }
112:
113: if (provider == null) {
114: // error
115: providerCode = null;
116: return;
117: }
118:
119: if (ebStub.menuOutOfDate || provider.updateEveryTime()) {
120: ebStub.menuOutOfDate = false;
121:
122: while (getMenuComponentCount() != initialComponentCount)
123: remove(getMenuComponentCount() - 1);
124:
125: if (provider != null)
126: provider.update(this );
127: }
128: } //}}}
129:
130: //{{{ Protected members
131: protected int initialComponentCount;
132: protected ActionContext context;
133:
134: protected String providerCode;
135: protected DynamicMenuProvider provider;
136:
137: protected EditBusStub ebStub;
138:
139: //{{{ finalize() method
140: protected void finalize() throws Exception {
141: if (ebStub != null)
142: EditBus.removeFromBus(ebStub);
143: } //}}}
144:
145: //}}}
146:
147: //{{{ EditBusStub class
148: /* EnhancedMenu has a reference to EditBusStub, but not the other
149: * way around. So when the EnhancedMenu is being garbage collected
150: * its finalize() method removes the EditBusStub from the edit bus. */
151: static class EditBusStub implements EBComponent {
152: String name;
153: boolean menuOutOfDate;
154:
155: EditBusStub(String name) {
156: this .name = name;
157: menuOutOfDate = true;
158: }
159:
160: public void handleMessage(EBMessage msg) {
161: if (msg instanceof DynamicMenuChanged
162: && name.equals(((DynamicMenuChanged) msg)
163: .getMenuName())) {
164: menuOutOfDate = true;
165: } else if (msg instanceof PropertiesChanged) {
166: // while this might be questionable, some
167: // menus depend on properties
168: menuOutOfDate = true;
169: }
170: }
171: } //}}}
172: }
|