Search code examples
javaswtnattable

Showing NatTable context menu


I use NatTable. How to show context menu item on certain condition depending on the content of the cell? And how to select cell over which context menu was called? I bind menu with the following code

uiBindingRegistry.registerMouseDownBinding(
            new MouseEventMatcher(SWT.NONE, null, MouseEventMatcher.RIGHT_BUTTON), new PopupMenuAction(menu));

UPD: I create menu like this, but 'Test' item is visible in spite of isActive always return false. What's wrong with it?

menu = new PopupMenuBuilder(natTable).withMenuItemProvider(ITEM_ID, new IMenuItemProvider() {
        @Override
        public void addMenuItem(final NatTable natTable, final Menu popupMenu) {
            final MenuItem menuItem = new MenuItem(popupMenu, SWT.PUSH);
            menuItem.setText("Test");
            menuItem.setEnabled(true);
            menuItem.addSelectionListener(new SelectionAdapter() {
                @Override
                public void widgetSelected(final SelectionEvent event) {
                    System.out.println("test");
                }
            });
        }
    }).withVisibleState(ITEM_ID, new IMenuItemState() {
        @Override
        public boolean isActive(final NatEventData natEventData) {
            return false;
        }
    }).build();

Solution

  • The given answer is correct. Although it can be improved. You don't need the SelectionLayer.

    class CellPopupMenuAction implements IMouseAction {
    
        private final Menu menu;
    
        public CellPopupMenuAction(Menu menu) {
            this.menu = menu;
        }
    
        @Override
        public void run(NatTable natTable, MouseEvent event) {
            int columnPosition = natTable.getColumnPositionByX(event.x);
            int rowPosition = natTable.getRowPositionByY(event.y);
    
            ILayerCell cell = natTable.getCellByPosition(columnPosition, rowPosition);
    
            if (!cell.getDisplayMode().equals(DisplayMode.SELECT)) {
                natTable.doCommand(
                        new SelectCellCommand(
                                natTable,
                                columnPosition,
                                rowPosition,
                                false,
                                false));
            }
    
            menu.setData(MenuItemProviders.NAT_EVENT_DATA_KEY, event.data);
            menu.setVisible(true);
        }
    }
    

    This way you completely remove the need to reference the SelectionLayer and even improve the functionality because the SelectCellCommand is never fired if you right click on a selected cell.