001: // The contents of this file are subject to the Mozilla Public License Version
002: // 1.1
003: //(the "License"); you may not use this file except in compliance with the
004: //License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
005: //
006: //Software distributed under the License is distributed on an "AS IS" basis,
007: //WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
008: //for the specific language governing rights and
009: //limitations under the License.
010: //
011: //The Original Code is "The Columba Project"
012: //
013: //The Initial Developers of the Original Code are Frederik Dietz and Timo
014: // Stich.
015: //Portions created by Frederik Dietz and Timo Stich are Copyright (C) 2003.
016: //
017: //All Rights Reserved.
018: package org.columba.core.gui.menu;
019:
020: import java.io.IOException;
021: import java.io.InputStream;
022: import java.util.Iterator;
023: import java.util.logging.Logger;
024:
025: import javax.swing.JRadioButtonMenuItem;
026:
027: import org.columba.api.gui.frame.IFrameMediator;
028: import org.columba.api.plugin.IExtension;
029: import org.columba.api.plugin.IExtensionHandler;
030: import org.columba.api.plugin.IExtensionHandlerKeys;
031: import org.columba.api.plugin.PluginException;
032: import org.columba.api.plugin.PluginHandlerNotFoundException;
033: import org.columba.core.gui.action.AbstractColumbaAction;
034: import org.columba.core.gui.action.AbstractSelectableAction;
035: import org.columba.core.gui.action.CCheckBoxMenuItem;
036: import org.columba.core.gui.base.CMenuItem;
037: import org.columba.core.logging.Logging;
038: import org.columba.core.plugin.PluginManager;
039: import org.jdom.Document;
040: import org.jdom.Element;
041: import org.jdom.JDOMException;
042: import org.jdom.input.SAXBuilder;
043:
044: /**
045: * Generate menu from xml-file.
046: * <p>
047: * Translation of resources is mostly done in {@link AbstractColumbaAction},
048: * for JMenuItem, JCheckboxMenuItem, JRadioButtonMenuItem. But, the menu names,
049: * visible on the menubar and the popup menu name are translated here. This is
050: * achieved by passing a {@link IFrameMediator} instance, and using its
051: * <code>getString()</code> method to pass along the translation to the
052: * appropriate resourceloader.
053: * <p>
054: * Example: <br/>
055: *
056: * <pre>
057: * ExtendablePopupMenu menu = new MenuXMLDecoder(frameController)
058: * .createPopupMenu("org/columba/core/contextmenu.xml");
059: * </pre>
060: *
061: * @author fdietz
062: *
063: */
064: public class MenuXMLDecoder {
065:
066: private static final String PLACEHOLDERID = "placeholderid";
067:
068: private static final Logger LOG = Logger
069: .getLogger("org.columba.core.gui.menu");
070:
071: private static final String PLACEHOLDER = "placeholder";
072:
073: private static final String SEPARATOR = "separator";
074:
075: private static final String RADIOBUTTONMENUITEM = "radiobuttonmenuitem";
076:
077: private static final String CHECKBOXMENUITEM = "checkboxmenuitem";
078:
079: private static final String IMENU = "imenu";
080:
081: private static final String ID = "id";
082:
083: private static final String MENUITEM = "menuitem";
084:
085: private static final String MENU = "menu";
086:
087: private static final String MENUBAR = "menubar";
088:
089: private IExtensionHandler pluginHandler;
090:
091: private IFrameMediator mediator;
092:
093: public MenuXMLDecoder(IFrameMediator mediator) {
094: super ();
095:
096: this .mediator = mediator;
097:
098: try {
099: pluginHandler = PluginManager
100: .getInstance()
101: .getExtensionHandler(
102: IExtensionHandlerKeys.ORG_COLUMBA_CORE_ACTION);
103: } catch (PluginHandlerNotFoundException e) {
104: e.printStackTrace();
105: }
106: }
107:
108: private AbstractColumbaAction getAction(String id,
109: IFrameMediator controller) {
110: if (id == null)
111: throw new IllegalArgumentException("id == null");
112: if (controller == null)
113: throw new IllegalArgumentException("controller == null");
114:
115: IExtension extension = pluginHandler.getExtension(id);
116:
117: AbstractColumbaAction a = null;
118:
119: try {
120: if (extension != null)
121: a = (AbstractColumbaAction) extension
122: .instanciateExtension(new Object[] { controller });
123: } catch (Exception e) {
124: LOG.severe(e.getMessage());
125: if (Logging.DEBUG)
126: e.printStackTrace();
127:
128: }
129:
130: return a;
131:
132: }
133:
134: private IMenu getIMenu(String id, IFrameMediator controller)
135: throws Exception {
136: IExtension extension = pluginHandler.getExtension(id);
137:
138: IMenu menu = null;
139: try {
140: menu = (IMenu) extension
141: .instanciateExtension(new Object[] { controller });
142: } catch (PluginException e) {
143: e.printStackTrace();
144: }
145:
146: return menu;
147: }
148:
149: public ExtendablePopupMenu createPopupMenu(InputStream is) {
150: Document doc = retrieveDocument(is);
151:
152: Element menuElement = doc.getRootElement();
153: if (menuElement.getName().equals(MenuXMLDecoder.MENU) == false) {
154: LOG.severe("root element <menu> expected");
155: return null;
156: }
157:
158: ExtendablePopupMenu menu = new ExtendablePopupMenu("id");
159: parsePopupMenu(menu, menuElement);
160:
161: return menu;
162: }
163:
164: public ExtendableMenuBar createMenuBar(InputStream is) {
165:
166: Document doc = retrieveDocument(is);
167:
168: Element menubarElement = doc.getRootElement();
169: if (menubarElement.getName().equals(MenuXMLDecoder.MENUBAR) == false) {
170: LOG.severe("root element <menubar> expected");
171: return null;
172: }
173:
174: ExtendableMenuBar menuBar = new ExtendableMenuBar();
175: Iterator it = menubarElement.getChildren().listIterator();
176: while (it.hasNext()) {
177: Element menuElement = (Element) it.next();
178: if (menuElement.getName().equals(MenuXMLDecoder.MENU)) {
179:
180: String menuId = menuElement
181: .getAttributeValue(MenuXMLDecoder.ID);
182:
183: String menuName = mediator.getString("menu",
184: "mainframe", menuId);
185:
186: ExtendableMenu menu = new ExtendableMenu(menuId,
187: menuName);
188: parseMenu(menu, menuElement);
189: menuBar.add(menu);
190: }
191: }
192:
193: return menuBar;
194: }
195:
196: /**
197: * @param xmlResource
198: * @return
199: */
200: private Document retrieveDocument(InputStream is) {
201: SAXBuilder builder = new SAXBuilder();
202: builder.setIgnoringElementContentWhitespace(true);
203: Document doc = null;
204: try {
205: doc = builder.build(is);
206: } catch (JDOMException e) {
207: LOG.severe(e.getMessage());
208: e.printStackTrace();
209: } catch (IOException e) {
210: LOG.severe(e.getMessage());
211: e.printStackTrace();
212: }
213: return doc;
214: }
215:
216: private void parseMenu(ExtendableMenu parentMenu,
217: Element parentElement) {
218: Iterator it = parentElement.getChildren().listIterator();
219: while (it.hasNext()) {
220: Element menuElement = (Element) it.next();
221:
222: if (menuElement.getName().equals(MenuXMLDecoder.MENU)) {
223:
224: String menuId = menuElement
225: .getAttributeValue(MenuXMLDecoder.ID);
226: String menuName = mediator.getString("menu",
227: "mainframe", menuId);
228:
229: ExtendableMenu menu = new ExtendableMenu(menuId,
230: menuName);
231: parseMenu(menu, menuElement);
232: parentMenu.add(menu);
233: } else if (menuElement.getName().equals(
234: MenuXMLDecoder.MENUITEM)) {
235: String id = menuElement
236: .getAttributeValue(MenuXMLDecoder.ID);
237: AbstractColumbaAction action = getAction(id, mediator);
238: if (action == null)
239: continue;
240:
241: CMenuItem menuItem = new CMenuItem(action);
242: menuItem.addMouseListener(mediator
243: .getMouseTooltipHandler());
244: parentMenu.add(menuItem);
245: } else if (menuElement.getName().equals(
246: MenuXMLDecoder.CHECKBOXMENUITEM)) {
247: String id = menuElement
248: .getAttributeValue(MenuXMLDecoder.ID);
249: AbstractSelectableAction action = (AbstractSelectableAction) getAction(
250: id, mediator);
251: if (action == null)
252: continue;
253:
254: CCheckBoxMenuItem menuItem = new CCheckBoxMenuItem(
255: action);
256: menuItem.addMouseListener(mediator
257: .getMouseTooltipHandler());
258: parentMenu.add(menuItem);
259: } else if (menuElement.getName().equals(
260: MenuXMLDecoder.RADIOBUTTONMENUITEM)) {
261: String id = menuElement
262: .getAttributeValue(MenuXMLDecoder.ID);
263: AbstractColumbaAction action = getAction(id, mediator);
264: if (action == null)
265: continue;
266:
267: JRadioButtonMenuItem menuItem = new JRadioButtonMenuItem(
268: action);
269: menuItem.addMouseListener(mediator
270: .getMouseTooltipHandler());
271: parentMenu.add(menuItem);
272: } else if (menuElement.getName().equals(
273: MenuXMLDecoder.SEPARATOR)) {
274: parentMenu.addSeparator();
275: } else if (menuElement.getName().equals(
276: MenuXMLDecoder.IMENU)) {
277: String id = menuElement
278: .getAttributeValue(MenuXMLDecoder.ID);
279: IMenu imenu;
280: try {
281: imenu = getIMenu(id, mediator);
282: if (imenu == null)
283: continue;
284:
285: parentMenu.add(imenu);
286: } catch (Exception e) {
287: LOG.severe(e.getMessage());
288: if (Logging.DEBUG)
289: e.printStackTrace();
290: }
291: } else if (menuElement.getName().equals(
292: MenuXMLDecoder.PLACEHOLDER)) {
293: String id = menuElement
294: .getAttributeValue(MenuXMLDecoder.ID);
295: parentMenu.addPlaceholder(id);
296: }
297: }
298:
299: }
300:
301: private void parsePopupMenu(ExtendablePopupMenu parentMenu,
302: Element parentElement) {
303: Iterator it = parentElement.getChildren().listIterator();
304: while (it.hasNext()) {
305: Element menuElement = (Element) it.next();
306: if (menuElement.getName().equals(MenuXMLDecoder.MENU)) {
307:
308: String menuId = menuElement
309: .getAttributeValue(MenuXMLDecoder.ID);
310: String menuName = mediator.getString("menu",
311: "mainframe", menuId);
312:
313: ExtendableMenu menu = new ExtendableMenu(menuId,
314: menuName);
315: parseMenu(menu, menuElement);
316: parentMenu.add(menu);
317: } else if (menuElement.getName().equals(
318: MenuXMLDecoder.MENUITEM)) {
319: String id = menuElement
320: .getAttributeValue(MenuXMLDecoder.ID);
321: AbstractColumbaAction action = getAction(id, mediator);
322: if (action == null)
323: continue;
324:
325: CMenuItem menuItem = new CMenuItem(action);
326: menuItem.addMouseListener(mediator
327: .getMouseTooltipHandler());
328: parentMenu.add(menuItem);
329: } else if (menuElement.getName().equals(
330: MenuXMLDecoder.CHECKBOXMENUITEM)) {
331: String id = menuElement
332: .getAttributeValue(MenuXMLDecoder.ID);
333: AbstractSelectableAction action = (AbstractSelectableAction) getAction(
334: id, mediator);
335: if (action == null)
336: continue;
337: CCheckBoxMenuItem menuItem = new CCheckBoxMenuItem(
338: action);
339: menuItem.addMouseListener(mediator
340: .getMouseTooltipHandler());
341: parentMenu.add(menuItem);
342: } else if (menuElement.getName().equals(
343: MenuXMLDecoder.RADIOBUTTONMENUITEM)) {
344: String id = menuElement
345: .getAttributeValue(MenuXMLDecoder.ID);
346: AbstractColumbaAction action = getAction(id, mediator);
347: if (action == null)
348: continue;
349: JRadioButtonMenuItem menuItem = new JRadioButtonMenuItem(
350: action);
351: menuItem.addMouseListener(mediator
352: .getMouseTooltipHandler());
353: parentMenu.add(menuItem);
354: } else if (menuElement.getName().equals(
355: MenuXMLDecoder.SEPARATOR)) {
356: parentMenu.addSeparator();
357: } else if (menuElement.getName().equals(
358: MenuXMLDecoder.IMENU)) {
359: String id = menuElement
360: .getAttributeValue(MenuXMLDecoder.ID);
361: IMenu imenu;
362: try {
363: imenu = getIMenu(id, mediator);
364: if (imenu == null)
365: continue;
366: parentMenu.add(imenu);
367: } catch (Exception e) {
368: e.printStackTrace();
369: }
370: } else if (menuElement.getName().equals(
371: MenuXMLDecoder.PLACEHOLDER)) {
372: String id = menuElement
373: .getAttributeValue(MenuXMLDecoder.ID);
374: parentMenu.addPlaceholder(id);
375: }
376: }
377:
378: }
379:
380: /**
381: * Extend menubar from xml resource.
382: *
383: * @param menubar
384: * menubar
385: * @param xmlResource
386: * xml resource to retrieve menu structure
387: */
388: public void extendMenuBar(ExtendableMenuBar menubar, InputStream is) {
389: Document doc = retrieveDocument(is);
390: Element menubarElement = doc.getRootElement();
391: if (menubarElement.getName().equals(MenuXMLDecoder.MENUBAR) == false) {
392: LOG.severe("root element <menubar> expected");
393: return;
394: }
395:
396: Iterator it = menubarElement.getChildren().listIterator();
397: while (it.hasNext()) {
398: Element menuElement = (Element) it.next();
399: if (menuElement.getName().equals(MenuXMLDecoder.MENU)) {
400:
401: String menuId = menuElement
402: .getAttributeValue(MenuXMLDecoder.ID);
403: String placeholderId = menuElement
404: .getAttributeValue(MenuXMLDecoder.PLACEHOLDERID);
405:
406: String menuName = mediator.getString("menu",
407: "mainframe", menuId);
408:
409: if (menubar.exists(menuId)) {
410: // extend existing menu
411: ExtendableMenu menu = menubar.getMenu(menuId);
412: extendMenu(menubar, menu, menuElement,
413: placeholderId);
414: } else {
415: // create new menu
416: ExtendableMenu menu = new ExtendableMenu(menuId,
417: menuName);
418: menubar.insert(menu);
419: parseMenu(menu, menuElement);
420: }
421: }
422: }
423:
424: }
425:
426: public void extendMenu(ExtendableMenuBar menubar,
427: ExtendableMenu parentMenu, Element parentElement,
428: String placeholderId) {
429: if (placeholderId == null)
430: throw new IllegalArgumentException("placeholderId == null");
431:
432: Iterator it = parentElement.getChildren().listIterator();
433: while (it.hasNext()) {
434: Element menuElement = (Element) it.next();
435: if (menuElement.getName().equals(MenuXMLDecoder.MENU)) {
436:
437: String menuId = menuElement
438: .getAttributeValue(MenuXMLDecoder.ID);
439:
440: String menuName = mediator.getString("menu",
441: "mainframe", menuId);
442:
443: if (menubar.exists(menuId)) {
444: // extend existing menu
445: ExtendableMenu menu = menubar.getMenu(menuId);
446: extendMenu(menubar, menu, menuElement,
447: placeholderId);
448: } else {
449: // create new menu
450: ExtendableMenu menu = new ExtendableMenu(menuId,
451: menuName);
452: parseMenu(menu, menuElement);
453: parentMenu.insert(menu, placeholderId);
454: }
455:
456: } else if (menuElement.getName().equals(
457: MenuXMLDecoder.MENUITEM)) {
458: String id = menuElement
459: .getAttributeValue(MenuXMLDecoder.ID);
460: AbstractColumbaAction action = getAction(id, mediator);
461: if (action == null)
462: continue;
463:
464: CMenuItem menuItem = new CMenuItem(action);
465: menuItem.addMouseListener(mediator
466: .getMouseTooltipHandler());
467: parentMenu.insert(menuItem, placeholderId);
468: } else if (menuElement.getName().equals(
469: MenuXMLDecoder.CHECKBOXMENUITEM)) {
470: String id = menuElement
471: .getAttributeValue(MenuXMLDecoder.ID);
472: AbstractSelectableAction action = (AbstractSelectableAction) getAction(
473: id, mediator);
474: if (action == null)
475: continue;
476: CCheckBoxMenuItem menuItem = new CCheckBoxMenuItem(
477: action);
478: menuItem.addMouseListener(mediator
479: .getMouseTooltipHandler());
480: parentMenu.insert(menuItem, placeholderId);
481: } else if (menuElement.getName().equals(
482: MenuXMLDecoder.RADIOBUTTONMENUITEM)) {
483: String id = menuElement
484: .getAttributeValue(MenuXMLDecoder.ID);
485: AbstractColumbaAction action = getAction(id, mediator);
486: if (action == null)
487: continue;
488: JRadioButtonMenuItem menuItem = new JRadioButtonMenuItem(
489: action);
490: menuItem.addMouseListener(mediator
491: .getMouseTooltipHandler());
492: parentMenu.insert(menuItem, placeholderId);
493: } else if (menuElement.getName().equals(
494: MenuXMLDecoder.SEPARATOR)) {
495: parentMenu.insertSeparator(placeholderId);
496: } else if (menuElement.getName().equals(
497: MenuXMLDecoder.IMENU)) {
498: String id = menuElement
499: .getAttributeValue(MenuXMLDecoder.ID);
500: IMenu imenu;
501: try {
502: imenu = getIMenu(id, mediator);
503: if (imenu == null)
504: continue;
505: parentMenu.insert(imenu, placeholderId);
506: } catch (Exception e) {
507: LOG.severe(e.getMessage());
508: if (Logging.DEBUG)
509: e.printStackTrace();
510: }
511: } else if (menuElement.getName().equals(
512: MenuXMLDecoder.PLACEHOLDER)) {
513: String id = menuElement
514: .getAttributeValue(MenuXMLDecoder.ID);
515: parentMenu.insertPlaceholder(id, placeholderId);
516: }
517: }
518: }
519: }
|