vesii
vesii

Reputation: 3128

TableViewer does not update the default value of a cell

I have a UI bug in a legacy code in our Java project. We display a table, with three columns (HumanReadable, name and value) in a window. In that window, users can click on each cell and update the values. Before that, user clicks the "add" button to add a new row (three new cells). Each cell has a default value, until the user decides to update the value. Now, when the users decides to update the value of the cell, he clicks on the cell and types in the value. The bug is that, once done editing, it keeps the default value in the UI. In the backend, the value has changed (if you click the cell again, it will go into editing mode and show you the value).

I uploaded a short GIF that shows the issue and can be found here.

In that GIF you can see that I updated the default value of the first column to be test. Then I click some other place (to exit the edit mode) and it showed the default value instead of test in the first column.

The method that creates the table:

private void createTable(final Composite parent) {
    final Table varTable = new Table(parent, SWT.MULTI);
    varTable.setHeaderVisible(true);
    varTable.setLinesVisible(true);
    GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(varTable);
    varTableViewer = new TableViewer(varTable);
    final DataBindingContext bindingContext = new DataBindingContext();
    final TableViewerColumn col1 = GuiUtils.createTableColumn(varTableViewer, "Human Readable");
    col1.setEditingSupport(new StringEditingSupport(varTableViewer, bindingContext, dataProperty));
    col1.getColumn().setWidth(120);
    final TableViewerColumn col2 = GuiUtils.createTableColumn(varTableViewer, "Name");
    col2.getColumn().setWidth(120);
    col2.setEditingSupport(new StringEditingSupport(varTableViewer, bindingContext, nameProperty));
    final TableViewerColumn col3 = GuiUtils.createTableColumn(varTableViewer, "Value");
    col3.setEditingSupport(new StringEditingSupport(varTableViewer, bindingContext, valueProperty));
    KeyBoardNavigationSupport.createSupport(varTableViewer);
    input = new WritableList(globalVars, FlowVar.class);
    ViewerSupport.bind(varTableViewer, input, BeanProperties.values(new String[] { dataProperty, nameProperty, valueProperty }));
}

The StringEditingSupport class:


public class StringEditingSupport extends ObservableValueEditingSupport {
    private class CellEditorPrintValidatorErrors extends TextCellEditor {
        public CellEditorPrintValidatorErrors(Composite control) {
            super(control);
        }

        @Override
        protected void focusLost(){
            if(this.getErrorMessage() != null) {
                MessageDialog.openError(this.getControl().getShell(), "Invalid input", this.getErrorMessage());
            }
        }
    }

    private final CellEditor cellEditor;
    String propertyName;

    public StringEditingSupport(final ColumnViewer viewer, final DataBindingContext dbc, final String propertyName) {
        super(viewer, dbc);
        cellEditor = new TextCellEditor((Composite) viewer.getControl());
        this.propertyName = propertyName;
    }

    public StringEditingSupport(final ColumnViewer viewer, final DataBindingContext dbc, final String propertyName, final ICellEditorValidator validator) {
        super(viewer, dbc);
        cellEditor = new CellEditorPrintValidatorErrors((Composite) viewer.getControl());
        cellEditor.setValidator(validator);
        this.propertyName = propertyName;
    }

    @Override
    protected IObservableValue doCreateCellEditorObservable(final CellEditor cellEditor) {
        return SWTObservables.observeText(cellEditor.getControl(), SWT.Modify);
    }

    @Override
    protected IObservableValue doCreateElementObservable(final Object element, final ViewerCell cell) {
        return BeansObservables.observeValue(element, propertyName);
    }

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

    public String getErrorMessage(){
        return cellEditor.getErrorMessage();
    }
}

I believe it has something to do with the StringEditingSupport class. This class allows to edit the value in each cell of table. But I couldn't figure out a way to "update" the value shown in the GUI. As I understand input (of type WritableList) contains all the information. Here is the add button listener method:

private class AddButtonSelectionListener extends SelectionAdapter {
    @Override
    public void widgetSelected(final SelectionEvent e) {
        String name = nameProperty;
        String meaning = dataProperty;

        final List<String> names = new ArrayList<String>();
        final List<String> meanings = new ArrayList<String>();
        for (final Object var : input) {
            names.add(((FlowVar) var).getName());
            meanings.add(((FlowVar) var).getData());
        }
        int index = 0;
        while (names.contains(name)) {
            name = nameProperty + ++index;
        }

        index = 0;
        while (meanings.contains(meaning)) {
            meaning = dataProperty + ++index;
        }
        input.add(new FlowVar(name, valueProperty, meaning));
    }
}

So, as I understand, I need to somehow bind the input to the UI (the content of each cell). I did try many attempts like trying to set a listener to the whole table (varTableViewer.addSelectionChangedListener) but none of them worked. Is it possible to suggest a way to solve this kind of issue?

If anything is missing, please let me know and I'll add it.

Upvotes: 2

Views: 116

Answers (0)

Related Questions