| <html> |
| |
| <head> |
| <meta content="text/html; charset=utf-8" http-equiv="Content-Type"> |
| <title>Providing update functionality</title> |
| <link href="../book.css" rel="Stylesheet" type="text/css"> |
| <link href="../code.css" rel="Stylesheet" type="text/css"> |
| </head> |
| |
| <body> |
| |
| <h1>Providing Update Functionality</h1> |
| <h2>Strategies for Update</h2> |
| <p>As described in the chapter “<a href="add-feature.htm">providing add functionality</a>” |
| 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.</p> |
| <p>For that purpose we need an update feature which is used by the editor to react |
| on business model changes.</p> |
| <p> </p> |
| <p>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. </p> |
| <p>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:</p> |
| <ol> |
| <li>If the <b>automatic update is active</b>, then a change in the business |
| model will immediately update the diagram.</li> |
| <li>If the <b>automatic update is inactive</b>, 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.<br></li> |
| </ol> |
| <p> </p> |
| <p> |
| <img alt="" border="0" height="114" src="visio/outdated-shape.gif" width="264"></p> |
| <p><strong>Figure: Shape marked as outdated (tooltip shows reason)</strong></p> |
| <p> </p> |
| <p> |
| <img alt="" border="0" height="125" src="visio/outdated-shape-update.gif" width="225"></p> |
| <p><strong>Figure: Outdated shape can be updated manually</strong></p> |
| <p> </p> |
| <p>By default the automatic update is inactive, but this can be configured by overwriting |
| the following methods in the |
| <a href="../../../javadoc/org/eclipse/graphiti/dt/IDiagramTypeProvider.html">IDiagramTypeProvider</a>:</p> |
| <ul> |
| <li>If |
| <a href="../../../javadoc/org/eclipse/graphiti/dt/IDiagramTypeProvider.html#isAutoUpdateAtStartup()"> |
| isAutoUpdateAtStartup</a> returns true, then the diagram will be updated, when |
| it is initially opened in the graphical editor. This will make the editor dirty. |
| </li> |
| <li>If |
| <a href="../../../javadoc/org/eclipse/graphiti/dt/IDiagramTypeProvider.html#isAutoUpdateAtRuntime()"> |
| isAutoUpdateAtRuntime</a> returns true, then the diagram will be updated, when |
| it is already open in the graphical editor, but only if the editor is already |
| dirty.</li> |
| <li>If |
| <a href="../../../javadoc/org/eclipse/graphiti/dt/IDiagramTypeProvider.html#isAutoUpdateAtReset()"> |
| isAutoUpdateAtReset</a> returns true, then the diagram will be updated, if the |
| editor is already dirty and the user chooses to discard his changes (reset the |
| diagram), when a change from outside the diagram occurs.</li> |
| </ul> |
| <h2>Creating an Update Feature</h2> |
| <p>An update feature has to implement the interface |
| <a href="../../../javadoc/org/eclipse/graphiti/features/IUpdateFeature.html">IUpdateFeature</a>. |
| Instead of implementing it directly it should extend one of the available base classes. |
| In this example we extend the base class |
| <a href="../../../javadoc/org/eclipse/graphiti/features/impl/AbstractUpdateFeature.html"> |
| AbstractUpdateFeature</a></p> |
| <p>In this case we have to implement/overwrite 3 methods:</p> |
| <ul> |
| <li>The method |
| <a href="../../../javadoc/org/eclipse/graphiti/func/IUpdate.html#canUpdate(org.eclipse.graphiti.features.context.IUpdateContext)"> |
| canUpdate</a> has to check whether the values of the current pictogram element |
| of the given context can be updated.</li> |
| <li>The method |
| <a href="../../../javadoc/org/eclipse/graphiti/func/IUpdate.html#update(org.eclipse.graphiti.features.context.IUpdateContext)"> |
| update</a> 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.</li> |
| <li>The method |
| <a href="../../../javadoc/org/eclipse/graphiti/func/IUpdate.html#updateNeeded(org.eclipse.graphiti.features.context.IUpdateContext)"> |
| updateNeeded</a> 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. </li> |
| </ul> |
| <p><b><u>Hint:</u></b> 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.</p> |
| <p>In this example we want to update the EClass name. You can see the complete implementation |
| of the update feature here:</p> |
| <p> </p> |
| <div class="literallayout"> |
| <div class="incode"> |
| <p class="code"><span class="keyword">package </span>org.eclipse.graphiti.examples.tutorial.features;<br> <br> |
| <span class="keyword">public class</span> TutorialUpdateEClassFeature |
| <span class="keyword">extends </span>AbstractUpdateFeature {<br> <br> |
| <span class="keyword">public </span>TutorialUpdateEClassFeature(IFeatureProvider |
| fp) {<br> |
| <span class="keyword">super</span>(fp);<br> }<br> <br> |
| <span class="keyword">public boolean</span> canUpdate(IUpdateContext context) |
| {<br> <span class="comment">// |
| return true, if linked business object is a EClass</span><br> |
| Object bo =<br> |
| getBusinessObjectForPictogramElement(context.getPictogramElement());<br> |
| <span class="keyword">return </span>(bo <span class="keyword">instanceof |
| </span>EClass);<br> }<br> <br> |
| <span class="keyword">public </span>IReason updateNeeded(IUpdateContext |
| context) {<br> |
| <span class="comment">// retrieve name from pictogram model</span><br> |
| String pictogramName = <span class="keyword">null</span>;<br> |
| PictogramElement pictogramElement = context.getPictogramElement();<br> |
| <span class="keyword">if </span>(pictogramElement <span class="keyword"> |
| instanceof </span>ContainerShape) {<br> |
| ContainerShape cs = (ContainerShape) pictogramElement;<br> |
| <span class="keyword">for </span>(Shape shape : cs.getChildren()) {<br> |
| <span class="keyword">if </span>(shape.getGraphicsAlgorithm() |
| <span class="keyword">instanceof </span>Text) {<br> |
| Text text = (Text) shape.getGraphicsAlgorithm();<br> |
| pictogramName = text.getValue();<br> |
| }<br> |
| }<br> }<br> <br> |
| <span class="comment">// retrieve name from business model</span><br> |
| String businessName = <span class="keyword">null</span>;<br> |
| Object bo = getBusinessObjectForPictogramElement(pictogramElement);<br> |
| <span class="keyword">if </span>(bo <span class="keyword">instanceof |
| </span>EClass) {<br> |
| EClass eClass = (EClass) bo;<br> |
| businessName = eClass.getName();<br> |
| }<br> <br> |
| <span class="comment">// update needed, if names are different</span><br> |
| <span class="keyword">boolean </span>updateNameNeeded =<br> |
| ((pictogramName == <span class="keyword">null </span>&& businessName != |
| <span class="keyword">null</span>) || <br> |
| (pictogramName != <span class="keyword">null </span>&& !pictogramName.equals(businessName)));<br> |
| <span class="keyword">if </span>(updateNameNeeded) {<br> |
| <span class="keyword">return </span>Reason.createTrueReason(<span class="string">"Name |
| is out of date"</span>);<br> } |
| <span class="keyword">else </span>{<br> |
| <span class="keyword">return </span>Reason.createFalseReason();<br> |
| }<br> }<br> <br> |
| <span class="keyword">public boolean</span> update(IUpdateContext context) |
| {<br> <span class="comment">// |
| retrieve name from business model</span><br> |
| String businessName = <span class="keyword">null</span>;<br> |
| PictogramElement pictogramElement = context.getPictogramElement();<br> |
| Object bo = getBusinessObjectForPictogramElement(pictogramElement);<br> |
| <span class="keyword">if </span>(bo <span class="keyword">instanceof |
| </span>EClass) {<br> |
| EClass eClass = (EClass) bo;<br> |
| businessName = eClass.getName();<br> |
| }<br> <br> |
| <span class="comment">// Set name in pictogram model</span><br> |
| <span class="keyword">if</span> (pictogramElement instanceof ContainerShape) |
| {<br> |
| ContainerShape cs = (ContainerShape) pictogramElement;<br> |
| <span class="keyword">for</span> (Shape shape : cs.getChildren()) {<br> |
| <span class="keyword">if</span> (shape.getGraphicsAlgorithm() |
| <span class="keyword">instanceof </span>Text) {<br> |
| Text text = (Text) shape.getGraphicsAlgorithm();<br> |
| text.setValue(businessName);<br> |
| <span class="keyword">return true</span>;<br> |
| }<br> |
| }<br> }<br> <br> |
| <span class="keyword">return false</span>;<br> }<br>} |
| </p> |
| </div> |
| </div> |
| <p> </p> |
| <p>Additionally the feature provider has to deliver our newly created feature (overwrite |
| the method |
| <a href="../../../javadoc/org/eclipse/graphiti/features/IFeatureProvider.html#getUpdateFeature(org.eclipse.graphiti.features.context.IUpdateContext)"> |
| getUpdateFeature</a>)<i>. </i></p> |
| <p>This implementation can be seen here:</p> |
| <p> </p> |
| <div class="literallayout"> |
| <div class="incode"> |
| <p class="code">@Override<br><span class="keyword">public </span>IUpdateFeature |
| getUpdateFeature(IUpdateContext context) {<br> PictogramElement |
| pictogramElement = context.getPictogramElement();<br> |
| <span class="keyword">if</span> (pictogramElement <span class="keyword"> |
| instanceof </span>ContainerShape) {<br> |
| Object bo = getBusinessObjectForPictogramElement(pictogramElement);<br> |
| <span class="keyword">if </span>(bo <span class="keyword">instanceof |
| </span>EClass) {<br> |
| <span class="keyword">return new</span> TutorialUpdateEClassFeature(<span class="keyword">this</span>);<br> |
| }<br> }<br> <span class="keyword">return super</span>.getUpdateFeature(context);<br> |
| } </p> |
| </div> |
| </div> |
| <p> </p> |
| <h2>Test: Update a EClass Name</h2> |
| <p><strong>Note:</strong> if the Graphiti project wizard for a "<a href="example-projects.htm">New |
| Graphiti Sample Project</a>" does not work correctly and you can not test the update |
| feature as described below, please continue with the next chapters and |
| <a href="custom-feature.htm">provide custom functionality</a> to rename a EClass. |
| That will allow testing the update feature by changing the same EClass in two different |
| diagrams.</p> |
| <p>Now start the editor again and test it:</p> |
| <ol> |
| <li>create new diagram</li> |
| <li>create a EClass “A” </li> |
| <li>save current diagram</li> |
| <li>move this new EClass to make the diagram editor dirty</li> |
| <li>go to the Project Explorer</li> |
| <li>find the new EClass under "EClasses"</li> |
| <li>rename this EClass via context menu to “B”</li> |
| <li>when you activate the editor, you will receive a popup, choose yes and you |
| will get the updated EClass (since <i>isAutoUpdateAtReset</i> is set to <b>true</b> |
| by default)</li> |
| <li>save current diagram </li> |
| <li>close the editor</li> |
| <li>go to the Project Explorer</li> |
| <li>rename this EClass via context menu to “C”</li> |
| <li>reopen the diagram editor</li> |
| <li>the diagram will not be updated automatically, instead the editor visualizes |
| dirty states, when the editor is activated (since <i>isAutoUpdateAtStartup</i> |
| is set to <b>false</b> by default)</li> |
| <li>move mouse on dirty EClass shape and hit appearing update button. The name |
| "C" should appear.</li> |
| </ol> |
| |
| </body> |
| |
| </html> |