001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.xml.actions;
042:
043: import java.beans.PropertyChangeListener;
044: import java.beans.PropertyChangeEvent;
045: import java.util.*;
046:
047: import javax.swing.JMenuItem;
048:
049: import org.openide.awt.JInlineMenu;
050: import org.openide.windows.TopComponent.Registry;
051: import org.openide.windows.WindowManager;
052: import org.openide.util.actions.SystemAction;
053: import org.openide.util.actions.Presenter;
054: import org.openide.util.Lookup;
055:
056: public abstract class CollectSystemAction extends SystemAction
057: implements Presenter.Popup {
058: /** Serial Version UID */
059: private static final long serialVersionUID = 6517322512481423122L;
060:
061: /** All Actions Lookup Result. */
062: private Lookup.Result allActionsResult;
063:
064: /** empty array of menu items */
065: static JMenuItem[] NONE = new JMenuItem[] {};
066:
067: /** Which Class should be used for Lookup? */
068: protected abstract Class getActionLookClass();
069:
070: /** @return all instances of <code>getActionLookClass</code>.
071: */
072: protected synchronized Collection getPossibleActions() {
073: if (allActionsResult == null) {
074: allActionsResult = Lookup.getDefault().lookup(
075: new Lookup.Template(getActionLookClass()));
076: }
077: return allActionsResult.allInstances();
078: }
079:
080: private JMenuItem[] createMenu() {
081: JMenuItem[] menu;
082:
083: menu = createMenu(getPossibleActions());
084:
085: if (Util.THIS.isLoggable()) /* then */
086: Util.THIS
087: .debug("--- CollectSystemAction.createMenu: menu = "
088: + menu);//, new RuntimeException());
089:
090: return menu;
091: }
092:
093: private JMenuItem[] createMenu(Collection coll) {
094: if (Util.THIS.isLoggable()) /* then */
095: Util.THIS.debug("\n--> CollectSystemAction.createMenu: ( "
096: + coll + " )");
097:
098: ArrayList items = new ArrayList();
099:
100: Iterator it = coll.iterator();
101: while (it.hasNext()) {
102: SystemAction a = (SystemAction) it.next();
103:
104: if (Util.THIS.isLoggable()) /* then */
105: Util.THIS
106: .debug("-*- CollectSystemAction.createMenu: next action "
107: + a
108: + " -- "
109: + (a.isEnabled() ? "<enabled>"
110: : "[disabled]"));
111:
112: if (a.isEnabled()) {
113: JMenuItem item = null;
114: if (a instanceof Presenter.Popup) {
115: item = ((Presenter.Popup) a).getPopupPresenter();
116: }
117:
118: if (Util.THIS.isLoggable()) /* then */
119: Util.THIS
120: .debug("-*- CollectSystemAction.createMenu: menu item = "
121: + item);
122:
123: // test if we obtained the item
124: if (item != null) {
125: items.add(item);
126: }
127: }
128: }
129:
130: if (Util.THIS.isLoggable()) /* then */
131: Util.THIS
132: .debug("<-- CollectSystemAction.createMenu: all items = "
133: + items + "\n");
134:
135: JMenuItem[] array = new JMenuItem[items.size()];
136: items.toArray(array);
137: return array;
138: }
139:
140: /* @return popup presenter.
141: */
142: public JMenuItem getPopupPresenter() {
143: return new Menu();
144: }
145:
146: /* Do nothing.
147: * This action itself does nothing, it only presents other actions.
148: * @param ev ignored
149: */
150: public void actionPerformed(java.awt.event.ActionEvent e) {
151: }
152:
153: /** Presenter for this action.
154: */
155: private class Menu extends JInlineMenu {
156: private static final long serialVersionUID = -4962039848190160129L;
157:
158: /** last registered items */
159: private JMenuItem[] last = NONE;
160: /** own property change listner */
161: private PropL propL = new PropL();
162:
163: /**
164: */
165: Menu() {
166: changeMenuItems(createMenu());
167:
168: Registry r = WindowManager.getDefault().getRegistry();
169:
170: r.addPropertyChangeListener(org.openide.util.WeakListeners
171: .propertyChange(propL, r));
172: }
173:
174: /** Changes the selection to new items.
175: * @param items the new items
176: */
177: synchronized void changeMenuItems(JMenuItem[] items) {
178: removeListeners(last);
179: addListeners(items);
180: last = items;
181: setMenuItems(items);
182: }
183:
184: /** Add listeners to menu items.
185: * @param items the items
186: */
187: private void addListeners(JMenuItem[] items) {
188: int len = items.length;
189: for (int i = 0; i < len; i++) {
190: items[i].addPropertyChangeListener(propL);
191: }
192: }
193:
194: /** Remove all listeners from menu items.
195: * @param items the items
196: */
197: private void removeListeners(JMenuItem[] items) {
198: int len = items.length;
199: for (int i = 0; i < len; i++) {
200: items[i].removePropertyChangeListener(propL);
201: }
202: }
203:
204: boolean needsChange = false;
205:
206: public void addNotify() {
207: if (needsChange) {
208: changeMenuItems(createMenu());
209: needsChange = false;
210: }
211: super .addNotify();
212: }
213:
214: public void removeNotify() {
215: removeListeners(last);
216: last = NONE;
217: }
218:
219: /** Property listnener to watch changes of enable state.
220: */
221: private class PropL implements PropertyChangeListener {
222: public void propertyChange(PropertyChangeEvent ev) {
223: String name = ev.getPropertyName();
224: if (name == null
225: || name.equals(SystemAction.PROP_ENABLED)
226: || name.equals(Registry.PROP_ACTIVATED_NODES)) {
227: // change items later
228: needsChange = true;
229: }
230: }
231: }
232:
233: } // end: class Menu
234:
235: }
|