001: /*
002: * Copyright 2001-2006 C:1 Financial Services GmbH
003: *
004: * This software is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License Version 2.1, as published by the Free Software Foundation.
007: *
008: * This software is distributed in the hope that it will be useful,
009: * but WITHOUT ANY WARRANTY; without even the implied warranty of
010: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
011: * Lesser General Public License for more details.
012: *
013: * You should have received a copy of the GNU Lesser General Public
014: * License along with this library; if not, write to the Free Software
015: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
016: */
017:
018: package de.finix.contelligent.client.util;
019:
020: import java.awt.Font;
021: import java.awt.event.ActionEvent;
022: import java.beans.PropertyChangeListener;
023: import java.util.Collections;
024: import java.util.Comparator;
025: import java.util.Iterator;
026: import java.util.List;
027: import java.util.Set;
028: import java.util.TreeSet;
029: import java.util.Vector;
030: import java.util.logging.Level;
031: import java.util.logging.Logger;
032:
033: import javax.swing.AbstractAction;
034: import javax.swing.AbstractButton;
035: import javax.swing.Action;
036: import javax.swing.Box;
037: import javax.swing.JLabel;
038: import javax.swing.JMenu;
039: import javax.swing.JMenuBar;
040: import javax.swing.JMenuItem;
041: import javax.swing.JPopupMenu;
042: import javax.swing.JToolBar;
043:
044: import de.finix.contelligent.client.ContelligentClient;
045: import de.finix.contelligent.client.base.Session;
046: import de.finix.contelligent.client.event.ContelligentEventDispatcher;
047: import de.finix.contelligent.client.event.TaskEventListener;
048: import de.finix.contelligent.client.event.TaskFinishedEvent;
049: import de.finix.contelligent.client.event.TaskStartedEvent;
050: import de.finix.contelligent.client.gui.ContelligentAction;
051: import de.finix.contelligent.client.gui.SeparatorAction;
052: import de.finix.contelligent.client.i18n.Resources;
053: import de.finix.contelligent.client.modules.preferences.PreferencesModule;
054:
055: /**
056: *
057: * Build up all menus and toolbars associated to given action bundles.
058: */
059: public class MenuAndToolbarComposer implements TaskEventListener {
060:
061: private static Logger logger = Logger
062: .getLogger(MenuAndToolbarComposer.class.getName());
063:
064: public static void resetActionListeners(AbstractAction action) {
065: PropertyChangeListener[] pls = action
066: .getPropertyChangeListeners();
067: // System.out.println("+++ Action: "+action.getValue(Action.NAME)+":
068: // "+pls.length);
069: for (int i = 0; i < pls.length; i++) {
070: PropertyChangeListener pl = pls[i];
071: action.removePropertyChangeListener(pl);
072: }
073: /*
074: * pls = action.getPropertyChangeListeners(); System.out.println("---
075: * Action: "+action.getValue(Action.NAME)+": "+pls.length); for (int
076: * i=0; i < pls.length; i++) { PropertyChangeListener pl = pls[i];
077: * System.out.println("Listener "+i+": "+pl); }
078: */
079: }
080:
081: public final static int MAIN_TOOLBAR = 0;
082:
083: public final static int OPTIONAL_TOOLBAR = 0;
084:
085: private JMenuBar menuBar;
086:
087: private List<OptionalToolBar> optionalToolBars = new Vector<OptionalToolBar>();
088:
089: private List<OptionalPopupMenu> optionalPopupMenus = new Vector<OptionalPopupMenu>();
090:
091: private JToolBar toolBar;
092:
093: private JPopupMenu popupMenu;
094:
095: private JLabel taskIndicator;
096:
097: private int openTasks;
098:
099: private GroupManager groupManager = new GroupManager();
100:
101: private List<ActionBundle> actionBundles = new Vector<ActionBundle>();
102:
103: private static String PERMANENT_BUNDLE = "permanent-actions";
104:
105: private Font buttonFont;
106:
107: private boolean buttonTextVisible = false;
108:
109: public MenuAndToolbarComposer(JMenuBar menuBar) {
110: this .menuBar = menuBar;
111: init();
112: }
113:
114: public MenuAndToolbarComposer(JToolBar toolBar) {
115: this .toolBar = toolBar;
116: init();
117: }
118:
119: public MenuAndToolbarComposer(JPopupMenu popupMenu) {
120: this .popupMenu = popupMenu;
121: init();
122: }
123:
124: public MenuAndToolbarComposer(JMenuBar menuBar, JToolBar toolBar) {
125: this .menuBar = menuBar;
126: this .toolBar = toolBar;
127: init();
128: }
129:
130: public MenuAndToolbarComposer(JMenuBar menuBar, JToolBar toolBar,
131: JPopupMenu popupMenu) {
132: this .menuBar = menuBar;
133: this .toolBar = toolBar;
134: this .popupMenu = popupMenu;
135: init();
136: }
137:
138: public void showInfo(boolean showInfo) {
139: if (showInfo) {
140: // add info action
141: addTemporaryActionBundle(ActionBundle.CONTELLIGENT_ACTIONS,
142: new Action[] { new ShowInfoAction() });
143: } else {
144: // remove info action
145: addTemporaryActionBundle(ActionBundle.CONTELLIGENT_ACTIONS,
146: new Action[0]);
147: }
148: }
149:
150: private void init() {
151: int offset = PreferencesModule.getPreferences().getInt(
152: PreferencesModule.FONTSIZE_OFFSET,
153: PreferencesModule.DEFAULT_FONTSIZE_OFFSET);
154: buttonFont = new Font("Verdana", Font.PLAIN, 10 + offset);
155: taskIndicator = new JLabel(Resources.smallStatic);
156: Session.getInstance().addTaskEventListener(this ,
157: ContelligentEventDispatcher.DOES_USE_SWING);
158: }
159:
160: public void onTaskStarted(TaskStartedEvent e) {
161: openTasks++;
162: if (openTasks == 1) {
163: taskIndicator.setIcon(Resources.smallAnimation);
164: }
165: }
166:
167: public void onTaskFinished(TaskFinishedEvent e) {
168: openTasks--;
169: if (openTasks == 0) {
170: taskIndicator.setIcon(Resources.smallStatic);
171: }
172: }
173:
174: public void setMenuBar(JMenuBar menuBar) {
175: this .menuBar = menuBar;
176: }
177:
178: public void addOptionalToolBar(OptionalToolBar optionalToolBar) {
179: logger.log(Level.FINEST, "OptionalToolbar " + optionalToolBar
180: + " added to " + this );
181: optionalToolBars.add(optionalToolBar);
182: }
183:
184: public void removeOptionalToolBar(OptionalToolBar optionalToolBar) {
185: optionalToolBars.remove(optionalToolBar);
186: }
187:
188: public void setPopupMenu(JPopupMenu popupMenu) {
189: this .popupMenu = popupMenu;
190: }
191:
192: public JPopupMenu getPopupMenu() {
193: return popupMenu;
194: }
195:
196: public void addOptionalPopupMenu(OptionalPopupMenu optionalPopupMenu) {
197: logger.log(Level.FINEST, "OptionalToolbar " + optionalPopupMenu
198: + " added to " + this );
199: optionalPopupMenus.add(optionalPopupMenu);
200: }
201:
202: public void removeOptionalPopupMenu(
203: OptionalPopupMenu optionalPopupMenu) {
204: optionalPopupMenus.remove(optionalPopupMenu);
205: }
206:
207: public void setButtonTextVisible(boolean buttonTextVisible) {
208: this .buttonTextVisible = buttonTextVisible;
209: }
210:
211: public boolean isButtonTextVisible() {
212: return buttonTextVisible;
213: }
214:
215: public void setButtonFont(Font buttonFont) {
216: this .buttonFont = buttonFont;
217: }
218:
219: public Font getButtonFont() {
220: return buttonFont;
221: }
222:
223: public void addPermanentActionBundle(Action[] actions) {
224: addTemporaryActionBundle(PERMANENT_BUNDLE, actions);
225: }
226:
227: public void addTemporaryActionBundle(String bundleName,
228: Action[] actions) {
229: ActionBundle actionBundle = new ActionBundle(bundleName,
230: actions);
231: if (actionBundles.contains(actionBundle)) {
232: logger.log(Level.FINEST,
233: "setActionBundle(): replace actionBundle '"
234: + actionBundle.getName() + "'");
235: int index = actionBundles.indexOf(actionBundle);
236: actionBundles.remove(actionBundle);
237: actionBundles.add(index, actionBundle);
238: } else {
239: actionBundles.add(actionBundle);
240: }
241: compose();
242: }
243:
244: public void addActionBundles(List bundles) {
245: for (Iterator i = bundles.iterator(); i.hasNext();) {
246: ActionBundle actionBundle = (ActionBundle) i.next();
247: if (actionBundles.contains(actionBundle)) {
248: logger.log(Level.FINEST,
249: "setActionBundle(): replace actionBundle '"
250: + actionBundle.getName() + "'");
251: int index = actionBundles.indexOf(actionBundle);
252: actionBundles.remove(actionBundle);
253: actionBundles.add(index, actionBundle);
254: } else {
255: actionBundles.add(actionBundle);
256: }
257: }
258: compose();
259: }
260:
261: public void removeActionBundle(String bundleName) {
262: for (Iterator i = actionBundles.iterator(); i.hasNext();) {
263: if (((ActionBundle) i.next()).getName().equals(bundleName)) {
264: i.remove();
265: break;
266: }
267: }
268: compose();
269: }
270:
271: public void removeActionBundles(List bundles) {
272: for (Iterator i = bundles.iterator(); i.hasNext();) {
273: ActionBundle actionBundle = (ActionBundle) i.next();
274: for (Iterator j = actionBundles.iterator(); j.hasNext();) {
275: if (j.next().equals(actionBundle)) {
276: j.remove();
277: break;
278: }
279: }
280: }
281: compose();
282: }
283:
284: public void removeAllActionBundles() {
285: actionBundles.clear();
286: compose();
287: }
288:
289: private void deleteActionsFromJMenu(JMenu menu) {
290: java.awt.Component[] components = menu.getMenuComponents();
291: for (int i = 0; i < components.length; i++) {
292: java.awt.Component component = components[i];
293: if (component instanceof JMenuItem) {
294: JMenuItem item = (JMenuItem) component;
295: item.setAction(null);
296: item.removeAll();
297: }
298: }
299: }
300:
301: private void deleteActionsFromJMenuBar(JMenuBar bar) {
302: for (int i = 0; i < bar.getMenuCount(); i++) {
303: JMenu menu = bar.getMenu(i);
304: if (menu != null) {
305: deleteActionsFromJMenu(menu);
306: // has to be done afterwards, hehe...
307: menu.removeAll();
308: }
309: }
310: bar.removeAll();
311: }
312:
313: private void resetAllBarsAndMenus() {
314: if (menuBar != null) {
315: deleteActionsFromJMenuBar(menuBar);
316: }
317: if (toolBar != null) {
318: toolBar.removeAll();
319: toolBar.setRollover(true);
320: }
321: if (optionalToolBars.size() > 0) {
322: for (int k = 0; k < optionalToolBars.size(); k++) {
323: ((OptionalToolBar) optionalToolBars.get(k)).removeAll();
324: ((OptionalToolBar) optionalToolBars.get(k))
325: .setRollover(true);
326: }
327: }
328: if (popupMenu != null) {
329: popupMenu.removeAll();
330: }
331: if (optionalPopupMenus.size() > 0) {
332: for (int k = 0; k < optionalPopupMenus.size(); k++) {
333: ((OptionalPopupMenu) optionalPopupMenus.get(k))
334: .removeAll();
335: }
336: }
337: }
338:
339: private void composeAction(AbstractAction action, JMenu menu,
340: ActionGroup actionGroup) {
341: // toolbar composing
342: boolean optionalToolBarExists = false;
343: Object buttonTarget = action
344: .getValue(ContelligentAction.BUTTON_TARGET);
345: // check if this goes to toolbar
346: if (buttonTarget != null
347: && buttonTarget.equals(ContelligentAction.TOOLBAR)) {
348: // first add action to optional toolbar if desired
349: for (int k = 0; k < optionalToolBars.size(); k++) {
350: OptionalToolBar optionalToolBar = (OptionalToolBar) optionalToolBars
351: .get(k);
352: if (optionalToolBar.hasActionGroup(actionGroup)
353: || optionalToolBar
354: .hasActionBundle((ActionBundle) action
355: .getValue(ContelligentAction.ACTION_BUNDLE))) {
356: optionalToolBar.add(createButton(action));
357: optionalToolBarExists = true;
358: }
359: }
360: // if not added to optional toolbar, add to ordinary toolbar if
361: // there is one
362: if (!optionalToolBarExists && toolBar != null) {
363: toolBar.add(createButton(action));
364: }
365: }
366: // menubar composing
367: Object menuTarget = action
368: .getValue(ContelligentAction.MENU_TARGET);
369: if (menuBar != null
370: && menuTarget != null
371: && (menuTarget.equals(ContelligentAction.MENU) || menuTarget
372: .equals(ContelligentAction.SUBMENU))) {
373: if (ContelligentAction.SEPARATOR_ACTION.equals(action
374: .getValue(ContelligentAction.TYPE))) {
375: menu.addSeparator();
376: } else {
377: JMenuItem item = ButtonComposer.createMenuItem(action);
378: if (menuTarget.equals(ContelligentAction.SUBMENU)) {
379: // add action to parent menu...
380: // XXX remember: this only works if the child action is of
381: // the same type (actionGroup) as the parent action
382: // and is added to the menu afer the parent!!
383: JMenuItem parentMenu = (JMenuItem) ((ContelligentAction) action
384: .getValue(ContelligentAction.MENU_PARENT_ACTION))
385: .getValue(ContelligentAction.MENU_INSTANCE);
386: if (parentMenu != null) {
387: parentMenu.add(item);
388: }
389: } else {
390: // or to menubar...
391: menu.add(item);
392: }
393: action.putValue(ContelligentAction.MENU_INSTANCE, item);
394: }
395: }
396:
397: // popup menu composing
398: boolean optionalPopupMenuExists = false;
399: Object popupTarget = action
400: .getValue(ContelligentAction.POPUP_TARGET);
401: if (popupTarget != null
402: && (popupTarget.equals(ContelligentAction.POPUP_MENU) || popupTarget
403: .equals(ContelligentAction.POPUP_SUBMENU))) {
404: for (int k = 0; k < optionalPopupMenus.size(); k++) {
405: OptionalPopupMenu optionalPopupMenu = (OptionalPopupMenu) optionalPopupMenus
406: .get(k);
407: if (optionalPopupMenu.hasActionGroup(actionGroup)
408: || optionalPopupMenu
409: .hasActionBundle((ActionBundle) action
410: .getValue(ContelligentAction.ACTION_BUNDLE))) {
411: JMenuItem item = ButtonComposer
412: .createMenuItem(action);
413: if (popupTarget
414: .equals(ContelligentAction.POPUP_SUBMENU)) {
415: // add action to parent menu...
416: // XXX remember: this only works if the child action is
417: // of the same type (actionGroup) as the parent action
418: // and is added to the menu afer the parent!!
419: JMenuItem parentMenu = (JMenuItem) ((ContelligentAction) action
420: .getValue(ContelligentAction.POPUP_PARENT_ACTION))
421: .getValue(ContelligentAction.POPUP_INSTANCE);
422: if (parentMenu != null) {
423: parentMenu.add(item);
424: }
425: } else {
426: // or to popup menu...
427: optionalPopupMenu.add(item);
428: }
429: optionalPopupMenuExists = true;
430: }
431: }
432: }
433:
434: if (!optionalPopupMenuExists
435: && popupMenu != null
436: && popupTarget != null
437: && (popupTarget.equals(ContelligentAction.POPUP_MENU) || popupTarget
438: .equals(ContelligentAction.POPUP_SUBMENU))) {
439: if (action.getValue(ContelligentAction.TYPE).equals(
440: ContelligentAction.SEPARATOR_ACTION)) {
441: popupMenu.addSeparator();
442: } else {
443: JMenuItem item = ButtonComposer.createMenuItem(action);
444: if (popupTarget
445: .equals(ContelligentAction.POPUP_SUBMENU)) {
446: // add action to parent menu...
447: // XXX remember: this only works if the child action is of
448: // the same type (actionGroup) as the parent action
449: // and is added to the menu afer the parent!!
450: JMenuItem parentMenu = (JMenuItem) ((ContelligentAction) action
451: .getValue(ContelligentAction.POPUP_PARENT_ACTION))
452: .getValue(ContelligentAction.POPUP_INSTANCE);
453: if (parentMenu != null) {
454: parentMenu.add(item);
455: }
456: } else {
457: // or to toolbar...
458: popupMenu.add(item);
459: }
460: action
461: .putValue(ContelligentAction.POPUP_INSTANCE,
462: item);
463: }
464: }
465: }
466:
467: public void repaint() {
468: if (menuBar != null) {
469: menuBar.validate();
470: menuBar.repaint();
471: }
472: if (toolBar != null) {
473: toolBar.validate();
474: toolBar.repaint();
475: }
476: for (int k = 0; k < optionalToolBars.size(); k++) {
477: OptionalToolBar optionalToolBar = (OptionalToolBar) optionalToolBars
478: .get(k);
479: optionalToolBar.validate();
480: optionalToolBar.repaint();
481: }
482: }
483:
484: public void compose() {
485: logger.log(Level.FINE, "Starting composition of actions");
486: groupManager.digestActionBundles(actionBundles);
487: List actionGroups = groupManager.getActionGroups();
488:
489: resetAllBarsAndMenus();
490:
491: // for each action group...
492: for (Iterator i = actionGroups.iterator(); i.hasNext();) {
493: ActionGroup actionGroup = (ActionGroup) i.next();
494: // ...generate a menu...
495: JMenu menu = ButtonComposer.createMenu(actionGroup);
496: // ...and attach all actions in this group to it
497: List actions = actionGroup.getActions();
498: Set<AbstractAction> sorted = new TreeSet<AbstractAction>(
499: new Comparator<AbstractAction>() {
500: public int typeIdx(String str) {
501: for (int i = 0; i < ContelligentAction.actionTypes.length; i++) {
502: if (ContelligentAction.actionTypes[i]
503: .equals(str)) {
504: return i;
505: }
506: }
507: return -1;
508: }
509:
510: public int compare(AbstractAction a1,
511: AbstractAction a2) {
512: // This makes sure that all Actions end up at their desired
513: // position.
514: // Roughly, it sorts first by ACTION_TYPE, then by
515: // ACTION_GROUP and ACTION_POS.
516: // There is also special handling for submenu items like the
517: // ones in
518: // the search context menu.
519: // A group/pos of null is currently evaluated less than any
520: // actual integer,
521: // so they will end up at the top of their respective
522: // blocks. This way,
523: // they can more easily be found and fixed.
524: // This Comparator is not consistent with equals, but you
525: // shouldnt add
526: // multiple equal actions to the menu anyway.
527: String type1 = (String) a1
528: .getValue(ContelligentAction.ACTION_TYPE);
529: String type2 = (String) a2
530: .getValue(ContelligentAction.ACTION_TYPE);
531: Integer group1 = (Integer) a1
532: .getValue(ContelligentAction.ACTION_GROUP);
533: Integer group2 = (Integer) a2
534: .getValue(ContelligentAction.ACTION_GROUP);
535: Integer pos1 = (Integer) a1
536: .getValue(ContelligentAction.ACTION_POS);
537: Integer pos2 = (Integer) a2
538: .getValue(ContelligentAction.ACTION_POS);
539: AbstractAction parent1 = (AbstractAction) a1
540: .getValue(ContelligentAction.MENU_PARENT_ACTION);
541: if (parent1 == null) {
542: parent1 = (AbstractAction) a1
543: .getValue(ContelligentAction.POPUP_PARENT_ACTION);
544: }
545: AbstractAction parent2 = (AbstractAction) a2
546: .getValue(ContelligentAction.MENU_PARENT_ACTION);
547: if (parent2 == null) {
548: parent2 = (AbstractAction) a2
549: .getValue(ContelligentAction.POPUP_PARENT_ACTION);
550: }
551: if ((parent1 != null) && (parent2 != null)) {
552: if (!parent1.equals(parent2)) {
553: return compare(parent1, parent2);
554: }
555: } else if (parent1 != null) {
556: if (parent1.equals(a2)) {
557: return 1;
558: } else {
559: return compare(parent1, a2);
560: }
561: } else if (parent2 != null) {
562: if (parent2.equals(a1)) {
563: return -1;
564: } else {
565: return compare(a1, parent2);
566: }
567: } // Break else level here to account for parents
568: // being equal
569:
570: if ((type1 == null) && (type2 == null)) {
571: if ((pos1 == null) && (pos2 == null)) {
572: // No idea, just return anything
573: return a1.hashCode() < a2
574: .hashCode() ? -1 : 1;
575: } else if (pos1 == null) {
576: return -1;
577: } else if (pos2 == null) {
578: return 1;
579: } else {
580: return pos1.intValue() < pos2
581: .intValue() ? -1 : 1;
582: }
583: } else if (type1 == null) {
584: return -1;
585: } else if (type2 == null) {
586: return 1;
587: } else {
588: int idx1 = typeIdx(type1);
589: int idx2 = typeIdx(type2);
590: if (idx1 < idx2) {
591: return -1;
592: } else if (idx1 > idx2) {
593: return 1;
594: } else if ((group1 == null)
595: && (group2 == null)) {
596: if ((pos1 == null)
597: && (pos2 == null)) {
598: // No idea, just return anything
599: return a1.hashCode() < a2
600: .hashCode() ? -1 : 1;
601: } else if (pos1 == null) {
602: return -1;
603: } else if (pos2 == null) {
604: return 1;
605: } else {
606: return pos1.intValue() < pos2
607: .intValue() ? -1 : 1;
608: }
609: } else if (group1 == null) {
610: return -1;
611: } else if (group2 == null) {
612: return 1;
613: } else if (group1.intValue() < group2
614: .intValue()) {
615: return -1;
616: } else if (group1.intValue() > group2
617: .intValue()) {
618: return 1;
619: } else {
620: if ((pos1 == null)
621: && (pos2 == null)) {
622: // No idea, just return anything
623: return a1.hashCode() < a2
624: .hashCode() ? -1 : 1;
625: } else if (pos1 == null) {
626: return -1;
627: } else if (pos2 == null) {
628: return 1;
629: } else {
630: return pos1.intValue() < pos2
631: .intValue() ? -1 : 1;
632: }
633: }
634: }
635: }
636: });
637:
638: for (Iterator j = actions.iterator(); j.hasNext();) {
639: AbstractAction action = (AbstractAction) j.next();
640: // We don't allow manually inserting separators anymore; this
641: // must be done
642: // by setting the right group properties now.
643: if (!action.getValue(ContelligentAction.TYPE).equals(
644: ContelligentAction.SEPARATOR_ACTION)) {
645: sorted.add(action);
646: }
647: }
648:
649: int lastGroup = -1;
650: String lastType = "";
651: for (Iterator j = sorted.iterator(); j.hasNext();) {
652: AbstractAction action = (AbstractAction) j.next();
653: String type = (String) action
654: .getValue(ContelligentAction.ACTION_TYPE);
655: Integer group = (Integer) action
656: .getValue(ContelligentAction.ACTION_GROUP);
657: if (ContelligentAction.MENU.equals(action
658: .getValue(ContelligentAction.MENU_TARGET))) {
659: // Nice for debugging if you have random ungrouped menu
660: // entries
661: /*
662: * if (group == null) { System.out.println("Fix me:
663: * "+action.getClass()); }
664: */
665: if (type.equals(lastType)) {
666: if ((group != null)) {
667: if (group.intValue() != lastGroup) {
668: // new group; insert separator
669: if (lastGroup >= 0) {
670: SeparatorAction sep = new SeparatorAction(
671: type);
672: composeAction(sep, menu,
673: actionGroup);
674: }
675: lastGroup = group.intValue();
676: }
677: }
678: } else {
679: if (group != null) {
680: lastGroup = group.intValue();
681: } else {
682: lastGroup = 0;
683: }
684: lastType = type;
685: }
686: }
687: // make really sure, that all these listners are dropped, as
688: // they tend to be a bit sticky:
689: // FIXME: strictly speaking this is a bug, as at this point
690: // there
691: // should be not listeners attached to our actions in the first
692: // place
693: // In fact, if we did not clear them here, there would be an
694: // ever
695: // and quickly growing amount of them here, making the system
696: // too slow to use after short time...
697: resetActionListeners(action);
698: composeAction(action, menu, actionGroup);
699: }
700:
701: // add newly genereated menu to menuBar if there is one and there is
702: // something
703: // attached to menu
704: if (menuBar != null && actionGroup.containsMenuBarAction()) {
705: menuBar.add(menu);
706: } else {
707: deleteActionsFromJMenu(menu);
708: menu = null;
709: }
710: if (toolBar != null && actionGroup.containsToolBarAction()) {
711: toolBar.addSeparator();
712: }
713: }
714: if (toolBar != null) {
715: toolBar.add(Box.createHorizontalGlue());
716: toolBar.add(taskIndicator);
717: }
718: repaint();
719: logger.log(Level.FINE, "composed actions successfully");
720: }
721:
722: public AbstractButton createButton(Action action) {
723: return ButtonComposer.createButton(action, buttonTextVisible,
724: buttonFont, true, true);
725: }
726:
727: private static class GroupManager {
728:
729: private List oldActionGroups = null;
730:
731: private List actionGroups = null;
732:
733: // helper
734: public static JMenu getJMenuForGroupName(
735: java.awt.Container menuBar, String groupName) {
736: java.awt.Component[] comps = menuBar.getComponents();
737: for (int i = 0; i < comps.length; i++) {
738: java.awt.Component comp = comps[i];
739: String name = comp.getName();
740: if (comp instanceof JMenu && name != null
741: && name.equals(groupName)) {
742: return (JMenu) comp;
743: }
744: }
745: return null;
746: }
747:
748: public void digestActionBundles(List actionBundles) {
749: // save actionGroups for later comparision
750: oldActionGroups = actionGroups;
751: actionGroups = createAllActionGroups(actionBundles);
752: sortActionGroups(this .actionGroups);
753: }
754:
755: public List getActionGroups() {
756: return actionGroups;
757: }
758:
759: public static List getUnion(List l1, List l2) {
760: for (Iterator i = l1.iterator(); i.hasNext();) {
761: Object o = i.next();
762: if (!l2.contains(o)) {
763: l2.add(o);
764: }
765: }
766: return l2;
767: }
768:
769: public List getDeletedActionGroups() {
770: List deleted = new Vector();
771: if (oldActionGroups != null) {
772: for (Iterator i = oldActionGroups.iterator(); i
773: .hasNext();) {
774: ActionGroup actionGroup = (ActionGroup) i.next();
775: if (findActionGroupByName(actionGroups, actionGroup
776: .getName()) == null) {
777: deleted.add(actionGroup);
778: }
779: }
780: }
781: return deleted;
782: }
783:
784: public List getChangedActionGroups() {
785: List changed = new Vector();
786: if (oldActionGroups != null) {
787: for (Iterator i = actionGroups.iterator(); i.hasNext();) {
788: ActionGroup actionGroup = (ActionGroup) i.next();
789: if (isGroupChanged(actionGroup, false)) {
790: changed.add(actionGroup);
791: }
792: }
793: }
794: return changed;
795: }
796:
797: public List getnewlyAddActionGroups() {
798: if (oldActionGroups == null) {
799: return actionGroups;
800: }
801: List added = new Vector();
802: for (Iterator i = actionGroups.iterator(); i.hasNext();) {
803: ActionGroup actionGroup = (ActionGroup) i.next();
804: if (findActionGroupByName(oldActionGroups, actionGroup
805: .getName()) == null) {
806: added.add(actionGroup);
807: }
808: }
809: return added;
810: }
811:
812: public boolean isGroupChanged(ActionGroup actionGroup,
813: boolean newIsChanged) {
814: if (oldActionGroups == null) {
815: return newIsChanged;
816: }
817: ActionGroup oldActionGroup = findActionGroupByName(
818: oldActionGroups, actionGroup.getName());
819: if (oldActionGroup == null) {
820: return newIsChanged;
821: }
822: return oldActionGroup.getActions().equals(
823: actionGroup.getActions());
824: }
825:
826: private ActionGroup findActionGroupByName(List actionGroups,
827: String name) {
828: for (Iterator i = actionGroups.iterator(); i.hasNext();) {
829: ActionGroup actionGroup = (ActionGroup) i.next();
830: if (actionGroup.getName().equals(name)) {
831: return actionGroup;
832: }
833: }
834: return null;
835: }
836:
837: private List createAllActionGroups(List actionBundles) {
838: List actionGroups = new Vector();
839:
840: // create all action groups
841: for (Iterator it = actionBundles.iterator(); it.hasNext();) {
842: ActionBundle actionBundle = (ActionBundle) it.next();
843:
844: Action[] actions = actionBundle.getActions();
845: for (int j = 0; j < actions.length; j++) {
846: if (actions[j]
847: .getValue(ContelligentAction.ACTION_TYPE) != null) {
848: ActionGroup actionGroup = findActionGroupByName(
849: actionGroups,
850: (String) actions[j]
851: .getValue(ContelligentAction.ACTION_TYPE));
852: if (actionGroup == null) {
853: String aType = (String) actions[j]
854: .getValue(ContelligentAction.ACTION_TYPE);
855: int mnemonic = -1;
856: for (int i = 0; i < ContelligentAction.actionTypes.length; i++) {
857: if (ContelligentAction.actionTypes[i]
858: .equals(aType)) {
859: if (PreferencesModule
860: .getDefaultLanguage()
861: .equals("de")) {
862: mnemonic = ContelligentAction.actionMnemonics_de[i];
863: } else {
864: mnemonic = ContelligentAction.actionMnemonics_en[i];
865: }
866: }
867: }
868: actionGroup = new ActionGroup(aType,
869: mnemonic);
870: actionGroups.add(actionGroup);
871: logger.log(Level.FINEST,
872: "composeMenuAndToolbar(): adding action group '"
873: + actionGroup.getName()
874: + "'");
875: }
876: logger.log(Level.FINEST,
877: "composeMenuAndToolbar(): adding action '"
878: + actions[j]
879: + "' to actionGroup '"
880: + actionGroup.getName() + "'");
881: actionGroup.addAction(actions[j], actionBundle);
882: } else {
883: logger
884: .log(
885: Level.WARNING,
886: "composeMenuAndToolbar(): action MUST define property ACTION_TYPE! Please check action '"
887: + actions[j] + "'");
888: }
889: }
890: }
891: return actionGroups;
892: }
893:
894: private void sortActionGroups(List actionGroups) {
895: Collections.sort(actionGroups, new Comparator() {
896: public int compare(Object o1, Object o2) {
897: int index1 = getGroupIndex(((ActionGroup) o1)
898: .getName());
899: int index2 = getGroupIndex(((ActionGroup) o2)
900: .getName());
901: if (index1 == index2)
902: return 0;
903: return index1 < index2 ? -1 : 1;
904: }
905:
906: public boolean equals(Object obj) {
907: return (obj == this );
908: }
909:
910: public int hashCode() {
911: return -1;
912: }
913:
914: });
915: }
916:
917: private int getGroupIndex(String group) {
918: for (int i = 0; i < ContelligentAction.actionTypes.length; i++) {
919: if (ContelligentAction.actionTypes[i].equals(group)) {
920: return i;
921: }
922: }
923: return -1;
924: }
925: }
926:
927: public class ShowInfoAction extends AbstractAction implements
928: ContelligentAction {
929: public ShowInfoAction() {
930: super ("about_action", Resources.serverIcon);
931: putValue(SHORT_DESCRIPTION, "about_action_description");
932: putValue(TYPE, PUSH_ACTION);
933: putValue(ACTION_TYPE, HELP_ACTION);
934: putValue(ACTION_GROUP, HELP_ABOUT_GROUP);
935: putValue(MENU_TARGET, MENU);
936: putValue(BUTTON_TARGET, NO_BUTTON);
937: }
938:
939: public void actionPerformed(ActionEvent e) {
940: SplashScreen splashScreen = new SplashScreen(
941: ContelligentClient.getActiveFrame(),
942: SplashScreen.DISPOSE_ON_MOUSECLICK);
943: splashScreen.setVisible(true);
944: }
945: }
946: }
|