| <!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"> |
| <html> |
| |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> |
| <title>GEF Interactions</title> |
| <link rel="stylesheet" href="http://dev.eclipse.org/default_style.css" type="text/css" /> |
| <style> |
| <!-- |
| .whatsnew {border-left:solid #70A070 1px; border-right:solid #70A070 1px;border-bottom:solid #70A070 1px;width:100%;border-collapse:collapse;bordercolor:#111111} |
| .paracolumn {text-align:justify; margin-right:10px} |
| .related {float:right;top:80px;width:280px;text-align:right} |
| .relatedtable {width:100%;cellpadding:0;cellspacing:0;border-collapse:collapse;bordercolor:#111111} |
| .section {margin-left:60px; margin-bottom:8; margin-top:15} |
| --> |
| </style> |
| </head> |
| |
| <body topmargin="4" leftmargin="4"> |
| |
| <table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="100%" id="AutoNumber1"> |
| <tbody> |
| <tr> |
| <td width="120"> |
| <img src="http://www.eclipse.org/articles/Article-Builders/images/Idea.jpg" width="120" height="86" /></td> |
| <td> |
| <h1 align="center">Standard User Interactions in GEF<br /> |
| <font class="indexsub">article : graphical editing framework</font></h1> |
| </td> |
| <td width="120"></td> |
| </tr> |
| </tbody> |
| </table> |
| <blockquote> |
| <p><b>Summary</b><br /> |
| This article discusses the types of user interactions that are recognized and |
| supported in GEF.  This article does not cover native DND operations, but |
| does include: resizing, aligning, moving, reparenting, reconnecting, bending, |
| creating, and deleting.  The purpose of this article is to give the developer |
| an overall feel of what is available, and to introduce a consistent terminology |
| for describing interactions.  This article assumes a basic familiarity with |
| GEF's MVC architecture (Model-Figure-EditPart).</p> |
| <p><b>By Randy Hudson, IBM Research Triangle Park<br /> |
| </b><font size="-1">May 7, 2003</font></p> |
| </blockquote> |
| <h2>Introduction</h2> |
| <p>An interaction is defined as a user-invoked change to an Editor's model. |
| There are two broad categories of interactions in GEF.  The first is |
| Actions.  |
| <i>IAction</i> is a <i>JFace</i> concept, but GEF includes several action |
| implementations. Actions usually appear in menus, toolbars, popup, and usually |
| operate on the current selection.  Examples include delete, align, and |
| undo.</p> |
| <p>The other type of interaction is graphical. Graphical interactions are those |
| which are performed on just a Canvas using the mouse (or keyboard accessible |
| equivalent) and perhaps some key modifiers. Mouse interactions are handled by <b><i> |
| Tool</i>s</b> (Native drag-and-drop is a separate topic). A Tool represents a |
| mode. The active tool or mode determines how mouse events are interpreted. <b> |
| Note:</b> You may be asking why native drag and drop isn't used.</p> |
| <p>It is important to point out that 99% of all interactions should be carried |
| out as <i>Commands</i> which modify the application model.  The model |
| drives everything in GEF.  Exceptions would be non-persisted data or data |
| that isn't part of the model, such as expansion state or maybe the zoom level.</p> |
| <p> </p> |
| <table border="0" cellpadding="2" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" id="AutoNumber2" width="800"> |
| <tr> |
| <td valign="top" colspan="3" bgcolor="#0070A0"> |
| <h2 style="line-height: 100%; margin-bottom: 3px"><font color="#FFFFFF">Tool-based Interactions</font></h2> |
| </td> |
| </tr> |
| <tr> |
| <td valign="top" colspan="3"> |
| <h3 class="section">Creation</h3> |
| </td> |
| </tr> |
| <tr> |
| <td valign="top"> |
| <p align="right"> |
| <img border="0" src="images/creation.gif?cvsroot=Tools_Project" /></td> |
| <td valign="top"> |
| <div class="paracolumn"> |
| <p>Creation of an "object" (which may be a node, class, state, activity, |
| etc.) occurs when the user is in the creation mode and clicks on the editor. |
| The CreationTool will process the click, and target the appropriate EditPart |
| under the mouse, and send it the appropriate CreateRequest. The result |
| should be an executable command which is executed, causing the appropriate |
| change to the model.</p> |
| <p>The interesting information during creation is the point at which the |
| user clicked, the targeted EditPart, and optionally the rectangle drawn-out |
| by the user if size-on-drop is used/supported. </p> |
| </div> |
| <p> </td> |
| <td valign="top"> |
| <table class="relatedtable"> |
| <tbody> |
| <tr> |
| <td bgcolor="#70A070" height="15" rowspan="2" nowrap="" align="center"> |
| <font color="#FFFFFF"> |
| <b>Related Classes</b></font></td> |
| <td width="61%"> </td> |
| </tr> |
| <tr> |
| <td bgcolor="#70A070" height="3"> |
| </td> |
| </tr> |
| </tbody> |
| </table> |
| <table class="whatsnew"> |
| <tbody> |
| <tr> |
| <td valign="top" colspan="2"><b>Tool:</b></td> |
| </tr> |
| <tr> |
| <td valign="top"> </td> |
| <td valign="top">CreationTool</td> |
| </tr> |
| <tr> |
| <td valign="top" colspan="2"> |
| <b>EditPolicies:</b></td> |
| </tr> |
| <tr> |
| <td valign="top"> </td> |
| <td valign="top">LayoutEditPolicy and/or<br> |
| ContainerEditPolicy</td> |
| </tr> |
| <tr> |
| <td valign="top" colspan="2"> |
| <b>Request:</b></td> |
| </tr> |
| <tr> |
| <td valign="top"> </td> |
| <td valign="top">CreateRequest</td> |
| </tr> |
| </tbody> |
| </table> |
| </td> |
| </tr> |
| <tr> |
| <td valign="top" colspan="3"> |
| <h3 class="section">Move, Resize, and Reparent</h3> |
| </td> |
| </tr> |
| <tr> |
| <td valign="top"> |
| <p align="right"> |
| <img border="0" src="images/resize.gif?cvsroot=Tools_Project" /></td> |
| <td valign="top"> |
| <div class="paracolumn"> |
| <p>Once you have something created, you can interact with that object |
| directly in several ways. Many interactions in GEF are performed while the |
| editor is in its default mode, with the SelectionTool active.</p> |
| <p>The selection tool obtains a <i>DragTracker</i> at the time the user |
| presses the mouse, and delegates events to that tracker until the mouse is |
| released. Which drag tracker is used is dependant on the mouse |
| location and other data. |
| <b>RESIZE</b> handles allow the user to resize all of the selected EditParts |
| in the direction determined by the handle. Objects that are not |
| resizable will not participate in the resize and should not show resize |
| feedback.</p> |
| <p>A DragTacker can also be returned from the EditPart itself. |
| Dragging an EditPart within the confines of its original container will be |
| interpreted as a <b>MOVE</b>. Once the user drags the mouse over a new |
| container, the interaction becomes a <b>REPARENT</b>. While a move |
| operation only involves one container, a reparent involves both the original |
| and new containers. The old container is asked to ORPHAN the child, |
| while the new container is asked to ADD the child.</p> |
| </div> |
| <p> </td> |
| <td valign="top"> |
| <table class="relatedtable"> |
| <tbody> |
| <tr> |
| <td bgcolor="#70A070" height="15" rowspan="2" nowrap="" align="center"> |
| <font color="#FFFFFF"> |
| <b>Related Classes</b></font></td> |
| <td width="61%"> </td> |
| </tr> |
| <tr> |
| <td bgcolor="#70A070" height="3"> |
| </td> |
| </tr> |
| </tbody> |
| </table> |
| <table class="whatsnew"> |
| <tbody> |
| <tr> |
| <td valign="top" colspan="2"><b>Drag Trackers:</b></td> |
| </tr> |
| <tr> |
| <td valign="top"> </td> |
| <td valign="top">ResizeTracker, DragEditPartsTracker</td> |
| </tr> |
| <tr> |
| <td valign="top" colspan="2"> |
| <b>EditPolicies:</b></td> |
| </tr> |
| <tr> |
| <td valign="top"> </td> |
| <td>ResizableEditPolicy and XYLayoutEditPolicy</td> |
| </tr> |
| <tr> |
| <td valign="top" colspan="2"> |
| <b>Request:</b></td> |
| </tr> |
| <tr> |
| <td align="right" valign="top"> |
| </td> |
| <td>ChangeBoundsRequest</td> |
| </tr> |
| </tbody> |
| </table> |
| </td> |
| </tr> |
| <tr> |
| <td valign="top" colspan="3"> |
| <h3 class="section">Connection Creation</h3> |
| </td> |
| </tr> |
| <tr> |
| <td valign="top"> |
| <p align="right"> |
| <img border="0" src="images/connect.gif?cvsroot=Tools_Project" /></td> |
| <td valign="top"> |
| <div class="paracolumn"> |
| <p>Creation of a "connection" (a.k.a. link, flow) is done with <i>ConnectionCreationTool</i>. |
| The connection tool requires that the user click twice, once on the source, |
| and again on the target.  This allows the user to scroll the diagram between |
| clicks.</p> |
| <p> |
| The responsibility of creating the connection is divided between the source |
| and target EditParts.  The source is asked for a "Connection Start" command.  |
| This command is not necessarily executed, but is passed to the target part when |
| the target is asked for the "Connection End" command.  This allows the |
| source to pass information, such as which "terminal" the user clicked on, to |
| the target.  It also allows the source to communicate whether the user |
| clicked in a valid location, via the returned command's isExecutable() result.  |
| Even though the command must indicate that it is executable, it won't get executed |
| because it is only being used to pass data to the target.</p> |
| <table border="0" cellpadding="3" cellspacing="1" style="border-collapse: collapse" bordercolor="#111111" id="AutoNumber3" bgcolor="#FFFF99"> |
| <tr> |
| <td valign="top"> |
| <img border="0" src="images/tip.gif?cvsroot=Tools_Project" /></td> |
| <td align="justify">During connection creation, the connection editpart |
| does not exist yet. Therefore, GEF will ask the <i>source</i> editpart |
| to show feedback for the creation of the connection. Once the connection |
| editpart exists, it is the primary means for showing feedback.</td> |
| </tr> |
| </table> |
| </div></td> |
| <td valign="top"> |
| <table class="relatedtable"> |
| <tbody> |
| <tr> |
| <td bgcolor="#70A070" height="15" rowspan="2" nowrap="" align="center"> |
| <font color="#FFFFFF"> |
| <b>Related Classes</b></font></td> |
| <td width="61%"> </td> |
| </tr> |
| <tr> |
| <td bgcolor="#70A070" height="3"> |
| </td> |
| </tr> |
| </tbody> |
| </table> |
| <table class="whatsnew"> |
| <tbody> |
| <tr> |
| <td width="37%" valign="top" colspan="2"><b>Tool:</b></td> |
| </tr> |
| <tr> |
| <td align="right" valign="top"> </td> |
| <td>ConnectionCreationTool</td> |
| </tr> |
| <tr> |
| <td valign="top" colspan="2"> |
| <b>EditPolicy:</b></td> |
| </tr> |
| <tr> |
| <td align="right" valign="top"> </td> |
| <td>GraphicalNodeEditPolicy</td> |
| </tr> |
| <tr> |
| <td valign="top" colspan="2"> |
| <b>Request:</b></td> |
| </tr> |
| <tr> |
| <td> |
| </td> |
| <td>CreateConnectionRequest</td> |
| </tr> |
| </tbody> |
| </table> |
| </td> |
| </tr> |
| <tr> |
| <td valign="top" colspan="3"> |
| <h3 class="section">Reconnecting</h3> |
| </td> |
| </tr> |
| <tr> |
| <td valign="top"> |
| <p align="right"> |
| <img border="0" src="images/reconnect.gif?cvsroot=Tools_Project" /></td> |
| <td valign="top"> |
| <div class="paracolumn"> |
| <p>When a connection is selected it displays handles. There are two types of |
| connection handles in GEF that allow for two different interactions. The |
| first and most common interaction is called a<i> reconnect</i>.</p> |
| <p>Reconnection is a <b>semantic</b> change to the document. A connection end is moved from one node or |
| "anchor point" to another. (Some applications have only one basic anchor point per node.)</p> |
| <p>Reconnecting is done using the drag tracker returned by the handle at |
| either end of a connection. Reconnecting is a <i>targeting</i> operation. |
| As such, the target editpart is responsible for making the change to the |
| model. But, the connection editpart is still involved in showing |
| feedback during the interaction.</p> |
| </div> |
| </td> |
| <td valign="top"> |
| <table class="relatedtable"> |
| <tbody> |
| <tr> |
| <td bgcolor="#70A070" height="15" rowspan="2" nowrap="" align="center"> |
| <font color="#FFFFFF"> |
| <b>Related Classes</b></font></td> |
| <td width="61%"> </td> |
| </tr> |
| <tr> |
| <td bgcolor="#70A070" height="3"> |
| </td> |
| </tr> |
| </tbody> |
| </table> |
| <table class="whatsnew"> |
| <tbody> |
| <tr> |
| <td width="37%" valign="top" colspan="2"><b>Tool:</b></td> |
| </tr> |
| <tr> |
| <td valign="top"> </td> |
| <td>ConnectionEndpointTracker</td> |
| </tr> |
| <tr> |
| <td valign="top" colspan="2"> |
| <b>EditPolicy:</b></td> |
| </tr> |
| <tr> |
| <td valign="top"> </td> |
| <td>GraphicalNodeEditPolicy<br> |
| EndpointEditPolicy</td> |
| </tr> |
| <tr> |
| <td valign="top" colspan="2"> |
| <b>Request:</b></td> |
| </tr> |
| <tr> |
| <td> |
| </td> |
| <td>ReconnectRequest</td> |
| </tr> |
| </tbody> |
| </table> |
| </td> |
| </tr> |
| <tr> |
| <td valign="top" colspan="3"> |
| <h3 class="section">Bending Connections</h3> |
| </td> |
| </tr> |
| <tr> |
| <td valign="top"> |
| <p align="right"> |
| <img border="0" src="images/bend.gif?cvsroot=Tools_Project" /></td> |
| <td valign="top"> |
| <div class="paracolumn"> |
| Bending connections is an <b>aesthetic</b> change. Different applications |
| will use separate approaches to connection bending (a.k.a. routing). Some |
| even allow the user to choose different routing mechanisms at the diagram or |
| even per connection.<p>When the user clicks on a bendpoint handle, only that |
| bendpoint is modified. In other words, the set of selected connections |
| has no effect on the interaction.</p> |
| <p>Bending a connection can also be used to remove an existing bendpoint. |
| For "oblique" connection routing, the bendpoint should be removed whenever |
| it falls along the imaginary line between the previous and next point in the |
| connection. Different interpretations are necessary for different routing |
| strategies. For this reason, there is no "remove bendpoint" request in |
| GEF anywhere. It is up to the bendpoint policy to recognize when |
| removal should be done.</div> |
| </td> |
| <td valign="top"> |
| <table class="relatedtable"> |
| <tbody> |
| <tr> |
| <td bgcolor="#70A070" height="15" rowspan="2" nowrap="" align="center"> |
| <font color="#FFFFFF"> |
| <b>Related Classes</b></font></td> |
| <td width="61%"> </td> |
| </tr> |
| <tr> |
| <td bgcolor="#70A070" height="3"> |
| </td> |
| </tr> |
| </tbody> |
| </table> |
| <table class="whatsnew"> |
| <tbody> |
| <tr> |
| <td width="37%" valign="top" colspan="2"><b>Tool:</b></td> |
| </tr> |
| <tr> |
| <td valign="top"> |
| </td> |
| <td>ConnectionBendpointTracker</td> |
| </tr> |
| <tr> |
| <td valign="top" colspan="2"> |
| <b>EditPolicy:</b></td> |
| </tr> |
| <tr> |
| <td valign="top"> |
| </td> |
| <td>BendpointEditPolicy</td> |
| </tr> |
| <tr> |
| <td valign="top" colspan="2"> |
| <b>Request:</b></td> |
| </tr> |
| <tr> |
| <td> |
| </td> |
| <td>BendpointRequest</td> |
| </tr> |
| </tbody> |
| </table> |
| </td> |
| </tr> |
| <tr> |
| <td valign="top" colspan="3" bgcolor="#0070A0"> |
| <h2 style="line-height: 100%; margin-bottom: 3px"><font color="#FFFFFF">Action-driven Interactions</font></h2> |
| </td> |
| </tr> |
| <tr> |
| <td valign="top" colspan="3"> |
| <h3 class="section">Alignment</h3> |
| </td> |
| </tr> |
| <tr> |
| <td valign="top"> |
| <p align="right"> |
| <img border="0" src="images/alignment.gif?cvsroot=Tools_Project" /></td> |
| <td valign="top"> |
| <div class="paracolumn"> |
| Alignment can be performed whenever two or more editparts that support |
| alignment are selected. There are three types of horizontal |
| alignments (left, center, right), and three vertical (top, middle, bottom).<p> |
| Each of the selected nodes is aligned with the <i>primary</i> selected node. |
| The primary selection is indicated by black selection handles, non-primary |
| selection is indicated by white handles with a black outline.</p> |
| <table border="0" cellpadding="3" cellspacing="1" style="border-collapse: collapse" bordercolor="#111111" id="AutoNumber3" bgcolor="#FFFF99"> |
| <tr> |
| <td valign="top"> |
| <img border="0" src="images/tip.gif?cvsroot=Tools_Project" /></td> |
| <td align="justify">The set of selected editparts is filtered in two |
| passes. First, If both a child and parent are selected, the child is |
| ignored. Second, from the parts remaining after step one, parts that |
| don't understand alignment are ignored. This allows for connections to |
| be ignored.</td> |
| </tr> |
| </table> |
| <p> </div> |
| </td> |
| <td valign="top"> |
| <table class="relatedtable"> |
| <tbody> |
| <tr> |
| <td bgcolor="#70A070" height="15" rowspan="2" nowrap="" align="center"> |
| <font color="#FFFFFF"> |
| <b>Related Classes</b></font></td> |
| <td width="61%"> </td> |
| </tr> |
| <tr> |
| <td bgcolor="#70A070" height="3"> |
| </td> |
| </tr> |
| </tbody> |
| </table> |
| <table class="whatsnew"> |
| <tbody> |
| <tr> |
| <td width="37%" valign="top" colspan="2"> |
| <b>Action:</b></td> |
| </tr> |
| <tr> |
| <td valign="top"> |
| </td> |
| <td>AlignmentAction</td> |
| </tr> |
| <tr> |
| <td width="37%" valign="top" colspan="2"> |
| <b>EditPolicy:</b></td> |
| </tr> |
| <tr> |
| <td valign="top"> |
| </td> |
| <td>ResizableEditPolicy</td> |
| </tr> |
| <tr> |
| <td valign="top" colspan="2"> |
| <b>Request:</b></td> |
| </tr> |
| <tr> |
| <td valign="top"> |
| </td> |
| <td>AlignmentRequest</td> |
| </tr> |
| </tbody> |
| </table> |
| </td> |
| </tr> |
| <tr> |
| <td valign="top" colspan="3"> |
| <h3 class="section">Delete</h3> |
| </td> |
| </tr> |
| <tr> |
| <td valign="top"> |
| <p align="right"> |
| <img border="0" src="images/delete.gif?cvsroot=Tools_Project" /></td> |
| <td valign="top"> |
| <div class="paracolumn"> |
| <p>Delete is an action which operates on the <i>selection set</i>. The <code> |
| DeleteAction</code> creates a <code>DeleteRequest</code>, and asks each selected |
| editpart to contribute to the delete.  The contributions are combined into |
| a compound command.  Whenever the selection changes, the delete action |
| must be updated to calculate its enabled state.  It does this by building |
| the compound command, and testing whether it can be executed.</p> |
| <table border="0" cellpadding="3" cellspacing="1" style="border-collapse: collapse" bordercolor="#111111" id="AutoNumber3" bgcolor="#FFFF99"> |
| <tr> |
| <td valign="top"> |
| <img border="0" src="images/tip.gif?cvsroot=Tools_Project" /></td> |
| <td align="justify">It is worth pointing out that a view's selection is |
| never empty. When the user deselects everything, the viewer returns the |
| <b> <i>contents</i></b> |
| edit part from the viewer as the current selection.  Therefore, the delete action only disables |
| if the contents editpart returns a non-executable command in response to a delete |
| request.  This can be achieved by installing a <code>RootComponentEditPolicy</code> |
| on the contents part.</td> |
| </tr> |
| </table> |
| <p> </div> |
| <p> </td> |
| <td valign="top"> |
| <table class="relatedtable"> |
| <tbody> |
| <tr> |
| <td bgcolor="#70A070" height="15" rowspan="2" nowrap="" align="center"> |
| <font color="#FFFFFF"> |
| <b>Related Classes</b></font></td> |
| <td width="61%"> </td> |
| </tr> |
| <tr> |
| <td bgcolor="#70A070" height="3"> |
| </td> |
| </tr> |
| </tbody> |
| </table> |
| <table class="whatsnew"> |
| <tbody> |
| <tr> |
| <td valign="top" colspan="2"><b>Action:</b></td> |
| </tr> |
| <tr> |
| <td valign="top"> </td> |
| <td>DeleteAction</td> |
| </tr> |
| <tr> |
| <td valign="top" colspan="2"> |
| <b>EditPolicy:</b></td> |
| </tr> |
| <tr> |
| <td valign="top"> </td> |
| <td>ComponentEditPolicy<br> |
| RootComponentEditPolicy</td> |
| </tr> |
| </tbody> |
| </table> |
| </td> |
| </tr> |
| <tr> |
| <td valign="top"> |
| </td> |
| <td valign="top"> |
| </td> |
| <td valign="top"> |
| </td> |
| </tr> |
| <tr> |
| <td valign="top"> |
| </td> |
| <td valign="top"> |
| </td> |
| <td valign="top"> |
| </td> |
| </tr> |
| </table> |
| |
| </body> |
| |
| </html> |