在nebula中,官方默认提供了一个构造natTable的builder类,并且提供了一个debugInfo的默认右键菜单,但是当我们通过官方提供的builder去创建natTable,并且要添加多个右键菜单的时候,显得就不太灵活了,需要自己动手改改了,直接上代码吧:
1、创建一个抽象的菜单类AbstractMenuConfiguration:
public abstract class AbstractMenuConfiguration implements IMenuItemProvider {
private final String NAT\_EVENT\_DATA\_KEY = "natEventData"; //$NON-NLS-1$
@Override
public void addMenuItem(NatTable natTable, Menu popupMenu) {
MenuItem inspectLabelsMenuItem = new MenuItem(popupMenu, SWT.PUSH);
inspectLabelsMenuItem.setText(getMenuName());
inspectLabelsMenuItem.setEnabled(true);
inspectLabelsMenuItem.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
processEvent(getNatEventData(e));
}
});
}
private NatEventData getNatEventData(SelectionEvent selectionEvent) {
Widget widget = selectionEvent.widget;
if (widget == null || !(widget instanceof MenuItem)) {
return null;
}
MenuItem menuItem = (MenuItem) widget;
Menu parentMenu = menuItem.getParent();
Object data = null;
while (parentMenu != null) {
if (parentMenu.getData(this.NAT\_EVENT\_DATA\_KEY) == null) {
parentMenu = parentMenu.getParentMenu();
} else {
data = parentMenu.getData(this.NAT\_EVENT\_DATA\_KEY);
break;
}
}
return data != null ? (NatEventData) data : null;
}
protected abstract void processEvent(NatEventData natEventData);
protected abstract String getMenuName();
}
2、创建一个自定义PopupMenu构建类CustomerPopupMenuBuilder:
public class CustomerPopupMenuBuilder {
/\*\*
\* The active NatTable instance the context menu should be added to. Needed
\* in advance to be able to add custom menu items that need the NatTable
\* instance.
\*/
protected NatTable natTable;
/\*\*
\* The {@link Menu} that is created with this popup menu builder.
\*/
protected Menu popupMenu;
/\*\*
\* The {@link MenuManager} that is used by this popup menu builder. Can be
\* null
if plain SWT menu mechanisms are used.
\*/
protected MenuManager menuManager;
/\*\*
\* Collection of all registered visibility state checkers for configured
\* id's.
\*/
protected final MenuItemStateMap visibility = new MenuItemStateMap();
/\*\*
\* Collection of all registered enablement state checkers for configured
\* id's.
\*/
protected final MenuItemStateMap enablement = new MenuItemStateMap();
/\*\*
\* Creates {@link CustomerPopupMenuBuilder} that builds up a new
\* {@link Menu} that is only configurable with this instance of
\* {@link CustomerPopupMenuBuilder}. Uses a {@link MenuManager} internally
\* to be able to configure visibility and enabled states.
\*
\* @param parent
\* The active NatTable instance the context menu should be added
\* to.
\*/
public CustomerPopupMenuBuilder(NatTable parent) {
this(parent, new MenuManager());
}
/\*\*
\* Creates a {@link CustomerPopupMenuBuilder} that builds up a new
\* {@link Menu} using the given {@link MenuManager}.
\*
\* @param parent
\* The active NatTable instance the context menu should be added
\* to.
\* @param manager
\* The {@link MenuManager} that should be used to create the
\* {@link Menu}.
\*/
public CustomerPopupMenuBuilder(NatTable parent, MenuManager manager) {
this.natTable = parent;
this.menuManager = manager;
this.popupMenu = manager.createContextMenu(this.natTable);
}
/\*\*
\* Creates a popup menu builder based on the given menu. Using this enables
\* the possibility to use configured context menus from plugin.xml and
\* adding NatTable commands programmatically.
\* <p>
\* As an example you might want to create a PopupMenuBuilder by using a
\* configured menu with the id
\* <i>org.eclipse.nebula.widgets.nattable.example.contextmenu</i>
\* <p>
\*
\* <pre>
\* ISelectionProvider isp =
\* new RowSelectionProvider<?>(selectionLayer, bodyDataProvider, false);
\* MenuManager menuManager = new MenuManager();
\* menuManager.add(new Separator(IWorkbenchActionConstants.MB\_ADDITIONS));
\* getSite().registerContextMenu(
\* "org.eclipse.nebula.widgets.nattable.example.contextmenu", menuManager, isp);
\* PopupMenuBuilder popupMenu =
\* new PopupMenuBuilder(menuManager.createContextMenu(natTable));
\* </pre>
\* <p>
\* For usage with Eclipse 4 you can use the EMenuService
to
\* register the menu to a NatTable instance. Afterwards get the menu and
\* remove it from the NatTable to avoid the SWT control menu. The generated
\* menu carries a {@link MenuManager} in the {@link Menu#getData()} which
\* will be used within this {@link CustomerPopupMenuBuilder}.
\* </p>
\*
\* <pre>
\* menuService.registerContextMenu(natTable, menuId);
\* Menu swtMenu = natTable.getMenu();
\* natTable.setMenu(null);
\* </pre>
\*
\* @param natTable
\* The active NatTable instance which might be needed for
\* creation of menu items that need the NatTable instance to
\* work.
\* @param menu
\* The registered context menu.
\*/
public CustomerPopupMenuBuilder(NatTable natTable, Menu menu) {
this.natTable = natTable;
this.popupMenu = menu;
// if the menu is build up using a MenuManager, remember that for
// further use
if (menu.getData() != null && menu.getData() instanceof MenuManager) {
this.menuManager = (MenuManager) menu.getData();
}
}
/\*\*
\* Adds the menu item provided by the given {@link IMenuItemProvider} to the
\* popup menu. You can use this to add your own item to the popup menu.
\* <p>
\* Items added by this method can not be identified by id, so adding visible
\* or enabled state checkers is not possible for these providers.
\* </p>
\*
\* @param menuItemProvider
\* The {@link IMenuItemProvider} that provides the menu item that
\* should be added to the popup menu.
\* @return The current {@link CustomerPopupMenuBuilder} with the added item.
\*/
public CustomerPopupMenuBuilder withMenuItemProvider(IMenuItemProvider menuItemProvider) {
if (this.menuManager == null) {
menuItemProvider.addMenuItem(this.natTable, this.popupMenu);
} else {
this.menuManager.add(new PopupContributionItem(menuItemProvider));
}
return this;
}
/\*\*
\* Adds the menu item provided by the given {@link IMenuItemProvider} to the
\* popup menu. You can use this to add your own item to the popup menu.
\* <p>
\* As items added by this method can be identified via the given id it is
\* possible to register visible or enabled state checkers for these
\* providers.
\* </p>
\*
\* @param id
\* The id under which the given {@link IMenuItemProvider} should
\* be identifiable.
\* @param menuItemProvider
\* The {@link IMenuItemProvider} that provides the menu item that
\* should be added to the popup menu.
\* @return The current {@link CustomerPopupMenuBuilder} with the added item.
\*/
public CustomerPopupMenuBuilder withMenuItemProvider(String id, IMenuItemProvider menuItemProvider) {
if (this.menuManager == null) {
menuItemProvider.addMenuItem(this.natTable, this.popupMenu);
} else {
this.menuManager.add(new PopupContributionItem(id, menuItemProvider));
}
return this;
}
/\*\*
\* Adds the menu item(s) provided by the given {@link ContributionItem} to
\* the popup menu. You can use this to add your own item to the popup menu.
\* <p>
\* This method is only working if the {@link CustomerPopupMenuBuilder} is
\* using a {@link MenuManager}.
\* </p>
\* <p>
\* Using this adds support for visibility and enabled states of menu items.
\* </p>
\*
\* @param contributionItem
\* The {@link ContributionItem} that is used to add a menu item
\* to the menu.
\* @return The current {@link CustomerPopupMenuBuilder} with the added item.
\* @throws IllegalStateException
\* if this {@link CustomerPopupMenuBuilder} does not use a
\* {@link MenuManager}
\*/
public CustomerPopupMenuBuilder withContributionItem(ContributionItem contributionItem) {
if (this.menuManager == null) {
throw new IllegalStateException("This PopupMenuBuilder is not created using a MenuManager, " //$NON-NLS-1$
+ "therefore ContributionItems can not be added"); //$NON-NLS-1$
} else {
this.menuManager.add(contributionItem);
}
return this;
}
public CustomerPopupMenuBuilder configureMenuItemProvider(String mid, IMenuItemProvider menuItemProvider) {
return withMenuItemProvider(
mid,
menuItemProvider);
}
/\*\*
\* Adds a separator to the popup menu with the given id.
\*
\* @param id
\* The id to identify the separator. Necessary if there should be
\* visibility constraints for specific separators.
\* @return The {@link CustomerPopupMenuBuilder} with an added separator.
\* @see MenuItemProviders#separatorMenuItemProvider()
\*/
public CustomerPopupMenuBuilder withSeparator(String id) {
return withMenuItemProvider(id, MenuItemProviders.separatorMenuItemProvider());
}
/\*\*
\* Builds and returns the created {@link Menu}.
\* <p>
\* <b>Note:</b> Calling this method will also add a {@link DisposeListener}
\* to the NatTable instance to ensure the created {@link Menu} is disposed
\* when the NatTable itself gets disposed.
\* </p>
\*
\* @return The {@link Menu} that is created by this builder.
\*/
public Menu build() {
this.natTable.addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
if (CustomerPopupMenuBuilder.this.popupMenu != null
&& !CustomerPopupMenuBuilder.this.popupMenu.isDisposed())
CustomerPopupMenuBuilder.this.popupMenu.dispose();
}
});
return this.popupMenu;
}
/\*\*
\* Associate a visibility {@link IMenuItemState} with the menu item
\* identified by the given id.
\* <p>
\* The visibility state is handled by the internal {@link MenuManager}. If
\* no {@link MenuManager} is used, this method will have not effect.
\* </p>
\* <p>
\* For the item to be visible, all associated {@link IMenuItemState} must be
\* active OR no {@link IMenuItemState} must be associated with the item.
\* </p>
\*
\* @param id
\* the registered {@link IMenuItemState} will affect the menu
\* item identified by the given id.
\* @param state
\* the {@link IMenuItemState} to queried for the visibility state
\* of the menu item with the given id.
\* @return This {@link CustomerPopupMenuBuilder} with the visible state
\* checker for the given id.
\*/
public CustomerPopupMenuBuilder withVisibleState(String id, IMenuItemState state) {
this.visibility.addMenuItemState(id, state);
return this;
}
/\*\*
\* Associate a enabled {@link IMenuItemState} with the menu item identified
\* by the given id.
\* <p>
\* The enabled state is handled by the internal {@link MenuManager}. If no
\* {@link MenuManager} is used, this method will have not effect.
\* </p>
\* <p>
\* For the item to be enabled, all associated {@link IMenuItemState} must be
\* active OR no {@link IMenuItemState} must be associated with the item.
\* </p>
\*
\* @param id
\* the registered {@link IMenuItemState} will affect the menu
\* item identified by the given id.
\* @param state
\* the {@link IMenuItemState} to queried for the enabled state of
\* the menu item with the given id.
\* @return This {@link CustomerPopupMenuBuilder} with the enabled state
\* checker for the given id.
\*/
public CustomerPopupMenuBuilder withEnabledState(String id, IMenuItemState state) {
this.enablement.addMenuItemState(id, state);
return this;
}
/\*\*
\* Wrapper class to build up a {@link ContributionItem} based on a given
\* {@link IMenuItemProvider}. If an id is set it is possible to register
\* state checkers for enabled and visible state.
\*/
protected class PopupContributionItem extends ContributionItem {
private IMenuItemProvider provider;
public PopupContributionItem(IMenuItemProvider provider) {
this(null, provider);
}
public PopupContributionItem(String id, IMenuItemProvider provider) {
super(id);
this.provider = provider;
}
@Override
public void fill(Menu menu, int index) {
List<MenuItem> beforeItems = Arrays.asList(menu.getItems());
this.provider.addMenuItem(CustomerPopupMenuBuilder.this.natTable, menu);
MenuItem\[\] afterItems = menu.getItems();
for (MenuItem item : afterItems) {
if (!beforeItems.contains(item)) {
// isEnabled() seems to be not called by the framework on
// opening a menu therefore we set it ourself. For this we
// also need to ensure isDynamic() returns true for
// re-rendering.
item.setEnabled(isEnabled());
}
}
}
@Override
public boolean isDynamic() {
return (getId() != null);
}
@Override
public boolean isEnabled() {
if (getId() != null) {
Object eventData = CustomerPopupMenuBuilder.this.popupMenu.getData(MenuItemProviders.NAT\_EVENT\_DATA\_KEY);
if (eventData != null && eventData instanceof NatEventData) {
return CustomerPopupMenuBuilder.this.enablement.isActive(getId(), (NatEventData) eventData);
}
}
return true;
}
@Override
public boolean isVisible() {
if (getId() != null) {
Object eventData = CustomerPopupMenuBuilder.this.popupMenu.getData(MenuItemProviders.NAT\_EVENT\_DATA\_KEY);
if (eventData != null && eventData instanceof NatEventData) {
return CustomerPopupMenuBuilder.this.visibility.isActive(getId(), (NatEventData) eventData);
}
}
return true;
}
}
}
3、实现自定义多右键菜单配置CustomerPopupMenuConfiguration:
public class CustomerPopupMenuConfiguration extends AbstractUiBindingConfiguration {
private Menu menu;
private CustomerPopupMenuBuilder customerPopupMenuBuilder;
public CustomerPopupMenuConfiguration(NatTable natTable) {
this.customerPopupMenuBuilder = new CustomerPopupMenuBuilder(natTable);
}
public CustomerPopupMenuConfiguration configureMenuItemProvider(String mid, IMenuItemProvider menuItemProvider) {
this.customerPopupMenuBuilder.configureMenuItemProvider(mid, menuItemProvider);
return this;
}
public CustomerPopupMenuConfiguration build() {
this.menu = this.customerPopupMenuBuilder.build();
return this;
}
@Override
public void configureUiBindings(UiBindingRegistry uiBindingRegistry) {
uiBindingRegistry.registerMouseDownBinding(
new MouseEventMatcher(SWT.NONE, null, 3),
new PopupMenuAction(this.menu));
}
}
4、后面剩下的就是怎么使用自定义菜单了配置了:
public class Test{
public void configure(NatTable natTable){
……
natTable.addConfiguration(new CustomerPopupMenuConfiguration(natTable).configureMenuItemProvider("addRowMenuItem", new AbstractMenuConfi guration(){
@Override
protected String getMenuName() {
return "add";
}
@Override
protected void processEvent(NatEventData natEventData) {
//处理增加
}
}).configureMenuItemProvider("updateRowMenuItem", new AbstractMenuConfiguration(){
@Override
protected String getMenuName() {
return "update";
}
@Override
protected void processEvent(NatEventData natEventData) {
// 处理修改
}
}).configureMenuItemProvider("deleteRowMenuItem", new AbstractMenuConfiguration(){
@Override
protected String getMenuName() {
return "delete";
}
@Override
protected void processEvent(NatEventData natEventData) {
//处理删除
}
}).build());
…..
}
}
以上就实现了灵活自定义右键菜单。
手机扫一扫
移动阅读更方便
你可能感兴趣的文章