Skip to content

06_Editing

Dirk Fauth edited this page Sep 11, 2024 · 1 revision

Editing

NatTable supports the following editing features:

  1. Inline cell editing via a text box, combobox or a checkbox
  2. Multiple values can be edited simultaneously via a popup on pressing F2
  3. Editing updates the underlying list data structure

There is no special layer needed to enable editing in NatTable. Everything is done via configuration.

The default cell editing configuration is provided by the DefaultEditConfiguration that is used by the DefaultGridLayerConfiguration. This default configuration tells the NatTable to be not editable and sets the TextCellEditor as default editor in case editing is turned on for specific cells. It also adds the validation error style to render the content of a cell red on validation errors.
To enable editing on user interactions, several bindings need to be configured. The default bindings are configured in the DefaultEditBindings configuration, which is also part of the DefaultGridLayerConfiguration.

The EditableGridExample and EditErrorHandlingExample are the best places to look at.

Making cells editable

Editing is turned off by default. To enable editing an IEditableRule has to be registered. Usually you will register an IEditableRule against a cell label if you only want to enable editing for specific conditions like shown in the code below:

configRegistry.registerConfigAttribute( 
    EditConfigAttributes.CELL_EDITABLE_RULE, 
    IEditableRule.ALWAYS_EDITABLE, 
    DisplayMode.EDIT, 
    "myCellLabel");

The above snippet sets cells with label myCellLabel to be always editable

You can also create your own IEditableRule if you need to decide whether a cell should be editable or not. Just ensure that IEditableRule.isEditable() returns true if your cell should be editable.
Creating your own IEditableRule is useful if you want to register an IEditableRule globally (instead of only for a specific cell label) that reacts on a global flag (like enable/disable editing in the UI).

Cell editor

This is the widget which gets activated when a cell is put into edit mode. A cell editor needs to implement the ICellEditor interface. The following editors are provided out of the box:

  • TextCellEditor
  • CheckBoxCellEditor
  • ComboBoxCellEditor
  • PasswordCellEditor (as a specialization of TextCellEditor)

Note that there is only one instance of a cell editor active at any time. The editor must be registered against the cell label as follows:

configRegistry.registerConfigAttribute( 
    EditConfigAttributes.CELL\_EDITOR, 
    new CheckBoxCellEditor(), 
    DisplayMode.EDIT, 
    "myCheckboxLabel");

The above code configures the usage of a CheckBoxCellEditor for cells with label myCheckboxLabel

While TextCellEditor and CheckBoxCellEditor can be created without additional information, the ComboBoxCellEditor needs the list of values contained within the combobox.

As editing and rendering in different display modes are separated tasks you should check which cell painter is used for your editable cell. There are predefined cell painters for the existing cell editors in NatTable.

  • TextCellEditor - TextPainter
  • CheckBoxCellEditor - CheckBoxPainter
  • ComboBoxCellEditor - ComboBoxPainter
  • PasswordCellEditor - PasswordTextPainter

As TextCellEditor and TextPainter are configured by default, you only have to check the cell painter for CheckBoxCellEditor and ComboBoxCellEditor if this is intended.

//register a checkbox editor for DisplayMode.EDIT 
configRegistry.registerConfigAttribute( 
    EditConfigAttributes.CELL_EDITOR, 
    new CheckBoxCellEditor(), 
    DisplayMode.EDIT, 
    "myCheckboxLabel"); 

//register the checkbox painter DisplayMode.NORMAL 
configRegistry.registerConfigAttribute( 
    CellConfigAttributes.CELL_PAINTER, 
    new CheckBoxPainter(), 
    DisplayMode.NORMAL, 
    "myCheckboxLabel"); 
    
//register a combobox editor for DisplayMode.EDIT 
configRegistry.registerConfigAttribute( 
    EditConfigAttributes.CELL_EDITOR, 
    new ComboBoxCellEditor(Arrays.asList(new String[] {"Value1", "Value2"} )), 
    DisplayMode.EDIT, 
    "myComboBoxLabel"); 
    
//register the combobox painter for DisplayMode.NORMAL 
configRegistry.registerConfigAttribute( 
    EditConfigAttributes.CELL_PAINTER, 
    new ComboBoxPainter(), 
    DisplayMode.EDIT, 
    "myComboBoxLabel");

Data conversion

NatTable renders every information that should be showed within a cell as Strings. To support other data types, conversion is needed. This is done by registering a IDisplayConverter against a cell label.

configRegistry.registerConfigAttribute( 
    CellConfigAttributes.DISPLAY_CONVERTER, 
    new DefaultBooleanDisplayConverter(), 
    "myCheckboxLabel");

The above snippet configures the DefaultBooleanDisplayConverter for cells with label myCheckboxLabel

There are several default converter shipped with the NatTable:

  • DefaultDisplayConverter
  • DefaultCharacterDisplayConverter
  • DefaultBooleanDisplayConverter
  • DefaultByteDisplayConverter
  • DefaultShortDisplayConverter
  • DefaultIntegerDisplayConverter
  • DefaultLongDisplayConverter
  • DefaultFloatDisplayConverter
  • DefaultDoubleDisplayConverter
  • DefaultBigIntegerDisplayConverter
  • DefaultBigDecimalDisplayConverter
  • DefaultDateDisplayConverter
  • PercentageDisplayConverter

Note that the provided default converter are simple default implementations. If you need a more specific conversion, e.g. convert double values via NumberFormat, you'll have to create your own.
Feel free to contribute any generic converter that fits into the NatTable.

To create your own IDisplayConverter you should choose one of the existing abstract implementations dependent on your requirements:

  • DisplayConverter
    extend this class to support simple value conversion.
  • ContextualDisplayConverter
    extend this class to support value conversion dependent on additional context information.

If you want to use specialized conversion failure messages, you need to throw a ConversionFailedException that will be evaluated by the configured error handling strategy (see below).

Data validation

You can configure data validation rules for the editable cells of the NatTable instance. Model updates will only be applied to the underlying list if if they pass the validation check. To add data validation to the NatTable you have to register a IDataValidator against a cell label.

configRegistry.registerConfigAttribute( 
    EditConfigAttributes.DATA_VALIDATOR, 
    getSecurtityIdValidator(), 
    DisplayMode.EDIT, 
    "myCellLabel");

The above snippets shows how to configure using the data validator returned by getSecurtityIdValidator() on commiting values for cells with label myCellLabel

To create your own IDataValidator you should choose one of the existing abstract implementations dependent on your requirements:

  • DataValidator
    extend this class to support simple data validation.
  • ContextualDataValidator
    extend this class to support data validation dependent on additional context information.

If you want to use specialized validation failure messages, you need to throw a ValidationFailedException that will be evaluated by the configured error handling strategy (see below).

Error handling

Conversion and validation errors will always result in not updating the values of the underlying list. How these errors are handled within the UI can be configured in NatTable. Currently the following error handling strategies are supported:

  • LoggingErrorHandling
    Will only write a log entry with the conversion/validation error message. Default if no other error handling is registered.
  • DiscardValueErrorHandling
    Will only close the open editor which discards the entered value without updating the values of the underlying list.
  • DialogErrorHandling
    Will show a dialog with the conversion/validation error message and the option to discard or change the entered value. Discard will close the editor without updating the values of the underlying list, Change will leave the editor open to allow corrections.
  • RenderErrorHandling
    Used to visualize errors on entering them into a TextCellEditor. It is set by default to render entered values with a red font color for handling conversion and validation errors.

It is also possible to wrap those handlers, for example to open a dialog and write a log entry the same time.

The following code snippet from the EditErrorHandlingExample shows how to add DialogErrorHandling for conversion and validation errors.

configRegistry.registerConfigAttribute( 
    EditConfigAttributes.CONVERSION_ERROR_HANDLER, 
    new DialogErrorHandling(), 
    DisplayMode.EDIT, 
    EditErrorHandlingExample.COLUMN_FOUR_LABEL); 
    
configRegistry.registerConfigAttribute( 
    EditConfigAttributes.VALIDATION_ERROR_HANDLER, 
    new DialogErrorHandling(), 
    DisplayMode.EDIT, 
    EditErrorHandlingExample.COLUMN_FOUR_LABEL);

If you want to change the error handling while editing within the TextCellEditor you need to set your customized IEditErrorHandler as inputConversionErrorHandler or inputValidationErrorHandler.

It is not allowed to set those handlers to null.

Text editor control decoration

If you want to present the user with some more contextual information in a non-intrusive manner then you can use a ControlDecoration. This allows you to show a small icon, e.g. an error or info/warning icon, to one side of the editor and when the mouse is hovered over it then a tooltip is shown with a text info message. If you're not familiar with ControlDecorations you'll almost definitely have seen them in action in Eclipse as it's how some content-assist info is presented!

For example, here's a text editor with a control decoration set to show on the top, left of the editor, with the mouse hovering over the icon hence showing the tooltip:

Text editor control decoration

This is very simple to achieve (snippet from EditableGridExample):

TextCellEditor textCellEditor = new TextCellEditor(); 
textCellEditor.setErrorDecorationEnabled(true); 
textCellEditor.setErrorDecorationText( 
    "Security Id must be 3 alpha characters optionally followed by numbers"); 
textCellEditor.setDecorationPositionOverride(SWT.LEFT | SWT.TOP); 

configRegistry.registerConfigAttribute( 
    EditConfigAttributes.CELL_EDITOR, 
    textCellEditor, 
    DisplayMode.NORMAL, 
    SECURITY_ID_EDITOR);

This works in tandem with the cells ICellValidator (and internally with the TextCellEditors RenderErrorHandling instances).

You can get further access for customization by calling TextCellEditor.getDecorationProvider() e.g. to force the hover text to be shown immediately rather than on hover. The returned ControlDecorationProvider can also be reused in your own custom editors.

How are cell values commited

A cell editor fires an UpdateDataCommand to commit the new value for a cell. This command is handled by the DataLayer via the UpdateDataCommandHandler. Ultimately the IDataProvider will update the underlying data structure.

Update data command handling

Handling the data update differently

If you want to execute a custom action when the user edits a cell you will have to:

  1. Deregister the UpdateDataCommandHandler
  2. Register your custom command handler for handling the UpdateDataCommand

The code will look something like this

bodyDataLayer.unregisterCommandHandler(UpdateDataCommand.class); 
bodyDataLayer.registerCommandHandler(new MyUpdateDataCommandHandler());