| /******************************************************************************* |
| * Copyright (c) 2000, 2020 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Tom Hochstein (Freescale) - Bug 407522 - Perspective reset not working correctly |
| * Lars Vogel <Lars.Vogel@vogella.com> - Bug 422040, 431992, 472654 |
| * Andrey Loskutov <loskutov@gmx.de> - Bug 456729, 404348, 421178, 420956, 424638, 460503 |
| * Rolf Theunissen <rolf.theunissen@gmail.com> - Bug 558765 |
| *******************************************************************************/ |
| package org.eclipse.ui.internal.dialogs.cpd; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import org.eclipse.core.commands.ParameterizedCommand; |
| import org.eclipse.core.commands.common.NotDefinedException; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.e4.core.commands.ECommandService; |
| import org.eclipse.e4.core.contexts.IEclipseContext; |
| import org.eclipse.e4.ui.bindings.EBindingService; |
| import org.eclipse.e4.ui.internal.workbench.OpaqueElementUtil; |
| import org.eclipse.e4.ui.internal.workbench.RenderedElementUtil; |
| import org.eclipse.e4.ui.model.application.MApplication; |
| import org.eclipse.e4.ui.model.application.commands.MParameter; |
| import org.eclipse.e4.ui.model.application.ui.MUIElement; |
| import org.eclipse.e4.ui.model.application.ui.MUILabel; |
| import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar; |
| import org.eclipse.e4.ui.model.application.ui.basic.MTrimElement; |
| import org.eclipse.e4.ui.model.application.ui.menu.MDirectMenuItem; |
| import org.eclipse.e4.ui.model.application.ui.menu.MDynamicMenuContribution; |
| import org.eclipse.e4.ui.model.application.ui.menu.MHandledItem; |
| import org.eclipse.e4.ui.model.application.ui.menu.MHandledMenuItem; |
| import org.eclipse.e4.ui.model.application.ui.menu.MItem; |
| import org.eclipse.e4.ui.model.application.ui.menu.MMenu; |
| import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement; |
| import org.eclipse.e4.ui.model.application.ui.menu.MToolBar; |
| import org.eclipse.e4.ui.model.application.ui.menu.MToolBarElement; |
| import org.eclipse.e4.ui.model.application.ui.menu.MToolBarSeparator; |
| import org.eclipse.e4.ui.workbench.IPresentationEngine; |
| import org.eclipse.e4.ui.workbench.IResourceUtilities; |
| import org.eclipse.e4.ui.workbench.renderers.swt.MenuManagerRenderer; |
| import org.eclipse.e4.ui.workbench.renderers.swt.ToolBarManagerRenderer; |
| import org.eclipse.e4.ui.workbench.swt.util.ISWTResourceUtilities; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.jface.action.ActionContributionItem; |
| import org.eclipse.jface.action.ContributionItem; |
| import org.eclipse.jface.action.IAction; |
| import org.eclipse.jface.action.IContributionItem; |
| import org.eclipse.jface.action.IContributionManager; |
| import org.eclipse.jface.action.IMenuManager; |
| import org.eclipse.jface.action.LegacyActionTools; |
| import org.eclipse.jface.action.MenuManager; |
| import org.eclipse.jface.action.SubContributionItem; |
| import org.eclipse.jface.action.SubMenuManager; |
| import org.eclipse.jface.action.ToolBarManager; |
| import org.eclipse.jface.bindings.TriggerSequence; |
| import org.eclipse.jface.dialogs.IDialogConstants; |
| import org.eclipse.jface.dialogs.TrayDialog; |
| import org.eclipse.jface.internal.provisional.action.ToolBarContributionItem2; |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.jface.viewers.AbstractTreeViewer; |
| import org.eclipse.jface.viewers.ArrayContentProvider; |
| import org.eclipse.jface.viewers.CheckboxTableViewer; |
| import org.eclipse.jface.viewers.CheckboxTreeViewer; |
| import org.eclipse.jface.viewers.ComboViewer; |
| import org.eclipse.jface.viewers.ICheckStateListener; |
| import org.eclipse.jface.viewers.ICheckStateProvider; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.StructuredSelection; |
| import org.eclipse.jface.viewers.StructuredViewer; |
| import org.eclipse.jface.viewers.TableViewer; |
| import org.eclipse.jface.viewers.TreeViewer; |
| import org.eclipse.jface.viewers.Viewer; |
| import org.eclipse.jface.viewers.ViewerFilter; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.SashForm; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Combo; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.MenuItem; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.swt.widgets.TabFolder; |
| import org.eclipse.swt.widgets.TabItem; |
| import org.eclipse.swt.widgets.Table; |
| import org.eclipse.swt.widgets.TableColumn; |
| import org.eclipse.swt.widgets.ToolItem; |
| import org.eclipse.swt.widgets.Tree; |
| import org.eclipse.ui.IPerspectiveDescriptor; |
| import org.eclipse.ui.IPerspectiveRegistry; |
| import org.eclipse.ui.IWorkbenchCommandConstants; |
| import org.eclipse.ui.IWorkbenchWindow; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.actions.ActionFactory; |
| import org.eclipse.ui.actions.OpenPerspectiveAction; |
| import org.eclipse.ui.activities.WorkbenchActivityHelper; |
| import org.eclipse.ui.application.ActionBarAdvisor; |
| import org.eclipse.ui.application.IWorkbenchWindowConfigurer; |
| import org.eclipse.ui.internal.ActionSetActionBars; |
| import org.eclipse.ui.internal.ActionSetContributionItem; |
| import org.eclipse.ui.internal.ActionSetMenuManager; |
| import org.eclipse.ui.internal.CoolBarToTrimManager; |
| import org.eclipse.ui.internal.IWorkbenchHelpContextIds; |
| import org.eclipse.ui.internal.Perspective; |
| import org.eclipse.ui.internal.PluginActionCoolBarContributionItem; |
| import org.eclipse.ui.internal.PluginActionSet; |
| import org.eclipse.ui.internal.PluginActionSetBuilder; |
| import org.eclipse.ui.internal.WorkbenchMessages; |
| import org.eclipse.ui.internal.WorkbenchPage; |
| import org.eclipse.ui.internal.WorkbenchPlugin; |
| import org.eclipse.ui.internal.WorkbenchWindow; |
| import org.eclipse.ui.internal.actions.NewWizardShortcutAction; |
| import org.eclipse.ui.internal.dialogs.WorkbenchWizardElement; |
| import org.eclipse.ui.internal.dialogs.cpd.TreeManager.TreeItem; |
| import org.eclipse.ui.internal.e4.compatibility.ModeledPageLayout; |
| import org.eclipse.ui.internal.intro.IIntroConstants; |
| import org.eclipse.ui.internal.registry.ActionSetDescriptor; |
| import org.eclipse.ui.internal.registry.ActionSetRegistry; |
| import org.eclipse.ui.internal.registry.IActionSetDescriptor; |
| import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants; |
| import org.eclipse.ui.internal.util.BundleUtility; |
| import org.eclipse.ui.menus.CommandContributionItem; |
| import org.eclipse.ui.menus.CommandContributionItemParameter; |
| import org.eclipse.ui.model.WorkbenchViewerComparator; |
| import org.eclipse.ui.part.PageBook; |
| import org.eclipse.ui.views.IViewCategory; |
| import org.eclipse.ui.views.IViewDescriptor; |
| import org.eclipse.ui.views.IViewRegistry; |
| import org.eclipse.ui.wizards.IWizardCategory; |
| import org.eclipse.ui.wizards.IWizardDescriptor; |
| |
| /** |
| * Dialog to allow users the ability to customize the perspective. This includes |
| * customizing menus and toolbars by adding, removing, or re-arranging commands |
| * or groups of commands. |
| * |
| */ |
| public class CustomizePerspectiveDialog extends TrayDialog { |
| |
| /** |
| * Flag showing that we have initialized all legacy action sets for given window |
| */ |
| private static final String ALL_SETS_INITIALIZED = "ALL_SETS_INITIALIZED"; //$NON-NLS-1$ |
| private static final String TOOLBAR_ICON = "$nl$/icons/full/obj16/toolbar.png"; //$NON-NLS-1$ |
| private static final String SUBMENU_ICON = "$nl$/icons/full/obj16/submenu.png"; //$NON-NLS-1$ |
| private static final String MENU_ICON = "$nl$/icons/full/obj16/menu.png"; //$NON-NLS-1$ |
| private static final String WARNING_ICON = "$nl$/icons/full/obj16/warn_tsk.png"; //$NON-NLS-1$ |
| |
| private static final String SHORTCUT_CONTRIBUTION_ITEM_ID_OPEN_PERSPECTIVE = "openPerspective"; //$NON-NLS-1$ |
| private static final String SHORTCUT_CONTRIBUTION_ITEM_ID_SHOW_VIEW = "showView"; //$NON-NLS-1$ |
| |
| static final String KEYS_PREFERENCE_PAGE_ID = "org.eclipse.ui.preferencePages.Keys"; //$NON-NLS-1$ |
| |
| static final String NEW_LINE = System.lineSeparator(); |
| |
| static final int MIN_TOOLTIP_WIDTH = 160; |
| |
| WorkbenchWindow window; |
| |
| private WorkbenchPage windowPage; |
| |
| private Perspective perspective; |
| |
| private TabFolder tabFolder; |
| |
| private static final int TAB_WIDTH_IN_DLUS = 490; |
| |
| private static final int TAB_HEIGHT_IN_DLUS = 230; |
| |
| private final String shortcutMenuColumnHeaders[] = { WorkbenchMessages.ActionSetSelection_menuColumnHeader, |
| WorkbenchMessages.ActionSetSelection_descriptionColumnHeader }; |
| |
| private int[] shortcutMenuColumnWidths = { 125, 300 }; |
| |
| ImageDescriptor menuImageDescriptor; |
| |
| ImageDescriptor submenuImageDescriptor; |
| |
| ImageDescriptor toolbarImageDescriptor; |
| |
| ImageDescriptor warningImageDescriptor; |
| |
| private TreeManager treeManager; |
| |
| private DisplayItem menuItems; |
| |
| private DisplayItem toolBarItems; |
| |
| private Category shortcuts; |
| |
| private DisplayItem wizards; |
| |
| private DisplayItem perspectives; |
| |
| private DisplayItem views; |
| |
| Map<String, ActionSet> idToActionSet = new HashMap<>(); |
| |
| private final List<ActionSet> actionSets = new ArrayList<>(); |
| |
| private IWorkbenchWindowConfigurer configurer; |
| |
| private TabItem actionSetTab; |
| |
| private CheckboxTableViewer actionSetAvailabilityTable; |
| |
| private TreeViewer actionSetMenuViewer; |
| |
| private TreeViewer actionSetToolbarViewer; |
| |
| private CheckboxTreeViewer menuStructureViewer1; |
| |
| private CheckboxTreeViewer menuStructureViewer2; |
| |
| private CheckboxTreeViewer toolbarStructureViewer1; |
| |
| private CheckboxTreeViewer toolbarStructureViewer2; |
| |
| private CustomizeActionBars customizeActionBars; |
| |
| private MenuManagerRenderer menuMngrRenderer; |
| private ToolBarManagerRenderer toolbarMngrRenderer; |
| |
| private ISWTResourceUtilities resUtils; |
| private IEclipseContext context; |
| |
| /** |
| * Represents a menu item or a toolbar item. |
| * |
| * @since 3.5 |
| */ |
| class DisplayItem extends TreeItem { |
| /** The logic item represented */ |
| private IContributionItem item; |
| |
| /** The action set this item belongs to (optional) */ |
| ActionSet actionSet; |
| |
| public DisplayItem(String label, IContributionItem item) { |
| treeManager.super(label == null ? null : LegacyActionTools.removeMnemonics(removeShortcut(label))); |
| this.item = item; |
| } |
| |
| public void setActionSet(ActionSet actionSet) { |
| this.actionSet = actionSet; |
| if (actionSet != null) { |
| actionSet.addItem(this); |
| } |
| } |
| |
| public ActionSet getActionSet() { |
| return actionSet; |
| } |
| |
| public IContributionItem getIContributionItem() { |
| return item; |
| } |
| |
| @Override |
| public String toString() { |
| return super.toString() + (item == null ? "" : (" [" + item.getId() + "]")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| } |
| } |
| |
| /** |
| * Represents a menu item whose content is dynamic. Contains a list of the |
| * current items being displayed. |
| * |
| * @since 3.5 |
| */ |
| class DynamicContributionItem extends DisplayItem { |
| private List<MenuItem> preview; |
| |
| public DynamicContributionItem(String label, IContributionItem item) { |
| super(WorkbenchMessages.HideItems_dynamicItemName + " - " + label, item); //$NON-NLS-1$ |
| preview = new ArrayList<>(); |
| } |
| |
| public DynamicContributionItem(IContributionItem item) { |
| super(WorkbenchMessages.HideItems_dynamicItemName, item); |
| preview = new ArrayList<>(); |
| } |
| |
| public void addCurrentItem(MenuItem item) { |
| preview.add(item); |
| } |
| |
| public List<MenuItem> getCurrentItems() { |
| return preview; |
| } |
| } |
| |
| /** |
| * @param descriptor |
| * @param window |
| * @return the appropriate {@link IContributionItem} for the given wizard |
| */ |
| private static ActionContributionItem getIContributionItem(IWizardDescriptor descriptor, IWorkbenchWindow window) { |
| IAction action = new NewWizardShortcutAction(window, descriptor); |
| return new ActionContributionItem(action); |
| } |
| |
| /** |
| * @param descriptor |
| * @param window |
| * @return the appropriate {@link IContributionItem} for the given perspective |
| */ |
| private static ActionContributionItem getIContributionItem(IPerspectiveDescriptor descriptor, |
| IWorkbenchWindow window) { |
| IAction action = new OpenPerspectiveAction(window, descriptor, null); |
| return new ActionContributionItem(action); |
| } |
| |
| /** |
| * @param window |
| * @return the appropriate {@link IContributionItem} for showing views |
| */ |
| private static ActionContributionItem getIContributionItem(IWorkbenchWindow window) { |
| IAction action = ActionFactory.SHOW_VIEW_MENU.create(window); |
| return new ActionContributionItem(action); |
| } |
| |
| /** |
| * Represents a menu item which needs to be shown in the Shortcuts tab. |
| * |
| * @since 3.5 |
| */ |
| class ShortcutItem extends DisplayItem { |
| /** The description to show in the table */ |
| private String description; |
| |
| /** The category this shortcut is in (should be set) */ |
| private Category category; |
| |
| private Object descriptor; |
| |
| public ShortcutItem(String label, IWizardDescriptor descriptor) { |
| super(label, CustomizePerspectiveDialog.getIContributionItem(descriptor, window)); |
| this.descriptor = descriptor; |
| } |
| |
| public ShortcutItem(String label, IPerspectiveDescriptor descriptor) { |
| super(label, CustomizePerspectiveDialog.getIContributionItem(descriptor, window)); |
| this.descriptor = descriptor; |
| } |
| |
| public ShortcutItem(String label, IViewDescriptor descriptor) { |
| super(label, CustomizePerspectiveDialog.getIContributionItem(window)); |
| this.descriptor = descriptor; |
| } |
| |
| public Object getDescriptor() { |
| return descriptor; |
| } |
| |
| public void setDescription(String description) { |
| this.description = description; |
| } |
| |
| public String getDescription() { |
| return description; |
| } |
| |
| public void setCategory(Category category) { |
| this.category = category; |
| } |
| |
| public Category getCategory() { |
| return category; |
| } |
| } |
| |
| /** |
| * Represents a category in the shortcuts menu. Since categories can have a |
| * tree-structure, the functionality provided by the TreeManager and TreeItem |
| * classes is used, however the logic for visibility changes and gray states is |
| * more sophisticated. |
| * |
| * @since 3.5 |
| */ |
| class Category extends TreeItem { |
| |
| /** ShortcutItems which are contributed in this Category */ |
| private List<ShortcutItem> contributionItems; |
| |
| public Category(String label) { |
| treeManager.super(label == null ? null : LegacyActionTools.removeMnemonics(removeShortcut(label))); |
| this.contributionItems = new ArrayList<>(); |
| } |
| |
| public List<ShortcutItem> getContributionItems() { |
| return contributionItems; |
| } |
| |
| /** |
| * Adds another ShortcutItem to this Category's list of ShortcutItems and |
| * creates a pseudo-child/parent relationship. |
| * |
| * @param item the item to add |
| */ |
| public void addShortcutItem(ShortcutItem item) { |
| contributionItems.add(item); |
| item.setCategory(this); |
| } |
| |
| /** |
| * While the child/parent state in the Category hierarchy is automatically |
| * maintained, the pseudo-child/parent relationship must be explicitly updated. |
| * This method will update Categories if their states need to change as a result |
| * of their ShortcutItems. |
| */ |
| public void update() { |
| for (ShortcutItem shortcutItem : contributionItems) { |
| DisplayItem item = shortcutItem; |
| if (item.getState()) { |
| this.setCheckState(true); |
| return; |
| } |
| } |
| |
| this.setCheckState(false); |
| } |
| |
| /** |
| * Changes the state of all pseudo-descendant ShortcutItems, causing the |
| * effective state of this Category and all its sub-Categories to match. |
| * |
| * @param state The state to set this branch to. |
| */ |
| public void setItemsState(boolean state) { |
| for (ShortcutItem shortcutItem : contributionItems) { |
| shortcutItem.setCheckState(state); |
| } |
| |
| for (Object o : getChildren()) { |
| Category category = (Category) o; |
| category.setItemsState(state); |
| } |
| } |
| } |
| |
| /** |
| * Represents an action set, under which ContributionItems exist. There is no |
| * inherent hierarchy in action sets - they exist independent of one another, |
| * simply contribution menu items and toolbar items. |
| * |
| * @since 3.5 |
| */ |
| class ActionSet { |
| /** The descriptor which describes the action set represented */ |
| ActionSetDescriptor descriptor; |
| |
| /** ContributionItems contributed by this action set */ |
| private List<DisplayItem> contributionItems; |
| |
| private boolean active; |
| |
| private boolean wasChanged = false; |
| |
| public ActionSet(ActionSetDescriptor descriptor, boolean active) { |
| this.descriptor = descriptor; |
| this.active = active; |
| this.contributionItems = new ArrayList<>(); |
| } |
| |
| public void addItem(DisplayItem item) { |
| contributionItems.add(item); |
| } |
| |
| @Override |
| public String toString() { |
| return descriptor.getLabel(); |
| } |
| |
| public boolean isActive() { |
| return active; |
| } |
| |
| public boolean wasChanged() { |
| return wasChanged; |
| } |
| |
| public void setActive(boolean active) { |
| boolean wasActive = this.active; |
| this.active = active; |
| if (!active) { |
| for (DisplayItem item : contributionItems) { |
| item.setCheckState(false); |
| } |
| } |
| if (wasActive != active) { |
| actionSetAvailabilityChanged(); |
| } |
| |
| wasChanged = true; |
| } |
| } |
| |
| /** |
| * Create an instance of this Dialog. |
| * |
| * @param configurer the configurer |
| * @param persp the perspective |
| * @param context The runtime context for this window |
| */ |
| public CustomizePerspectiveDialog(IWorkbenchWindowConfigurer configurer, Perspective persp, |
| IEclipseContext context) { |
| super(configurer.getWindow().getShell()); |
| this.treeManager = new TreeManager(); |
| this.configurer = configurer; |
| this.context = context; |
| perspective = persp; |
| window = (WorkbenchWindow) configurer.getWindow(); |
| windowPage = (WorkbenchPage) window.getActivePage(); |
| menuMngrRenderer = context.get(MenuManagerRenderer.class); |
| toolbarMngrRenderer = context.get(ToolBarManagerRenderer.class); |
| resUtils = (ISWTResourceUtilities) context.get(IResourceUtilities.class); |
| |
| initializeIcons(); |
| |
| initializeActionSetInput(); |
| loadMenuAndToolbarStructure(); |
| } |
| |
| @Override |
| protected void configureShell(Shell shell) { |
| super.configureShell(shell); |
| String title = perspective.getDesc().getLabel(); |
| |
| title = NLS.bind(WorkbenchMessages.ActionSetSelection_customize, title); |
| shell.setText(title); |
| window.getWorkbench().getHelpSystem().setHelp(shell, IWorkbenchHelpContextIds.ACTION_SET_SELECTION_DIALOG); |
| } |
| |
| @Override |
| protected void createButtonsForButtonBar(Composite parent) { |
| |
| Button okButton = createButton(parent, IDialogConstants.OK_ID, |
| WorkbenchMessages.CustomizePerspectiveDialog_okButtonLabel, true); |
| okButton.setFocus(); |
| |
| createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); |
| } |
| |
| @Override |
| protected Control createDialogArea(Composite parent) { |
| Composite composite = (Composite) super.createDialogArea(parent); |
| |
| // tab folder |
| tabFolder = new TabFolder(composite, SWT.NONE); |
| |
| GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); |
| gd.widthHint = convertHorizontalDLUsToPixels(TAB_WIDTH_IN_DLUS); |
| gd.heightHint = convertVerticalDLUsToPixels(TAB_HEIGHT_IN_DLUS); |
| tabFolder.setLayoutData(gd); |
| |
| // Toolbar Item Hiding Page |
| TabItem tab = new TabItem(tabFolder, SWT.NONE); |
| tab.setText(WorkbenchMessages.HideToolBarItems_toolBarItemsTab); |
| tab.setControl(createToolBarVisibilityPage(tabFolder)); |
| |
| // Menu Item Hiding Page |
| tab = new TabItem(tabFolder, SWT.NONE); |
| tab.setControl(createMenuVisibilityPage(tabFolder)); |
| tab.setText(WorkbenchMessages.HideMenuItems_menuItemsTab); |
| |
| // Action Set Availability Page |
| actionSetTab = new TabItem(tabFolder, SWT.NONE); |
| actionSetTab.setText(WorkbenchMessages.ActionSetSelection_actionSetsTab); |
| actionSetTab.setControl(createActionSetAvailabilityPage(tabFolder)); |
| |
| // Shortcuts Page |
| if (showShortcutTab()) { |
| TabItem item1 = new TabItem(tabFolder, SWT.NONE); |
| item1.setText(WorkbenchMessages.Shortcuts_shortcutTab); |
| item1.setControl(createShortCutsPage(tabFolder)); |
| } |
| |
| applyDialogFont(tabFolder); |
| |
| return composite; |
| } |
| |
| private Composite createShortCutsPage(Composite parent) { |
| GridData data; |
| |
| Composite menusComposite = new Composite(parent, SWT.NONE); |
| GridLayout layout = new GridLayout(); |
| menusComposite.setLayout(layout); |
| |
| // Select... label |
| Label label = new Label(menusComposite, SWT.WRAP); |
| label.setText(NLS.bind(WorkbenchMessages.Shortcuts_selectShortcutsLabel, perspective.getDesc().getLabel())); |
| data = new GridData(SWT.FILL, SWT.CENTER, true, false); |
| label.setLayoutData(data); |
| |
| Label sep = new Label(menusComposite, SWT.HORIZONTAL | SWT.SEPARATOR); |
| sep.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); |
| |
| SashForm sashComposite = new SashForm(menusComposite, SWT.HORIZONTAL); |
| data = new GridData(SWT.FILL, SWT.FILL, true, true); |
| sashComposite.setLayoutData(data); |
| |
| // Menus List |
| Composite menusGroup = new Composite(sashComposite, SWT.NONE); |
| layout = new GridLayout(); |
| layout.marginHeight = 0; |
| layout.marginWidth = 0; |
| menusGroup.setLayout(layout); |
| menusGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); |
| |
| label = new Label(menusGroup, SWT.WRAP); |
| label.setText(WorkbenchMessages.Shortcuts_availableMenus); |
| label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); |
| |
| Combo menusCombo = new Combo(menusGroup, SWT.READ_ONLY); |
| menusCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); |
| ComboViewer menusViewer = new ComboViewer(menusCombo); |
| menusViewer.setContentProvider(TreeManager.getTreeContentProvider()); |
| menusViewer.setLabelProvider(TreeManager.getLabelProvider()); |
| |
| // Categories Tree |
| label = new Label(menusGroup, SWT.WRAP); |
| label.setText(WorkbenchMessages.Shortcuts_availableCategories); |
| label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); |
| |
| final CheckboxTreeViewer menuCategoriesViewer = new CheckboxTreeViewer(menusGroup); |
| menuCategoriesViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); |
| menuCategoriesViewer.setLabelProvider(TreeManager.getLabelProvider()); |
| menuCategoriesViewer.setContentProvider(TreeManager.getTreeContentProvider()); |
| menuCategoriesViewer.setComparator(new WorkbenchViewerComparator()); |
| menuCategoriesViewer.setCheckStateProvider(new CategoryCheckProvider()); |
| menuCategoriesViewer.addCheckStateListener(event -> { |
| Category category = (Category) event.getElement(); |
| category.setItemsState(event.getChecked()); |
| updateCategoryAndParents(menuCategoriesViewer, category); |
| }); |
| |
| treeManager.addListener(changedItem -> { |
| if (changedItem instanceof Category) { |
| menuCategoriesViewer.update(changedItem, null); |
| } else if (changedItem instanceof ShortcutItem) { |
| ShortcutItem item = (ShortcutItem) changedItem; |
| if (item.getCategory() != null) { |
| item.getCategory().update(); |
| updateCategoryAndParents(menuCategoriesViewer, item.getCategory()); |
| } |
| } |
| }); |
| |
| // Menu items list |
| Composite menuItemsGroup = new Composite(sashComposite, SWT.NONE); |
| layout = new GridLayout(); |
| layout.marginHeight = 0; |
| layout.marginWidth = 0; |
| menuItemsGroup.setLayout(layout); |
| menuItemsGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); |
| |
| label = new Label(menuItemsGroup, SWT.WRAP); |
| label.setText(WorkbenchMessages.Shortcuts_allShortcuts); |
| label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); |
| |
| final CheckboxTableViewer menuItemsViewer = CheckboxTableViewer.newCheckList(menuItemsGroup, |
| SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); |
| Table menuTable = menuItemsViewer.getTable(); |
| menuTable.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); |
| menuItemsViewer.setLabelProvider(new ShortcutLabelProvider()); |
| menuItemsViewer.setCheckStateProvider(TreeManager.getCheckStateProvider()); |
| menuItemsViewer.addCheckStateListener(treeManager.getViewerCheckStateListener()); |
| treeManager.getCheckListener(menuItemsViewer); |
| |
| menuItemsViewer.setContentProvider(new TreeManager.TreeItemContentProvider() { |
| @Override |
| public Object[] getChildren(Object parentElement) { |
| if (parentElement instanceof Category) { |
| return ((Category) parentElement).getContributionItems().toArray(); |
| } |
| return super.getChildren(parentElement); |
| } |
| }); |
| menuItemsViewer.setComparator(new WorkbenchViewerComparator()); |
| |
| // update menuCategoriesViewer, and menuItemsViewer on a change to |
| // menusViewer |
| menusViewer.addSelectionChangedListener(event -> { |
| Category category = (Category) event.getStructuredSelection().getFirstElement(); |
| menuCategoriesViewer.setInput(category); |
| menuItemsViewer.setInput(category); |
| if (category.getChildrenCount() != 0) { |
| setSelectionOn(menuCategoriesViewer, category.getChildren().get(0)); |
| } |
| }); |
| |
| // update menuItemsViewer on a change to menuCategoriesViewer |
| menuCategoriesViewer.addSelectionChangedListener(event -> { |
| Category category = (Category) event.getStructuredSelection().getFirstElement(); |
| menuItemsViewer.setInput(category); |
| }); |
| |
| menuTable.setHeaderVisible(true); |
| int[] columnWidths = new int[shortcutMenuColumnWidths.length]; |
| for (int i = 0; i < shortcutMenuColumnWidths.length; i++) { |
| columnWidths[i] = convertHorizontalDLUsToPixels(shortcutMenuColumnWidths[i]); |
| } |
| for (int i = 0; i < shortcutMenuColumnHeaders.length; i++) { |
| TableColumn tc = new TableColumn(menuTable, SWT.NONE, i); |
| tc.setResizable(true); |
| tc.setText(shortcutMenuColumnHeaders[i]); |
| tc.setWidth(columnWidths[i]); |
| } |
| sashComposite.setWeights(new int[] { 30, 70 }); |
| |
| menusViewer.setInput(shortcuts); |
| |
| if (shortcuts.getChildrenCount() > 0) { |
| setSelectionOn(menusViewer, shortcuts.getChildren().get(0)); |
| } |
| |
| return menusComposite; |
| } |
| |
| private Composite createActionSetAvailabilityPage(Composite parent) { |
| GridData data; |
| |
| Composite actionSetsComposite = new Composite(parent, SWT.NONE); |
| GridLayout layout = new GridLayout(); |
| actionSetsComposite.setLayout(layout); |
| |
| // Select... label |
| Label label = new Label(actionSetsComposite, SWT.WRAP); |
| label.setText( |
| NLS.bind(WorkbenchMessages.ActionSetSelection_selectActionSetsLabel, perspective.getDesc().getLabel())); |
| data = new GridData(SWT.FILL, SWT.CENTER, true, false); |
| label.setLayoutData(data); |
| |
| Label sep = new Label(actionSetsComposite, SWT.HORIZONTAL | SWT.SEPARATOR); |
| sep.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); |
| |
| SashForm sashComposite = new SashForm(actionSetsComposite, SWT.HORIZONTAL); |
| data = new GridData(SWT.FILL, SWT.FILL, true, true); |
| sashComposite.setLayoutData(data); |
| |
| // Action Set List Composite |
| Composite actionSetGroup = new Composite(sashComposite, SWT.NONE); |
| layout = new GridLayout(); |
| layout.marginHeight = 0; |
| layout.marginWidth = 0; |
| actionSetGroup.setLayout(layout); |
| actionSetGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); |
| |
| label = new Label(actionSetGroup, SWT.WRAP); |
| label.setText(WorkbenchMessages.ActionSetSelection_availableActionSets); |
| label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); |
| |
| final CheckboxTableViewer actionSetsViewer = CheckboxTableViewer.newCheckList(actionSetGroup, |
| SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); |
| actionSetAvailabilityTable = actionSetsViewer; |
| actionSetsViewer.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); |
| actionSetsViewer.setContentProvider(ArrayContentProvider.getInstance()); |
| actionSetsViewer.setComparator(new WorkbenchViewerComparator()); |
| actionSetsViewer.setCheckStateProvider(new ICheckStateProvider() { |
| @Override |
| public boolean isChecked(Object element) { |
| return ((ActionSet) element).isActive(); |
| } |
| |
| @Override |
| public boolean isGrayed(Object element) { |
| return false; |
| } |
| }); |
| actionSetsViewer.setInput(actionSets.toArray()); |
| |
| Table table = actionSetsViewer.getTable(); |
| new TableToolTip(table); |
| |
| final ActionSet[] selectedActionSet = { null }; |
| |
| // Filter to show only branches necessary for the selected action set. |
| final ViewerFilter setFilter = new ViewerFilter() { |
| @Override |
| public boolean select(Viewer viewer, Object parentElement, Object element) { |
| if (selectedActionSet[0] == null) { |
| return false; |
| } |
| return includeInSetStructure((DisplayItem) element, selectedActionSet[0]); |
| } |
| }; |
| |
| // Updates the check state of action sets |
| actionSetsViewer.addCheckStateListener(event -> { |
| final ActionSet actionSet = (ActionSet) event.getElement(); |
| if (event.getChecked()) { |
| actionSet.setActive(true); |
| for (DisplayItem item : actionSet.contributionItems) { |
| item.setCheckState(true); |
| } |
| } else { |
| actionSet.setActive(false); |
| } |
| }); |
| |
| // Menu and toolbar composite |
| Composite actionGroup = new Composite(sashComposite, SWT.NONE); |
| layout = new GridLayout(); |
| layout.numColumns = 2; |
| layout.makeColumnsEqualWidth = true; |
| layout.marginHeight = 0; |
| layout.marginWidth = 0; |
| layout.horizontalSpacing = 0; |
| actionGroup.setLayout(layout); |
| actionGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); |
| |
| Composite menubarGroup = new Composite(actionGroup, SWT.NONE); |
| layout = new GridLayout(); |
| layout.marginHeight = 0; |
| layout.marginWidth = 0; |
| menubarGroup.setLayout(layout); |
| menubarGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); |
| |
| label = new Label(menubarGroup, SWT.WRAP); |
| label.setText(WorkbenchMessages.ActionSetSelection_menubarActions); |
| label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); |
| |
| actionSetMenuViewer = new TreeViewer(menubarGroup); |
| actionSetMenuViewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS); |
| actionSetMenuViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); |
| actionSetMenuViewer.setUseHashlookup(true); |
| actionSetMenuViewer.setContentProvider(TreeManager.getTreeContentProvider()); |
| actionSetMenuViewer.setLabelProvider(new GrayOutUnavailableLabelProvider(null)); |
| actionSetMenuViewer.addFilter(setFilter); |
| actionSetMenuViewer.setInput(menuItems); |
| |
| Tree tree = actionSetMenuViewer.getTree(); |
| new ItemDetailToolTip(this, actionSetMenuViewer, tree, false, true, setFilter); |
| |
| Composite toolbarGroup = new Composite(actionGroup, SWT.NONE); |
| layout = new GridLayout(); |
| layout.marginHeight = 0; |
| layout.marginWidth = 0; |
| toolbarGroup.setLayout(layout); |
| toolbarGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); |
| |
| label = new Label(toolbarGroup, SWT.WRAP); |
| label.setText(WorkbenchMessages.ActionSetSelection_toolbarActions); |
| label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); |
| |
| actionSetToolbarViewer = new TreeViewer(toolbarGroup); |
| actionSetToolbarViewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS); |
| actionSetToolbarViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); |
| actionSetToolbarViewer.setUseHashlookup(true); |
| actionSetToolbarViewer.setContentProvider(TreeManager.getTreeContentProvider()); |
| actionSetToolbarViewer.setLabelProvider(new GrayOutUnavailableLabelProvider(null)); |
| actionSetToolbarViewer.addFilter(setFilter); |
| actionSetToolbarViewer.setInput(toolBarItems); |
| |
| tree = actionSetToolbarViewer.getTree(); |
| new ItemDetailToolTip(this, actionSetToolbarViewer, tree, false, true, setFilter); |
| |
| // Updates the menu item and toolbar items tree viewers when the |
| // selection changes |
| actionSetsViewer.addSelectionChangedListener(event -> { |
| selectedActionSet[0] = (ActionSet) event.getStructuredSelection().getFirstElement(); |
| actionSetMenuViewer.setInput(menuItems); |
| actionSetToolbarViewer.setInput(toolBarItems); |
| }); |
| |
| sashComposite.setWeights(new int[] { 30, 70 }); |
| |
| return actionSetsComposite; |
| } |
| |
| /** |
| * Creates the page used to allow users to choose menu items to hide. |
| */ |
| private Composite createMenuVisibilityPage(Composite parent) { |
| GridData data; |
| |
| Composite hideMenuItemsComposite = new Composite(parent, SWT.NONE); |
| GridLayout layout = new GridLayout(); |
| hideMenuItemsComposite.setLayout(layout); |
| |
| // Label for entire tab |
| Label label = new Label(hideMenuItemsComposite, SWT.WRAP); |
| label.setText(WorkbenchMessages.HideMenuItems_chooseMenuItemsLabel); |
| data = new GridData(SWT.FILL, SWT.CENTER, true, false); |
| label.setLayoutData(data); |
| |
| Label sep = new Label(hideMenuItemsComposite, SWT.HORIZONTAL | SWT.SEPARATOR); |
| sep.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); |
| |
| // Main contents of tab |
| final PageBook book = new PageBook(hideMenuItemsComposite, SWT.NONE); |
| data = new GridData(GridData.FILL_BOTH); |
| book.setLayoutData(data); |
| |
| // Simple view: just the menu structure |
| final Composite simpleComposite = createItemStructureGroup(book, WorkbenchMessages.HideMenuItems_menuStructure); |
| menuStructureViewer1 = initStructureViewer(simpleComposite, new TreeManager.ViewerCheckStateListener(), null); |
| |
| // Update the viewer when the model changes |
| treeManager.getCheckListener(menuStructureViewer1); // To update ctv on |
| // model changes |
| |
| // Simply grab the checkstate out of the model |
| menuStructureViewer1.setCheckStateProvider(TreeManager.getCheckStateProvider()); |
| |
| // Init with input |
| menuStructureViewer1.setInput(menuItems); |
| |
| // Advanced view: action set with filtered menu structure |
| final SashForm advancedComposite = new SashForm(book, SWT.HORIZONTAL); |
| data = new GridData(SWT.FILL, SWT.FILL, true, true); |
| advancedComposite.setLayoutData(data); |
| |
| // Action set list |
| final TableViewer actionSetViewer = initActionSetViewer(createActionSetGroup(advancedComposite)); |
| |
| // Filter to only show action sets which have useful menu items |
| actionSetViewer.addFilter(new ShowUsedActionSetsFilter(menuItems)); |
| |
| // Init with input |
| actionSetViewer.setInput(actionSets.toArray()); |
| |
| // Filter to only show items in the current action set |
| final ActionSetFilter menuStructureFilterByActionSet = new ActionSetFilter(); |
| |
| final Composite menuStructureComposite = createItemStructureGroup(advancedComposite, |
| WorkbenchMessages.HideMenuItems_menuStructure); |
| final ICheckStateListener menuStructureFilter = new FilteredViewerCheckListener( |
| TreeManager.getTreeContentProvider(), menuStructureFilterByActionSet); |
| menuStructureViewer2 = initStructureViewer(menuStructureComposite, menuStructureFilter, |
| menuStructureFilterByActionSet); |
| |
| treeManager.addListener(new FilteredModelCheckListener(menuStructureFilterByActionSet, menuStructureViewer2)); |
| |
| menuStructureViewer2.addFilter(menuStructureFilterByActionSet); |
| |
| // Update filter when a new action set is selected |
| actionSetViewer.addSelectionChangedListener( |
| new ActionSetSelectionChangedListener(menuStructureViewer2, menuStructureFilterByActionSet)); |
| |
| // Check state provider to emulate standard SWT |
| // behaviour on visual tree |
| menuStructureViewer2.setCheckStateProvider( |
| new FilteredTreeCheckProvider(TreeManager.getTreeContentProvider(), menuStructureFilterByActionSet)); |
| |
| // Init input |
| menuStructureViewer2.setInput(menuItems); |
| |
| // Override any attempts to set an item to visible |
| // which exists in an unavailable action set |
| treeManager.addListener(changedItem -> { |
| if (!(changedItem instanceof DisplayItem)) { |
| return; |
| } |
| if (!changedItem.getState()) { |
| return; |
| } |
| if (isAvailable((DisplayItem) changedItem)) { |
| return; |
| } |
| changedItem.setCheckState(false); |
| }); |
| |
| final Button showCommandGroupFilterButton = new Button(hideMenuItemsComposite, SWT.CHECK); |
| showCommandGroupFilterButton.setText(WorkbenchMessages.HideItems_turnOnActionSets); |
| showCommandGroupFilterButton.addSelectionListener(new SelectionAdapter() { |
| |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| if (showCommandGroupFilterButton.getSelection()) { |
| Object o = ((StructuredSelection) menuStructureViewer1.getSelection()).getFirstElement(); |
| ActionSet initSelectAS = null; |
| DisplayItem initSelectCI = null; |
| if (o instanceof DisplayItem) { |
| initSelectCI = ((DisplayItem) o); |
| initSelectAS = initSelectCI.getActionSet(); |
| } |
| if (initSelectAS == null) { |
| initSelectAS = (ActionSet) actionSetViewer.getElementAt(0); |
| } |
| if (initSelectAS != null) { |
| setSelectionOn(actionSetViewer, initSelectAS); |
| actionSetViewer.reveal(initSelectAS); |
| } |
| if (initSelectCI != null) { |
| setSelectionOn(menuStructureViewer2, initSelectCI); |
| menuStructureViewer2.reveal(initSelectCI); |
| } |
| book.showPage(advancedComposite); |
| } else { |
| book.showPage(simpleComposite); |
| } |
| } |
| }); |
| |
| book.showPage(simpleComposite); |
| advancedComposite.setWeights(new int[] { 30, 70 }); |
| |
| return hideMenuItemsComposite; |
| } |
| |
| /** |
| * Creates the page used to allow users to choose menu items to hide. |
| */ |
| private Composite createToolBarVisibilityPage(Composite parent) { |
| GridData data; |
| |
| Composite hideToolbarItemsComposite = new Composite(parent, SWT.NONE); |
| GridLayout layout = new GridLayout(); |
| hideToolbarItemsComposite.setLayout(layout); |
| |
| // Label for entire tab |
| Label label = new Label(hideToolbarItemsComposite, SWT.WRAP); |
| label.setText(WorkbenchMessages.HideToolBarItems_chooseToolBarItemsLabel); |
| data = new GridData(SWT.FILL, SWT.CENTER, true, false); |
| label.setLayoutData(data); |
| |
| Label sep = new Label(hideToolbarItemsComposite, SWT.HORIZONTAL | SWT.SEPARATOR); |
| sep.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); |
| |
| // Main contents of tab |
| final PageBook book = new PageBook(hideToolbarItemsComposite, SWT.NONE); |
| data = new GridData(GridData.FILL_BOTH); |
| book.setLayoutData(data); |
| |
| // Simple view: just the toolbar structure |
| final Composite simpleComposite = createItemStructureGroup(book, |
| WorkbenchMessages.HideToolBarItems_toolBarStructure); |
| toolbarStructureViewer1 = initStructureViewer(simpleComposite, new TreeManager.ViewerCheckStateListener(), |
| null); |
| |
| // Update the viewer when the model changes |
| treeManager.getCheckListener(toolbarStructureViewer1); // To update ctv |
| // on model |
| // changes |
| |
| // Simply grab the check state out of the model |
| toolbarStructureViewer1.setCheckStateProvider(TreeManager.getCheckStateProvider()); |
| |
| // Init with input |
| toolbarStructureViewer1.setInput(toolBarItems); |
| |
| // Advanced view: action set with filtered toolbar structure |
| final SashForm advancedComposite = new SashForm(book, SWT.HORIZONTAL); |
| data = new GridData(SWT.FILL, SWT.FILL, true, true); |
| advancedComposite.setLayoutData(data); |
| |
| // Action set list |
| final TableViewer actionSetViewer = initActionSetViewer(createActionSetGroup(advancedComposite)); |
| |
| // Filter to only show action sets which have useful toolbar items |
| actionSetViewer.addFilter(new ShowUsedActionSetsFilter(toolBarItems)); |
| |
| // Init with input |
| actionSetViewer.setInput(actionSets.toArray()); |
| |
| // Filter to only show items in the current action set |
| final ActionSetFilter toolbarStructureFilterByActionSet = new ActionSetFilter(); |
| |
| final Composite toolbarStructureComposite = createItemStructureGroup(advancedComposite, |
| WorkbenchMessages.HideToolBarItems_toolBarStructure); |
| final ICheckStateListener toolbarStructureFilter = new FilteredViewerCheckListener( |
| TreeManager.getTreeContentProvider(), toolbarStructureFilterByActionSet); |
| toolbarStructureViewer2 = initStructureViewer(toolbarStructureComposite, toolbarStructureFilter, |
| toolbarStructureFilterByActionSet); |
| |
| toolbarStructureViewer2.addFilter(toolbarStructureFilterByActionSet); |
| |
| treeManager.addListener( |
| new FilteredModelCheckListener(toolbarStructureFilterByActionSet, toolbarStructureViewer2)); |
| |
| // Update filter when a new action set is selected |
| actionSetViewer.addSelectionChangedListener( |
| new ActionSetSelectionChangedListener(toolbarStructureViewer2, toolbarStructureFilterByActionSet)); |
| |
| // Check state provider to emulate standard SWT |
| // behaviour on visual tree |
| toolbarStructureViewer2.setCheckStateProvider( |
| new FilteredTreeCheckProvider(TreeManager.getTreeContentProvider(), toolbarStructureFilterByActionSet)); |
| |
| // Init input |
| toolbarStructureViewer2.setInput(toolBarItems); |
| |
| // Override any attempts to set an item to visible |
| // which exists in an unavailable action set |
| treeManager.addListener(changedItem -> { |
| if (!(changedItem instanceof DisplayItem)) { |
| return; |
| } |
| if (!changedItem.getState()) { |
| return; |
| } |
| if (isAvailable((DisplayItem) changedItem)) { |
| return; |
| } |
| changedItem.setCheckState(false); |
| }); |
| |
| final Button showCommandGroupFilterButton = new Button(hideToolbarItemsComposite, SWT.CHECK); |
| showCommandGroupFilterButton.setText(WorkbenchMessages.HideItems_turnOnActionSets); |
| showCommandGroupFilterButton.addSelectionListener(new SelectionAdapter() { |
| |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| if (showCommandGroupFilterButton.getSelection()) { |
| Object o = ((StructuredSelection) toolbarStructureViewer1.getSelection()).getFirstElement(); |
| ActionSet initSelectAS = null; |
| DisplayItem initSelectCI = null; |
| if (o instanceof DisplayItem) { |
| initSelectCI = ((DisplayItem) o); |
| initSelectAS = initSelectCI.getActionSet(); |
| } |
| if (initSelectAS == null) { |
| initSelectAS = (ActionSet) actionSetViewer.getElementAt(0); |
| } |
| if (initSelectAS != null) { |
| setSelectionOn(actionSetViewer, initSelectAS); |
| actionSetViewer.reveal(initSelectAS); |
| } |
| if (initSelectCI != null) { |
| setSelectionOn(toolbarStructureViewer2, initSelectCI); |
| toolbarStructureViewer2.reveal(initSelectCI); |
| } |
| book.showPage(advancedComposite); |
| } else { |
| book.showPage(simpleComposite); |
| } |
| } |
| }); |
| |
| book.showPage(simpleComposite); |
| advancedComposite.setWeights(new int[] { 30, 70 }); |
| |
| return hideToolbarItemsComposite; |
| } |
| |
| /** |
| * Creates a table to display action sets. |
| * |
| * @param parent |
| * @return a viewer to display action sets |
| */ |
| private static TableViewer initActionSetViewer(Composite parent) { |
| // List of categories |
| final TableViewer actionSetViewer = new TableViewer(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); |
| actionSetViewer.getTable().setLayoutData(new GridData(GridData.FILL_BOTH)); |
| actionSetViewer.setLabelProvider(new GrayOutUnavailableLabelProvider(null)); |
| actionSetViewer.setComparator(new WorkbenchViewerComparator()); |
| actionSetViewer.setContentProvider(ArrayContentProvider.getInstance()); |
| |
| // Tooltip on tree items |
| Table table = actionSetViewer.getTable(); |
| new TableToolTip(table); |
| return actionSetViewer; |
| } |
| |
| /** |
| * Creates a CheckboxTreeViewer to display menu or toolbar structure. |
| * |
| * @param parent |
| * @param checkStateListener the listener which listens to the viewer for check |
| * changes |
| * @param filter the filter used in the viewer (null for none) |
| * @return A viewer within <code>parent</code> which will show menu or toolbar |
| * structure. It comes setup, only missing a CheckStateProvider and its |
| * input. |
| */ |
| private CheckboxTreeViewer initStructureViewer(Composite parent, ICheckStateListener checkStateListener, |
| ViewerFilter filter) { |
| CheckboxTreeViewer ctv = new CheckboxTreeViewer(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); |
| ctv.getControl().setLayoutData(new GridData(GridData.FILL_BOTH)); |
| ctv.setUseHashlookup(true); |
| ctv.setContentProvider(TreeManager.getTreeContentProvider()); |
| // use an UnavailableContributionItemCheckListener to filter check |
| // events: if it is legal, forward it to the actual checkStateListener, |
| // if not, inform the user |
| ctv.addCheckStateListener(new UnavailableContributionItemCheckListener(this, ctv, checkStateListener)); |
| ctv.setLabelProvider(new GrayOutUnavailableLabelProvider(filter)); |
| new ItemDetailToolTip(this, ctv, ctv.getTree(), true, true, filter); |
| return ctv; |
| } |
| |
| /** |
| * Creates a composite to put a tree viewer in to display menu or toolbar items. |
| */ |
| private static Composite createItemStructureGroup(final Composite composite, String labelText) { |
| GridLayout layout; |
| Label label; |
| layout = new GridLayout(); |
| Composite menubarGroup = new Composite(composite, SWT.NONE); |
| layout.marginHeight = 0; |
| layout.marginWidth = 0; |
| menubarGroup.setLayout(layout); |
| menubarGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); |
| |
| label = new Label(menubarGroup, SWT.WRAP); |
| label.setText(labelText); |
| label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); |
| |
| return menubarGroup; |
| } |
| |
| /** |
| * Creates a composite to put a viewer in to display action sets. |
| */ |
| private static Composite createActionSetGroup(final Composite composite) { |
| GridLayout layout; |
| Label label; |
| Composite actionSetGroup = new Composite(composite, SWT.NONE); |
| layout = new GridLayout(); |
| layout.marginHeight = 0; |
| layout.marginWidth = 0; |
| actionSetGroup.setLayout(layout); |
| actionSetGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); |
| |
| label = new Label(actionSetGroup, SWT.WRAP); |
| label.setText(WorkbenchMessages.HideItems_commandGroupTitle); |
| label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); |
| |
| return actionSetGroup; |
| } |
| |
| /** |
| * Set the selection on a structured viewer. |
| * |
| * @param viewer |
| * @param selected |
| */ |
| private static void setSelectionOn(Viewer viewer, final Object selected) { |
| ISelection selection; |
| if (selected == null) { |
| selection = StructuredSelection.EMPTY; |
| } else { |
| selection = new StructuredSelection(selected); |
| } |
| boolean reveal = selection != StructuredSelection.EMPTY; |
| viewer.setSelection(selection, reveal); |
| } |
| |
| /** |
| * Searches deeply to see if <code>item</code> is a node in a branch containing |
| * a ContributionItem contributed by <code>set</code>. |
| * |
| * @param item the item in question |
| * @param set the action set to look for |
| * @return true iff <code>item</code> is required in build a tree including |
| * elements in <code>set</code> |
| */ |
| static boolean includeInSetStructure(DisplayItem item, ActionSet set) { |
| if (item.actionSet != null && item.actionSet.equals(set)) { |
| return true; |
| } |
| for (TreeItem treeItem : item.getChildren()) { |
| DisplayItem child = (DisplayItem) treeItem; |
| if (includeInSetStructure(child, set)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * @param item |
| * @return true iff the item is available - i.e. if it belongs to an action set, |
| * that that action set is available, or has a child which is available |
| * thus must be displayed in order to display the child |
| */ |
| static boolean isAvailable(DisplayItem item) { |
| if (item.getActionSet() != null && item.getChildren().isEmpty()) { |
| return item.getActionSet().isActive(); |
| } |
| for (TreeItem treeItem : item.getChildren()) { |
| DisplayItem child = (DisplayItem) treeItem; |
| if (isAvailable(child)) { |
| return true; |
| } |
| } |
| return item.getIContributionItem() != null && item.getIContributionItem().isVisible(); |
| } |
| |
| /** |
| * @param item |
| * @return true iff the item will show up in a menu or toolbar structure - i.e. |
| * it is available, or has a child which is available thus must be |
| * displayed in order to display the child |
| */ |
| static boolean isEffectivelyAvailable(DisplayItem item, ViewerFilter filter) { |
| if (!isAvailable(item)) { |
| return false; |
| } |
| final List<TreeItem> children = item.getChildren(); |
| if (children.isEmpty()) { |
| return true; |
| } |
| for (TreeItem treeItem : children) { |
| DisplayItem child = (DisplayItem) treeItem; |
| if (filter != null && !filter.select(null, null, child)) { |
| continue; |
| } |
| if (isAvailable(child)) { |
| return true; |
| } |
| } |
| for (TreeItem treeItem : children) { |
| DisplayItem child = (DisplayItem) treeItem; |
| if (filter != null && !filter.select(null, null, child)) { |
| continue; |
| } |
| if (isEffectivelyAvailable(child, filter)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * On a change to availability, updates the appropriate widgets. |
| */ |
| private void actionSetAvailabilityChanged() { |
| actionSetAvailabilityTable.refresh(); |
| actionSetMenuViewer.refresh(); |
| actionSetToolbarViewer.refresh(); |
| |
| menuStructureViewer1.refresh(); |
| menuStructureViewer2.refresh(); |
| toolbarStructureViewer1.refresh(); |
| toolbarStructureViewer2.refresh(); |
| } |
| |
| private void initializeActionSetInput() { |
| // Just get the action sets at this point. |
| ActionSetRegistry reg = WorkbenchPlugin.getDefault().getActionSetRegistry(); |
| IActionSetDescriptor[] sets = reg.getActionSets(); |
| |
| // Populate all legacy actionsets into the model, see bug 549898 |
| // Note: all (also invisible) actions sets will be loaded here and |
| // respective actions will be created. This is not good ("invisible" |
| // actions will live from this moment on till shutdown) and we need |
| // a better solution. |
| Object initDone = context.get(ALL_SETS_INITIALIZED); |
| if (initDone == null) { |
| context.set(ALL_SETS_INITIALIZED, Boolean.TRUE); |
| window.getActionPresentation().setActionSets(sets); |
| window.updateActionSets(); |
| } |
| |
| IActionSetDescriptor[] actionSetDescriptors = ((WorkbenchPage) window.getActivePage()).getActionSets(); |
| List<IActionSetDescriptor> initiallyAvailableActionSets = Arrays.asList(actionSetDescriptors); |
| |
| for (IActionSetDescriptor set : sets) { |
| ActionSetDescriptor actionSetDesc = (ActionSetDescriptor) set; |
| if (WorkbenchActivityHelper.filterItem(actionSetDesc)) { |
| continue; |
| } |
| ActionSet actionSet = new ActionSet(actionSetDesc, initiallyAvailableActionSets.contains(actionSetDesc)); |
| idToActionSet.put(actionSetDesc.getId(), actionSet); |
| actionSets.add(actionSet); |
| } |
| } |
| |
| private String getToolbarLabel(MUIElement elt) { |
| MApplication app = context.get(MApplication.class); |
| String toolbarLabel = CoolBarToTrimManager.getToolbarLabel(app, elt); |
| if (toolbarLabel != null) { |
| return toolbarLabel; |
| } |
| String elementId = elt.getElementId(); |
| if (elementId == null) { |
| return "Unnamed element"; //$NON-NLS-1$ |
| } |
| ActionSetRegistry registry = WorkbenchPlugin.getDefault().getActionSetRegistry(); |
| IActionSetDescriptor findActionSet = registry.findActionSet(elementId); |
| if (findActionSet != null) { |
| return findActionSet.getLabel(); |
| } |
| // Nothing is available. Let's smartly guess the name then. |
| String[] nameParts = elementId.split("\\."); //$NON-NLS-1$ |
| return nameParts[nameParts.length - 1]; |
| } |
| |
| private void initializeIcons() { |
| menuImageDescriptor = ImageDescriptor |
| .createFromURLSupplier(true, () -> BundleUtility.find(PlatformUI.PLUGIN_ID, MENU_ICON)); |
| submenuImageDescriptor = ImageDescriptor |
| .createFromURLSupplier(true, () -> BundleUtility.find(PlatformUI.PLUGIN_ID, SUBMENU_ICON)); |
| toolbarImageDescriptor = ImageDescriptor |
| .createFromURLSupplier(true, () -> BundleUtility.find(PlatformUI.PLUGIN_ID, TOOLBAR_ICON)); |
| warningImageDescriptor = ImageDescriptor |
| .createFromURLSupplier(true, () -> BundleUtility.find(PlatformUI.PLUGIN_ID, WARNING_ICON)); |
| } |
| |
| private void initializeNewWizardsMenu(DisplayItem menu, Category parentCategory, IWizardCategory element, |
| List<String> activeIds) { |
| Category category = new Category(element.getLabel()); |
| parentCategory.addChild(category); |
| |
| Object[] wizards = element.getWizards(); |
| for (Object wizard2 : wizards) { |
| WorkbenchWizardElement wizard = (WorkbenchWizardElement) wizard2; |
| |
| ShortcutItem item = new ShortcutItem(wizard.getLabel(), wizard); |
| item.setLabel(wizard.getLabel()); |
| item.setDescription(wizard.getDescription()); |
| if (wizard.getImageDescriptor() != null) { |
| item.setImageDescriptor(wizard.getImageDescriptor()); |
| } |
| item.setCheckState(activeIds.contains(wizard.getId())); |
| menu.addChild(item); |
| category.addShortcutItem(item); |
| } |
| // @issue should not pass in null |
| for (IWizardCategory child : element.getCategories()) { |
| initializeNewWizardsMenu(menu, category, child, activeIds); |
| } |
| } |
| |
| private void initializeNewWizardsMenu(DisplayItem menu) { |
| Category rootForNewWizards = new Category(WorkbenchMessages.ActionSetDialogInput_wizardCategory); |
| shortcuts.addChild(rootForNewWizards); |
| |
| IWizardCategory wizardCollection = WorkbenchPlugin.getDefault().getNewWizardRegistry().getRootCategory(); |
| IWizardCategory[] wizardCategories = wizardCollection.getCategories(); |
| List<String> activeIDs = Arrays.asList(perspective.getNewWizardShortcuts()); |
| |
| for (IWizardCategory element : wizardCategories) { |
| if (WorkbenchActivityHelper.filterItem(element)) { |
| continue; |
| } |
| initializeNewWizardsMenu(menu, rootForNewWizards, element, activeIDs); |
| } |
| } |
| |
| private void initializePerspectivesMenu(DisplayItem menu) { |
| Category rootForPerspectives = new Category(WorkbenchMessages.ActionSetDialogInput_perspectiveCategory); |
| shortcuts.addChild(rootForPerspectives); |
| |
| IPerspectiveRegistry perspReg = WorkbenchPlugin.getDefault().getPerspectiveRegistry(); |
| IPerspectiveDescriptor[] persps = perspReg.getPerspectives(); |
| |
| List<String> activeIds = Arrays.asList(perspective.getPerspectiveShortcuts()); |
| |
| for (IPerspectiveDescriptor perspective : persps) { |
| if (WorkbenchActivityHelper.filterItem(perspective)) { |
| continue; |
| } |
| |
| ShortcutItem child = new ShortcutItem(perspective.getLabel(), perspective); |
| child.setImageDescriptor(perspective.getImageDescriptor()); |
| child.setDescription(perspective.getDescription()); |
| child.setCheckState(activeIds.contains(perspective.getId())); |
| menu.addChild(child); |
| |
| rootForPerspectives.addShortcutItem(child); |
| } |
| } |
| |
| private void initializeViewsMenu(DisplayItem menu) { |
| Category rootForViews = new Category(WorkbenchMessages.ActionSetDialogInput_viewCategory); |
| |
| shortcuts.addChild(rootForViews); |
| |
| IViewRegistry viewReg = WorkbenchPlugin.getDefault().getViewRegistry(); |
| IViewCategory[] categories = viewReg.getCategories(); |
| |
| List<String> activeIds = Arrays.asList(perspective.getShowViewShortcuts()); |
| |
| for (IViewCategory category : categories) { |
| if (WorkbenchActivityHelper.filterItem(category)) { |
| continue; |
| } |
| |
| Category viewCategory = new Category(category.getLabel()); |
| rootForViews.addChild(viewCategory); |
| |
| IViewDescriptor[] views = category.getViews(); |
| |
| if (views != null) { |
| for (IViewDescriptor view : views) { |
| if (view.getId().equals(IIntroConstants.INTRO_VIEW_ID)) { |
| continue; |
| } |
| if (WorkbenchActivityHelper.filterItem(view)) { |
| continue; |
| } |
| |
| ShortcutItem child = new ShortcutItem(view.getLabel(), view); |
| child.setImageDescriptor(view.getImageDescriptor()); |
| child.setDescription(view.getDescription()); |
| child.setCheckState(activeIds.contains(view.getId())); |
| menu.addChild(child); |
| viewCategory.addShortcutItem(child); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Loads the current perspective's menu structure and also loads which menu |
| * items are visible and not. |
| */ |
| private void loadMenuAndToolbarStructure() { |
| customizeActionBars = new CustomizeActionBars(configurer, context); |
| |
| // Fill fake action bars with static menu information. |
| window.fillActionBars(customizeActionBars, |
| ActionBarAdvisor.FILL_PROXY | ActionBarAdvisor.FILL_MENU_BAR | ActionBarAdvisor.FILL_COOL_BAR); |
| |
| // Populate the action bars with the action sets' data |
| for (ActionSet actionSet : actionSets) { |
| ActionSetDescriptor descriptor = actionSet.descriptor; |
| PluginActionSet pluginActionSet = buildMenusAndToolbarsFor(customizeActionBars, descriptor); |
| |
| if (pluginActionSet != null) { |
| pluginActionSet.dispose(); |
| } |
| } |
| |
| // Add actionSet MenuManagers to menu |
| MenuManager menuManager = customizeActionBars.menuManager; |
| IContributionItem[] items = menuManager.getItems(); |
| for (IContributionItem item : items) { |
| if (item instanceof ActionSetContributionItem) { |
| ActionSetContributionItem asci = (ActionSetContributionItem) item; |
| menuManager.add(asci.getInnerItem()); |
| } |
| } |
| |
| // Make all menu items visible so they are included in the list. |
| customizeActionBars.menuManager.setVisible(true); |
| |
| makeAllContributionsVisible(customizeActionBars.menuManager); |
| |
| customizeActionBars.menuRenderer.reconcileManagerToModel(customizeActionBars.menuManager, |
| customizeActionBars.mainMenu); |
| |
| IPresentationEngine engine = context.get(IPresentationEngine.class); |
| engine.createGui(customizeActionBars.mainMenu, customizeActionBars.windowModel.getWidget(), |
| customizeActionBars.windowModel.getContext()); |
| |
| shortcuts = new Category(""); //$NON-NLS-1$ |
| toolBarItems = createTrimBarEntries(window.getTopTrim()); |
| menuItems = createMenuStructure(customizeActionBars.mainMenu); |
| } |
| |
| private PluginActionSet buildMenusAndToolbarsFor(CustomizeActionBars customizeActionBars, |
| ActionSetDescriptor actionSetDesc) { |
| String id = actionSetDesc.getId(); |
| ActionSetActionBars bars = new ActionSetActionBars(customizeActionBars, window, customizeActionBars, id); |
| bars.getMenuManager().setVisible(true); |
| PluginActionSetBuilder builder = new PluginActionSetBuilder(); |
| PluginActionSet actionSet = null; |
| try { |
| actionSet = (PluginActionSet) actionSetDesc.createActionSet(); |
| actionSet.init(null, bars); |
| } catch (CoreException ex) { |
| WorkbenchPlugin.log("Unable to create action set " + actionSetDesc.getId(), ex); //$NON-NLS-1$ |
| return null; |
| } |
| builder.buildMenuAndToolBarStructure(actionSet, window); |
| return actionSet; |
| } |
| |
| /** |
| * @return can return null |
| */ |
| static String getCommandID(DisplayItem item) { |
| Object object = item.getIContributionItem(); |
| |
| if (item instanceof ShortcutItem && isShowView(item)) { |
| return IWorkbenchCommandConstants.VIEWS_SHOW_VIEW; |
| } |
| |
| return getIDFromIContributionItem(object); |
| } |
| |
| /** |
| * Given an object, tries to find an id which will uniquely identify it. |
| * |
| * @param object an instance of {@link IContributionItem}, |
| * {@link IPerspectiveDescriptor}, {@link IViewDescriptor} or |
| * {@link WorkbenchWizardElement}. |
| * @return an id, can return null |
| * @throws IllegalArgumentException if object is not one of the listed types |
| */ |
| public static String getIDFromIContributionItem(Object object) { |
| if (object instanceof ActionContributionItem) { |
| ActionContributionItem item = (ActionContributionItem) object; |
| IAction action = item.getAction(); |
| if (action == null) { |
| return null; |
| } |
| if (action instanceof NewWizardShortcutAction) { |
| return IWorkbenchCommandConstants.FILE_NEW; |
| } |
| if (action instanceof OpenPerspectiveAction) { |
| return IWorkbenchCommandConstants.PERSPECTIVES_SHOW_PERSPECTIVE; |
| } |
| String id = action.getActionDefinitionId(); |
| if (id != null) { |
| return id; |
| } |
| return action.getId(); |
| } |
| if (object instanceof ActionSetContributionItem) { |
| ActionSetContributionItem item = (ActionSetContributionItem) object; |
| IContributionItem subitem = item.getInnerItem(); |
| return getIDFromIContributionItem(subitem); |
| } |
| if (object instanceof CommandContributionItem) { |
| CommandContributionItem item = (CommandContributionItem) object; |
| ParameterizedCommand command = item.getCommand(); |
| if (command == null) { |
| return null; |
| } |
| return command.getId(); |
| } |
| if (object instanceof IPerspectiveDescriptor) { |
| return ((IPerspectiveDescriptor) object).getId(); |
| } |
| if (object instanceof IViewDescriptor) { |
| return ((IViewDescriptor) object).getId(); |
| } |
| if (object instanceof WorkbenchWizardElement) { |
| return ((WorkbenchWizardElement) object).getLocalId(); |
| } |
| if (object instanceof IContributionItem) { |
| String id = ((IContributionItem) object).getId(); |
| if (id != null) { |
| return id; |
| } |
| return object.getClass().getName(); |
| } |
| return null; // couldn't determine the id |
| } |
| |
| static String getParamID(DisplayItem object) { |
| if (object instanceof ShortcutItem) { |
| ShortcutItem shortcutItem = (ShortcutItem) object; |
| |
| if (isNewWizard(shortcutItem)) { |
| ActionContributionItem item = (ActionContributionItem) object.getIContributionItem(); |
| NewWizardShortcutAction nwsa = (NewWizardShortcutAction) item.getAction(); |
| return nwsa.getLocalId(); |
| } |
| |
| if (isShowPerspective(shortcutItem)) { |
| ActionContributionItem item = (ActionContributionItem) object.getIContributionItem(); |
| OpenPerspectiveAction opa = (OpenPerspectiveAction) item.getAction(); |
| return opa.getLocalId(); |
| } |
| |
| if (isShowView(shortcutItem)) { |
| IViewDescriptor descriptor = (IViewDescriptor) shortcutItem.getDescriptor(); |
| return descriptor.getId(); |
| } |
| } |
| |
| return null; |
| } |
| |
| static boolean isNewWizard(DisplayItem item) { |
| if (!(item instanceof ShortcutItem)) { |
| return false; |
| } |
| return ((ShortcutItem) item).getDescriptor() instanceof IWizardDescriptor; |
| } |
| |
| static boolean isShowPerspective(DisplayItem item) { |
| if (!(item instanceof ShortcutItem)) { |
| return false; |
| } |
| return ((ShortcutItem) item).getDescriptor() instanceof IPerspectiveDescriptor; |
| } |
| |
| static boolean isShowView(DisplayItem item) { |
| if (!(item instanceof ShortcutItem)) { |
| return false; |
| } |
| return ((ShortcutItem) item).getDescriptor() instanceof IViewDescriptor; |
| } |
| |
| private static String getActionSetID(IContributionItem item) { |
| if (item instanceof ActionSetContributionItem) { |
| return ((ActionSetContributionItem) item).getActionSetId(); |
| } |
| if (item instanceof PluginActionCoolBarContributionItem) { |
| return ((PluginActionCoolBarContributionItem) item).getActionSetId(); |
| } |
| if (item instanceof ContributionItem) { |
| IContributionManager parent = ((ContributionItem) item).getParent(); |
| if (parent instanceof ActionSetMenuManager) { |
| return ((ActionSetMenuManager) parent).getActionSetId(); |
| } |
| if (item instanceof ToolBarContributionItem2) { |
| return item.getId(); |
| } |
| } |
| return null; |
| } |
| |
| private static String getActionSetID(MUIElement item) { |
| String id = (String) item.getTransientData().get(IWorkbenchRegistryConstants.TAG_ACTION_SET); |
| if (id != null) { |
| return id; |
| } |
| Object data = OpaqueElementUtil.getOpaqueItem(item); |
| if (data == null) { |
| data = item.getTransientData().get(CoolBarToTrimManager.OBJECT); |
| } |
| if (data instanceof IContributionItem) { |
| return getActionSetID((IContributionItem) data); |
| } |
| return null; |
| } |
| |
| /** |
| * Causes all items under the manager to be visible, so they can be read. |
| * |
| * @param manager |
| */ |
| private static void makeAllContributionsVisible(IContributionManager manager) { |
| IContributionItem[] items = manager.getItems(); |
| |
| for (IContributionItem item : items) { |
| makeContributionVisible(item); |
| } |
| } |
| |
| /** |
| * Makes all items under the item to be visible, so they can be read. |
| * |
| * @param item |
| */ |
| private static void makeContributionVisible(IContributionItem item) { |
| item.setVisible(true); |
| |
| if (item instanceof IContributionManager) { |
| makeAllContributionsVisible((IContributionManager) item); |
| } |
| if (item instanceof SubContributionItem) { |
| makeContributionVisible(((SubContributionItem) item).getInnerItem()); |
| } |
| } |
| |
| private DisplayItem createMenuStructure(MMenu menu) { |
| DisplayItem root = new DisplayItem("", null); //$NON-NLS-1$ |
| createMenuEntries(menu, root); |
| return root; |
| } |
| |
| private void createMenuEntries(MMenu menu, DisplayItem parent) { |
| DynamicContributionItem dynamicEntry = null; |
| |
| Map<IContributionItem, DisplayItem> processedOpaqueItems = new HashMap<>(); |
| for (MMenuElement menuItem : menu.getChildren()) { |
| dynamicEntry = createMenuEntry(parent, dynamicEntry, menuItem, processedOpaqueItems); |
| } |
| } |
| |
| private DynamicContributionItem createMenuEntry(DisplayItem parent, DynamicContributionItem dynamicEntry, |
| MMenuElement menuItem, Map<IContributionItem, DisplayItem> processedOpaqueItems) { |
| if (!menuItem.isToBeRendered()) { |
| return null; |
| } |
| |
| if (menuItem instanceof MMenu) { |
| MenuManager manager = menuMngrRenderer.getManager((MMenu) menuItem); |
| |
| ImageDescriptor iconDescriptor; |
| DisplayItem menuEntry; |
| if (OpaqueElementUtil.isOpaqueMenu(menuItem)) { |
| if (processedOpaqueItems.containsKey(manager)) { |
| // Manager already processed as wrapped item, which determines the position |
| // Still the child entries must be added |
| menuEntry = processedOpaqueItems.get(manager); |
| } else { |
| menuEntry = new DisplayItem(manager.getMenuText(), manager); |
| parent.addChild(menuEntry); |
| } |
| iconDescriptor = manager.getImageDescriptor(); |
| } else { |
| menuEntry = new DisplayItem(menuItem.getLocalizedLabel(), manager); |
| iconDescriptor = getIconDescriptor(menuItem); |
| parent.addChild(menuEntry); |
| } |
| |
| if (iconDescriptor != null) { |
| menuEntry.setImageDescriptor(iconDescriptor); |
| } else if (parent.getParent() == null) { |
| menuEntry.setImageDescriptor(menuImageDescriptor); |
| } else { |
| menuEntry.setImageDescriptor(submenuImageDescriptor); |
| } |
| |
| menuEntry.setActionSet(idToActionSet.get(getActionSetID(menuItem))); |
| |
| // Compatibility sub-menus for some opaque menus |
| String managerId = manager != null ? manager.getId() : null; |
| if (ActionFactory.NEW.getId().equals(managerId)) { |
| initializeNewWizardsMenu(menuEntry); |
| wizards = menuEntry; |
| } else if (SHORTCUT_CONTRIBUTION_ITEM_ID_OPEN_PERSPECTIVE.equals(managerId)) { |
| initializePerspectivesMenu(menuEntry); |
| perspectives = menuEntry; |
| } else if (SHORTCUT_CONTRIBUTION_ITEM_ID_SHOW_VIEW.equals(managerId)) { |
| initializeViewsMenu(menuEntry); |
| views = menuEntry; |
| } else { |
| createMenuEntries((MMenu) menuItem, menuEntry); |
| } |
| |
| if (menuEntry.getChildren().isEmpty()) { |
| menuEntry.setCheckState(getMenuItemIsVisible(menuEntry)); |
| } |
| } else if (RenderedElementUtil.isRenderedMenuItem(menuItem)) { |
| IContributionItem contributionItem = menuMngrRenderer.getContribution(menuItem); |
| |
| if (dynamicEntry == null || !contributionItem.equals(dynamicEntry.getIContributionItem())) { |
| // Only create one dynamic item for multiple (successive) dynamic contribution |
| // items |
| dynamicEntry = new DynamicContributionItem(contributionItem); |
| dynamicEntry.setActionSet(idToActionSet.get(getActionSetID(menuItem))); |
| dynamicEntry.setCheckState(getMenuItemIsVisible(dynamicEntry)); |
| parent.addChild(dynamicEntry); |
| } |
| |
| if (menuItem.getWidget() != null) { |
| // TODO See Bug 558766: add children; widgets are no longer available |
| dynamicEntry.addCurrentItem((MenuItem) menuItem.getWidget()); |
| } |
| |
| return dynamicEntry; |
| } else if (OpaqueElementUtil.isOpaqueMenuItem(menuItem)) { |
| IContributionItem contributionItem = menuMngrRenderer.getContribution(menuItem); |
| |
| if (contributionItem instanceof SubContributionItem) { |
| // get the wrapped contribution item |
| contributionItem = ((SubContributionItem) contributionItem).getInnerItem(); |
| } |
| if (contributionItem instanceof SubMenuManager) { |
| // get the wrapped contribution item |
| contributionItem = (IMenuManager) ((SubMenuManager) contributionItem).getParent(); |
| } |
| |
| if (processedOpaqueItems.containsKey(contributionItem)) { |
| // Only the first occurrence of an item will be shown |
| return null; |
| } |
| |
| if (contributionItem.isDynamic()) { |
| if (dynamicEntry == null || !contributionItem.equals(dynamicEntry.getIContributionItem())) { |
| // Only create one dynamic item for multiple (successive) dynamic contribution |
| // items |
| dynamicEntry = new DynamicContributionItem(contributionItem); |
| dynamicEntry.setActionSet(idToActionSet.get(getActionSetID(contributionItem))); |
| dynamicEntry.setCheckState(getMenuItemIsVisible(dynamicEntry)); |
| parent.addChild(dynamicEntry); |
| processedOpaqueItems.put(contributionItem, dynamicEntry); |
| } |
| |
| if (menuItem.getWidget() != null) { |
| // TODO See Bug 558766: add children; widgets are no longer available |
| dynamicEntry.addCurrentItem((MenuItem) menuItem.getWidget()); |
| } |
| |
| return dynamicEntry; |
| } else if (contributionItem instanceof CommandContributionItem) { |
| CommandContributionItem cci = (CommandContributionItem) contributionItem; |
| CommandContributionItemParameter data = cci.getData(); |
| DisplayItem menuEntry = new DisplayItem(data.label, contributionItem); |
| menuEntry.setImageDescriptor(data.icon); |
| menuEntry.setActionSet(idToActionSet.get(getActionSetID(contributionItem))); |
| menuEntry.setCheckState(getMenuItemIsVisible(menuEntry)); |
| parent.addChild(menuEntry); |
| processedOpaqueItems.put(contributionItem, menuEntry); |
| } else if (contributionItem instanceof ActionContributionItem) { |
| final IAction action = ((ActionContributionItem) contributionItem).getAction(); |
| DisplayItem menuEntry = new DisplayItem(action.getText(), contributionItem); |
| menuEntry.setImageDescriptor(action.getImageDescriptor()); |
| menuEntry.setActionSet(idToActionSet.get(getActionSetID(contributionItem))); |
| menuEntry.setCheckState(getMenuItemIsVisible(menuEntry)); |
| parent.addChild(menuEntry); |
| processedOpaqueItems.put(contributionItem, menuEntry); |
| } else if (contributionItem instanceof MenuManager) { |
| MenuManager manager = (MenuManager) contributionItem; |
| DisplayItem menuEntry = new DisplayItem(manager.getMenuText(), contributionItem); |
| menuEntry.setImageDescriptor(manager.getImageDescriptor()); |
| menuEntry.setActionSet(idToActionSet.get(getActionSetID(contributionItem))); |
| menuEntry.setCheckState(getMenuItemIsVisible(menuEntry)); |
| parent.addChild(menuEntry); |
| |
| // The child entries will be processes when the not-wrapped item is processed, |
| // see MMenu case |
| processedOpaqueItems.put(contributionItem, menuEntry); |
| } |
| } else if (menuItem instanceof MDynamicMenuContribution) { |
| IContributionItem contributionItem = menuMngrRenderer.getContribution(menuItem); |
| dynamicEntry = new DynamicContributionItem(menuItem.getLocalizedLabel(), contributionItem); |
| dynamicEntry.setImageDescriptor(getIconDescriptor(menuItem)); |
| dynamicEntry.setActionSet(idToActionSet.get(getActionSetID(menuItem))); |
| dynamicEntry.setCheckState(getMenuItemIsVisible(dynamicEntry)); |
| |
| // TODO See Bug 558766: add children |
| |
| parent.addChild(dynamicEntry); |
| } else if (menuItem instanceof MDirectMenuItem) { |
| IContributionItem contributionItem = menuMngrRenderer.getContribution(menuItem); |
| DisplayItem menuEntry = new DisplayItem(menuItem.getLocalizedLabel(), contributionItem); |
| menuEntry.setImageDescriptor(getIconDescriptor(menuItem)); |
| menuEntry.setActionSet(idToActionSet.get(getActionSetID(menuItem))); |
| menuEntry.setCheckState(getMenuItemIsVisible(menuEntry)); |
| parent.addChild(menuEntry); |
| } else if (menuItem instanceof MHandledMenuItem) { |
| IContributionItem contributionItem = menuMngrRenderer.getContribution(menuItem); |
| |
| MHandledMenuItem hmi = (MHandledMenuItem) menuItem; |
| String text = hmi.getLocalizedLabel(); |
| if (text == null && hmi.getWbCommand() != null) { |
| try { |
| text = hmi.getWbCommand().getName(); |
| } catch (NotDefinedException e) { |
| // we'll just ignore a failure |
| } |
| } |
| |
| DisplayItem menuEntry = new DisplayItem(text, contributionItem); |
| menuEntry.setImageDescriptor(getIconDescriptor(menuItem)); |
| menuEntry.setActionSet(idToActionSet.get(getActionSetID(menuItem))); |
| menuEntry.setCheckState(getMenuItemIsVisible(menuEntry)); |
| parent.addChild(menuEntry); |
| } |
| return null; |
| } |
| |
| private ImageDescriptor getIconDescriptor(MUILabel item) { |
| String iconURI = item.getIconURI(); |
| if (iconURI != null && iconURI.length() > 0) { |
| return resUtils.imageDescriptorFromURI(URI.createURI(iconURI)); |
| } |
| return null; |
| } |
| |
| private boolean getMenuItemIsVisible(DisplayItem item) { |
| return getItemIsVisible(item, ModeledPageLayout.HIDDEN_MENU_PREFIX); |
| } |
| |
| private boolean getToolbarItemIsVisible(DisplayItem item) { |
| return getItemIsVisible(item, ModeledPageLayout.HIDDEN_TOOLBAR_PREFIX); |
| } |
| |
| private boolean getItemIsVisible(DisplayItem item, String prefix) { |
| return isAvailable(item) && !isHiddenItem(item, prefix); |
| } |
| |
| private boolean isHiddenItem(DisplayItem item, String prefix) { |
| String itemId = prefix + getCommandID(item) + ","; //$NON-NLS-1$ |
| return windowPage.getHiddenItems().contains(itemId); |
| } |
| |
| /** |
| * Causes a viewer to update the state of a category and all its ancestors. |
| * |
| * @param viewer |
| * @param category |
| */ |
| private void updateCategoryAndParents(StructuredViewer viewer, Category category) { |
| while (category.getParent() != shortcuts) { |
| viewer.update(category, null); |
| category = (Category) category.getParent(); |
| } |
| } |
| |
| private static boolean hasVisibleItems(MToolBar toolBar) { |
| for (MToolBarElement e : toolBar.getChildren()) { |
| if (!(e instanceof MToolBarSeparator)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| private DisplayItem createTrimBarEntries(MTrimBar trimBar) { |
| // create a root element |
| DisplayItem root = new DisplayItem(null, null); |
| if (trimBar == null) { |
| return root; |
| } |
| for (MTrimElement trimElement : trimBar.getChildren()) { |
| if (!(trimElement instanceof MToolBar)) { |
| continue; |
| } |
| MToolBar toolBar = (MToolBar) trimElement; |
| ToolBarManager manager = toolbarMngrRenderer.getManager(toolBar); |
| if (manager != null) { |
| IContributionItem contributionItem = (IContributionItem) toolBar.getTransientData() |
| .get(CoolBarToTrimManager.OBJECT); |
| String text = getToolbarLabel(toolBar); |
| DisplayItem toolBarEntry = new DisplayItem(text, contributionItem); |
| toolBarEntry.setImageDescriptor(toolbarImageDescriptor); |
| toolBarEntry.setActionSet(idToActionSet.get(getActionSetID(toolBar))); |
| if (!hasVisibleItems(toolBar)) { |
| // TODO: there are two "Launch" toolbars, one of them is |
| // empty. Why? |
| continue; |
| } |
| root.addChild(toolBarEntry); |
| toolBarEntry.setCheckState(getToolbarItemIsVisible(toolBarEntry)); |
| createToolbarEntries(toolBar, toolBarEntry); |
| } |
| } |
| return root; |
| } |
| |
| private void createToolbarEntries(MToolBar toolbar, DisplayItem parent) { |
| if (toolbar == null) { |
| return; |
| } |
| for (MToolBarElement element : toolbar.getChildren()) { |
| createToolbarEntry(parent, element); |
| } |
| } |
| |
| private void createToolbarEntry(DisplayItem parent, MToolBarElement element) { |
| IContributionItem contributionItem = toolbarMngrRenderer.getContribution(element); |
| if (isGroupOrSeparator(element, contributionItem)) { |
| return; |
| } |
| |
| if (OpaqueElementUtil.isOpaqueToolItem(element)) { |
| if (contributionItem instanceof ActionContributionItem) { |
| final IAction action = ((ActionContributionItem) contributionItem).getAction(); |
| DisplayItem toolbarEntry = new DisplayItem(action.getText(), contributionItem); |
| toolbarEntry.setImageDescriptor(action.getImageDescriptor()); |
| toolbarEntry.setActionSet(idToActionSet.get(getActionSetID(contributionItem))); |
| if (toolbarEntry.getChildren().isEmpty()) { |
| toolbarEntry.setCheckState(getToolbarItemIsVisible(toolbarEntry)); |
| } |
| parent.addChild(toolbarEntry); |
| } |
| return; |
| } |
| |
| String text = null; |
| if (element instanceof MItem) { |
| text = getToolTipText((MItem) element); |
| } |
| ImageDescriptor iconDescriptor = element instanceof MItem ? getIconDescriptor((MItem) element) : null; |
| if (element.getWidget() instanceof ToolItem) { |
| ToolItem item = (ToolItem) element.getWidget(); |
| if (text == null) { |
| text = item.getToolTipText(); |
| } |
| if (text == null) { |
| text = item.getText(); |
| } |
| if (iconDescriptor == null) { |
| Image image = item.getImage(); |
| if (image != null) { |
| iconDescriptor = ImageDescriptor.createFromImage(image); |
| } |
| } |
| } |
| if (text == null) { |
| text = getToolbarLabel(element); |
| } |
| |
| DisplayItem toolBarEntry = new DisplayItem(text, contributionItem); |
| if (iconDescriptor != null) { |
| toolBarEntry.setImageDescriptor(iconDescriptor); |
| } |
| toolBarEntry.setActionSet(idToActionSet.get(getActionSetID(element))); |
| if (toolBarEntry.getChildren().isEmpty()) { |
| toolBarEntry.setCheckState(getToolbarItemIsVisible(toolBarEntry)); |
| } |
| parent.addChild(toolBarEntry); |
| } |
| |
| private static boolean isGroupOrSeparator(MToolBarElement element, IContributionItem contributionItem) { |
| return element instanceof MToolBarSeparator |
| || (contributionItem == null || contributionItem.isGroupMarker() || contributionItem.isSeparator()); |
| } |
| |
| private static ParameterizedCommand generateParameterizedCommand(final MHandledItem item, |
| final IEclipseContext lclContext) { |
| ECommandService cmdService = lclContext.get(ECommandService.class); |
| Map<String, Object> parameters = null; |
| List<MParameter> modelParms = item.getParameters(); |
| if (modelParms != null && !modelParms.isEmpty()) { |
| parameters = new HashMap<>(); |
| for (MParameter mParm : modelParms) { |
| parameters.put(mParm.getName(), mParm.getValue()); |
| } |
| } |
| ParameterizedCommand cmd = cmdService.createCommand(item.getCommand().getElementId(), parameters); |
| item.setWbCommand(cmd); |
| return cmd; |
| } |
| |
| private String getToolTipText(MItem item) { |
| String text = item.getLocalizedTooltip(); |
| if (item instanceof MHandledItem) { |
| MHandledItem handledItem = (MHandledItem) item; |
| EBindingService bs = context.get(EBindingService.class); |
| ParameterizedCommand cmd = handledItem.getWbCommand(); |
| if (cmd == null) { |
| cmd = generateParameterizedCommand(handledItem, context); |
| } |
| TriggerSequence sequence = bs.getBestSequenceFor(handledItem.getWbCommand()); |
| if (sequence != null) { |
| if (text == null) { |
| try { |
| text = cmd.getName(); |
| } catch (NotDefinedException e) { |
| return null; |
| } |
| } |
| text = text + " (" + sequence.format() + ')'; //$NON-NLS-1$ |
| } |
| return text; |
| } else if (OpaqueElementUtil.isOpaqueMenuItem(item)) { |
| Object opaque = OpaqueElementUtil.getOpaqueItem(item); |
| if (opaque instanceof ActionContributionItem) { |
| return ((ActionContributionItem) opaque).getAction().getText(); |
| } |
| } else if (OpaqueElementUtil.isOpaqueToolItem(item)) { |
| Object opaque = OpaqueElementUtil.getOpaqueItem(item); |
| if (opaque instanceof ActionContributionItem) { |
| return ((ActionContributionItem) opaque).getAction().getToolTipText(); |
| } |
| } |
| return text; |
| } |
| |
| /** |
| * Returns whether the shortcut tab should be shown. |
| * |
| * @return <code>true</code> if the shortcut tab should be shown, and |
| * <code>false</code> otherwise |
| * @since 3.0 |
| */ |
| private boolean showShortcutTab() { |
| return window.containsSubmenu(WorkbenchWindow.NEW_WIZARD_SUBMENU) |
| || window.containsSubmenu(WorkbenchWindow.OPEN_PERSPECTIVE_SUBMENU) |
| || window.containsSubmenu(WorkbenchWindow.SHOW_VIEW_SUBMENU); |
| } |
| |
| private static ArrayList<String> getVisibleIDs(DisplayItem root) { |
| if (root == null) { |
| return new ArrayList<>(); |
| } |
| ArrayList<String> ids = new ArrayList<>(root.getChildrenCount()); |
| for (TreeItem treeItem : root.getChildren()) { |
| DisplayItem object = (DisplayItem) treeItem; |
| if (object instanceof ShortcutItem && object.getState()) { |
| ids.add(getParamID(object)); |
| } |
| } |
| return ids; |
| } |
| |
| private void getChangedIds(DisplayItem item, List<String> invisible, List<String> visible) { |
| if (item instanceof ShortcutItem) { |
| return; |
| } |
| |
| if (item == wizards || item == perspectives || item == views) { |
| // We always want the top-level wizard/perspective/view shortcuts to |
| // be visible, see bug 293448 |
| return; |
| } else if (item.getChildrenCount() > 0) { |
| if (item.isChangedByUser()) { |
| String id = getCommandID(item); |
| if (id != null) { |
| if (item.getState()) { |
| visible.add(id); |
| } else { |
| invisible.add(id); |
| } |
| } |
| } |
| for (TreeItem treeItem : item.getChildren()) { |
| getChangedIds((DisplayItem) treeItem, invisible, visible); |
| } |
| } else if (item.isChangedByUser()) { |
| String id = getCommandID(item); |
| if (id != null) { |
| if (item.getState()) { |
| visible.add(id); |
| } else { |
| invisible.add(id); |
| } |
| } |
| } |
| } |
| |
| private boolean updateHiddenElements(List<ActionSet> items, String currentHidden, String prefix) { |
| List<String> changedAndVisible = new ArrayList<>(); |
| List<String> changedAndInvisible = new ArrayList<>(); |
| for (ActionSet actionSet : items) { |
| if (!actionSet.wasChanged()) { |
| continue; |
| } |
| if (actionSet.isActive()) { |
| changedAndVisible.add(actionSet.descriptor.getId()); |
| } else { |
| changedAndInvisible.add(actionSet.descriptor.getId()); |
| } |
| } |
| return updateHiddenElements(currentHidden, prefix, changedAndVisible, changedAndInvisible); |
| } |
| |
| private boolean updateHiddenElements(DisplayItem items, String currentHidden, String prefix) { |
| List<String> changedAndVisible = new ArrayList<>(); |
| List<String> changedAndInvisible = new ArrayList<>(); |
| getChangedIds(items, changedAndInvisible, changedAndVisible); |
| |
| return updateHiddenElements(currentHidden, prefix, changedAndVisible, changedAndInvisible); |
| } |
| |
| private boolean updateHiddenElements(String currentHidden, String prefix, List<String> changedAndVisible, |
| List<String> changedAndInvisible) { |
| boolean hasChanges = false; |
| // Remove explicitly 'visible' elements from the current list |
| for (String id : changedAndVisible) { |
| String itemId = prefix + id; |
| if (currentHidden.contains(itemId + ",")) { //$NON-NLS-1$ |
| hasChanges = true; |
| windowPage.removeHiddenItems(itemId); |
| } |
| } |
| |
| // Add explicitly 'hidden' elements to the current list |
| for (String id : changedAndInvisible) { |
| String itemId = prefix + id; |
| if (!currentHidden.contains(itemId + ",")) { //$NON-NLS-1$ |
| hasChanges = true; |
| windowPage.addHiddenItems(itemId); |
| } |
| } |
| |
| return hasChanges; |
| } |
| |
| @Override |
| protected void okPressed() { |
| |
| // Shortcuts |
| if (showShortcutTab()) { |
| windowPage.setNewShortcuts(getVisibleIDs(wizards), ModeledPageLayout.NEW_WIZARD_TAG); |
| windowPage.setNewShortcuts(getVisibleIDs(perspectives), ModeledPageLayout.PERSP_SHORTCUT_TAG); |
| windowPage.setNewShortcuts(getVisibleIDs(views), ModeledPageLayout.SHOW_VIEW_TAG); |
| } |
| |
| // Determine if anything has changed and, if so, update the menu & tb's |
| boolean requiresUpdate = false; |
| |
| // Action Sets |
| ArrayList<ActionSetDescriptor> toAdd = new ArrayList<>(); |
| ArrayList<ActionSetDescriptor> toRemove = new ArrayList<>(); |
| |
| for (ActionSet actionSet : actionSets) { |
| if (!actionSet.wasChanged()) { |
| continue; |
| } |
| |
| // Something has changed |
| requiresUpdate = true; |
| |
| if (actionSet.isActive()) { |
| toAdd.add(actionSet.descriptor); |
| } else { |
| toRemove.add(actionSet.descriptor); |
| } |
| } |
| |
| perspective.turnOnActionSets(toAdd.toArray(new IActionSetDescriptor[toAdd.size()])); |
| perspective.turnOffActionSets(toRemove.toArray(new IActionSetDescriptor[toRemove.size()])); |
| |
| requiresUpdate |= updateHiddenElements(actionSets, windowPage.getHiddenItems(), |
| ModeledPageLayout.HIDDEN_ACTIONSET_PREFIX); |
| // Menu and Toolbar Items |
| requiresUpdate |= updateHiddenElements(menuItems, windowPage.getHiddenItems(), |
| ModeledPageLayout.HIDDEN_MENU_PREFIX); |
| requiresUpdate |= updateHiddenElements(toolBarItems, windowPage.getHiddenItems(), |
| ModeledPageLayout.HIDDEN_TOOLBAR_PREFIX); |
| |
| if (requiresUpdate) { |
| perspective.updateActionBars(); |
| } |
| |
| super.okPressed(); |
| } |
| |
| @Override |
| public boolean close() { |
| |
| treeManager.dispose(); |
| customizeActionBars.dispose(); |
| |
| return super.close(); |
| } |
| |
| private static String removeShortcut(String label) { |
| if (label == null) { |
| return label; |
| } |
| int end = label.lastIndexOf('@'); |
| if (end >= 0) { |
| label = label.substring(0, end); |
| } |
| |
| end = label.lastIndexOf('\t'); |
| if (end >= 0) { |
| label = label.substring(0, end); |
| } |
| |
| return label; |
| } |
| |
| @Override |
| protected boolean isResizable() { |
| return true; |
| } |
| |
| void showActionSet(final DisplayItem item) { |
| if (item.getActionSet() != null) { |
| showActionSet(item.getActionSet()); |
| } |
| } |
| |
| void showActionSet(final ActionSet actionSet) { |
| tabFolder.setSelection(actionSetTab); |
| actionSetAvailabilityTable.reveal(actionSet); |
| setSelectionOn(actionSetAvailabilityTable, actionSet); |
| actionSetAvailabilityTable.getControl().setFocus(); |
| } |
| |
| } |