blob: 39d621fe7de58e841dae3bcd810c039dd84a7144 [file] [log] [blame]
<div id="midcolumn">
<h3>Editing</h3>
<div id="doccontent">
<div class="chapter">
<div class="content">
<p>NatTable supports the following editing features:
<ol>
<li>Inline cell editing via a text box, combobox or a checkbox</li>
<li>Multiple values can be edited simultaneously via a popup on pressing F2</li>
<li>Editing updates the underlying list data structure</li>
</ol>
There is no special layer needed to enable editing in NatTable. Everything is done via configuration.
</p>
<p>
The default cell editing configuration is provided by the <span class="code">DefaultEditConfiguration</span>
that is used by the <span class="code">DefaultGridLayerConfiguration</span>. This default configuration
tells the NatTable to be not editable and sets the <span class="code">TextCellEditor</span> 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.<br/>
To enable editing on user interactions, several bindings need to be configured. The default bindings are
configured in the <span class="code">DefaultEditBindings</span> configuration, which is also part of the
<span class="code">DefaultGridLayerConfiguration</span>.
</p>
<p>
The <span class="code">EditableGridExample</span> and <span class="code">EditErrorHandlingExample</span>
are the best places to look at.
</p>
</div>
</div>
<div class="chapter">
<h5>Making cells editable</h5>
<div class="content">
<p>
Editing is turned <i>off</i> by default. To enable editing an <span class="code">IEditableRule</span> has to be
registered. Usually you will register an <span class="code">IEditableRule</span> against a cell label
if you only want to enable editing for specific conditions like shown in the code below:
</p>
<div class="codeBlock">configRegistry.registerConfigAttribute(
EditConfigAttributes.CELL_EDITABLE_RULE,
IEditableRule.ALWAYS_EDITABLE,
DisplayMode.EDIT,
"myCellLabel");</div>
<p class="subline">Set cells with label <i>myCellLabel</i> to be always editable</p>
<p>
You can also create your own <span class="code">IEditableRule</span> if you need to decide whether
a cell should be editable or not. Just ensure that <span class="code">IEditableRule.isEditable()</span>
returns <span class="code">true</span> if your cell should be editable.<br/>
Creating your own <span class="code">IEditableRule</span> is useful if you want to register an
<span class="code">IEditableRule</span> globally (instead of only for a specific cell label) that
reacts on a global flag (like enable/disable editing in the UI).
</p>
</div>
</div>
<div class="chapter">
<h5>Cell editor</h5>
<div class="content">
<p>
This is the widget which gets activated when a cell is put into edit mode. A cell editor needs to
implement the <span class="code">ICellEditor</span> interface.
The following editors are provided out of the box:
<ul>
<li>TextCellEditor</li>
<li>CheckBoxCellEditor</li>
<li>ComboBoxCellEditor</li>
<li>PasswordCellEditor (as a specialization of TextCellEditor)</li>
</ul>
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:
</p>
<div class="codeBlock">configRegistry.registerConfigAttribute(
EditConfigAttributes.CELL_EDITOR,
new CheckBoxCellEditor(),
DisplayMode.EDIT,
"myCheckboxLabel");</div>
<p class="subline">Use a CheckBoxCellEditor for cells with label <i>myCheckboxLabel</i></p>
<p>
While <span class="code">TextCellEditor</span> and <span class="code">CheckBoxCellEditor</span>
can be created without additional information, the <span class="code">ComboBoxCellEditor</span>
needs the list of values contained within the combobox.
</p>
<p>
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.
<ul>
<li>TextCellEditor - TextPainter</li>
<li>CheckBoxCellEditor - CheckBoxPainter</li>
<li>ComboBoxCellEditor - ComboBoxPainter</li>
<li>PasswordCellEditor - PasswordTextPainter</li>
</ul>
As <span class="code">TextCellEditor</span> and <span class="code">TextPainter</span> are configured
by default, you only have to check the cell painter for <span class="code">CheckBoxCellEditor</span> and
<span class="code">ComboBoxCellEditor</span> if this is intended.
<div class="codeBlock">//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");</div>
<p class="subline">Ensure to use the matching cell painter together with the editor</p>
</p>
</div>
</div>
<div class="chapter">
<h5>Data conversion</h5>
<div class="content">
<p>
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 <span class="code">IDisplayConverter</span>
against a cell label.
</p>
<div class="codeBlock">configRegistry.registerConfigAttribute(
CellConfigAttributes.DISPLAY_CONVERTER,
new DefaultBooleanDisplayConverter(),
"myCheckboxLabel");</div>
<p class="subline">Use the DefaultBooleanDisplayConverter for cells with label <i>myCheckboxLabel</i></p>
<p>
There are several default converter shipped with the NatTable:
<ul>
<li>DefaultDisplayConverter</li>
<li>DefaultCharacterDisplayConverter</li>
<li>DefaultBooleanDisplayConverter</li>
<li>DefaultByteDisplayConverter</li>
<li>DefaultShortDisplayConverter</li>
<li>DefaultIntegerDisplayConverter</li>
<li>DefaultLongDisplayConverter</li>
<li>DefaultFloatDisplayConverter</li>
<li>DefaultDoubleDisplayConverter</li>
<li>DefaultBigIntegerDisplayConverter</li>
<li>DefaultBigDecimalDisplayConverter</li>
<li>DefaultDateDisplayConverter</li>
<li>PercentageDisplayConverter</li>
</ul>
</p>
<p>
Note that the provided default converter are simple default implementations. If you need a more
specific conversion, e.g. convert double values via <span class="code">NumberFormat</span>, you'll
have to create your own. <br/>
Feel free to contribute any generic converter that fits into the NatTable.
</p>
<p>
To create your own <span class="code">IDisplayConverter</span> you should choose one of the
existing abstract implementations dependent on your requirements:
<ul>
<li>DisplayConverter<br/>
extend this class to support simple value conversion. </li>
<li>ContextualDisplayConverter<br/>
extend this class to support value conversion dependent on additional context information.</li>
</ul>
If you want to use specialized conversion failure messages, you need to
throw a <span class="code">ConversionFailedException</span> that will be evaluated by the
configured error handling strategy (see below).
</p>
</div>
</div>
<div class="chapter">
<h5>Data validation</h5>
<div class="content">
<p>
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 <span class="code">IDataValidator</span>
against a cell label.
</p>
<div class="codeBlock">configRegistry.registerConfigAttribute(
EditConfigAttributes.DATA_VALIDATOR,
getSecurtityIdValidator(),
DisplayMode.EDIT,
"myCellLabel");</div>
<p class="subline">Use the data validator returned by getSecurtityIdValidator() on commiting values
for cells with label <i>myCellLabel</i></p>
<p>
To create your own <span class="code">IDataValidator</span> you should choose one of the
existing abstract implementations dependent on your requirements:
<ul>
<li>DataValidator<br/>
extend this class to support simple data validation. </li>
<li>ContextualDataValidator<br/>
extend this class to support data validation dependent on additional context information.</li>
</ul>
If you want to use specialized validation failure messages, you need to
throw a <span class="code">ValidationFailedException</span> that will be evaluated by the
configured error handling strategy (see below).
</p>
</div>
</div>
<div class="chapter">
<h5>Error handling</h5>
<div class="content">
<p>
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:
<ul>
<li>LoggingErrorHandling<br/>
Will only write a log entry with the conversion/validation error message.
Default if no other error handling is registered.</li>
<li>DiscardValueErrorHandling<br/>
Will only close the open editor which discards the entered value without updating the values of
the underlying list.</li>
<li>DialogErrorHandling<br/>
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.</li>
<li>RenderErrorHandling<br/>
Used to visualize errors on entering them into a <span class="code">TextCellEditor</span>.
It is set by default to render entered values with a red font color for handling conversion
and validation errors.
</li>
</ul>
It is also possible to wrap those handlers, for example to open a dialog and write a log entry
the same time.
</p>
<p>
The following code shows how to add <span class="code">DialogErrorHandling</span> for conversion
and validation errors.
<div class="codeBlock">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);</div>
<p class="subline">Snippet from EditErrorHandlingExample</p>
</p>
<p>
If you want to change the error handling while editing within the <span class="code">TextCellEditor</span>
you need to set your customized <span class="code">IEditErrorHandler</span> as inputConversionErrorHandler
or inputValidationErrorHandler.
</p>
<p>
It is not allowed to set those handlers to <span class="code">null</span>.
</p>
</div>
</div>
<div class="chapter">
<h5>Text editor control decoration</h5>
<div class="content">
<p>
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!
</p>
<p>
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:
</p>
<p style="text-align: center;">
<img align="middle" src="images/control_decoration_during_editing.png" border="0" alt="Text editor control decoration" width="448"/>
</p>
<p>
This is very simple to achieve:
<div class="codeBlock">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);</div>
<p class="subline">Snippet from EditableGridExample</p>
This works in tandem with the cells ICellValidator (and internally with the TextCellEditors RenderErrorHandling instances).
</p>
<p>
You can get further access for customization by calling <span class="code">TextCellEditor.getDecorationProvider()</span>
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.
</p>
</div>
</div>
<div class="chapter">
<h5>How are cell values commited</h5>
<div class="content">
<p>
A cell editor fires an <span class="code">UpdateDataCommand</span> to commit the new value for a cell.
This command is handled by the <span class="code">DataLayer</span> via the <span class="code">UpdateDataCommandHandler</span>.
Ultimately the <span class="code">IDataProvider</span> will update the underlying data structure.
</p>
<img align="middle" src="images/updateDataCommandHandling.png" border="0" alt="Update data command handling"/>
</div>
</div>
<div class="chapter">
<h5>Handling the data update differently</h5>
<div class="content">
<p>
If you want to execute a custom action when the user edits a cell you will have to:
<ol>
<li>Deregister the UpdateDataCommandHandler</li>
<li>Register your custom command handler for handling the UpdateDataCommand</li>
</ol>
</p>
<p>The code will look something like this</p>
<div class="codeBlock">bodyDataLayer.unregisterCommandHandler(UpdateDataCommand.class);
bodyDataLayer.registerCommandHandler(new MyUpdateDataCommandHandler());</div>
</div>
</div>
</div>
</div>