Source code for this tutorial is available on googlecode as a single zip archive, as a Team Project Set or you can checkout the SVN projects directly.
Preparations
For this tutorial I created a Plug-in Project with a simple editor extension. The editor contains a TableViewer with some sample columns. Nothing special about that. Have a look at the source code or Lars' excellent editor tutorial if you are not familiar with these steps.
Step 1: Creating the editor context menu
To enable context menus, we need to register them in our editor code. The typical snippet to do this looks as follows:
MenuManager menuManager = new MenuManager(); Menu contextMenu = menuManager.createContextMenu(table); table.setMenu(contextMenu); getSite().registerContextMenu(menuManager, tableViewer);registerContextMenu() automatically searches for a menu contribution with locationURI = popup:<part.id>. In our case it would look for popup:com.codeandme.editor.sample. You may also provide a dedicated id when registering the context menu. Just make sure you provide the id without the "popup:" prefix, while the menu contribution needs the "popup:" prefix in its locationURI.
You will end up with a context menu already populated with some default entries like Run As, Compare With, Team, and some more. To get rid of them, we need to register the menu using a different site:
getEditorSite().registerContextMenu(menuManager, tableViewer, false);The boolean parameter allows to enable/disable context menu entries for the editor input part.
Step 2: Track the active column
When we want our context menu entry to behave differently depending on the column from where it was triggered, we need to track columns. Some solutions on the web use MouseListeners, which work well for the table body, but not for the header row. A nicer solution relies on MenuDetect events:
fTableViewer.getTable().addListener(SWT.MenuDetect, this); @Override public void handleEvent(Event event) { Table table = fTableViewer.getTable(); // calculate click offset within table area Point point = Display.getDefault().map(null, table, new Point(event.x, event.y)); Rectangle clientArea = table.getClientArea(); fHeaderArea = (clientArea.y <= point.y) && (point.y < (clientArea.y + table.getHeaderHeight())); ViewerCell cell = fTableViewer.getCell(point); if (cell != null) fSelectedColumnIndex = cell.getColumnIndex(); else { // no cell detected, click on header int xOffset = point.x; int columnIndex = 0; int[] order = table.getColumnOrder(); while ((columnIndex < table.getColumnCount()) && (xOffset > table.getColumn(order[columnIndex]).getWidth())) { xOffset -= table.getColumn(order[columnIndex]).getWidth(); columnIndex++; } fSelectedColumnIndex = (columnIndex < table.getColumnCount()) ? order[columnIndex] : NO_COLUMN; } }The full helper class is available under EPL and can be downloaded from the source repository.
Step 2: Delete the active column
To provide a usage example for the TableColumnTracker we will extend our editor and allow users to delete the column under the cursor using the context menu.
The command implementation simply asks the current editor to do the job:
@Override public Object execute(ExecutionEvent event) throws ExecutionException { IWorkbenchPart part = HandlerUtil.getActivePart(event); if (part instanceof SampleEditor) ((SampleEditor) part).deleteColumn(); return null; }The editor needs to install the tracker and dispose the selected column upon request:
public class SampleEditor extends EditorPart { private TableColumnTracker fColumnTracker; @Override public void createPartControl(Composite parent) { [...] MenuManager menuManager = new MenuManager(); Menu contextMenu = menuManager.createContextMenu(table); table.setMenu(contextMenu); getEditorSite().registerContextMenu(menuManager, fTableViewer, false); fColumnTracker = new TableColumnTracker(fTableViewer); } public void deleteColumn() { int columnIndex = fColumnTracker.getSelectedColumnIndex(); if (columnIndex != TableColumnTracker.NO_COLUMN) { fTableViewer.getTable().getColumn(columnIndex).dispose(); fTableViewer.refresh(); } } }