Skip to main content



      Home
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 Go to next message
Eclipse UserFriend
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 Go to previous messageGo to next message
Eclipse UserFriend
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 #1713593 is a reply to message #1713573] Thu, 05 November 2015 06:19 Go to previous messageGo to next message
Eclipse UserFriend
Hi Matthias,

understood so far.

In createUpdateModelOperation() i can create the ChangeItemPositionOperation and pass in the IVisualPart via getHost(), so i can navigate to the model.

But how do I get to have my dragging offset as x/y?
This transformations, I don't understand them so far. Where should I start to read, to get an understanding?

thx
Frank

Re: [GEF4] drag relocation, how to update the model [message #1713601 is a reply to message #1713593] Thu, 05 November 2015 07:38 Go to previous messageGo to next message
Eclipse UserFriend
The drag offset is stored as the translation of an affine transformation that is maintained for each host. We use a provider to retrieve (and update it). As you can see within FXTransformPolicy.getNodeTransform(), it is obtained via the adapter mechanism:

getHost().getAdapter(TRANSFORM_PROVIDER_KEY).get();


The drag offset can thus be retrieved via the tx and ty values of the node transform.
Re: [GEF4] drag relocation, how to update the model [message #1713605 is a reply to message #1713593] Thu, 05 November 2015 07:49 Go to previous messageGo to next message
Eclipse UserFriend
The translation can be extracted from the transformation as shown by Alexander. However, you also have to take into account how the visual is moved to its model position.

For example, you can carry the model position over to the visual transformation within the AbstractContentPart#doRefreshVisual() method, so that the exact translation values can also be carried over to the model later.

@Override
public void doRefreshVisual(V visual) {
    Affine transform = getHost().getAdapter(TRANSFORM_PROVIDER_KEY).get();
    transform.setTx(getContent().getPositionX());
    transform.setTy(getContent().getPositionY());
}


Best regards,
Matthias
Re: [GEF4] drag relocation, how to update the model [message #1713686 is a reply to message #1713605] Thu, 05 November 2015 18:15 Go to previous messageGo to next message
Eclipse UserFriend
Hi Matthias, Hi Alexander,

Thanks, this works!
My operation now looks like
@Override
public IStatus execute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
	Affine transform = part.getAdapter(FXTransformPolicy.TRANSFORM_PROVIDER_KEY).get();
	// tell the part, which updates the model, will also trigger a doRefreshVisuals
	part.translate(transform.getTx(), transform.getTy()); 
	// reset the transformation
	transform.setTx(0);
	transform.setTy(0);
	return Status.OK_STATUS;
}


A complete working example can be found here:
https://github.com/keinfarbton/gef4.mvc.tutorial/tree/master/gef4.mvc.tutorial4

A description of the example can be found here:
http://fbenoit.blogspot.de/2015/11/gef4-tutorial-part-4-dragging-and-store.html

Frank

Re: [GEF4] drag relocation, how to update the model [message #1713721 is a reply to message #1713686] Fri, 06 November 2015 03:33 Go to previous messageGo to next message
Eclipse UserFriend
Hi Frank,

thank you for sharing, I will have a look into it later today Smile

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 Go to previous messageGo to next message
Eclipse UserFriend
Hi Frank,

I just looked into it, and it looks promising Smile

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 Go to previous messageGo to next message
Eclipse UserFriend
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. Smile
Re: [GEF4] drag relocation, how to update the model [message #1713894 is a reply to message #1713836] Sat, 07 November 2015 11:31 Go to previous messageGo to next message
Eclipse UserFriend
Hi Matthias,

can you please re-check the sources. I think i implemented what you suggested.

Frank
Re: [GEF4] drag relocation, how to update the model [message #1714096 is a reply to message #1713894] Mon, 09 November 2015 16:06 Go to previous messageGo to next message
Eclipse UserFriend
We have shipped Neon M3 today, including a couple of renamings in the FX module. If you need help to adopt your tutorials, please give us feedback.
Re: [GEF4] drag relocation, how to update the model [message #1714101 is a reply to message #1714096] Mon, 09 November 2015 17:00 Go to previous messageGo to next message
Eclipse UserFriend
Thanks for notifying, no problem. The commit message was helpful Wink
Re: [GEF4] drag relocation, how to update the model [message #1714576 is a reply to message #1714101] Fri, 13 November 2015 11:33 Go to previous message
Eclipse UserFriend
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
Previous Topic:[GEF4] How to add a global policy to handle shortcuts
Next Topic:Variable Diagram Size
Goto Forum:
  


Current Time: Sat Nov 08 05:36:08 EST 2025

Powered by FUDForum. Page generated in 0.04871 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top