Search code examples
nattable

Unable to expand Tree Node in NatTable


I'm trying to create a Nattable with 2 columns and Row Header with a checkbox. Whenever, the root node is expanded, it is getting expanded. But, whenever the first level nodes are expanded, they are not getting expanded. I can notice the scrollbar expanding and Shrinking, on further clicks, but, the nodes are not getting expanded. When I click on alt+tab to move to another application and come to my nattable application, I can see that the nodes are expanded, now :)

Collapse works without any problem.

Find below the behavior

Find below the code snippet used for rendering the elements:

public class AdvancedPackageManagementNattable {

  public static final String COLUMN_COMPONENT_NAME = "componentTreeRoot";
  public static final String COLUMN_VERSION = "version";


  ICellPainter checkBoxPainter;


  public Control createAdvancePackageTable(final Composite parent) {
    Composite composite = new Composite(parent, SWT.BORDER);
    GridDataFactory.fillDefaults().grab(true, true).span(9, 9).align(SWT.FILL, SWT.FILL).applyTo(composite);
    GridLayoutFactory.fillDefaults().applyTo(composite);

    ConfigRegistry configRegistry = new ConfigRegistry();
    configRegistry.registerConfigAttribute(SortConfigAttributes.SORT_COMPARATOR, DefaultComparator.getInstance());

    EventList<ComponentTreeItem> eventList = GlazedLists.eventList(datums.values());
    SortedList<ComponentTreeItem> sortedList = new SortedList<>(eventList, null);


    String[] propertyNames = new String[] {
        AdvancedPackageManagementNattable.COLUMN_COMPONENT_NAME,
        AdvancedPackageManagementNattable.COLUMN_VERSION };
    IColumnPropertyAccessor<ComponentTreeItem> columnPropertyAccessor =
        new ReflectiveColumnPropertyAccessor<>(propertyNames);

    Map<String, String> propertyNameToLabel = new HashMap<>();
    propertyNameToLabel.put(AdvancedPackageManagementNattable.COLUMN_COMPONENT_NAME, "Component(Package) Name");
    propertyNameToLabel.put(AdvancedPackageManagementNattable.COLUMN_VERSION, "Version Number");

    IDataProvider columnHeaderDataProvider = new DefaultColumnHeaderDataProvider(propertyNames, propertyNameToLabel);
    DataLayer columnHeaderDataLayer = new DefaultColumnHeaderDataLayer(columnHeaderDataProvider);


    // Body layer
    ISortModel sortModel =
        new GlazedListsSortModel<>(sortedList, columnPropertyAccessor, configRegistry, columnHeaderDataLayer);

    final TreeList<ComponentTreeItem> treeList =
        new TreeList<>(sortedList, new ComponentTreeFormat(sortModel), TreeList.nodesStartCollapsed());
    GlazedListTreeData<?> treeData = new GlazedListTreeData<>(treeList);

    ListDataProvider<?> bodyDataProvider =
        new ListDataProvider<>(treeList, new TreeReflectiveColumnPropertyAccessor(columnPropertyAccessor));
    final DataLayer bodyDataLayer = new DataLayer(bodyDataProvider);


    ColumnReorderLayer columnReorderLayer = new ColumnReorderLayer(bodyDataLayer);
    ColumnHideShowLayer columnHideShowLayer = new ColumnHideShowLayer(columnReorderLayer);
    SelectionLayer selectionLayer = new SelectionLayer(columnHideShowLayer);

    final TreeLayer treeLayer = new TreeLayer(selectionLayer, new GlazedListTreeRowModel<>(treeData));

    ViewportLayer viewportLayer = new ViewportLayer(treeLayer);

    ColumnHeaderLayer columnHeaderLayer = new ColumnHeaderLayer(columnHeaderDataLayer, viewportLayer, selectionLayer);

    ColumnOverrideLabelAccumulator labelAccumulator = new ColumnOverrideLabelAccumulator(columnHeaderDataLayer);
    columnHeaderDataLayer.setConfigLabelAccumulator(labelAccumulator);
    SortHeaderLayer<?> sortHeaderLayer = new SortHeaderLayer<>(columnHeaderLayer, sortModel, false);

    // row header
    RowHeaderDataProvider rowHeaderDataProvider = new RowHeaderDataProvider(bodyDataProvider, bodyDataLayer);
    DataLayer rowHeaderDataLayer = new DataLayer(rowHeaderDataProvider);
    RowHeaderLayer rowHeaderLayer = new RowHeaderLayer(rowHeaderDataLayer, viewportLayer, selectionLayer);

    // Corner layer
    CornerLayer cornerLayer =
        createCornerLayer(columnHeaderDataProvider, sortHeaderLayer, rowHeaderDataProvider, rowHeaderLayer);

    // Grid
    GridLayer gridLayer = new GridLayer(viewportLayer, sortHeaderLayer, rowHeaderLayer, cornerLayer);
    NatTable natTable = new NatTable(composite, gridLayer, false);
    bodyDataLayer.setColumnPercentageSizing(true);
    GridDataFactory.fillDefaults().grab(true, true).applyTo(natTable);


    natTable.setConfigRegistry(configRegistry);
    addConfigurations(natTable, bodyDataLayer);
    columnHeaderDataLayer.setConfigLabelAccumulator(new ColumnLabelAccumulator());


    final ColumnOverrideLabelAccumulator columnLabelAccumulator = new ColumnOverrideLabelAccumulator(bodyDataLayer);
    bodyDataLayer.setConfigLabelAccumulator(columnLabelAccumulator);
    registerColumnLabels(columnLabelAccumulator);

    natTable.configure();

    addStyleThemeConfiguration(natTable);
    return natTable;
  }

  private CornerLayer createCornerLayer(final IDataProvider columnHeaderDataProvider,
      final SortHeaderLayer<?> sortHeaderLayer, final RowHeaderDataProvider rowHeaderDataProvider,
      final RowHeaderLayer rowHeaderLayer) {
    DefaultCornerDataProvider cornerDataProvider =
        new DefaultCornerDataProvider(columnHeaderDataProvider, rowHeaderDataProvider);
    DataLayer cornerDataLayer = new DataLayer(cornerDataProvider);
    return new CornerLayer(cornerDataLayer, rowHeaderLayer, sortHeaderLayer);
  }


  private void addStyleThemeConfiguration(final NatTable natTable) {
    natTable.setTheme(new ModernNatTableThemeConfiguration());
    natTable.configure();
  }


  private void addConfigurations(final NatTable natTable, final DataLayer bodyDataLayer) {
    natTable.addConfiguration(new DefaultNatTableStyleConfiguration());
    natTable.addConfiguration(new HeaderMenuConfiguration(natTable));
    natTable.addConfiguration(new SingleClickSortConfiguration());
    natTable.addConfiguration(new CommonNattableConfiguration(bodyDataLayer));
    natTable.addConfiguration(new DefaultEditBindings());
  }


  private void registerColumnLabels(final ColumnOverrideLabelAccumulator columnLabelAccumulator) {
    columnLabelAccumulator.registerColumnOverrides(0, COLUMN_COMPONENT_NAME);
    columnLabelAccumulator.registerColumnOverrides(1, COLUMN_VERSION);
  }


}

public class CommonNattableConfiguration extends DefaultNatTableStyleConfiguration {

  private static final String CONFIG_LABEL_VERSION = "version";

  private final DataLayer dataLayer;

  public CommonNattableConfiguration(final DataLayer bodyDataLayer) {
    this.dataLayer = bodyDataLayer;
  }

  @Override
  public void configureRegistry(final IConfigRegistry configRegistry) {
    super.configureRegistry(configRegistry);
    addVersionComboConfig(configRegistry);
    addCheckBoxConfig(configRegistry);
    nattableStyleConfig(configRegistry);

  }

  private void nattableStyleConfig(final IConfigRegistry configRegistry) {
    Style style = new Style();
    style.setAttributeValue(CellStyleAttributes.BACKGROUND_COLOR, GUIHelper.COLOR_WIDGET_LIGHT_SHADOW);
    configRegistry.registerConfigAttribute(CellConfigAttributes.CELL_STYLE, style, DisplayMode.NORMAL,
        GridRegion.CORNER);
    configRegistry.registerConfigAttribute(CellConfigAttributes.CELL_STYLE, style, DisplayMode.NORMAL,
        GridRegion.COLUMN_HEADER);
  }

  private void addVersionComboConfig(final IConfigRegistry configRegistry) {
    configRegistry.registerConfigAttribute(EditConfigAttributes.CELL_EDITABLE_RULE, IEditableRule.ALWAYS_EDITABLE,
        DisplayMode.EDIT, CommonNattableConfiguration.CONFIG_LABEL_VERSION);
    configRegistry.registerConfigAttribute(EditConfigAttributes.CELL_EDITOR, new VersionComboBoxEditor(this.dataLayer),
        DisplayMode.EDIT, CommonNattableConfiguration.CONFIG_LABEL_VERSION);
    configRegistry.registerConfigAttribute(CellConfigAttributes.DISPLAY_CONVERTER, new VersionDisplayConverter(),
        DisplayMode.NORMAL, CommonNattableConfiguration.CONFIG_LABEL_VERSION);

    configRegistry.registerConfigAttribute(CellConfigAttributes.DISPLAY_CONVERTER, new ComponentNameDisplayConverter(),
        DisplayMode.NORMAL, AdvancedPackageManagementNattable.COLUMN_COMPONENT_NAME);


  }

  private void addCheckBoxConfig(final IConfigRegistry configRegistry) {
    configRegistry.registerConfigAttribute(EditConfigAttributes.CELL_EDITOR, new CheckBoxCellEditor(), DisplayMode.EDIT,
        GridRegion.ROW_HEADER);

    configRegistry.registerConfigAttribute(EditConfigAttributes.CELL_EDITABLE_RULE, IEditableRule.ALWAYS_EDITABLE,
        DisplayMode.EDIT, GridRegion.ROW_HEADER);

    Style style = new Style();
    style.setAttributeValue(CellStyleAttributes.HORIZONTAL_ALIGNMENT, HorizontalAlignmentEnum.CENTER);

    configRegistry.registerConfigAttribute(CellConfigAttributes.CELL_PAINTER, new RowHeaderCheckboxPainter(),
        DisplayMode.NORMAL, GridRegion.ROW_HEADER);
    configRegistry.registerConfigAttribute(CellConfigAttributes.CELL_PAINTER, new RowHeaderCheckboxPainter(),
        DisplayMode.SELECT, GridRegion.ROW_HEADER);

    configRegistry.registerConfigAttribute(CellConfigAttributes.DISPLAY_CONVERTER, new DefaultBooleanDisplayConverter(),
        DisplayMode.NORMAL, GridRegion.ROW_HEADER);

    configRegistry.registerConfigAttribute(CellConfigAttributes.DISPLAY_CONVERTER, new DefaultBooleanDisplayConverter(),
        DisplayMode.EDIT, GridRegion.ROW_HEADER);

  }


  @Override
  public void configureUiBindings(final UiBindingRegistry uiBindingRegistry) {
    uiBindingRegistry.registerSingleClickBinding(
        new MouseEventMatcher(SWT.NONE, GridRegion.ROW_HEADER, MouseEventMatcher.LEFT_BUTTON), new MouseEditAction() {

          /**
           * {@inheritDoc}
           */
          @Override
          public void run(final NatTable natTable, final MouseEvent event) {
            super.run(natTable, event);
            natTable.refresh(false);
          }
        });

  }


}

Any help would be greatly appreciated.

TreeExpandCollapseAction is called in both the working and not working scenario. But, if I debug and go back to the product, it is working :)

Thanks, Palraj


Solution

  • You forgot to add the GlazedListsEventLayer in the body layer stack. Therefore the changes in the TreeList do not trigger the refresh.

    final DataLayer bodyDataLayer = new DataLayer(bodyDataProvider);
    
    GlazedListsEventLayer<?> glazedListsEventLayer = new GlazedListsEventLayer<>(bodyDataLayer, treeList);
    
    ColumnReorderLayer columnReorderLayer = new ColumnReorderLayer(glazedListsEventLayer);
    

    You can look at our examples to see how the structure should look like: TreeStructureGridExample