blob: 5b0fcc4a422e0289afa88cc494c06c528e22c57e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2017 xored software, Inc. and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* xored software, Inc. - initial API and Implementation (Alex Panchenko)
*******************************************************************************/
package org.eclipse.dltk.ui.actions;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuCreator;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MenuAdapter;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.IWorkbenchPart;
public abstract class AbstractMenuCreatorObjectActionDelegate implements
IObjectActionDelegate, IMenuCreator {
protected interface IMenuBuilder {
void addAction(IAction action);
void addSeparator();
}
private static class MenuBuilder implements IMenuBuilder {
private final Menu menu;
public MenuBuilder(Menu menu) {
this.menu = menu;
}
@Override
public void addAction(IAction action) {
new ActionContributionItem(action).fill(menu, -1);
}
@Override
public void addSeparator() {
new MenuItem(menu, SWT.SEPARATOR);
}
}
// current action
private IAction fDelegateAction;
// whether to re-fill the menu (reset on selection change)
private boolean fFillMenu = true;
// current selection
private IStructuredSelection currentSelection;
@Override
public void setActivePart(IAction action, IWorkbenchPart targetPart) {
// We don't have a need for the active part.
}
@Override
public void run(IAction action) {
// Never called because we become a menu.
}
@Override
public void selectionChanged(IAction action, ISelection newSelection) {
// if the selection is an IResource, save it and enable our action
if (newSelection instanceof IStructuredSelection) {
fFillMenu = true;
if (fDelegateAction != action) {
fDelegateAction = action;
fDelegateAction.setMenuCreator(this);
}
// enable our menu
action.setEnabled(true);
currentSelection = (IStructuredSelection) newSelection;
return;
}
action.setEnabled(false);
currentSelection = null;
}
@Override
public void dispose() {
// nothing to do
}
@Override
public Menu getMenu(Control parent) {
// never called
return null;
}
@Override
public Menu getMenu(Menu parent) {
/*
* Create the new menu. The menu will get filled when it is about to be
* shown. see fillMenu(Menu).
*/
final Menu menu = new Menu(parent);
/*
* Add listener to re-populate the menu each time it is shown because
* MenuManager.update(boolean, boolean) doesn't dispose pull-down
* ActionContribution items for each popup menu.
*/
menu.addMenuListener(new MenuAdapter() {
@Override
public void menuShown(MenuEvent e) {
if (fFillMenu) {
final Menu m = (Menu) e.widget;
final MenuItem[] items = m.getItems();
for (int i = 0; i < items.length; i++) {
items[i].dispose();
}
fillMenu(new MenuBuilder(m), currentSelection);
fFillMenu = false;
}
}
});
return menu;
}
/**
* @param menu
*/
protected abstract void fillMenu(IMenuBuilder menu,
IStructuredSelection selection);
}