eclipse-rcpnattablenebula

Nebula NatTable didn't display correct cell editor when use GridLayer.


I edited a Nebula example (_301_CustomDataProviderExample) to test the cell editing feature on pressing tab key (enable next cell editing on pressing tab key). The problem occurred when I used GridLayer: the cell editor was display incorrect. I think it's because of row and column headers but I don't know how to debug or fix. Can you help me or give me some hints? This is the code I have edited or added:

 @Override
public Control createExampleControl(Composite parent) {

    String[][] testData = new String[3][3];
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            testData[i][j] = "" + i + "/" + j;
        }
    }

    IDataProvider bodyDataProvider = new TwoDimensionalArrayDataProvider(testData);
    final DataLayer bodyDataLayer = new DataLayer(bodyDataProvider);

    SelectionLayer selectionLayer = new SelectionLayer(bodyDataLayer);
    ViewportLayer viewportLayer = new ViewportLayer(selectionLayer);
    viewportLayer.addConfiguration(new DefaultEditConfiguration());
    viewportLayer.addConfiguration(new DefaultEditBindings());

    IDataProvider rowHeaderDataProvider = new DefaultRowHeaderDataProvider(bodyDataProvider);
    DataLayer rowHeaderDataLayer = new DataLayer(rowHeaderDataProvider, 40, DataLayer.DEFAULT_ROW_HEIGHT);
    rowHeaderDataLayer.setColumnsResizableByDefault(true);
    ILayer rowHeaderLayer = new RowHeaderLayer(rowHeaderDataLayer, viewportLayer, selectionLayer);

    IDataProvider columnHeaderDataProvider = new LetterColumnHeaderDataProvider(20);
    ILayer columnHeaderLayer = new ColumnHeaderLayer(
            new DefaultColumnHeaderDataLayer(columnHeaderDataProvider), viewportLayer, selectionLayer);

    IDataProvider conerDataProvider = new DefaultCornerDataProvider(columnHeaderDataProvider, rowHeaderDataProvider);
    ILayer cornerLayer = new CornerLayer(new DataLayer(conerDataProvider), rowHeaderLayer, columnHeaderLayer);

    GridLayer gridLayer = new GridLayer(viewportLayer, columnHeaderLayer, rowHeaderLayer, cornerLayer, false);

    final NatTable natTable = new NatTable(parent, false);
    natTable.setLayer(/* viewportLayer */ gridLayer);

    natTable.addConfiguration(new DefaultNatTableStyleConfiguration() {
        @Override
        public void configureRegistry(IConfigRegistry configRegistry) {
            super.configureRegistry(configRegistry);
            configRegistry.registerConfigAttribute(
                    EditConfigAttributes.CELL_EDITABLE_RULE,
                    IEditableRule.ALWAYS_EDITABLE);
        }
    });

    natTable.configure();

    return natTable;
}

Added:

class LetterColumnHeaderDataProvider implements IDataProvider {

private int columns = 0;

public LetterColumnHeaderDataProvider(int columns) {
    this.columns = columns;
}

@Override
public Object getDataValue(int columnIndex, int rowIndex) {
    return (char) ('A' + columnIndex);
    // TODO: support column header AA-AZ, ZA-ZZ, ZZZ...
}

@Override
public void setDataValue(int columnIndex, int rowIndex, Object newValue) {
    throw new UnsupportedOperationException();
}

@Override
public int getColumnCount() {
    return this.columns;
}

@Override
public int getRowCount() {
    return 1;
}
}

enter image description here


Solution

  • The issue is related to registering the DefaultEditConfiguration on the ViewportLayer. Doing this will result in placing the editor that is identified on key press relative to the body layer stack and not the GridLayer. The default configuration applied with the GridLayer contains the necessary edit configurations already. But you disabled it via the last parameter in the GridLayer constructor.

    In short, remove the following two lines from your example, they are only needed in case of compositions without a GridLayer.

    viewportLayer.addConfiguration(new DefaultEditConfiguration());
    viewportLayer.addConfiguration(new DefaultEditBindings());
    

    and change the creation of the GridLayer to this

    GridLayer gridLayer = new GridLayer(viewportLayer, columnHeaderLayer, rowHeaderLayer, cornerLayer);
    

    And as a hint, be careful when copying code from different examples when not understanding their purpose. The NatTable examples typically contain explanations in code to explain them in more detail.