| <html> |
| |
| <head> |
| <meta content="text/html; charset=utf-8" http-equiv="Content-Type"> |
| <title>Providing context buttons</title> |
| <link href="../book.css" rel="Stylesheet" type="text/css"> |
| <link href="../code.css" rel="Stylesheet" type="text/css"> |
| </head> |
| |
| <body> |
| |
| <h1>Providing Context Buttons</h1> |
| <p>Context buttons allow adding actions as small, automatically appearing icons |
| for each pictogram element in the diagram.</p> |
| <p>They are shown along the borders of a pictogram element when the mouse is positioned |
| on that pictogram element. They are hidden again when the mouse is positioned outside |
| the area built by the pictogram element and the context buttons.</p> |
| <p>Context buttons can provide the same functionality as a |
| <a href="context-menu.htm">context menu</a>, but in a nicer and quicker way: the |
| context buttons are shown immediately. Another advantage of context buttons over |
| context menus is, that each context button can have several drag and drop features, |
| which get activated when the user drags from a context button and drops onto the |
| canvas or another object.</p> |
| <h2>Enhancing the Tool Behavior Provider</h2> |
| <p>Context buttons are defined in the tool behavior provider.</p> |
| <p>If you didn’t do so already you must <b>first create a tool behavior provider |
| and add it to the diagram type provider as described |
| <a href="tool-behavior-provider.htm">here</a>.</b></p> |
| <p>There is one method of the tool behavior provider to overwrite: </p> |
| <p>The method |
| <a href="../../../javadoc/org/eclipse/graphiti/tb/IToolBehaviorProvider.html#getContextButtonPad(org.eclipse.graphiti.features.context.IPictogramElementContext)"> |
| getContextButtonPad</a> has to return the context buttons for the given context |
| (which implement |
| <a href="../../../javadoc/org/eclipse/graphiti/tb/IContextButtonEntry.html">IContextButtonEntry</a>). |
| </p> |
| <p>There are different groups of context buttons:</p> |
| <ul> |
| <li>Generic context buttons: their look and behaviour is standardized for all |
| tools (e.g. “delete”, “remove” and “update”). They are shown at the top of the |
| pictogram element in a predefined order. A specific tool can only choose which |
| of the generic context buttons to switch on/off.</li> |
| <li>Domain specific context buttons: they are specific for each tool (e.g. “create |
| sub-class” in a class editor). They are shown at the right (and if necessary |
| also bottom) of the pictogram element. A specific tool must define the look |
| and behaviour for all domain specific context buttons. </li> |
| <li>Collapse context button: the look and position for the collapse context |
| button is standardized for all tools. A specific tool must define the behavior |
| of the collapse context button by defining the feature to call (see |
| <a href="../../../javadoc/org/eclipse/graphiti/tb/ContextEntryHelper.html#createCollapseContextButton(boolean, org.eclipse.graphiti.features.IFeature, org.eclipse.graphiti.features.context.IContext)"> |
| createCollapseContextButton</a>).</li> |
| </ul> |
| <p>The following restrictions are defined by usability engineers of SAP AG (but |
| currently not checked technically): there can be 0-3 generic context buttons, 0-5 |
| domain specific context buttons and 0-1 collapse context button.</p> |
| <p>The functionality of context buttons is always provided by features. </p> |
| <p>Each context button can have one click-feature, which is executed when clicking |
| the context-button, and/or several drag & drop features, which are executed when |
| the user starts dragging a connection from the context button. If several drag & |
| drop features are available, a context-menu will be offered to the user when he |
| drops the connection, and he can choose the feature to execute.</p> |
| <p>In this example we want to create one context button, which offers all available |
| <a href="create-connection-feature.htm">create connection features</a> as drag & |
| drop features, but has no click-feature. </p> |
| <p> </p> |
| <p> |
| <img alt="" border="0" height="120" src="visio/context-buttons-click.gif" width="353"></p> |
| <p><strong>Figure: A context button, which the user can click or start drag&drop |
| from it</strong></p> |
| <p> </p> |
| <p> </p> |
| <p> |
| <img alt="" border="0" height="102" src="visio/context-buttons-drag.gif" width="353"></p> |
| <p><strong>Figure: The user started dragging from the context button</strong></p> |
| <p> </p> |
| <p>You can see the complete implementation of the context button here:</p> |
| <!-- Begin code ------------------------------------------------------------------------------- --> |
| <p> </p> |
| <div class="literallayout"> |
| <div class="incode"> |
| <p class="code">@Override<br><span class="keyword">public</span> IContextButtonPadData |
| getContextButtonPad(<br> |
| IPictogramElementContext context) {<br> IContextButtonPadData |
| data = super.getContextButtonPad(context);<br> PictogramElement |
| pe = context.getPictogramElement();<br> <br> |
| <span class="comment">// 1. set the generic context buttons</span><br> |
| <span class="comment">// note, that we do not add 'remove' (just as an example)</span><br> |
| setGenericContextButtons(data, pe, <span class="string"><em>CONTEXT_BUTTON_DELETE</em></span> |
| | <br> |
| <span class="string"><em>CONTEXT_BUTTON_UPDATE</em></span>);<br> |
| <br> <span class="comment">// 2. set the collapse button |
| <br> // simply use a dummy custom feature (senseless example)</span><br> |
| CustomContext cc = <span class="keyword">new</span> CustomContext(<span class="keyword">new</span> |
| PictogramElement[] { pe });<br> ICustomFeature[] cf = |
| getFeatureProvider().getCustomFeatures(cc);<br> |
| <span class="keyword">for</span> (<span class="keyword">int</span> i = 0; |
| i < cf.<span class="string"><em>length</em></span>; i++) {<br> |
| ICustomFeature iCustomFeature = cf[i];<br> |
| <span class="keyword">if</span> (iCustomFeature <span class="keyword">instanceof</span> |
| TutorialCollapseDummyFeature) {<br> |
| IContextButtonEntry collapseButton = ContextEntryHelper.<br> |
| createCollapseContextButton(<span class="keyword">true</span>, iCustomFeature, |
| cc);<br> |
| data.setCollapseContextButton(collapseButton);<br> |
| <span class="keyword">break</span>;<br> |
| }<br> }<br> |
| <br> <span class="comment">// 3. add one domain specific |
| context-button, which offers all <br> // available connection-features |
| as drag&drop features...<br></span> <span class="comment"><br> |
| // 3.a. create new CreateConnectionContext</span><br> |
| CreateConnectionContext ccc = <span class="keyword">new</span> CreateConnectionContext();<br> |
| ccc.setSourcePictogramElement(pe);<br> Anchor anchor = |
| <span class="keyword">null</span>;<br> |
| <span class="keyword">if</span> (pe instanceof Anchor) {<br> |
| anchor = (Anchor) pe;<br> } <span class="keyword">else |
| if</span> (pe <span class="keyword">instanceof</span> AnchorContainer) {<br> |
| <span class="comment">// assume, that our shapes always have chopbox anchors</span><br> |
| anchor = Graphiti.getPeService()<br> |
| .getChopboxAnchor((AnchorContainer) pe);<br> }<br> |
| ccc.setSourceAnchor(anchor);<br> |
| <br> <span class="comment">// 3.b. create context button |
| and add all applicable features</span><br> ContextButtonEntry |
| button = <span class="keyword">new</span> ContextButtonEntry(<span class="keyword">null</span>, |
| context);<br> button.setText(<span class="string">"Create |
| connection"</span>);<br> button.setIconId(MyTutorialImageProvider.<span class="string"><em>IMG_EREFERENCE</em></span>);<br> |
| ICreateConnectionFeature[] features =<br> |
| getFeatureProvider().getCreateConnectionFeatures();<br> |
| <span class="keyword">for</span> (ICreateConnectionFeature feature : features) |
| {<br> <span class="keyword">if</span> |
| (feature.isAvailable(ccc) && feature.canStartConnection(ccc))<br> |
| button.addDragAndDropFeature(feature);<br> }<br> <br> |
| <span class="comment">// 3.c. add context button, if it contains at least |
| one feature</span><br> <span class="keyword">if</span> |
| (button.getDragAndDropFeatures().size() > 0) {<br> |
| data.getDomainSpecificContextButtons().add(button);<br> |
| }<br> <br> <span class="keyword">return</span> |
| data;<br>}<br></p> |
| </div> |
| </div> |
| <p> </p> |
| <!-- End code ------------------------------------------------------------------------------- --> |
| <p> </p> |
| <p>The implementation of <em>MyTutorialImageProvider</em> can be found |
| <a href="images.htm">here</a>. The implementation of the <em>TutorialCollapseDummyFeature</em> |
| can be found at <a href="#_Implementation_of_the">the end of this page</a>.</p> |
| <p>The context button entries contain information about icon, display text and tooltip |
| description.</p> |
| <p>The positioning of the context buttons can be influenced by changing the rectangle |
| around which the context buttons are placed (see |
| <a href="../../../javadoc/org/eclipse/graphiti/tb/IContextButtonPadData.html#getPadLocation()"> |
| getPadLocation</a>). By default the selection area is used (see |
| <a href="selection-behavior.htm">selection behavior</a>) if defined, or otherwise |
| the bounds of the pictogram elements main graphics algorithm are used.</p> |
| <h2>Test: Create a Connection by Drag & Drop from a Context Button</h2> |
| <p>Note that previously we implemented one |
| <a href="create-connection-feature.htm">create connection feature</a> which allows |
| creating an association between two EClasses.</p> |
| <p>Now start the editor and test this new context button:</p> |
| <ol> |
| <li>Create or open a diagram and create two EClasses in the diagram.</li> |
| <li>Position the mouse on top of the first EClass and the context button should |
| appear in the south-east of the shape.</li> |
| <li>Start dragging with the mouse from the context-button.</li> |
| <li>Drop the connection onto the second EClass, which will result in one of |
| the following possibilities:<ol> |
| <li>If only one create connection feature for the EClass exists, then the |
| association will be created immediately.</li> |
| <li>If several create connection features for the EClass exist, then a context-menu |
| will be shown to the user, where he can choose the feature to execute. Tip: |
| if you have only one create connection feature you can try this behaviour |
| by simply duplicating the line "button.addDragAndDropFeature(feature);"</li> |
| </ol> |
| </li> |
| </ol> |
| <p>Note, that our implementation of the create connection feature does not allow |
| a connection, if the source and target business object are identical. If you have |
| two different shapes associated with the same business object (e.g. via copy & paste), |
| then creating a connection between them is not possible.</p> |
| <h2>Implementation of the Tutorial Collapse Dummy Feature</h2> |
| <!-- Begin code ------------------------------------------------------------------------------- --> |
| <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> TutorialCollapseDummyFeature |
| <span class="keyword">extends</span> AbstractCustomFeature {<br> <br> |
| <span class="keyword">public</span> TutorialCollapseDummyFeature(IFeatureProvider |
| fp) {<br> |
| <span class="keyword">super</span>(fp);<br> |
| }<br> <br> @Override<br> |
| <span class="keyword">public boolean</span> canExecute(ICustomContext context) |
| {<br> |
| <span class="keyword"> boolean</span> ret = <span class="keyword">false</span>;<br> |
| PictogramElement[] pes = context.getPictogramElements();<br> |
| <span class="keyword">if</span> (pes != <span class="keyword">null</span> |
| && pes.<span class="string"><em>length</em></span> == 1) {<br> |
| Object bo = getBusinessObjectForPictogramElement(pes[0]);<br> |
| <span class="keyword">if</span> (bo <span class="keyword">instanceof</span> |
| EClass) {<br> |
| ret = <span class="keyword">true</span>;<br> |
| }<br> |
| }<br> |
| <span class="keyword">return</span> ret;<br> |
| }<br> <br> @Override<br> |
| <span class="keyword">public</span> String getName() {<br> |
| <span class="keyword">return</span> <span class="string">"Collapse"</span>;<br> |
| }<br> <br> @Override<br> |
| <span class="keyword">public</span> String getDescription() {<br> <br> |
| <span class="keyword">return</span> <span class="string">"Collapse Figure"</span>;<br> |
| }<br> <br> @Override<br> |
| <span class="keyword">public</span> String getImageId() {<br> |
| <span class="keyword">return</span> IPlatformImageConstants.<span class="string"><em>IMG_EDIT_COLLAPSE</em></span>;<br> |
| }<br> <br> @Override<br> |
| <span class="keyword">public boolean</span> isAvailable(IContext context) |
| {<br> |
| <span class="keyword"> return true</span>;<br> |
| }<br> <br> @Override<br> |
| <span class="keyword">public void</span> execute(ICustomContext context) |
| {<br> |
| MessageDialog.openInformation(PlatformUI.getWorkbench()<br> |
| .getActiveWorkbenchWindow().getShell(), <span class="string">"Information"</span>,<br> |
| <span class="string">"The 'Collapse Feature' is intentionally not implemented |
| yet."</span>);<br> }<br>} </p> |
| </div> |
| </div> |
| <p> </p> |
| <!-- End code ------------------------------------------------------------------------------- --> |
| <p>Finally the feature provider has to deliver our newly created custom feature |
| (overwrite the method |
| <a href="../../../javadoc/org/eclipse/graphiti/features/IFeatureProvider.html#getCustomFeatures(org.eclipse.graphiti.features.context.ICustomContext)"> |
| </a>).</p> |
| <p>This implementation can be seen here:</p> |
| <!-- Begin code ------------------------------------------------------------------------------- --> |
| <p> </p> |
| <div class="literallayout"> |
| <div class="incode"> |
| <p class="code">@Override<br><span class="keyword">public</span> ICustomFeature[] |
| getCustomFeatures(ICustomContext context) {<br> |
| <span class="keyword">return new</span> ICustomFeature[] <br> |
| { <span class="keyword">new</span> TutorialRenameEClassFeature(<span class="keyword">this</span>),<br> |
| <span class="keyword">new</span> TutorialDrillDownEClassFeature(<span class="keyword">this</span>),<br> |
| <span class="keyword">new</span> TutorialAssociateDiagramEClassFeature(<span class="keyword">this</span>),<br> |
| <span class="keyword">new</span> TutorialCollapseDummyFeature(<span class="keyword">this</span>)};<br> |
| } </p> |
| </div> |
| </div> |
| <!-- End code ------------------------------------------------------------------------------- --> |
| |
| </body> |
| |
| </html> |