KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > enode > SubMenuAction


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Nokia. Portions Copyright 2003-2004 Nokia.
17  * All Rights Reserved.
18  */

19
20 package org.netbeans.modules.enode;
21
22 import java.awt.Component JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.Collection JavaDoc;
25 import java.util.Collections JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.LinkedList JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.ListIterator JavaDoc;
30 import javax.swing.*;
31 import javax.swing.JComponent JavaDoc;
32 import javax.swing.JSeparator JavaDoc;
33
34 import org.openide.ErrorManager;
35 import org.openide.awt.Actions;
36 import org.openide.util.Lookup;
37
38 import org.netbeans.modules.enode.*;
39 import org.openide.util.ContextAwareAction;
40
41 /**
42  * Special action serving as a wrapper for submenus added to the popup
43  * menu.
44  * @author David Strupl
45  */

46 public class SubMenuAction extends AbstractAction implements
47     org.openide.util.actions.Presenter.Popup,
48     org.openide.util.actions.Presenter.Menu, ContextAwareAction {
49
50     private static ErrorManager log = ErrorManager.getDefault().getInstance(SubMenuAction.class.getName());
51     private static boolean LOGGABLE = log.isLoggable(ErrorManager.INFORMATIONAL);
52     
53     /** Name used for the display of this context */
54     private String JavaDoc name;
55     /** Lookup */
56     private Lookup ctx;
57     /** */
58     private List JavaDoc/*<SubMenuCache.CacheEntry>*/ entries = new ArrayList JavaDoc();
59     
60     /** This is the entry representing this menu*/
61     private SubMenuCache.MenuEntry currentEntry;
62     
63     /** Constructor used for testing */
64     public SubMenuAction() {
65         this("Test"); // NOI18N
66
}
67     
68     /** Creates a new instance of SubMenuAction.
69      */

70     public SubMenuAction(String JavaDoc name) {
71         this(name, null, null, null);
72     }
73     
74     /** Creates a new instance of SubMenuAction.
75      */

76     public SubMenuAction(SubMenuCache.MenuEntry current) {
77         this(current.getDisplayName(), null, current, null);
78     }
79     
80     /** Creates a new instance of SubMenuAction and remembers
81      * the parameters in private variables.
82      */

83     private SubMenuAction(String JavaDoc name, Lookup ctx, SubMenuCache.MenuEntry currentEntry, List JavaDoc/*<SubMenuCache.CacheEntry>*/ entries) {
84         this.name = name;
85         this.ctx = ctx;
86         this.currentEntry = currentEntry;
87         if (entries != null) {
88             this.entries = entries;
89         }
90     }
91     
92     /**
93      * This action creates a submenu. So invoking directly this
94      * action does not make any sense. This method throws
95      * an IllegalStateException.
96      */

97     public void actionPerformed(java.awt.event.ActionEvent JavaDoc e) {
98         throw new IllegalStateException JavaDoc("SubMenuAction should not be performed as action."); // NOI18N
99
}
100
101     /**
102      * Implementing the only method from ContextAwareAction.
103      */

104     public Action createContextAwareInstance(Lookup actionContext) {
105         return new SubMenuAction(name, actionContext, currentEntry, entries);
106     }
107     
108     /**
109      * Method implementing interface Presenter.Menu.
110      */

111     public JMenuItem getMenuPresenter() {
112         return getPopupPresenter();
113     }
114     
115     /**
116      * Method implementing interface Presenter.Popup.
117      */

118     public JMenuItem getPopupPresenter() {
119         return createMenu(name);
120     }
121
122     /**
123      *
124      */

125     private JMenuItem createMenu(String JavaDoc name) {
126         ENodePopupSubMenu menu = new ENodePopupSubMenu(name, currentEntry);
127         menu.addAllCacheItems(entries);
128         menu.buildMenu();
129         return menu;
130     }
131     
132     /**
133      * Overriden from Object. Uses only the name field for the comparison.
134      */

135     public boolean equals(Object JavaDoc another) {
136         if ((another == null) || (! (another instanceof SubMenuAction) ) ){
137             return false;
138         }
139         SubMenuAction other = (SubMenuAction)another;
140         if (name == null) {
141             return other.name == null;
142         }
143         return name.equals(other.name);
144     }
145     
146     /**
147      * Overriden to be in sync with equals.
148      */

149     public int hashCode() {
150         if (name == null) {
151             return 0;
152         }
153         return name.hashCode();
154     }
155
156     /**
157      * True if this submenu has zero elements.
158      */

159     public boolean isEmpty() {
160         return entries.isEmpty();
161     }
162     
163     /**
164      * Registers new item to this menu.
165      */

166     public void addItemFromCache(SubMenuCache.CacheEntry entry) {
167         entries.add(entry);
168     }
169     
170     public void addAllCacheItems(Collection JavaDoc/*<SubMenuCache.CacheEntry>*/ newEntries) {
171         entries.addAll(newEntries);
172     }
173     
174     /**
175      *
176      */

177     public Collection JavaDoc getCacheItries() {
178         return Collections.unmodifiableList(entries);
179     }
180     
181     /**
182      *
183      */

184     private static CacheEntryWithSubmenuPointer insertEntry(
185             List JavaDoc/*<CacheEntryWithSubmenuPointer>*/ list,
186             SubMenuCache.CacheEntry entry,
187             SubMenuCache.MenuEntry myMenu) {
188         SubMenuCache.CacheEntry e = entry;
189         while ((e.getParent() != null) && (!e.getParent().equals(myMenu))) {
190             e = e.getParent();
191         }
192         if (e.getParent() == null) {
193             log.log(entry + " is not under " + myMenu);
194             return null;
195         }
196         
197         CacheEntryWithSubmenuPointer fresh = new CacheEntryWithSubmenuPointer();
198         fresh.topLevel = e;
199         fresh.leaf = entry;
200         CacheEntryWithSubmenuPointer existing = null;
201         ListIterator JavaDoc it = list.listIterator();
202         while (it.hasNext()) {
203             existing = (CacheEntryWithSubmenuPointer)it.next();
204             if (! e.getParent().equals(existing.topLevel.getParent())) {
205                 throw new IllegalStateException JavaDoc(existing.topLevel + " doesn't have same parent as " + e);
206             }
207             int entryIndex = e.getIndex();
208             int existingIndex = existing.topLevel.getIndex();
209             if (entryIndex < existingIndex) {
210                 if (it.hasPrevious()) {
211                     it.previous();
212                 }
213                 it.add(fresh);
214                 return fresh;
215             }
216         }
217         // if this will be the last element in the list:
218
it.add(fresh);
219         return fresh;
220     }
221     
222     private class ENodePopupSubMenu extends JMenu {
223         private List JavaDoc/*<CacheEntryWithSubmenuPointer>*/ elements = new LinkedList JavaDoc();
224         private SubMenuCache.MenuEntry menuEntry;
225         public ENodePopupSubMenu(String JavaDoc name, SubMenuCache.MenuEntry menuEntry) {
226             super(name);
227             this.menuEntry = menuEntry;
228         }
229         /**
230          * Registers new item to this menu.
231          */

232         public void addItemFromCache(SubMenuCache.CacheEntry entry) {
233             CacheEntryWithSubmenuPointer e = insertEntry(elements, entry, menuEntry);
234         }
235
236         public void addAllCacheItems(Collection JavaDoc/*<SubMenuCache.CacheEntry>*/ newEntries) {
237             if (LOGGABLE) log.log("addAllCacheItems on menu" + getText());
238             for (Iterator JavaDoc it = newEntries.iterator(); it.hasNext();) {
239                 SubMenuCache.CacheEntry e = (SubMenuCache.CacheEntry)it.next();
240                 if (LOGGABLE) log.log("addAllCacheItems adding " + e);
241                 addItemFromCache(e);
242             }
243         }
244         /** Converts the items to real elements */
245         public void buildMenu() {
246             if (LOGGABLE) log.log("buildMenu() " + getText());
247             for (Iterator JavaDoc it = elements.iterator(); it.hasNext();) {
248                 CacheEntryWithSubmenuPointer cewsp = (CacheEntryWithSubmenuPointer)it.next();
249                 if (LOGGABLE) log.log("buildMenu() trying to add: " + cewsp.leaf + " cewsp.topLevel: " + cewsp.topLevel);
250                 if (cewsp.leaf.equals(cewsp.topLevel)) {
251                     if (cewsp.leaf instanceof SubMenuCache.ActionEntry) {
252                         SubMenuCache.ActionEntry actionEntry = (SubMenuCache.ActionEntry)cewsp.leaf;
253                         Object JavaDoc obj = actionEntry.getActionObject();
254                         if (obj instanceof Action) {
255                             Action a = (Action)obj;
256                             if ((ctx != null) && a instanceof ContextAwareAction) {
257                                 a = ((ContextAwareAction)a).createContextAwareInstance(ctx);
258                             }
259                             JMenuItem menuItem = new JMenuItem();
260                             Actions.connect(menuItem, a, true);
261                             add(menuItem);
262                         }
263                         if (obj instanceof JSeparator JavaDoc) {
264                             // create a "clone" of the separator
265
add(new JSeparator JavaDoc());
266                         } else {
267                             if (obj instanceof JComponent JavaDoc) {
268                                 add((JComponent JavaDoc)obj);
269                             }
270                         }
271                     }
272                 } else {
273                     log.log("Adding submenu for " + cewsp.leaf);
274                     if (cewsp.topLevel instanceof SubMenuCache.MenuEntry) {
275                         SubMenuCache.MenuEntry subMenu = (SubMenuCache.MenuEntry)cewsp.topLevel;
276                         String JavaDoc subMenuDisplayName = subMenu.getDisplayName();
277                         ENodePopupSubMenu sub = findSubMenu(subMenuDisplayName);
278                         if (sub != null) {
279                             sub.addItemFromCache(cewsp.leaf);
280                         } else {
281                             // create new one
282
ENodePopupSubMenu newSub = new ENodePopupSubMenu(subMenu.getDisplayName(), subMenu);
283                             newSub.addItemFromCache(cewsp.leaf);
284                             add(newSub);
285                         }
286                     } else {
287                         log.log("cewsp.topLevel " + cewsp.topLevel + " is not MenuEntry.");
288                     }
289                 }
290             }
291             Component JavaDoc[] subMenus = getMenuComponents();
292             for (int i = 0; i < subMenus.length; i++) {
293                 if (subMenus[i] instanceof ENodePopupSubMenu) {
294                     ENodePopupSubMenu sub = (ENodePopupSubMenu)subMenus[i];
295                     sub.buildMenu();
296                 }
297             }
298
299         }
300         
301         public ENodePopupSubMenu findSubMenu(String JavaDoc displayName) {
302             Component JavaDoc[] subMenus = getMenuComponents();
303             for (int i = 0; i < subMenus.length; i++) {
304                 if (subMenus[i] instanceof ENodePopupSubMenu) {
305                     ENodePopupSubMenu sub = (ENodePopupSubMenu)subMenus[i];
306                     if (displayName.equals(sub.getText())) {
307                         return sub;
308                     }
309                 }
310             }
311             return null;
312         }
313     }
314     
315     /**
316      * Invariant:
317      * leaf == topLevel or
318      * leaf.getParent() == topLevel or
319      * leaf.getParent().getParent() == topLevel or
320      * ...
321      */

322     private static class CacheEntryWithSubmenuPointer {
323         /** This is the sub menu pointer pointing
324          * to the submenu in current menu that
325          * is being built for leaf
326          */

327         public SubMenuCache.CacheEntry topLevel;
328         public SubMenuCache.CacheEntry leaf;
329     }
330 }
331
Popular Tags