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:
042: package gui.windowsystem;
043:
044: import javax.swing.JMenuBar;
045: import javax.swing.JPopupMenu;
046: import javax.swing.JMenu;
047: import javax.swing.JMenuItem;
048: import javax.swing.MenuElement;
049:
050: import java.util.Collection;
051: import java.util.ArrayList;
052: import java.util.TreeSet;
053: import java.util.Iterator;
054: import java.util.HashMap;
055: import java.util.HashSet;
056: import java.util.StringTokenizer;
057:
058: import java.io.PrintStream;
059:
060: import org.netbeans.jemmy.operators.JMenuBarOperator;
061:
062: import org.netbeans.jellytools.MainWindowOperator;
063:
064: /**
065: * @author lhasik@netbeans.org, mmirilovic@netbeans.org
066: */
067: public class MenuChecker {
068:
069: /** Creates a new instance of MenuChecker */
070: public MenuChecker() {
071: }
072:
073: /** Check whether JPopupMenu <b>popup</b> contains <B>item</B> ?
074: * @param popup looking for menu item in this popup menu
075: * @param item looking for this item
076: * @return true-popup contains item, false-doesn't contain item */
077: public boolean containsMenuItem(javax.swing.JPopupMenu popup,
078: String item) {
079: MenuElement[] elements = popup.getSubElements();
080: for (int k = 0; k < elements.length; k++) {
081:
082: if (elements[k] instanceof JMenuItem) {
083: if (item.equals(((JMenuItem) elements[k]).getText()))
084: return true;
085: }
086: }
087: return false;
088: }
089:
090: /** Open all menus in menubar
091: * @param menu to be visited */
092: public static void visitMenuBar(JMenuBar menu) {
093: MenuElement[] elements = menu.getSubElements();
094:
095: JMenuBarOperator op = new JMenuBarOperator(menu);
096:
097: for (int k = 0; k < elements.length; k++) {
098: if (elements[k] instanceof JMenuItem) {
099: op.pushMenu(((JMenuItem) elements[k]).getText(), "/",
100: true, true);
101: try {
102: op.wait(200);
103: } catch (Exception e) {
104: }
105: }
106: }
107: }
108:
109: /** Get MenuBar and tranfer it to ArrayList.
110: * @param menu menu to be tranfered
111: * @return tranfered menubar */
112: public static ArrayList getMenuBarArrayList(JMenuBar menu) {
113: visitMenuBar(menu);
114:
115: MenuElement[] elements = menu.getSubElements();
116:
117: ArrayList list = new ArrayList();
118: for (int k = 0; k < elements.length; k++) {
119: if (elements[k] instanceof JMenuItem) {
120: list.add(NbMenu.getNbMenu((JMenuItem) elements[k]));
121: JMenuBarOperator menuOp = new JMenuBarOperator(menu);
122: list.add(getMenuArrayList(menuOp.getMenu(k)));
123: }
124: /*if(elements[k] instanceof JMenuBar) {
125: JMenuBarOperator menuOp = new JMenuBarOperator(menu);
126: list.add(getMenuArrayList(menuOp.getMenu(0)));
127: }
128: */
129: }
130: return list;
131: }
132:
133: /** Get Menu and tranfer it to ArrayList.
134: * @param menu menu to be tranfered
135: * @return tranfered menu */
136: public static ArrayList getMenuArrayList(JMenu menu) {
137: MenuElement[] elements = menu.getSubElements();
138: ArrayList list = new ArrayList();
139:
140: for (int k = 0; k < elements.length; k++) {
141:
142: if (elements[k] instanceof JPopupMenu)
143: list
144: .add(getPopupMenuArrayList((JPopupMenu) elements[k]));
145:
146: if (elements[k] instanceof JMenuItem)
147: list.add(NbMenu.getNbMenu((JMenuItem) elements[k]));
148:
149: }
150: return list;
151: }
152:
153: /** Get PopupMenu and transfer it to ArrayList.
154: * @param popup menu to be tranfered
155: * @return transfered menu */
156: public static ArrayList getPopupMenuArrayList(JPopupMenu popup) {
157: MenuElement[] elements = popup.getSubElements();
158: ArrayList list = new ArrayList();
159:
160: for (int k = 0; k < elements.length; k++) {
161: if (elements[k] instanceof JMenu)
162: list.add(getMenuArrayList((JMenu) elements[k]));
163:
164: if (elements[k] instanceof JMenuItem)
165: list.add(NbMenu.getNbMenu((JMenuItem) elements[k]));
166: }
167: return list;
168: }
169:
170: /**
171: * @param a aarray to be printed
172: * @param stream where
173: * @param x level of array */
174: public static void printArray(ArrayList a, PrintStream stream, int x) {
175: Iterator it = a.iterator();
176: while (it.hasNext()) {
177: Object o = it.next();
178:
179: if (o instanceof NbMenu) {
180:
181: for (int i = 0; i < x; i++)
182: stream.print("-");
183:
184: stream.println(((NbMenu) o).name);
185: }
186:
187: if (o instanceof ArrayList) {
188: printArray((ArrayList) o, stream, x + 1);
189: }
190: }
191: }
192:
193: /**
194: * @param menu
195: * @return */
196: public static TreeSet getSortedMenuBar(JMenuBar menu,
197: String menuToTest) {
198:
199: StringTokenizer menuT = new StringTokenizer(menuToTest, ", ");
200: HashSet menuTT = new HashSet();
201:
202: while (menuT.hasMoreTokens())
203: menuTT.add(menuT.nextToken());
204:
205: MenuElement[] elements = menu.getSubElements();
206: TreeSet list = new TreeSet();
207:
208: for (int k = 0; k < elements.length; k++) {
209: if (elements[k] instanceof JMenuItem) {
210: //NbMenu m = NbMenu.getNbMenu((JMenuItem)elements[k]);
211: JMenuBarOperator menuOp = new JMenuBarOperator(menu);
212: //m.addSubMenu(getMenuArrayList(menuOp.getMenu(k)));
213: JMenu m = menuOp.getMenu(k);
214: if (menuTT.contains(m.getLabel())) {
215: list.addAll((Collection) getSortedMenu(menuOp
216: .getMenu(k)));
217: }
218: }
219: /*if(elements[k] instanceof JMenuBar) {
220: JMenuBarOperator menuOp = new JMenuBarOperator(menu);
221: list.add(getMenuArrayList(menuOp.getMenu(0)));
222: }
223: */
224: }
225: return list;
226: }
227:
228: /**
229: * @param menu
230: * @return */
231: public static TreeSet getSortedMenu(JMenu menu) {
232: menu.list();
233: MenuElement[] elements = menu.getSubElements();
234: TreeSet list = new TreeSet();
235: NbMenu last = NbMenu.getNbMenu(menu);
236: list.add(last);
237:
238: for (int k = 0; k < elements.length; k++) {
239: if (elements[k] instanceof JPopupMenu) {
240: //NbMenu last = (NbMenu)list.get(list.size() - 1);
241: last.addSubMenu(getSortedPopupMenu(
242: (JPopupMenu) elements[k], ""));
243: }
244: if (elements[k] instanceof JMenuItem) {
245: last = NbMenu.getNbMenu((JMenuItem) elements[k]);
246: list.add(last);
247: }
248:
249: }
250: return list;
251: }
252:
253: /**
254: * @param popup
255: * @return */
256: public static TreeSet getSortedPopupMenu(JPopupMenu popup,
257: String menuNotTest) {
258: StringTokenizer menuT = new StringTokenizer(menuNotTest, ", ");
259: HashSet menuTT = new HashSet();
260:
261: while (menuT.hasMoreTokens())
262: menuTT.add(menuT.nextToken());
263:
264: MenuElement[] elements = popup.getSubElements();
265: TreeSet list = new TreeSet();
266:
267: for (int k = 0; k < elements.length; k++) {
268:
269: if (elements[k] instanceof JMenu) {
270: JMenu m = (JMenu) elements[k];
271: if (!menuTT.contains(m.getLabel()))
272: list.addAll(getSortedMenu(m));
273: }
274:
275: if (elements[k] instanceof JMenuItem) {
276: list.add(NbMenu.getNbMenu((JMenuItem) elements[k]));
277: }
278: }
279: return list;
280: }
281:
282: /** Print (unsorted) structure of menu - as it really looks
283: * @param menu
284: * @param stream */
285: public static void printMenuBarStructure(JMenuBar menu,
286: PrintStream stream, String menuToBeTested,
287: boolean printEnabledOnly, boolean sorted) {
288: if (sorted) {
289: printSorted(getSortedMenuBar(menu, menuToBeTested), stream,
290: 1, printEnabledOnly);
291: stream.close();
292: } else
293: printArray(getMenuBarArrayList(menu), stream, 1);
294: }
295:
296: /** Print (unsorted) structure of menu - as it really looks
297: * @param menu
298: * @param stream */
299: public static void printPopupMenuStructure(JPopupMenu menu,
300: PrintStream stream, String menuNotToBeTested,
301: boolean printEnabledOnly, boolean sorted) {
302: if (sorted) {
303: printSorted(getSortedPopupMenu(menu, menuNotToBeTested),
304: stream, 1, printEnabledOnly);
305: stream.close();
306: } else {
307: printArray(getPopupMenuArrayList(menu), stream, 1);
308: }
309: }
310:
311: /** Print Sorted collection.
312: * @param a Collection to be sorted.
313: * @param stream output stream
314: * @param x indentation */
315: public static void printSorted(Collection a, PrintStream stream,
316: int x, boolean printEnabledOnly) {
317: Iterator it = a.iterator();
318:
319: while (it.hasNext()) {
320: Object o = it.next();
321: if (o instanceof NbMenu) {
322: NbMenu item = (NbMenu) o;
323:
324: if (!(printEnabledOnly ^ item.enabled)) {
325: for (int i = 0; i < x; i++)
326: stream.print("-");
327: stream.println(item.name);
328: }
329:
330: if (item.submenu != null) {
331: printSorted(item.getSubMenu(), stream, x + 1,
332: printEnabledOnly);
333: }
334:
335: }
336: }
337: }
338:
339: public static String checkMnemonicCollision() {
340: return checkMnemonicCollision(
341: getMenuBarArrayList(MainWindowOperator.getDefault()
342: .getJMenuBar())).toString();
343: }
344:
345: /** Check mnemonics in menu structure.
346: * @param list
347: * @return */
348: private static StringBuffer checkCollision(ArrayList list,
349: boolean checkShortCuts) {
350: StringBuffer collisions = new StringBuffer("");
351: Iterator it = list.iterator();
352:
353: HashMap check = new HashMap();
354:
355: while (it.hasNext()) {
356: Object o = it.next();
357:
358: if (o instanceof NbMenu) {
359: NbMenu item = (NbMenu) o;
360:
361: if (checkShortCuts) {
362: if (item.mnemo != 0) {
363: Integer mnemonic = new Integer(item.mnemo);
364: //stream.println("checking : " + item.name + " - " + item.mnemo);
365: if (check.containsKey(mnemonic)) {
366: char k = (char) item.mnemo;
367: collisions
368: .append("\n !!!!!! Collision! mnemonic='"
369: + k
370: + "' : "
371: + item.name
372: + " is in collision with "
373: + check.get(mnemonic));
374: } else {
375: check.put(mnemonic, item.name);
376: }
377: }
378: } else {
379: if (item.mnemo != 0) {
380: Integer mnemonic = new Integer(item.mnemo);
381: //stream.println("checking : " + item.name + " - " + item.mnemo);
382: if (check.containsKey(mnemonic)) {
383: char k = (char) item.mnemo;
384: collisions
385: .append("\n !!!!!! Collision! mnemonic='"
386: + k
387: + "' : "
388: + item.name
389: + " is in collision with "
390: + check.get(mnemonic));
391: } else {
392: check.put(mnemonic, item.name);
393: }
394: }
395: }
396: }
397:
398: if (o instanceof ArrayList) {
399: collisions
400: .append(checkMnemonicCollision((ArrayList) o));
401: }
402: }
403:
404: return collisions;
405: }
406:
407: /** Check mnemonics in menu structure.
408: * @param list
409: * @return */
410: private static StringBuffer checkMnemonicCollision(ArrayList list) {
411: StringBuffer collisions = new StringBuffer("");
412: Iterator it = list.iterator();
413:
414: HashMap check = new HashMap();
415:
416: while (it.hasNext()) {
417: Object o = it.next();
418:
419: if (o instanceof NbMenu) {
420: NbMenu item = (NbMenu) o;
421: if (item.mnemo != 0) {
422: Integer mnemonic = new Integer(item.mnemo);
423: //stream.println("checking : " + item.name + " - " + item.mnemo);
424: if (check.containsKey(mnemonic)) {
425: char k = (char) item.mnemo;
426: collisions
427: .append("\n !!!!!! Collision! mnemonic='"
428: + k
429: + "' : "
430: + item.name
431: + " is in collision with "
432: + check.get(mnemonic));
433: } else {
434: check.put(mnemonic, item.name);
435: }
436: }
437: }
438:
439: if (o instanceof ArrayList) {
440: collisions
441: .append(checkMnemonicCollision((ArrayList) o));
442: }
443: }
444:
445: return collisions;
446: }
447:
448: public static String checkShortCutCollision() {
449: return checkShortCutCollision(
450: getMenuBarArrayList(MainWindowOperator.getDefault()
451: .getJMenuBar())).toString();
452: }
453:
454: /** check shortcuts in menu structure
455: * @param a
456: * @return */
457: private static StringBuffer checkShortCutCollision(ArrayList a) {
458: StringBuffer collisions = new StringBuffer("");
459: Iterator it = a.iterator();
460: HashMap check = new HashMap();
461:
462: while (it.hasNext()) {
463: Object o = it.next();
464:
465: if (o instanceof NbMenu) {
466: NbMenu item = (NbMenu) o;
467:
468: if (item.accelerator != null) {
469: //stream.println("checking : " + item.name + " - " + item.accelerator);
470: if (check.containsKey(item.accelerator)) {
471: collisions
472: .append("\n !!!!!! Collision! accelerator ='"
473: + item.accelerator
474: + "' : "
475: + item.name
476: + " is in collision with "
477: + check.get(item.accelerator));
478: } else {
479: check.put(item.accelerator, item.name);
480: }
481: }
482: }
483:
484: if (o instanceof ArrayList) {
485: collisions
486: .append(checkShortCutCollision((ArrayList) o));
487: }
488: }
489:
490: return collisions;
491: }
492:
493: }
494:
495: class NbMenu implements Comparable {
496: /** label of menuitem */
497: public String name;
498: /** mnemonic in int */
499: public int mnemo;
500: /** jasne ? */
501: public String accelerator;
502: public boolean enabled;
503: TreeSet submenu = null;
504:
505: /**
506: * @param it
507: * @return instance of NbMenu constructed from parameter it */
508: public static NbMenu getNbMenu(JMenuItem it) {
509: NbMenu item = new NbMenu();
510: item.name = it.getText();//getLabel();
511: item.accelerator = (it.getAccelerator() == null) ? null : it
512: .getAccelerator().toString();
513: item.mnemo = it.getMnemonic();
514: item.enabled = it.isEnabled();
515: return item;
516: }
517:
518: /**
519: * @param m */
520: public void addSubMenu(TreeSet m) {
521: submenu = m;
522: }
523:
524: /**
525: * @return */
526: public TreeSet getSubMenu() {
527: return submenu;
528: }
529:
530: /** needed for comparing in TreeSet
531: * @param obj
532: * @return */
533: public int compareTo(Object obj) {
534: NbMenu n = (NbMenu) obj;
535: return (name != null) ? name.compareTo(n.name) : n.name
536: .compareTo(name);
537: }
538: }
|