blob: 89daaacc32bf2dc036b2aebf971488f2dcfd148c [file] [log] [blame]
/*******************************************************************************
* 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();
}
}