Home » Eclipse Projects » GEF » [GEF4] drag relocation, how to update the model
| [GEF4] drag relocation, how to update the model [message #1713522] |
Wed, 04 November 2015 13:39  |
Eclipse User |
|
|
|
With these binding, a visual can be dragged around:
adapterMapBinder
.addBinding(AdapterKey.get(FXTransformPolicy.class))
.to(FXTransformPolicy.class);
adapterMapBinder
.addBinding( AdapterKey.get(FXClickDragTool.DRAG_TOOL_POLICY_KEY))
.to(FXTranslateSelectedOnDragPolicy.class);
My model objects have a position (x/y), their size is automatic set by the contained text.
Now when I move around the items it works. But there is no connection/update to my model.
But when i change the position in the model and refresh the visuals, it get shown perfectly.
e.g.
1. model pos: 10, 25
2. mouse drag: +50, 0 -> shows item at 60, 25
3. change model from 10, 25 -> 15, 25, the item is shown at 65, 25.
So the mouse dragging offset is stored not in the model, it is in the visuals. From browsing the code, i see it is related to some affine transforms.
How can I reset the stored information in the visual, and update my model, so the visual output stays the same?
I want to persist the updated position.
|
|
|
| Re: [GEF4] drag relocation, how to update the model [message #1713573 is a reply to message #1713522] |
Thu, 05 November 2015 04:14   |
Eclipse User |
|
|
|
Hi,
your observations are correct, the translation is not carried over to the model. In order to achieve that, you have to extend the FXTransformPolicy class and in it the #commit() method as follows to update the model accordingly:
@Override
public ITransactionalOperation commit() {
ITransactionalOperation visualOperation = super.commit();
ITransactionalOperation modelOperation = createUpdateModelOperation();
ForwardUndoCompositeOperation commit = new ForwardUndoCompositeOperation("Translate()");
if (visualOperation != null) commit.add(visualOperation);
if (modelOperation != null) commit.add(modelOperation);
return commit.unwrap(true);
}
So, at first the "update visual operation" is retrieved from the super class. After that, an "update model operation" is created that applies the changes to the data model. The two operations are then composed into one ForwardUndoCompositeOperation, so that the visual operation will always be executed/undone before the model operation.
This composite operation is then returned and executed on the operation history.
All in all, what you need to do, so that the model is changed along with the visualization:
* Create a UpdateModelOperation class (e.g. ChangeItemPositionOperation), implementing ITransactionalOperation, that performs the model changes.
* Create a CustomTransformPolicy class (e.g. ItemTransformPolicy), extending FXTransformPolicy, overriding #commit() as outlined above.
* Bind the CustomTransformPolicy instead of the FXTransformPolicy under the AdapterKey.get(FXTransformPolicy.class) key.
Best regards,
Matthias
|
|
| | | | | |
| Re: [GEF4] drag relocation, how to update the model [message #1713797 is a reply to message #1713721] |
Fri, 06 November 2015 11:35   |
Eclipse User |
|
|
|
Hi Frank,
I just looked into it, and it looks promising 
However, a few things stuck out:
- The content parts declare a field for their visual. However, the AbstractVisualPart class already defines such a field ("visual"), together with an accessor ("getVisual()"). Therefore, the ModelPart does not need to hold a reference to its "contentLayer" and the TextNodePart does not need to hold a reference ot its "group".
- The name "contentLayer" is a little bit confusing as the GEF4 MVC FXRootPart already defines a "content layer", "feedback layer", and "handle layer".
- The model position is not applied using the node transformation. This is not a requirement, however, it would make the code easier to reason about as the translation (in the node transformation) would exactly match the model position. For example, there would not be a need to remove the translation from the transformation when writing the translation to the model later.
- The model operation is currently not undoable/redoable. Normally, the redo() method is implemented by calling execute() and the undo() method is implemented separately to perform the opposite of the execute() method.
- The model operation accesses the node transformation. In this specific case, the visual operation will always be executed before the model operation. Therefore, it should be OK to access the node transformation at this point. However, you could also pass-in translation parameters into the constructor of the model operation. These translation values can once be computed from the node transformation within the custom FXTransformPolicy.
If you have any questions, let me know. I can also provide you with a revised version that implements these changes.
Best regards,
Matthias
|
|
|
| Re: [GEF4] drag relocation, how to update the model [message #1713836 is a reply to message #1713797] |
Fri, 06 November 2015 15:29   |
Eclipse User |
|
|
|
Hi Matthias,
thank you for taking the time to look into it and write all this suggestions.
Quote:The content parts declare a field for their visual. However, the AbstractVisualPart class already defines such a field ("visual"), together with an accessor ("getVisual()"). Therefore, the ModelPart does not need to hold a reference to its "contentLayer" and the TextNodePart does not need to hold a reference ot its "group".
Quote:The name "contentLayer" is a little bit confusing as the GEF4 MVC FXRootPart already defines a "content layer", "feedback layer", and "handle layer".
True, i changed this.
Quote:The model position is not applied using the node transformation. This is not a requirement, however, it would make the code easier to reason about as the translation (in the node transformation) would exactly match the model position. For example, there would not be a need to remove the translation from the transformation when writing the translation to the model later.
So if i get you right, this means, i could create my visuals as position 0/0, and make the position with the TransformPolicy Tx/y only?
Quote:The model operation is currently not undoable/redoable. Normally, the redo() method is implemented by calling execute() and the undo() method is implemented separately to perform the opposite of the execute() method.
I don't even look into this aspect, but wanted to do it in a later step.
Quote:The model operation accesses the node transformation. In this specific case, the visual operation will always be executed before the model operation. Therefore, it should be OK to access the node transformation at this point. However, you could also pass-in translation parameters into the constructor of the model operation. These translation values can once be computed from the node transformation within the custom FXTransformPolicy.
So the clean way to write code for this is
1. creation time of the operation, get all information needed and store in the operation.
2. in execute/undo/redo, use the information.
When you already offered to give an implementation, that would be very welcome.
|
|
| | | |
| Re: [GEF4] drag relocation, how to update the model [message #1714576 is a reply to message #1714101] |
Fri, 13 November 2015 11:33  |
Eclipse User |
|
|
|
Hi Frank,
sorry for the late answer, I will give it another look this weekend.
> So if i get you right, this means, i could create my visuals as position 0/0, and make the position with the TransformPolicy Tx/y only?
Yes, exactly. So that within doRefreshVisual() the tx/ty values of the transformation are set to the model position. Then, when the new position is written to the model, the node transformation can remain the same.
> So the clean way to write code for this is
> 1. creation time of the operation, get all information needed and store in the operation.
> 2. in execute/undo/redo, use the information.
Yes. However, an operation should also be safe against multiple execute() or undo() calls. An operation knows two states: initial state, and final state. Additionally, there is the current state of the object that is modified by the operation. An operation is able to transition from the current state of an object to either the final state (execute()) or the initial state (undo()).
Best regards,
Matthias
|
|
|
Goto Forum:
Current Time: Sat Nov 08 05:36:08 EST 2025
Powered by FUDForum. Page generated in 0.04871 seconds
|