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();
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.
You need IMouseAction to select cell. An example code from here and some additional code added inside it to select call added over it below :
nattable.addConfiguration( new AbstractUiBindingConfiguration()
uiBindingRegistry.registerMouseDownBinding( new MouseEventMatcher( SWT.NONE, GridRegion.BODY,
MouseEventMatcher.RIGHT_BUTTON ), new CellPopupMenuAction(menu, selectionLayer) );
});
class CellPopupMenuAction implements IMouseAction {
private final Menu menu;
private final SelectionLayer selectionLayer;
public CellPopupMenuAction(Menu menu, SelectionLayer selectionLayer) {
this.menu = menu;
this.selectionLayer = selectionLayer;
}
@Override
public void run(NatTable natTable, MouseEvent event)
{
if( selectionLayer.getSelectedRowCount() <= 1 )
{
int colPosition = LayerUtil.convertColumnPosition( natTable,
natTable.getColumnPositionByX( event.x ), selectionLayer );
int rowPosition = LayerUtil.convertRowPosition( natTable,
natTable.getRowPositionByY( event.y ), selectionLayer );
natTable.doCommand( new SelectCellCommand( selectionLayer, colPosition, rowPosition, false,
false ) );
}
menu.setData(event.data);
menu.setVisible(true);
}
}
I assume you have the selectionLayer as a private variable in your code.
I used SomeDude's answer above and it worked but the menu item was displaying before the selection which looked odd. I moved the menu display to a UI thread asyncExec call and selection occurs first then the menu appears on top of it -
@Override
public void run(NatTable natTable, MouseEvent event) {
if (selectionLayer.getSelectedRowCount() <= 1) {
int colPosition = LayerUtil.convertColumnPosition(natTable, natTable.getColumnPositionByX(event.x),
selectionLayer);
int rowPosition = LayerUtil.convertRowPosition(natTable, natTable.getRowPositionByY(event.y),
selectionLayer);
natTable.doCommand(new SelectCellCommand(selectionLayer, colPosition, rowPosition, false, false));
}
Display.getDefault().asyncExec(new Runnable() {
public void run() {
menu.setData(event.data);
menu.setVisible(true);
}
});
}