As described in the chapter “providing add functionality” the values of the business objects (e.g. the EClass name) are stored in the graphics algorithm of the pictogram elements. But this is done only once. If the business model changes the example editor does not realize the changes.
For that purpose we need an update feature which is used by the editor to react on business model changes.
The behavior of the update is straight forward, when the user is changing the domain model directly via the diagram. For example if the user changes a text in the diagram using direct-editing or the property-sheet, then this text should be changed in the diagram immediately.
However, if the domain-model is changed outside the diagram (e.g. in a separate editor, maybe even by another user), then it is questionable, if the diagram should be updated immediately. Often an immediate update would destroy a previously good layout or hide previously important information. Therefore Graphiti supports two update-strategies:
1. If the automatic update is active, then a change in the business model will immediately update the diagram.
2. If the automatic update is inactive, then a change
in the business model will only mark the changed diagram shapes as outdated.
The user can then manually update the outdated shapes.
Figure: Shape marked as outdated (tooltip shows reason)
Figure: Outdated shape can be updated manually
By default the automatic update is inactive, but this can be configured by overwriting the following methods in the IDiagramTypeProvider:
An update feature has to implement the interface IUpdateFeature. Instead of implementing it directly it should extend one of the available base classes. In this example we extend the base class AbstractUpdateFeature.
In this case we have to implement/overwrite 3 methods:
The method canUpdate has to check whether the values of the current pictogram element of the given context can be updated.
The method update has to update this pictogram element. It has to copy the latest values from the business objects to the graphics algorithm of this pictogram element.
The method updateNeeded has to check whether the values in the pictogram element are up to date, that means whether the graphics algorithm of this pictogram element contain the latest values from the business objects.
Hint: An update feature can and should also be used (called) if any functionality of the editor (e.g. any custom feature) modifies parts of the domain model. This works just like the model view controller pattern.
In this example we want to update the EClass name. You can see the complete implementation of the update feature here:
package org.eclipse.graphiti.examples.tutorial.features;
public class TutorialUpdateEClassFeature extends AbstractUpdateFeature {
public TutorialUpdateEClassFeature(IFeatureProvider fp) { super(fp); }
public boolean canUpdate(IUpdateContext context) { // return true, if linked business object is a EClass Object bo = getBusinessObjectForPictogramElement(context.getPictogramElement()); return (bo instanceof EClass); }
public IReason updateNeeded(IUpdateContext context) { // retrieve name from pictogram model String pictogramName = null; PictogramElement pictogramElement = context.getPictogramElement(); if (pictogramElement instanceof ContainerShape) { ContainerShape cs = (ContainerShape) pictogramElement; for (Shape shape : cs.getChildren()) { if (shape.getGraphicsAlgorithm() instanceof Text) { Text text = (Text) shape.getGraphicsAlgorithm(); pictogramName = text.getValue(); } } }
// retrieve name from business model String businessName = null; Object bo = getBusinessObjectForPictogramElement(pictogramElement); if (bo instanceof EClass) { EClass eClass = (EClass) bo; businessName = eClass.getName(); }
// update needed, if names are different boolean updateNameNeeded = ((pictogramName == null && businessName != null) || (pictogramName != null && !pictogramName.equals(businessName))); if (updateNameNeeded) { return Reason.createTrueReason("Name is out of date"); } else { return Reason.createFalseReason(); } }
public boolean update(IUpdateContext context) { // retrieve name from business model String businessName = null; PictogramElement pictogramElement = context.getPictogramElement(); Object bo = getBusinessObjectForPictogramElement(pictogramElement); if (bo instanceof EClass) { EClass eClass = (EClass) bo; businessName = eClass.getName(); }
// Set name in pictogram model if (pictogramElement instanceof ContainerShape) { ContainerShape cs = (ContainerShape) pictogramElement; for (Shape shape : cs.getChildren()) { if (shape.getGraphicsAlgorithm() instanceof Text) { Text text = (Text) shape.getGraphicsAlgorithm(); text.setValue(businessName); return true; } } }
return false; } }
|
Additionally the feature provider has to deliver our newly created feature (overwrite the method getUpdateFeature).
This implementation can be seen here:
@Override public IUpdateFeature getUpdateFeature(IUpdateContext context) { PictogramElement pictogramElement = context.getPictogramElement(); if (pictogramElement instanceof ContainerShape) { Object bo = getBusinessObjectForPictogramElement(pictogramElement); if (bo instanceof EClass) { return new TutorialUpdateEClassFeature(this); } } return super.getUpdateFeature(context); }
|
Note: if the Graphiti project wizard for a "New Graphiti Sample Project" does not work correctly and you can not test the update feature as described below, please continue with the next chapters and provide custom functionality to rename a EClass. That will allow testing the update feature by changing the same EClass in two different diagrams.
Now start the editor again and test it: