Selection in StructuredTextEditor
structured source editing (sse) component
Date Revision info
9/20/2005 Initial contribution
9/28/2005 Added example usages

 
Overview
  One of the most visible cues of good integration between editors and views is synchronized selection: the selected Java method in the Outline view should reflect the caret position in the Java Editor, the Properties view should show properties for the DOM Element selected in the Outline view, the selected objects on a mutli-page editor's Design page should always be the same as on its Source page, etc. Rather than introduce and maintain our own mechanism for achieving this, the StructuredTextEditor exposes its selection handling using standard Eclipse platform APIs.


Selection notification in text editors
  block diagram of key selection objects for a text editor
In text editors, the editor sets a ISelectionProvider into its IEditorSite. The ISelectionProvider sends ITextSelection objects from the source viewer to its listeners and knows how to accept an ITextSelection and apply it to the SourceViewer. The workbench ISelectionService becomes a listener of the ISelectionProvider and any changes sent to the ISelectionService are forwarded to everyone listening to the service--most views, for example.

The flow of selection notification from the editor's source viewer changes looks like this:

     selection changes in the source viewer
          -> editor's ISelectionProvider receives selection changed and notifies its listeners
               -> ISelectionService receives selection changed and notifies its listeners
                    -> listeners react (views update)

The flow of setting selection into the editor looks like this:
     selection created
          -> editor's ISelectionProvider receives setSelection() message and updates the source viewer's selected text



How this applies to SSE and its StructuredTextEditor
  In the past, the StructuredTextEditor didn't affect any of this. As part of the changes for bug 109441 , StructuredTextEditor provides an ISelectionProvider that creates a single selection object implementing both ITextSelection and IStructuredSelection . Listeners that can only handle one of those types of selection can still function because this unified selection is provided in every selection changed event and as the result of ISelectionProvider.getSelection() . The ISelectionProvider also accepts both kinds of selection for ISelectionProvider.setSelection(ISelection), passing text selections straight through to the source viewer. The actual ISelectionProvider implementation being used is org.eclipse.wst.sse.ui.StructuredTextEditor.StructuredSelectionProvider .


Selection notification when embedded in Multi-page Editors
  block diagram of key selection objects for a text editor in a multi-page editor part The MultiPageEditorPart connects its own selection provider (2) to the selection service. That selection provider (2) is notified of selection changes by the selection providers (1) of all of its connected pages and forwards any notifications to the selection service. In Eclipse 3.1, this is done for plain selection notification only, not for post selection. Source viewers send cursor movements using post selection notification, and when using the base selection APIs, updating selection in views like the outline will rely on post selection notification coming from the source viewer through the MultiPageEditorPart and the selection service. Eclipse bug 108324 has been opened to address this for Eclipse 3.2. org.eclipse.wst.common.ui.provisional.editors.PostSelectionMultiPageEditorPart has been provided as a temporary workaround.


Guidelines for usage
 
Synchronizing selection from an editor to a view:
To synchronize selection from an editor to a view, the view should register itself as a listener of the ISelectionService when it is initialized. It will then automatically recieve notification about selection changes and the workbench part that originated them. Pages in a PageBookView should check their visibility before handling any selection change notifications as they'll receive notification from every workbench part. The PageBook will ensure that the page is only visible when the correct workbench part is active.
Synchronizing selection from a view to an editor:
It's rare for an editor to want just any view to control it, so this is also left as a task for the editor part itself. SSE's ConfigurableContentOutlinePage allows anyone to add an IDoubleClickListener to it, and multi-page editors built around the StructuredTextEditors would be expected to do so (StructuredTextEditor already does this if it creates the page) to respond to double-click events within the outline.
How to synchronize selection from one view to another view:
The first view is set up to provide selection notification to the selection service. The second view can then be driven from the first view's selection just as it would by an editor's selection. For a concrete example, when editing HTML, the StructuredTextEditor will provide its IStructuredSelection using DOM nodes. It's Outline provides IStructuredSelection using the same DOM nodes. The SSE Property Sheet can't tell the difference, and since it's only ever showing the properties of nodes supplied through the selection (which is now always an IStructuredSelection), it doesn't even need an IStructuredModel to be set on it--the node is supplied by the active part, whether it's the editor, outline, or otherwise.
Synchronizing selection within a Multi-Page Editor:
Currently, the main multi-page editor class must synchronize the selection between its pages by itself. For reference, ITextEditor returns an ISelectionProvider as part of its interface and the SSE IDesignViewer has been changed to do so as well. The provided XMLMultiPageEditorPart synchronizes using these interfaces and relies on the source viewer to notify the selection service.
Avoiding selection notification loops:
Setting the selection into a viewer causes it to also fire selection notifications, so if two viewers are synchronizing selection based on post selection notification, they might end up looping endlessly notifying each other when selection is applied to their Controls. The selection objects themselves will be different as each viewer will be generating a fresh selection event and selection from the underlying Control. The recommended solution for this problem is to make sure that a part never updates its selection from outside notification when it is the active part, nor when it is sending selection (or post selection) notification itself.
Listening to the selection service
Editors should not just be a listener of the selection service since selection changes in every part (including some listening for changes in that same editor) would be received.
How to get selected "nodes" and text from a StructuredTextEditor:
The StructuredTextEditor's selection provider returns an ITextSelection & IStructuredSelection combination when ISelectionProvider.getSelection() is called. Casting to an IStructuredSelection will give you the selected IndexedNodes for the current text selection. Casting to an ITextSelection will give the current text selection, just as you would receive from other text editors.
Caution: IStructuredSelection does not provide explicit typing for its selected objects (NodeSelectionChangedEvent didn't, either).
How to manage double-click:
As of now, we haven't provided a unified way to do this, and we're currently not planning to. Like selection, double-click does different things in different places. The XMLMultiPageEditorPart won't handle double-click from its design page to its source page properly in 1.0M8, that will be released early in 1.0M9 development.
API references
  org.eclipse.jface.text.ITextSelection
org.eclipse.jface.viewers.IPostSelectionProvider
org.eclipse.jface.viewers.ISelection
org.eclipse.jface.viewers.ISelectionChangedListener
org.eclipse.jface.viewers.ISelectionProvider
org.eclipse.jface.viewers.IStructuredSelection
org.eclipse.ui.ISelectionService


Other changes of interest:
 
  • org.eclipse.wst.sse.ui.internal.ViewerSelectionManager - deprecated
  • org.eclipse.wst.sse.ui.internal.CaretMediator - deprecated
  • org.eclipse.wst.sse.ui.internal.view.events - entire package deprecated
  • The selection range shown on the left of the source editor are not the same for XML languages as they were before. Code in org.eclipse.wst.sse.ui used to take advantage of the org.w3c.Node interfaces being in the JRE to base the selection range on a parent Element if a Text node was the selected node. This made assumptions about the nature of the IndexedNodes of an IStructuredModel that shouldn't be known in the core SSE UI plugin. When the caret is within a Text node you will now see a selection range reflecting the Text Node itself.