View Javadoc

1   /*
2    * Copyright 2004-2008 the Seasar Foundation and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.seasar.uruma.rcp.configuration.extension;
17  
18  import java.util.List;
19  
20  import org.seasar.framework.util.StringUtil;
21  import org.seasar.uruma.component.UIComponentContainer;
22  import org.seasar.uruma.component.UIElement;
23  import org.seasar.uruma.component.jface.MenuComponent;
24  import org.seasar.uruma.component.jface.MenuItemComponent;
25  import org.seasar.uruma.component.jface.SeparatorComponent;
26  import org.seasar.uruma.component.rcp.ViewPartComponent;
27  import org.seasar.uruma.component.rcp.WorkbenchComponent;
28  import org.seasar.uruma.core.UrumaConstants;
29  import org.seasar.uruma.rcp.binding.CommandDesc;
30  import org.seasar.uruma.rcp.binding.CommandRegistry;
31  import org.seasar.uruma.rcp.configuration.ConfigurationElement;
32  import org.seasar.uruma.rcp.configuration.Extension;
33  import org.seasar.uruma.rcp.configuration.ExtensionBuilder;
34  import org.seasar.uruma.rcp.configuration.ExtensionFactory;
35  import org.seasar.uruma.rcp.configuration.ExtensionPoints;
36  import org.seasar.uruma.rcp.configuration.elements.CategoryElement;
37  import org.seasar.uruma.rcp.configuration.elements.CommandElement;
38  import org.seasar.uruma.rcp.configuration.elements.ContextElement;
39  import org.seasar.uruma.rcp.configuration.elements.KeyElement;
40  import org.seasar.uruma.rcp.configuration.elements.MenuCommandElement;
41  import org.seasar.uruma.rcp.configuration.elements.MenuContributionElement;
42  import org.seasar.uruma.rcp.configuration.elements.MenuElement;
43  import org.seasar.uruma.rcp.configuration.elements.SchemeElement;
44  import org.seasar.uruma.rcp.configuration.elements.SeparatorElement;
45  import org.seasar.uruma.rcp.configuration.elements.ToolbarElement;
46  import org.seasar.uruma.rcp.util.UrumaServiceUtil;
47  import org.seasar.uruma.util.MnemonicUtil;
48  
49  /**
50   * <code>menus</code> 拡張ポイントを生成するための {@link ExtensionBuilder} です。<br />
51   * 
52   * @author y-komori
53   * @author y.sugigami
54   */
55  public class MenusBuilder extends AbstractExtensionBuilder implements
56          UrumaConstants {
57  
58      /**
59       * コンテクスト ID のサフィックスです。<br />
60       */
61      public static final String CONTEXT_SUFFIX = ".context";
62  
63      /**
64       * デフォルトのコマンド ID サフィックスです。<br />
65       */
66      public static final String DEFAULT_COMMAND_ID_SUFFIX = ".command.";
67  
68      /**
69       * デフォルトのメニュー ID サフィックスです。<br />
70       */
71      public static final String DEFAULT_MENUS_ID_SUFFIX = ".menus.";
72  
73      /**
74       * デフォルトのカテゴリ ID サフィックスです。<br />
75       */
76      public static String DEFAULT_CATEGORY_ID_SUFFIX = ".command.category";
77  
78      /**
79       * デフォルトの親コンテクストIDです。<br />
80       */
81      public static String DEFAULT_CONTEXT_PARENT_ID = "org.eclipse.ui.contexts.window";
82  
83      /**
84       * デフォルトのメニューURIです。<br />
85       */
86      protected static final String DEFAULT_MENU_URI = "menu:org.eclipse.ui.main.menu?after=additions";
87  
88      /**
89       * デフォルトのツールバーURIです。<br />
90       */
91      protected static final String DEFAULT_TOOLBAR_URI = "toolbar:org.eclipse.ui.main.toolbar?after=additions";
92  
93      /**
94       * デフォルトのポップアップURIです。<br />
95       */
96      protected static final String DEFAULT_POPUP_URI = "popup:org.eclipse.ui.popup.any?after=additions";
97  
98      protected int actionCount;
99  
100     protected Extension contexts;
101 
102     protected Extension commands;
103 
104     protected Extension handlers;
105 
106     protected Extension bindings;
107 
108     protected Extension menus;
109 
110     protected Extension definitions;
111 
112     protected CommandRegistry commandRegistry;
113 
114     protected String localContextId;
115 
116     /*
117      * @see org.seasar.uruma.rcp.configuration.ExtensionBuilder#buildExtension()
118      */
119     public Extension[] buildExtension() {
120         this.commandRegistry = service.getCommandRegistry();
121 
122         createExtensions();
123 
124         setupScheme();
125         setupContexts();
126 
127         MenuContributionElement menuContribution = setupMenuContribution();
128         MenuContributionElement popupContribution = setupPopupContribution();
129         MenuContributionElement toolbarContribution = setupToolbarContribution();
130 
131         CategoryElement category = setupCategory();
132 
133         WorkbenchComponent workbenchComponent = service.getWorkbenchComponent();
134         for (MenuComponent menu : workbenchComponent.getMenus()) {
135             traverseMenu(category, menu, null, menuContribution);
136             traverseToolbar(category, menu, null, toolbarContribution);
137         }
138 
139         for (ViewPartComponent view : service.getViewPartComponent()) {
140             // For View Menu And Toolbar
141             MenuContributionElement viewMenuContribution = setupViewMenuContribution(view);
142             MenuContributionElement viewToolbarContribution = setupViewToolbarContribution(view);
143             if (!StringUtil.isEmpty(view.menu)) {
144                 for (MenuComponent menu : view.getMenus()) {
145                     if (view.menu.equals(menu.getId())) {
146                         traverseMenu(category, menu, null, viewMenuContribution);
147                         traverseToolbar(category, menu, null,
148                                 viewToolbarContribution);
149                     }
150                 }
151             }
152 
153             for (MenuComponent menu : view.getMenus()) {
154                 // For Control Popup Menu
155                 // visitForMenuSearch(category, menu, popupContribution);
156             }
157         }
158         return new Extension[] { contexts, commands, handlers, bindings, menus,
159                 definitions };
160 
161     }
162 
163     private void visitForMenuSearch(final CategoryElement category,
164             final UIElement element,
165             final MenuContributionElement popupContribution) {
166         if (element instanceof UIComponentContainer) {
167             UIComponentContainer uiCC = (UIComponentContainer) element;
168 
169             if (element instanceof MenuComponent) {
170                 traverseMenu(category, (MenuComponent) element, null,
171                         popupContribution);
172             } else {
173                 for (UIElement child : uiCC.getChildren()) {
174                     visitForMenuSearch(category, child, popupContribution);
175                 }
176             }
177         }
178     }
179 
180     protected void createExtensions() {
181         contexts = ExtensionFactory.createExtension(ExtensionPoints.CONTEXTS);
182         commands = ExtensionFactory.createExtension(ExtensionPoints.COMMANDS);
183         handlers = ExtensionFactory.createExtension(ExtensionPoints.HANDLERS);
184         bindings = ExtensionFactory.createExtension(ExtensionPoints.BINDINGS);
185         menus = ExtensionFactory.createExtension(ExtensionPoints.MENUS);
186         definitions = ExtensionFactory
187                 .createExtension(ExtensionPoints.DEFINITIONS);
188     }
189 
190     protected void setupScheme() {
191         SchemeElement scheme = new SchemeElement(URUMA_APP_SCHEME_ID,
192                 URUMA_APP_SCHEME_NAME);
193         bindings.addElement(scheme);
194     }
195 
196     protected CategoryElement setupCategory() {
197         String pluginId = service.getPluginId();
198         CategoryElement category = new CategoryElement(pluginId
199                 + DEFAULT_CATEGORY_ID_SUFFIX, pluginId);
200         commands.addElement(category);
201         return category;
202     }
203 
204     protected MenuContributionElement setupMenuContribution() {
205         MenuContributionElement menuContribution = new MenuContributionElement();
206         menuContribution.locationURI = DEFAULT_MENU_URI;
207         this.menus.addElement(menuContribution);
208         return menuContribution;
209     }
210 
211     protected MenuContributionElement setupPopupContribution() {
212         MenuContributionElement menuContribution = new MenuContributionElement();
213         menuContribution.locationURI = DEFAULT_POPUP_URI;
214         this.menus.addElement(menuContribution);
215         return menuContribution;
216     }
217 
218     protected MenuContributionElement setupToolbarContribution() {
219         MenuContributionElement menuContribution = new MenuContributionElement();
220         menuContribution.locationURI = DEFAULT_TOOLBAR_URI;
221         this.menus.addElement(menuContribution);
222         return menuContribution;
223     }
224 
225     protected MenuContributionElement setupViewToolbarContribution(
226             final ViewPartComponent view) {
227         MenuContributionElement menuContribution = new MenuContributionElement();
228         menuContribution.locationURI = "toolbar:"
229                 + service.createRcpId(view.getId()) + "?after=additions";
230         this.menus.addElement(menuContribution);
231         return menuContribution;
232     }
233 
234     protected MenuContributionElement setupViewMenuContribution(
235             final ViewPartComponent view) {
236         MenuContributionElement menuContribution = new MenuContributionElement();
237         menuContribution.locationURI = "menu:"
238                 + service.createRcpId(view.getId()) + "?after=additions";
239         this.menus.addElement(menuContribution);
240         return menuContribution;
241     }
242 
243     protected void traverseMenu(final CategoryElement category,
244             final MenuComponent menuComponent,
245             final MenuElement parentMenuElement,
246             final MenuContributionElement menuContribution) {
247         List<UIElement> children = menuComponent.getChildren();
248         for (UIElement child : children) {
249             if (child instanceof MenuComponent) {
250                 MenuElement menuElement;
251                 if (DEFAULT_MENU_URI.equals(menuContribution.locationURI)
252                         || DEFAULT_POPUP_URI
253                                 .equals(menuContribution.locationURI)) {
254                     menuElement = setupMenu((MenuComponent) child,
255                             parentMenuElement, menuContribution);
256                 } else {
257                     menuElement = parentMenuElement;
258                 }
259                 traverseMenu(category, (MenuComponent) child, menuElement,
260                         menuContribution);
261             } else if (child instanceof SeparatorComponent) {
262                 SeparatorComponent separator = (SeparatorComponent) child;
263                 setupSeparator(separator, parentMenuElement, menuContribution);
264 
265             } else if (child instanceof SeparatorComponent) {
266                 SeparatorComponent separator = (SeparatorComponent) child;
267                 setupSeparator(separator, parentMenuElement, menuContribution);
268 
269             } else if (child instanceof MenuItemComponent) {
270                 MenuItemComponent menuItem = (MenuItemComponent) child;
271                 String commandId = createCommandId(menuItem);
272 
273                 setupCommand(category, commandId, menuItem);
274                 setupKey(commandId, menuItem);
275                 setupMenuCommand(commandId, menuItem, parentMenuElement,
276                         menuContribution);
277             }
278         }
279     }
280 
281     protected void traverseToolbar(final CategoryElement category,
282             final MenuComponent menuComponent,
283             final ToolbarElement parentToolbarElement,
284             final MenuContributionElement menuContribution) {
285         List<UIElement> children = menuComponent.getChildren();
286         for (UIElement child : children) {
287             if (child instanceof MenuComponent) {
288                 ToolbarElement toolbarElement;
289                 if (DEFAULT_TOOLBAR_URI.equals(menuContribution.locationURI)) {
290                     // Workbench Toolbar
291                     toolbarElement = setupToolbar((MenuComponent) child,
292                             parentToolbarElement, menuContribution);
293                 } else {
294                     // View Toolbar
295                     toolbarElement = parentToolbarElement;
296                 }
297                 traverseToolbar(category, (MenuComponent) child,
298                         toolbarElement, menuContribution);
299 
300             } else if (child instanceof SeparatorComponent) {
301                 // Do noting
302 
303             } else if (child instanceof MenuItemComponent) {
304                 MenuItemComponent menuItem = (MenuItemComponent) child;
305                 String commandId = createCommandId(menuItem);
306 
307                 setupCommand(category, commandId, menuItem);
308                 setupKey(commandId, menuItem);
309                 setupToolbarCommand(commandId, menuItem, parentToolbarElement,
310                         menuContribution);
311             }
312         }
313     }
314 
315     protected MenuElement setupMenu(final MenuComponent component,
316             final MenuElement parentElement,
317             final MenuContributionElement menuContribution) {
318         if (!(component.getParent() instanceof WorkbenchComponent)) {
319             String text = component.text;
320             if (text == null) {
321                 text = NULL_STRING;
322             }
323             MenuElement menu = new MenuElement(MnemonicUtil
324                     .chopMnemonicAndAccelerator(text));
325             if (!StringUtil.isEmpty(component.getId())) {
326                 menu.id = service.createRcpId(component.getId());
327             }
328 
329             if (!StringUtil.isEmpty(text)) {
330                 menu.mnemonic = MnemonicUtil.getMnemonic(text);
331             }
332 
333             if (!StringUtil.isEmpty(component.image)) {
334                 menu.icon = getRcpImagePath(component.image);
335             }
336 
337             if (parentElement == null) {
338                 // トップレベルメニューの場合
339                 menuContribution.addElement(menu);
340             } else {
341                 // サブメニューの場合
342                 parentElement.addElement(menu);
343             }
344 
345             return menu;
346         } else {
347             return null;
348         }
349     }
350 
351     protected ToolbarElement setupToolbar(final MenuComponent component,
352             final ToolbarElement parentElement,
353             final MenuContributionElement menuContribution) {
354         if (!(component.getParent() instanceof WorkbenchComponent)) {
355             String id = service.getPluginId() + ".toolbar." + component.text;
356             ToolbarElement toolbar = new ToolbarElement(id);
357 
358             if (parentElement == null) {
359                 // トップレベルメニューの場合
360                 menuContribution.addElement(toolbar);
361             } else {
362                 // サブメニューの場合
363                 parentElement.addElement(toolbar);
364             }
365             return toolbar;
366         } else {
367             return null;
368         }
369     }
370 
371     protected String createCommandId(final MenuItemComponent menuItem) {
372         String id = menuItem.getId();
373         if (StringUtil.isEmpty(id)) {
374             id = AUTO_ACTION_ID_PREFIX + actionCount++;
375             menuItem.setId(id);
376         }
377         id = service.getPluginId() + DEFAULT_COMMAND_ID_SUFFIX + id;
378         return id;
379     }
380 
381     protected void setupCommand(final CategoryElement category,
382             final String commandId, final MenuItemComponent component) {
383         if (component instanceof SeparatorComponent) {
384             return;
385         }
386 
387         for (ConfigurationElement ce : commands.getElements()) {
388             if (ce instanceof CommandElement) {
389                 CommandElement existCommandElement = (CommandElement) ce;
390                 if (existCommandElement.id.equals(commandId)) {
391                     return;
392                 }
393             }
394         }
395 
396         String name = MnemonicUtil.chopMnemonicAndAccelerator(component.text);
397 
398         CommandElement command = new CommandElement(commandId, name);
399         command.categoryId = category.id;
400         commands.addElement(command);
401 
402         CommandDesc desc = new CommandDesc(commandId, component.getId());
403         commandRegistry.registerCommandDesc(desc);
404     }
405 
406     protected void setupContexts() {
407         this.localContextId = UrumaServiceUtil.getService().getPluginId()
408                 + CONTEXT_SUFFIX;
409         ContextElement context = new ContextElement(localContextId,
410                 "Uruma allication local context", DEFAULT_CONTEXT_PARENT_ID);
411         contexts.addElement(context);
412     }
413 
414     protected void setupKey(final String commandId,
415             final MenuItemComponent menuItem) {
416         if (!StringUtil.isEmpty(menuItem.accelerator)) {
417             for (ConfigurationElement ce : bindings.getElements()) {
418                 if (ce instanceof KeyElement) {
419                     KeyElement existKeyElement = (KeyElement) ce;
420                     if (existKeyElement.commandId.equals(commandId)) {
421                         return;
422                     }
423                 }
424             }
425 
426             String sequence = menuItem.accelerator;
427             KeyElement key = new KeyElement(sequence, URUMA_APP_SCHEME_ID,
428                     DEFAULT_CONTEXT_PARENT_ID);
429             key.commandId = commandId;
430             // key.contextId = localContextId;
431 
432             bindings.addElement(key);
433         }
434     }
435 
436     protected void setupMenuCommand(final String commandId,
437             final MenuItemComponent menuItem,
438             final MenuElement parentMenuElement,
439             final MenuContributionElement menuContribution) {
440         MenuCommandElement command = new MenuCommandElement(commandId);
441         if (!StringUtil.isEmpty(menuItem.text)) {
442             command.mnemonic = MnemonicUtil.getMnemonic(menuItem.text);
443         }
444 
445         command.icon = getRcpImagePath(menuItem.image);
446         command.disabledIcon = getRcpImagePath(menuItem.disabledImage);
447         command.hoverIcon = getRcpImagePath(menuItem.hoverImage);
448         command.style = parseStyle(menuItem.getStyle());
449 
450         if (parentMenuElement == null) {
451             menuContribution.addElement(command);
452         } else {
453             parentMenuElement.addElement(command);
454         }
455 
456     }
457 
458     protected void setupToolbarCommand(final String commandId,
459             final MenuItemComponent menuItem,
460             final ToolbarElement parentToolbarElement,
461             final MenuContributionElement menuContribution) {
462         MenuCommandElement command = new MenuCommandElement(commandId);
463         if (!StringUtil.isEmpty(menuItem.text)) {
464             command.mnemonic = MnemonicUtil.getMnemonic(menuItem.text);
465         }
466 
467         command.icon = getRcpImagePath(menuItem.image);
468         command.disabledIcon = getRcpImagePath(menuItem.disabledImage);
469         command.hoverIcon = getRcpImagePath(menuItem.hoverImage);
470         command.style = parseStyle(menuItem.getStyle());
471 
472         if (parentToolbarElement == null) {
473             menuContribution.addElement(command);
474         } else {
475             parentToolbarElement.addElement(command);
476         }
477     }
478 
479     protected void setupSeparator(final SeparatorComponent separatorComponent,
480             final MenuElement parentMenuElement,
481             final MenuContributionElement menuContribution) {
482         SeparatorElement element = new SeparatorElement("none", true);
483         if (parentMenuElement == null) {
484             menuContribution.addElement(element);
485         } else {
486             parentMenuElement.addElement(element);
487         }
488     }
489 
490     protected String parseStyle(final String style) {
491         if (StringUtil.isEmpty(style)) {
492             return MenuCommandElement.STYLE_PUSH;
493         } else {
494             String result = style.toLowerCase();
495             if ("check".equals(result)) {
496                 return MenuCommandElement.STYLE_TOGGLE;
497             }
498             return result;
499         }
500     }
501 
502 }