Search code examples
javaswttableviewer

How to trigger EditingSupport on TableViewer


I'm currently writing an application where I use a JFace TableViewer. There's a Button next to the table that adds a new item to it. The TableViewer has only one column in this example, but this column has an EditingSupport assigned to it.

That all works as expected. A new item is added to the table when I click the button and it's also selected automatically.

However, what I want to achieve is that the EditingSupport of this column is triggered for the new item, i.e. when a new item is added, the cell within the new row should automatically show the text input that shows up when you use the editing support.

How would I achieve that? Do I need to fake up a mouse event or is there something in the API that I'm missing?

Here's some example code that roughly shows the current state of the table

public static void main(String[] args)
{
    final Display d = new Display();
    Shell s = new Shell(d);
    s.setLayout(new FillLayout());

    List<Project> projects = new ArrayList<>();

    Table table = new Table(s, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
    table.setHeaderVisible(true);
    TableViewer viewer = new TableViewer(table);
    viewer.setContentProvider(ArrayContentProvider.getInstance());
    viewer.setInput(projects);

    TableViewerColumn nameColumn = new TableViewerColumn(viewer, SWT.NONE);
    nameColumn.getColumn().setText("Project name");
    nameColumn.setLabelProvider(new ColumnLabelProvider()
    {
        @Override
        public String getText(Object element)
        {
            Project p = (Project) element;
            return p.name;
        }
    });
    // Add the editing support
    nameColumn.setEditingSupport(new ProjectNameEditingSupport(viewer));

    // Button to add new item
    Button add = new Button(s, SWT.PUSH);
    add.setText("Add");
    add.addListener(SWT.Selection, e -> {
        // Create the new item
        Project project = new Project("Project");
        projects.add(project);
        // Refresh the table
        viewer.refresh();
        // Select the item
        viewer.setSelection(new StructuredSelection(project), true);
        // TODO: Trigger editing support
    });

    for (TableColumn c : viewer.getTable().getColumns())
        c.pack();

    s.pack();
    s.open();
    s.setSize(300, 400);

    while (!s.isDisposed())
    {
        if (!d.readAndDispatch())
            d.sleep();
    }
    d.dispose();
}

private static class Project
{
    private String name;

    public Project(String name)
    {
        this.name = name;
    }
}

public static class ProjectNameEditingSupport extends EditingSupport
{

    private final TableViewer viewer;
    private final CellEditor  editor;

    public ProjectNameEditingSupport(TableViewer viewer)
    {
        super(viewer);
        this.viewer = viewer;
        this.editor = new TextCellEditor(viewer.getTable());
    }

    @Override
    protected CellEditor getCellEditor(Object element)
    {
        return editor;
    }

    @Override
    protected boolean canEdit(Object element)
    {
        return true;
    }

    @Override
    protected Object getValue(Object element)
    {
        return ((Project) element).name;
    }

    @Override
    protected void setValue(Object element, Object userInputValue)
    {
        ((Project) element).name = String.valueOf(userInputValue);
        viewer.update(element, null);
    }
}

Solution

  • IIRC you can use ColumnViewer::editElement in order to activate the editing control. The first method argument is the element that should be edited, the second argument is the index of the column on which the editor should be opened.

    For example:

    viewer.editElement( project, 0 );