Providing Update Functionality

Strategies for Update

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 diagram does not realize the changes.

For that purpose we need an update feature which is used by the diagram 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 or viewer, 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:

Creating an Update Feature

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:

Hint: An update feature can and should also be used (called) if any functionality of the editor or viewer (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);
}

 

Test: Update a EClass Name

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:

  1. create new diagram
  2. create a EClass "A"
  3. save current diagram
  4. move this new EClass to make the diagram editor dirty
  5. go to the Project Explorer
  6. find the new EClass under "EClasses"
  7. rename this EClass via context menu to "B"
  8. when you activate the editor, you will receive a popup, choose yes and you will get the updated EClass (since isAutoUpdateAtReset is set to true by default)
  9. save current diagram
  10. close the editor
  11. go to the Project Explorer
  12. rename this EClass via context menu to "C"
  13. reopen the diagram editor
  14. the diagram will not be updated automatically, instead the editor visualizes dirty states, when the editor is activated (since isAutoUpdateAtStartup is set to false by default)
  15. move mouse on dirty EClass shape and hit appearing update button. The name "C" should appear.