KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > awt > DynaMenuModel


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 Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.openide.awt;
21
22 import java.awt.Component JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.Arrays JavaDoc;
25 import java.util.Collections JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.Map JavaDoc;
30 import javax.swing.Action JavaDoc;
31 import javax.swing.Icon JavaDoc;
32 import javax.swing.ImageIcon JavaDoc;
33 import javax.swing.JComponent JavaDoc;
34 import javax.swing.JMenu JavaDoc;
35 import javax.swing.JMenuItem JavaDoc;
36 import javax.swing.JPopupMenu JavaDoc;
37 import javax.swing.JSeparator JavaDoc;
38 import org.openide.util.Utilities;
39 import org.openide.awt.DynamicMenuContent;
40 import org.openide.util.actions.Presenter;
41
42 /**
43  *
44  * @author mkleint
45  */

46 class DynaMenuModel {
47     private static final Icon JavaDoc BLANK_ICON = new ImageIcon JavaDoc(
48         Utilities.loadImage("org/openide/loaders/empty.gif")); // NOI18N
49

50     private List JavaDoc<JComponent JavaDoc> menuItems;
51     private HashMap JavaDoc<DynamicMenuContent, JComponent JavaDoc[]> actionToMenuMap;
52     private boolean isWithIcons = false;
53     /** Creates a new instance of DynaMenuModel */
54     public DynaMenuModel() {
55         actionToMenuMap = new HashMap JavaDoc<DynamicMenuContent, JComponent JavaDoc[]>();
56     }
57     
58     public void loadSubmenu(List JavaDoc cInstances, JMenu JavaDoc m) {
59         // clear first - refresh the menu's content
60
boolean addSeparator = false;
61         Icon JavaDoc curIcon = null;
62         Iterator JavaDoc it = cInstances.iterator();
63         menuItems = new ArrayList JavaDoc<JComponent JavaDoc>(cInstances.size());
64         actionToMenuMap.clear();
65         while (it.hasNext()) {
66             Object JavaDoc obj = it.next();
67             if (obj instanceof Presenter.Menu) {
68                 // does this still apply??
69
obj = ((Presenter.Menu)obj).getMenuPresenter();
70             }
71             if (obj instanceof DynamicMenuContent) {
72                 if(addSeparator) {
73                     menuItems.add(null);
74                     addSeparator = false;
75                 }
76                 DynamicMenuContent mn = (DynamicMenuContent)obj;
77                 JComponent JavaDoc[] itms = convertArray(mn.getMenuPresenters());
78                 actionToMenuMap.put(mn, itms);
79                 Iterator JavaDoc itx = Arrays.asList(itms).iterator();
80                 while (itx.hasNext()) {
81                     JComponent JavaDoc comp = (JComponent JavaDoc)itx.next();
82                     menuItems.add(comp);
83                     // check icon
84
isWithIcons = checkIcon(comp, isWithIcons);
85                 }
86                 continue;
87             }
88             
89             
90             if (obj instanceof JMenuItem JavaDoc) {
91                 if(addSeparator) {
92                     menuItems.add(null);
93                     addSeparator = false;
94                 }
95                 // check icon
96
isWithIcons = checkIcon(obj, isWithIcons);
97                 menuItems.add((JMenuItem JavaDoc)obj);
98             } else if (obj instanceof JSeparator JavaDoc) {
99                 addSeparator = menuItems.size() > 0;
100             } else if (obj instanceof Action JavaDoc) {
101                 if(addSeparator) {
102                     menuItems.add(null);
103                     addSeparator = false;
104                 }
105                 Action JavaDoc a = (Action JavaDoc)obj;
106                 Actions.MenuItem item = new Actions.MenuItem(a, true);
107                 // check icon
108
isWithIcons = checkIcon(item, isWithIcons);
109                 actionToMenuMap.put(item, new JComponent JavaDoc[] {item});
110                 menuItems.add(item);
111             }
112         }
113         
114         if (isWithIcons) {
115             menuItems = alignVertically(menuItems);
116         }
117         
118         // fill menu with built items
119
JComponent JavaDoc curItem = null;
120         boolean wasSeparator = false;
121         for (Iterator JavaDoc<JComponent JavaDoc> iter = menuItems.iterator(); iter.hasNext(); ) {
122             curItem = iter.next();
123             if (curItem == null) {
124                 // null means separator
125
curItem = new JSeparator JavaDoc();
126             }
127             m.add(curItem);
128             boolean isSeparator = curItem instanceof JSeparator JavaDoc;
129             if (isSeparator && wasSeparator) {
130                 curItem.setVisible(false);
131             }
132             if (!(curItem instanceof InvisibleMenuItem)) {
133                 wasSeparator = isSeparator;
134             }
135         }
136     }
137     
138     
139     private boolean checkIcon(Object JavaDoc obj, boolean isWithIconsAlready) {
140         if (isWithIconsAlready) {
141             return isWithIconsAlready;
142         }
143         if (obj instanceof JMenuItem JavaDoc) {
144             if (((JMenuItem JavaDoc)obj).getIcon() != null && !BLANK_ICON.equals(((JMenuItem JavaDoc)obj).getIcon())) {
145                 return true;
146             }
147         }
148         return false;
149     }
150     
151     public void checkSubmenu(JMenu JavaDoc menu) {
152         boolean oldisWithIcons = isWithIcons;
153         boolean changed = false;
154         for (Map.Entry JavaDoc<DynamicMenuContent, JComponent JavaDoc[]> entry: actionToMenuMap.entrySet()) {
155             DynamicMenuContent pres = entry.getKey();
156             JComponent JavaDoc[] old = entry.getValue();
157             int oldIndex = 0;
158             Component JavaDoc[] menuones = menu.getPopupMenu().getComponents();
159             int menuIndex = old.length > 0 ? findFirstItemIndex(old[0], menuones) : -1;
160             JComponent JavaDoc[] newones = convertArray(pres.synchMenuPresenters(unconvertArray(old)));
161             if (!compareEqualArrays(old, newones)) {
162                 if (menuIndex < 0) {
163                     menuIndex = 0;
164                 } else {
165                     for (int i = 0; i < old.length; i++) {
166                         if (old[i] != null) {
167                             menu.getPopupMenu().remove(old[i]);
168                             menuItems.remove(old[i]);
169                         }
170                     }
171                 }
172                 for (int i = 0; i < newones.length; i++) {
173                     ///TODO now what to do with icon alignments..
174
JComponent JavaDoc one = newones[i];
175                     menu.getPopupMenu().add(one, i + menuIndex);
176                     changed = true;
177                     menuItems.add(one);
178                     boolean thisOneHasIcon = checkIcon(one, false);
179                     if (!thisOneHasIcon && isWithIcons) {
180                         alignVertically(Collections.singletonList(one));
181                     }
182                     if (thisOneHasIcon && !isWithIcons) {
183                         isWithIcons = true;
184                     }
185                 }
186                 entry.setValue(newones);
187             }
188             
189         }
190         boolean hasAnyIcons = false;
191         Component JavaDoc[] menuones = menu.getPopupMenu().getComponents();
192         for (int i = 0; i < menuones.length; i++) {
193             if (menuones[i] != null) {
194                 hasAnyIcons = checkIcon(menuones[i], hasAnyIcons);
195                 if (hasAnyIcons) {
196                     break;
197                 }
198             }
199         }
200         checkSeparators(menuones, menu.getPopupMenu());
201         if (!hasAnyIcons && isWithIcons) {
202             isWithIcons = false;
203         }
204         if (oldisWithIcons != isWithIcons) {
205             menuItems = alignVertically(menuItems);
206         }
207         if (changed && Utilities.isWindows()) {
208             //#67847 on windows, we need revalidation otherwise strange effects kick in..
209
menu.getPopupMenu().revalidate();
210         }
211     }
212     
213     static void checkSeparators(Component JavaDoc[] menuones, JPopupMenu JavaDoc parent) {
214         boolean wasSeparator = false;
215         for (int i = 0; i < menuones.length; i++) {
216             Component JavaDoc curItem = menuones[i];
217             if (curItem != null) {
218                 boolean isSeparator = curItem instanceof JSeparator JavaDoc;
219                 if (isSeparator) {
220                     boolean isVisible = curItem.isVisible();
221                     if (isVisible != !wasSeparator) {
222                         //MACOSX whenever a property like enablement or visible is changed, need to remove and add.
223
// could be possibly split to work differetly on other platform..
224
parent.remove(i);
225                         JSeparator JavaDoc newOne = new JSeparator JavaDoc();
226                         newOne.setVisible(!wasSeparator);
227                         parent.add(newOne, i);
228                     }
229                 }
230                 if (!(curItem instanceof InvisibleMenuItem)) {
231                     wasSeparator = isSeparator;
232                 }
233             }
234         }
235     }
236     
237     private JComponent JavaDoc[] convertArray(JComponent JavaDoc[] arr) {
238         if (arr == null || arr.length == 0) {
239             return new JComponent JavaDoc[] { new InvisibleMenuItem() };
240         }
241         JComponent JavaDoc[] toRet = new JComponent JavaDoc[arr.length];
242         for (int i = 0; i < arr.length; i++) {
243             if (arr[i] == null) {
244                 toRet[i] = new JSeparator JavaDoc();
245             } else {
246                 toRet[i] = arr[i];
247             }
248         }
249         return toRet;
250     }
251     
252     private JComponent JavaDoc[] unconvertArray(JComponent JavaDoc[] arr) {
253         if (arr.length == 1 && arr[0] instanceof InvisibleMenuItem) {
254             return new JComponent JavaDoc[0];
255         } else {
256             return arr;
257         }
258     }
259         
260     private int findFirstItemIndex(JComponent JavaDoc first, Component JavaDoc[] menuItems) {
261         for (int i = 0; i < menuItems.length; i++) {
262             if (first == menuItems[i]) {
263                 return i;
264             }
265         }
266         return -1;
267     }
268     
269     private boolean compareEqualArrays(JComponent JavaDoc[] one, JComponent JavaDoc[] two) {
270         if (one.length != two.length) {
271             return false;
272         }
273         for (int i = 0; i < one.length; i++) {
274             if (one[i] != two[i]) {
275                 return false;
276             }
277         }
278         return true;
279     }
280     
281     /** Removes icons from all direct menu items of this menu.
282      * Not recursive, */

283     private List JavaDoc<JComponent JavaDoc> alignVertically(List JavaDoc<JComponent JavaDoc> menuItems) {
284         List JavaDoc<JComponent JavaDoc> result = new ArrayList JavaDoc<JComponent JavaDoc>(menuItems.size());
285         JMenuItem JavaDoc curItem = null;
286         for (JComponent JavaDoc obj: menuItems) {
287             if (obj instanceof JMenuItem JavaDoc) {
288                 curItem = (JMenuItem JavaDoc)obj;
289                 if (isWithIcons && curItem != null && curItem.getIcon() == null) {
290                     curItem.setIcon(BLANK_ICON);
291                 } else if (!isWithIcons && curItem != null) {
292                     curItem.setIcon(null);
293                 }
294             }
295             result.add(obj);
296         }
297         return result;
298     }
299     
300     static final class InvisibleMenuItem extends JMenuItem JavaDoc {
301         
302         public boolean isVisible() {
303             return false;
304         }
305         
306     }
307 }
308
Popular Tags