Saturday, November 7, 2015

GEF4 Tutorial - Part 5 - Editing text

In step 5 of this tutorial, the text nodes can be edited in the UI directly.

For the source of this tutorial step see github - gef4.mvc.tutorial5.


Note: parts of this tutorial are copied from other examples or from forum postings.

The text shall be editable when double clicked, or if the node is selected and ENTER is hit. The text is single line only. 
The text if ENTER is hit while editing. In case of ESC or if the focus is changed the edited test is discarded.













After the text is accepted the node size is adjusted, by keeping the position (left upper corner) stable.

To implement this the visual of the node is changed to use the StackPane as top level, having a RoundedRectangle, Text and TextField. The StackPane adjusts all widgets to be placed around the same center point. By switching on of the visibility and the managed state, it can show only the Text (normal mode) or the TestField (editing mode).

For this behavior, it is needed to react on mouse double click and on keyboard typing.
The classes TextNodeOnDoubleClickPolicy and TextNodeOnTypePolicy are added to the adapters. The given string for the role, is added to make those adapter not replace existing ones. So the value of the strings is in this case not important, it just must be different to what might be used elsewhere.

adapterMapBinder
    .addBinding( AdapterKey.get(
        FXClickDragTool.CLICK_TOOL_POLICY_KEY,
        "TextNodeOnDoubleClickPolicy"))
    .to( TextNodeOnDoubleClickPolicy.class);

adapterMapBinder
    .addBinding( AdapterKey.get(
        FXTypeTool.TOOL_POLICY_KEY,
        "TextNodeOnTypePolicy"))
    .to( TextNodeOnTypePolicy.class);

The double click policy checks if the click count is 2 and it was the primary button, then call to the part (TextNodePart) the new editModeStart() methods.

The type policy handles more cases in the «pressed» method:
F2 : start editing
ESC : cancel editing
ENTER if not yet in editing: start editing
ENTER if in editing: stop editing and take the value to the model

In case the key event was detected as action, the «event.consume()» shall be called, otherwise I had the case where the event was reported a second time.

The last case to handle is when the user clicks on another node and changes the focus.
For this, the TextNodePart registers/unregisters a listener for the focus model in it's doActivate/doDeactivate methods like this:

getViewer()
    .getAdapter(FocusModel.class)
    .addPropertyChangeListener( this::handleFocusModelUpdate );

If a change is detected and the current selected part is not this TextNodePart, the editing is cancelled.


No comments:

Post a Comment