如何让natTable表格支持自定义多个右键菜单
阅读原文时间:2023年07月10日阅读:1

在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&lt;?&gt;(selectionLayer, bodyDataProvider, false);  
  \* MenuManager menuManager = new MenuManager();  
  \* menuManager.add(new Separator(IWorkbenchActionConstants.MB\_ADDITIONS));  
  \* getSite().registerContextMenu(  
  \*         &quot;org.eclipse.nebula.widgets.nattable.example.contextmenu&quot;, 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());
…..
}
}

以上就实现了灵活自定义右键菜单。

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章