REOPENED - bug 112193: [Workbench/JFace] Using the Selection Service
https://bugs.eclipse.org/bugs/show_bug.cgi?id=112193
diff --git a/Article-WorkbenchSelections/SelectionProviderIntermediate.java b/Article-WorkbenchSelections/SelectionProviderIntermediate.java
index 178c1a3..6f22952 100644
--- a/Article-WorkbenchSelections/SelectionProviderIntermediate.java
+++ b/Article-WorkbenchSelections/SelectionProviderIntermediate.java
@@ -1,114 +1,118 @@
-package com.mountainminds.eclipse.selectionsample;
-
-import org.eclipse.jface.util.ListenerList;
-import org.eclipse.jface.viewers.IPostSelectionProvider;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.ISelectionChangedListener;
-import org.eclipse.jface.viewers.ISelectionProvider;
-import org.eclipse.jface.viewers.SelectionChangedEvent;
-
-/**
- * IPostSelectionProvider implementation that delegates to another
- * ISelectionProvider or IPostSelectionProvider. The selection provider used
- * for delegation can be exchanged dynamically. Registered listeners are
- * adjusted accordingly. This utility class may be used in workbench parts with
- * multiple viewers.
- *
- * @author Marc R. Hoffmann
- */
-public class SelectionProviderIntermediate implements IPostSelectionProvider {
-
- private final ListenerList selectionListeners = new ListenerList();
-
- private final ListenerList postSelectionListeners = new ListenerList();
-
- private ISelectionProvider delegate;
-
- private ISelectionChangedListener selectionListener = new ISelectionChangedListener() {
- public void selectionChanged(SelectionChangedEvent event) {
- if (event.getSelectionProvider() == delegate) {
- fireSelectionChanged(event.getSelection());
- }
- }
- };
-
- private ISelectionChangedListener postSelectionListener = new ISelectionChangedListener() {
- public void selectionChanged(SelectionChangedEvent event) {
- if (event.getSelectionProvider() == delegate) {
- firePostSelectionChanged(event.getSelection());
- }
- }
- };
-
- /**
- * Sets a new selection provider to delegate to. Selection listeners
- * registered with the previous delegate are removed before.
- *
- * @param newDelegate new selection provider
- */
- public void setSelectionProviderDelegate(ISelectionProvider newDelegate) {
- if (delegate != null) {
- delegate.removeSelectionChangedListener(selectionListener);
- if (delegate instanceof IPostSelectionProvider) {
- ((IPostSelectionProvider)delegate).removePostSelectionChangedListener(postSelectionListener);
- }
- }
- delegate = newDelegate;
- if (newDelegate != null) {
- newDelegate.addSelectionChangedListener(selectionListener);
- if (newDelegate instanceof IPostSelectionProvider) {
- ((IPostSelectionProvider)newDelegate).addPostSelectionChangedListener(postSelectionListener);
- }
- fireSelectionChanged(newDelegate.getSelection());
- }
- }
-
- protected void fireSelectionChanged(ISelection selection) {
- fireSelectionChanged(selectionListeners, selection);
- }
-
- protected void firePostSelectionChanged(ISelection selection) {
- fireSelectionChanged(postSelectionListeners, selection);
- }
-
- private void fireSelectionChanged(ListenerList list, ISelection selection) {
- SelectionChangedEvent event = new SelectionChangedEvent(delegate, selection);
- Object[] listeners = list.getListeners();
- for (int i = 0; i < listeners.length; i++) {
- ISelectionChangedListener listener = (ISelectionChangedListener) listeners[i];
- listener.selectionChanged(event);
- }
- }
-
- // IPostSelectionProvider Implementation
-
- public void addSelectionChangedListener(ISelectionChangedListener listener) {
- selectionListeners.add(listener);
- }
-
- public void removeSelectionChangedListener(
- ISelectionChangedListener listener) {
- selectionListeners.remove(listener);
- }
-
- public void addPostSelectionChangedListener(
- ISelectionChangedListener listener) {
- postSelectionListeners.add(listener);
- }
-
- public void removePostSelectionChangedListener(
- ISelectionChangedListener listener) {
- postSelectionListeners.remove(listener);
- }
-
- public ISelection getSelection() {
- return delegate == null ? null : delegate.getSelection();
- }
-
- public void setSelection(ISelection selection) {
- if (delegate != null) {
- delegate.setSelection(selection);
- }
- }
-
-}
+package com.mountainminds.eclipse.selectionsample;
+
+import org.eclipse.jface.util.ListenerList;
+import org.eclipse.jface.viewers.IPostSelectionProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+
+/**
+ * IPostSelectionProvider implementation that delegates to another
+ * ISelectionProvider or IPostSelectionProvider. The selection provider used
+ * for delegation can be exchanged dynamically. Registered listeners are
+ * adjusted accordingly. This utility class may be used in workbench parts with
+ * multiple viewers.
+ *
+ * @author Marc R. Hoffmann
+ */
+public class SelectionProviderIntermediate implements IPostSelectionProvider {
+
+ private final ListenerList selectionListeners = new ListenerList();
+
+ private final ListenerList postSelectionListeners = new ListenerList();
+
+ private ISelectionProvider delegate;
+
+ private ISelectionChangedListener selectionListener = new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ if (event.getSelectionProvider() == delegate) {
+ fireSelectionChanged(event.getSelection());
+ }
+ }
+ };
+
+ private ISelectionChangedListener postSelectionListener = new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ if (event.getSelectionProvider() == delegate) {
+ firePostSelectionChanged(event.getSelection());
+ }
+ }
+ };
+
+ /**
+ * Sets a new selection provider to delegate to. Selection listeners
+ * registered with the previous delegate are removed before.
+ *
+ * @param newDelegate new selection provider
+ */
+ public void setSelectionProviderDelegate(ISelectionProvider newDelegate) {
+ if (delegate == newDelegate) {
+ return;
+ }
+ if (delegate != null) {
+ delegate.removeSelectionChangedListener(selectionListener);
+ if (delegate instanceof IPostSelectionProvider) {
+ ((IPostSelectionProvider)delegate).removePostSelectionChangedListener(postSelectionListener);
+ }
+ }
+ delegate = newDelegate;
+ if (newDelegate != null) {
+ newDelegate.addSelectionChangedListener(selectionListener);
+ if (newDelegate instanceof IPostSelectionProvider) {
+ ((IPostSelectionProvider)newDelegate).addPostSelectionChangedListener(postSelectionListener);
+ }
+ fireSelectionChanged(newDelegate.getSelection());
+ firePostSelectionChanged(newDelegate.getSelection());
+ }
+ }
+
+ protected void fireSelectionChanged(ISelection selection) {
+ fireSelectionChanged(selectionListeners, selection);
+ }
+
+ protected void firePostSelectionChanged(ISelection selection) {
+ fireSelectionChanged(postSelectionListeners, selection);
+ }
+
+ private void fireSelectionChanged(ListenerList list, ISelection selection) {
+ SelectionChangedEvent event = new SelectionChangedEvent(delegate, selection);
+ Object[] listeners = list.getListeners();
+ for (int i = 0; i < listeners.length; i++) {
+ ISelectionChangedListener listener = (ISelectionChangedListener) listeners[i];
+ listener.selectionChanged(event);
+ }
+ }
+
+ // IPostSelectionProvider Implementation
+
+ public void addSelectionChangedListener(ISelectionChangedListener listener) {
+ selectionListeners.add(listener);
+ }
+
+ public void removeSelectionChangedListener(
+ ISelectionChangedListener listener) {
+ selectionListeners.remove(listener);
+ }
+
+ public void addPostSelectionChangedListener(
+ ISelectionChangedListener listener) {
+ postSelectionListeners.add(listener);
+ }
+
+ public void removePostSelectionChangedListener(
+ ISelectionChangedListener listener) {
+ postSelectionListeners.remove(listener);
+ }
+
+ public ISelection getSelection() {
+ return delegate == null ? null : delegate.getSelection();
+ }
+
+ public void setSelection(ISelection selection) {
+ if (delegate != null) {
+ delegate.setSelection(selection);
+ }
+ }
+
+}
diff --git a/Article-WorkbenchSelections/article.html b/Article-WorkbenchSelections/article.html
index 2fb66c4..f0b4f24 100644
--- a/Article-WorkbenchSelections/article.html
+++ b/Article-WorkbenchSelections/article.html
@@ -1,724 +1,731 @@
-<html>
-
-<head>
-<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252">
-<title>Eclipse Workbench: Using the Selection Service</title>
-<link rel="stylesheet" href="../default_style.css">
-</head>
-
-<body LINK="#0000ff" VLINK="#800080">
-<div align="right"> <font face="Times New Roman, Times, serif" size="2">Copyright
- © 2006 Marc R. Hoffmann</font>
- <table border=0 cellspacing=0 cellpadding=2 width="100%">
- <tr>
- <td align=LEFT valign=TOP colspan="2" bgcolor="#0080C0"><b><font face="Arial,Helvetica"><font color="#FFFFFF"> Eclipse
- Corner Article</font></font></b></td>
- </tr>
- </table>
-</div>
-<div align="left">
- <h1><img src="images/Idea.jpg" height=86 width=120 align=CENTER></h1>
-</div>
-<p> </p>
-
-<h1 ALIGN="CENTER">Eclipse Workbench: Using the Selection Service</h1>
-
-<blockquote>
-<b>Summary</b>
-
-<br>
- The selection service provided by the Eclipse workbench allows efficient
- linking of different parts within the workbench window. Knowing and using the
- existing selection mechanisms gives your plug-ins a clean design, smoothly
- integrates them into the workbench and opens them for future extensions.
- <p><b>By Marc R. Hoffmann, Mountainminds GmbH & Co. KG, hoffmann@mountainminds.com</b><br>
- <font size="-1">April 14, 2006</font>
- </p>
-</blockquote>
-
-<hr width="100%">
-
-<h2>Introduction</h2>
-
-<p>
- The Eclipse workbench is a powerful UI framework for IDEs and also other
- applications. It provides many services for a highly integrated and extensible
- user interfaces. One of the integration aspects are view parts that provide
- additional information for particular objects and update their content
- automatically whenever such objects are selected somewhere in the workbench
- window. For example the <i>"Properties"</i> view behaves in this way: Wherever
- an element is selected in the workbench this view lists the properties of
- that element.
-</p>
-
-<img src="images/screen1.gif" width="636" height="222" title="Screen 1">
-
-<p>
- Other aspects of the workbench like the enablement of global actions may also
- depend on the current selection.
-</p>
-
-<p>
- Instead of implementing "hard-wired communication" plug-ins can rely on the so
- called <i>selection service</i>. It decouples parts where items can be
- selected from others reacting on selection changes.
-</p>
-
-<p>
- This article outlines the functionality and usage of the selection service. A
- provided <a href="#example">sample plug-in</a> demonstrates the workbench
- selection behaviour and can also serve for debugging purposes.
-</p>
-
-
-<h2>The Big Picture</h2>
-
-<p>
- Each workbench window has its own <i>selection service</i> instance. The
- service keeps track of the selection in the currently active part and
- propagates selection changes to all registered listeners. Such selection
- events occur when the selection in the current part is changed or when a
- different part is activated. Both can be triggered by user interaction or
- programmatically.
-</p>
-
-<img src="images/diagram1.gif" width="629" height="321" title="Diagram 1">
-
-<p>
- The view where elements or text is selected does not need to know who is
- interested in the selection. Therefore we may create new views that depend on
- the selection of an existing view – without changing a single line of
- code in that view.
-</p>
-
-<p>
- The next sections explain <a href="#provider">who</a> provides
- <a href="#what">what</a> kind of selections to <a href="#listener">whom</a>.
-</p>
-
-
-<h2><a name="what">What can be selected?</h2>
-
-<p>
- From the users point of view a selection is a set of highlighted entries in a
- viewer like a table or tree widget. A selection can also be a piece of text in
- an editor. Behind the scene each visual element in the workbench is
- represented by a Java object. The MVC implementation of JFace maps
- between the domain model objects and the visual representations.
-</p>
-
-<p>
- Internally a selection is a data structure holding the model objects which
- corresponds to the graphical elements selected in the workbench. As pointed
- out before there are two fundamental different kinds of selections:
-</p>
-
-<ul>
- <li>A list of objects</li>
- <li>A piece of text</li>
-</ul>
-
-<p>
- Both can be empty, i.e. a empty list or a text string with zero length.
- Following the typical Eclipse philosophy these data structures are properly
- defined by interfaces:
-</p>
-
-<img src="images/diagram2.gif" width="445" height="206" title="Diagram 2">
-
-
-<p>
- The
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/IStructuredSelection.html"><code>IStructuredSelection</code></a>
- refers to a set of objects;
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/ITextSelection.html"><code>ITextSelection</code></a>
- and
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/IMarkSelection.html"><code>IMarkSelection</code></a>
- describe a piece of selected text.
-</p>
-
-<p>
- For convenience there are default implementations for these interfaces:
-</p>
-
-<ul>
- <li><a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/StructuredSelection.html"><code>org.eclipse.jface.viewers.StructuredSelection</code></a></li>
- <li><a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/TextSelection.html"><code>org.eclipse.jface.text.TextSelection</code></a></li>
- <li><a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/MarkSelection.html"><code>org.eclipse.jface.text.MarkSelection</code></a></li>
-</ul>
-
-<p>
- These implementations are used internally within the viewer when transforming
- low-level SWT events to
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/ISelection.html"><code>ISelection</code></a>
- objects. The implementations are also useful when elements should be selected
- programmatically by some application code, for example:
-</p>
-
-<pre>
- ISelection sel = new StructuredSelection(presetElement);
- treeviewer.setSelection(sel);
-</pre>
-
-<blockquote>
- <p>
- <img src="images/tryit.gif" width="61" height="13">
- Install the provided <a href="#example">sample plug-in</a> and check what
- kind of selections occur in different views. The
- <i>"Workbench Selection"</i> view shows the
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/ISelection.html"><code>ISelection</code></a>
- implementation class and the selected elements or text itself.
- </p>
-</blockquote>
-
-
-
-<h2><a name="provider">Telling the Workbench Window about Selections</h2>
-
-<p>
- All JFace viewers are so called <i>selection providers</i>. A selection
- provider implements the interface
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/ISelectionProvider.html"><code>ISelectionProvider</code></a>:
-</p>
-
-<img src="images/diagram3.gif" width="345" height="108" title="Diagram 3">
-
-<p>
- The different JFace viewers use and propagate different kind of selections:
-</p>
-
-<table>
- <tr>
- <td><b>Viewer</b></td>
- <td><b>Selection Type</b></td>
- </tr><tr>
- <td><code>ComboViewer</code></td>
- <td><a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/IStructuredSelection.html"><code>IStructuredSelection</code></a></td>
- </tr><tr>
- <td><code>ListViewer</code></td>
- <td><a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/IStructuredSelection.html"><code>IStructuredSelection</code></a></td>
- </tr><tr>
- <td><code>TreeViewer</code></td>
- <td><a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/IStructuredSelection.html"><code>IStructuredSelection</code></a></td>
- </tr><tr>
- <td><code> +- CheckboxTreeViewer</code></td>
- <td><a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/IStructuredSelection.html"><code>IStructuredSelection</code></a></td>
- </tr><tr>
- <td><code>TableViewer</code></td>
- <td><a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/IStructuredSelection.html"><code>IStructuredSelection</code></a></td>
- </tr><tr>
- <td><code> +- CheckboxTableViewer</code></td>
- <td><a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/IStructuredSelection.html"><code>IStructuredSelection</code></a></td>
- </tr><tr>
- <td><code>TextViewer</code></td>
- <td><a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/ITextSelection.html"><code>ITextSelection</code></a>,
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/IMarkSelection.html"><code>IMarkSelection</code></a></td>
- </tr><tr>
- <td><code> +- SourceViewer</code></td>
- <td><a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/ITextSelection.html"><code>ITextSelection</code></a>,
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/IMarkSelection.html"><code>IMarkSelection</code></a></td>
- </tr><tr>
- <td><code> +- ProjectionViewer</code></td>
- <td><a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/ITextSelection.html"><code>ITextSelection</code></a>,
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/IMarkSelection.html"><code>IMarkSelection</code></a></td>
- </tr>
-</table>
-
-<p>
- Also custom viewers may serve as selection providers and implement the
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/ISelectionProvider.html"><code>ISelectionProvider</code></a>
- interface.
-</p>
-
-<p>
- Any workbench part that holds a viewer should register this viewer as the
- selection provider with the respective view site:
-</p>
-
-<pre>
- getSite().setSelectionProvider(tableviewer);
-</pre>
-
-<p>
- Even if you don't see a need for propagating your selection right now, this
- opens your plug-in for future extensions by you or by other plug-in
- implementers. If your view defines actions that depend on the current
- selection, setting a selection provider is also necessary to allow dynamic
- enablement of these actions.
-</p>
-
-
-<blockquote>
- <p>
- <img src="images/tip.gif" width="61" height="13">
- Use the <a href="#example">sample plug-in</a> to check whether your views
- properly register selection providers.
- </p>
-</blockquote>
-
-
-<h2><a name="listener">Tracking the Current Selection</h2>
-
-<p>
- The workbench window is typically assembled in many parts, each coming with at
- least one viewer. The workbench keeps track about the currently selected part
- in the window and the selection within this part. Here starts the interesting
- part of the story: Plug-in implementations can access this information or
- register for notifications on selection changes.
-</p>
-
-<p>
- Each workbench window has an
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/ISelectionService.html"><code>ISelectionService</code></a> implementation
- which allows tracking the current selection. A view part can obtain a
- reference to it through its site:
-</p>
-
-<pre>
- getSite().getWorkbenchWindow().getSelectionService()
-</pre>
-
-<p>
- The selection service knows the current selection of the active part or of a
- part with a particular id:
-</p>
-
-<pre>
- ISelection getSelection()
- ISelection getSelection(String partId)
-</pre>
-
-<p>
- Typically views react on selection changes in the workbench window. In this
- case they better register an
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/ISelectionListener.html"><code>ISelectionListener</code></a>
- to get notified when the window's current selection changes:
-</p>
-
-<pre>
- void addSelectionListener(ISelectionListener listener)
- void removeSelectionListener(ISelectionListener listener)
-</pre>
-
-<p>
- Listeners registered in this way are notified when the selection in the active
- part is changed or when a different part is activated. Only selections within
- the active part are propagated. If the application is only interested in the
- selection of a particular part (independently of its actual activation) one
- may register the listener only for the respective part id:
-</p>
-
-<pre>
- void addSelectionListener(String partId, ISelectionListener listener)
- void removeSelectionListener(String partId, ISelectionListener listener)
-</pre>
-
-<p>
- This works even if there is currently no part with such a id. As soon as the
- part is created its initial selection will be propagated to the listeners
- registered for it. When the part is disposed, the listener is passed a
- <code>null</code> selection if the listener implements
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/INullSelectionListener.html"><code>INullSelectionListener</code></a>
- (see <a href="#nullselection">section below</a>).
-</p>
-
-<h3>Implementing a Selection Listener</h3>
-
-<p>
- The
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/ISelectionListener.html"><code>ISelectionListener</code></a>
- is a simple interface with just one method. A typical implementation
- looks like this:
-</p>
-
-<pre>
- private ISelectionListener mylistener = new ISelectionListener() {
- public void selectionChanged(IWorkbenchPart sourcepart, ISelection selection) {
-<img src="images/tag_1.gif" height="13" width="24" align="center"> if (sourcepart != MyView.this &&
-<img src="images/tag_2.gif" height="13" width="24" align="center"> selection instanceof IStructuredSelection) {
-<img src="images/tag_3.gif" height="13" width="24" align="center"> doSomething(((IStructuredSelection) selection).toList());
- }
- }
- };
-</pre>
-
-<p>
- Depending on your requirements your listener implementation probably needs to
- deal with the following issues as shown in the code snippet above:
-</p>
-
-<ul>
- <li>In case we also provide selections (e.g. a view or editor) we should
- <img src="images/tag_1.gif" height="13" width="24" align="center">
- exclude our own selection events from processing. This avoids unexpected
- results when the user selects elements within our part.
- </li>
- <li>Check whether we can handle this kind of selection
- (<img src="images/tag_2.gif" height="13" width="24" align="center">).
- </li>
- <li>Get the selected content from the selection and process it.
- (<img src="images/tag_3.gif" height="13" width="24" align="center">).
- </li>
-</ul>
-
-
-<blockquote>
- <p>
- <img src="images/tip.gif" width="61" height="13">
- Don't mix the
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/ISelectionListener.html"><code>ISelectionListener</code></a>
- interface up with
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/ISelectionChangedListener.html"><code>ISelectionChangedListener</code></a>
- used by JFace viewers to notify about selection changes.
- </p>
-</blockquote>
-
-
-<h3>Removing the Selection Listener</h3>
-
-<p>
- Don't forget to remove your selection listener when you can't handle events
- any more, e.g. when your view has been closed. The <code>dispose()</code>
- method is a good place to
- <img src="images/tag_1.gif" height="13" width="24" align="center"> remove your
- listener:
-</p>
-
-<pre>
- public void dispose() {
- ISelectionService s = getSite().getWorkbenchWindow().getSelectionService();
-<img src="images/tag_1.gif" height="13" width="24" align="center"> s.removeSelectionListener(mylistener);
- super.dispose();
- }
-</pre>
-
-
-
-
-<h2>More Selection Issues</h2>
-
-<p>
- Up to now we focused on the core functionality of the selection service, which covers most
- of the use cases. There are additional issues that might come into picture in implementation
- projects.
-</p>
-
-<h3>Post Selection</h3>
-
-<p>
- When navigating views the selection changes frequently - especially when the keyboard is
- used to scroll through long lists or the mouse is dragged over some text. This will lead
- to many unnecessary updates of the viewers registered as listeners to the selection service
- and may make your application less responsive.
-</p>
-
-<p>
- So called post selection events will be send-out with a slight delay. All intermediate
- selections during the delay time are ignored; just the final selection is propagated.
- The <code>ISelectionService</code> has additional methods to register listeners for the
- delayed selection events:
-</p>
-
-<pre>
- void addPostSelectionListener(ISelectionListener listener)
- void removePostSelectionListener(ISelectionListener listener)
- void addPostSelectionListener(String partId,
- ISelectionListener listener)
- void removePostSelectionListener(String partId,
- ISelectionListener listener)
-</pre>
-
-<p>
- To avoid performance issues viewers should typically register selection listeners this way.
-</p>
-
-<p>
- The selection providers are responsible for sending out the delayed events and have to
- implement the <code>IPostSelectionProvider</code> interface if they support it – all
- JFace viewers do so.
-</p>
-
-<blockquote>
- <p>
- <img src="images/tryit.gif" width="61" height="13">
- Change the <a href="#example">sample plug-in</a> to listen to post selection events and
- check when they are sent.
- </p>
-</blockquote>
-
-<h3><a name="nullselection">INullSelectionListener</h3>
-
-<p>
- The call-back method <code>selectionChanged()</code> defined in
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/ISelectionListener.html"><code>ISelectionListener</code></a>
- get the new selection as well as the originating part passed in as parameters:
-</p>
-
-<pre>
- public void selectionChanged(IWorkbenchPart part, ISelection selection);
-</pre>
-
-<p>
- The
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/INullSelectionListener.html"><code>INullSelectionListener</code></a>
- interface extends
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/ISelectionListener.html"><code>ISelectionListener</code></a>
- but does not declare any additional methods. It is a pure marker interface to
- indicate that implementers of the <code>selectionChanged()</code> method wants
- to bet notified even with <code>null</code> parameters. This is usefull when
- you need to know that there is no current selection simply due to the fact
- that there is no one who provides a selection. You step into this when:
-</p>
-
-<ul>
- <li>The active part has not set a selection provider.</li>
- <li>The specific part we have registered our listener for has not set a selection provider.</li>
- <li>There is no active part in the workbench window, all parts are closed.</li>
- <li>The specific part we have registered our listener for has been closed.</li>
-</ul>
-
-
-<h3>Which Selection Service: Page or Window?</h3>
-
-<p>
- If you study the workbench API carefully you will find out that there
- are two selection services: The
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/IWorkbenchPage.html"><code>IWorkbenchPage</code></a>
- is a
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/ISelectionService.html"><code>ISelectionService</code></a>.
- On the other hand the
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/IWorkbenchWindow.html"><code>IWorkbenchWindow</code></a>
- has a method <code>getSelectionService()</code>. Therefore e.g. registering
- a listener within a part implementation is possible in two ways:
-</p>
-
-<pre>
- getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(l);
-</pre>
-
-<p>
- or
-</p>
-
-<pre>
- getSite().getPage().addSelectionListener(l);
-</pre>
-
-<p>
- Actually this is totally equivalent because since Eclipse 2.0 a workbench
- window is limited to a single page only. Just don't mix both selection
- services when adding and removing a listener as two different implementations
- sit behind it.
-</p>
-
-
-<h3>Multiple Selection Providers Within a Part</h3>
-
-
-<p>
- Be aware that the part's site accepts a single selection provider only,
- which should be registered within the <code>createPartControl()</code>
- method only:
-</p>
-
-<pre>
- getSite().setSelectionProvider(provider);
-</pre>
-
-<p>
- Replacing the selection provider during the lifetime of the part is not
- properly supported by the workbench. If a part contains multiple viewers
- providing selections, like the <i>"Java Hierarchy"</i> view does, a intermediate
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/ISelectionProvider.html"><code>ISelectionProvider</code></a>
- implementation has to be provided that allows dynamically delegating to the
- currently active viewer within the part. As a starting point you may look into
- <a href="SelectionProviderIntermediate.java"><code>SelectionProviderIntermediate.java</code></a>
- provided with this article.
-</p>
-
-
-
-<h3>What to do With the Selected Objects?</h3>
-
-<p>
- This article claims that the <i>selection service</i> helps to decouple
- views reacting on each others selection. But the view handling a selection
- still needs to deal with the selected objects to provide any useful
- functionality. Check out the
- <a href="http://wiki.eclipse.org/index.php/FAQ_How_do_I_use_IAdaptable_and_IAdapterFactory%3F">adapter pattern</a>
- provided by the Eclipse runtime core, which allows attaching new functionality
- to existing model objects or the other way round providing required
- functionality for newly contributed objects.
-</p>
-
-<p>
- Actually our <a href="#example">example plug-in</a> does exactly this by using the workbench label
- provider which in turn relies on the
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/model/IWorkbenchAdapter.html"><code>IWorkbenchAdapter</code></a>
- to retrieve icons and text labels for the listed objects. The same mechanism
- is utilized by the <i>"Properties"</i> view, see article
- <a href="http://www.eclipse.org/articles/Article-Properties-View/properties-view.html">"Take control of your properties"</a>
- for details.
-</p>
-
-
-
-<h2><a name="example">Example Plug-in </h2>
-
-<p>
- This article comes with a small example plug-in that demonstrates the
- explained techniques. Additionally the plug-in may serve for debugging your
- selection providers. The example contributes a new view
- <i>"Workbench Selection"</i> which simply mirrors the current selection in the
- workbench. It works for element selections as well as for text selections.
-</p>
-
-<h3>Getting and Running the Example</h3>
-
-<p>
- Download the plug-in project
- <a href="com.mountainminds.eclipse.selectionsample.zip"><code>com.mountainminds.eclipse.selectionsample.zip</code></a>
- and import it into your workspace via the <i>"Import..."</i> wizard from the
- <i>"File"</i> menu. Select <i>"Existing Project into Workspace"</i> on the
- first wizard page. On the second page simply use the option
- <i>"Select archive file"</i> to import the downloaded archive.
-</p>
-
-<p>
- The fastest way to launch the example is right-clicking the plug-in project
- and select <a>"Run As"</a> → <a>"Eclipse Application"</a> in the
- context menu. From the menu of the launched workbench activate
- <a>"Window"</a> → <a>"Show View"</a> → <a>"Other..."</a> and select
- our view <i>"Workbench Selection"</i> in the category <a>"Other"</a>.
-</p>
-
-
-<p>
- Now you can play around with selections in various workbench parts and see how
- our <i>"Workbench Selection"</i> view reflects these selections:
-</p>
-
-<img src="images/screen2.gif" width="344" height="333" title="Screen 2">
-
-<p>
- The same works for text selections:
-</p>
-
-<img src="images/screen3.gif" width="401" height="333" title="Screen 3">
-
-<p>
- The example is implemented in a single class
- <a href="SelectionView.java"><code>SelectionView.java</code></a> applying the
- techniques discussed in this article. When reading through this short piece
- of code you may note that:
-</p>
-
-<ul>
- <li>
- The <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/ISelectionListener.html"><code>ISelectionListener</code></a>
- implementation makes sure that we do not react on our own selections.
- </li>
- <li>
- The title of the source part of the current selection as well as the
- implementation class of
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/ISelection.html"><code>ISelection</code></a>
- is shown in the view description (the optional grey bar at the top).
- </li>
- <li>
- The view uses two viewers: One for object lists and one for text blocks.
- Switching between the viewers is implemented done with a
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/part/PageBook.html"><code>PageBook</code></a>.
- <li>
- </li>
- The viewer for object lists itself registeres as a selection provider.
- Check it out: If you select a element listed in our
- <i>"Workbench Selection"</i> view its properties are shown in turn in the
- <i>"Properties"</i> view.
- </li>
-</ul>
-
-
-
-
-<h2>Conclusion</h2>
-
-<p>
- The mechanisms provided by the Eclipse workbench are simple to use and
- powerful. Not using this mechanisms result in plug-ins that poorly integrate
- with the rest of the workbench and will be hard to extend. To avoid such
- pitfalls simply follow these rules when selections come into picture:
-</p>
-
-<ul>
- <li>
- Avoid direct hard-wired inter-view communication. If one view needs to react
- on the selection in another view use the <code>ISelectionService</code>.
- </li>
- <li>
- Be cooperative and open for future extensions: Always register your viewers
- as selection providers with the part site.
- </li>
- <li>
- Use existing selection specific views like the <i>"Properties"</i> view when
- appropriate instead of creating new ones.
- </li>
-</ul>
-
-
-<h2>References</h2>
-
-<ul>
- <li>
- OTI Inc., Eclipse Platform Technical Overview, 2003<br>
- <a href="http://www.eclipse.org/whitepapers/eclipse-overview.pdf">http://www.eclipse.org/whitepapers/eclipse-overview.pdf</a>
- </li>
- <li>
- eclipse.org, JFace Viewer Package, 2005<br>
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/package-summary.html">http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/package-summary.html</a>
- </li>
- <li>
- eclipse.org, Workbench UI Package, 2005<br>
- <a href="http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/package-summary.html">http://help.eclipse.org/help31/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/package-summary.html</a>
- </li>
- <li>
- wiki.eclipse.org, FAQ How do I find out what object is selected?, 2006<br>
- <a href="http://wiki.eclipse.org/index.php/FAQ_How_do_I_find_out_what_object_is_selected%3F">http://wiki.eclipse.org/index.php/FAQ_How_do_I_find_out_what_object_is_selected%3F</a>
- </li>
- <li>
- wiki.eclipse.org, FAQ How do I make a view respond to selection changes in another view?, 2006<br>
- <a href="http://wiki.eclipse.org/index.php/FAQ_How_do_I_make_a_view_respond_to_selection_changes_in_another_view%3F">http://wiki.eclipse.org/index.php/FAQ_How_do_I_make_a_view_respond_to_selection_changes_in_another_view%3F</a>
- </li>
- <li>
- wiki.eclipse.org, FAQ How do I use IAdaptable and IAdapterFactory?, 2006<br>
- <a href="http://wiki.eclipse.org/index.php/FAQ_How_do_I_use_IAdaptable_and_IAdapterFactory%3F">http://wiki.eclipse.org/index.php/FAQ_How_do_I_use_IAdaptable_and_IAdapterFactory%3F</a>
- </li>
- <li>
- Dicky Johan, Take control of your properties, 2003<br>
- <a href="http://www.eclipse.org/articles/Article-Properties-View/properties-view.html">http://www.eclipse.org/articles/Article-Properties-View/properties-view.html</a>
- </li>
-</ul>
-
-<p>
- To discuss or report problems in this article see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=112193">bug 112193</a>.
-</p>
-
-<h2>Resources</h2>
-
-<p>
- This article come with the following resources:
-</p>
-
-
-<ul>
- <li>
- Example plug-in providing the <i>"Workbench Selection"</i> view<br>
- <a href="com.mountainminds.eclipse.selectionsample.zip">com.mountainminds.eclipse.selectionsample.zip</a>
- </li>
- <li>
- Selection provider implementation for delegating to multiple other selection providers<br>
- <a href="SelectionProviderIntermediate.java">SelectionProviderIntermediate.java</a>
- </li>
-</ul>
-
-</body>
-</html>
+<html>
+
+<head>
+<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252">
+<title>Eclipse Workbench: Using the Selection Service</title>
+<link rel="stylesheet" href="../default_style.css">
+</head>
+
+<body LINK="#0000ff" VLINK="#800080">
+<div align="right"> <font face="Times New Roman, Times, serif" size="2">Copyright
+ © 2006, 2008 Marc R. Hoffmann</font>
+ <table border=0 cellspacing=0 cellpadding=2 width="100%">
+ <tr>
+ <td align=LEFT valign=TOP colspan="2" bgcolor="#0080C0"><b><font face="Arial,Helvetica"><font color="#FFFFFF"> Eclipse
+ Corner Article</font></font></b></td>
+ </tr>
+ </table>
+</div>
+<div align="left">
+ <h1><img src="images/Idea.jpg" height=86 width=120 align=CENTER></h1>
+</div>
+<p> </p>
+
+<h1 ALIGN="CENTER">Eclipse Workbench: Using the Selection Service</h1>
+
+<blockquote>
+<b>Summary</b>
+
+<br>
+ The selection service provided by the Eclipse workbench allows efficient
+ linking of different parts within the workbench window. Knowing and using the
+ existing selection mechanisms gives your plug-ins a clean design, smoothly
+ integrates them into the workbench and opens them for future extensions.
+ <p><b>By Marc R. Hoffmann, Mountainminds GmbH & Co. KG, hoffmann@mountainminds.com</b><br>
+ <font size="-1">April 14, 2006, last update August 28, 2008</font>
+ </p>
+</blockquote>
+
+<hr width="100%">
+
+<h2>Introduction</h2>
+
+<p>
+ The Eclipse workbench is a powerful UI framework for IDEs and also other
+ applications. It provides many services for a highly integrated and extensible
+ user interfaces. One of the integration aspects are view parts that provide
+ additional information for particular objects and update their content
+ automatically whenever such objects are selected somewhere in the workbench
+ window. For example the <i>"Properties"</i> view behaves in this way: Wherever
+ an element is selected in the workbench this view lists the properties of
+ that element.
+</p>
+
+<img src="images/screen1.gif" width="636" height="222" title="Screen 1">
+
+<p>
+ Other aspects of the workbench like the enablement of global actions may also
+ depend on the current selection.
+</p>
+
+<p>
+ Instead of implementing "hard-wired communication" plug-ins can rely on the so
+ called <i>selection service</i>. It decouples parts where items can be
+ selected from others reacting on selection changes.
+</p>
+
+<p>
+ This article outlines the functionality and usage of the selection service. A
+ provided <a href="#example">sample plug-in</a> demonstrates the workbench
+ selection behaviour and can also serve for debugging purposes.
+</p>
+
+
+<h2>The Big Picture</h2>
+
+<p>
+ Each workbench window has its own <i>selection service</i> instance. The
+ service keeps track of the selection in the currently active part and
+ propagates selection changes to all registered listeners. Such selection
+ events occur when the selection in the current part is changed or when a
+ different part is activated. Both can be triggered by user interaction or
+ programmatically.
+</p>
+
+<img src="images/diagram1.gif" width="629" height="321" title="Diagram 1">
+
+<p>
+ The view where elements or text is selected does not need to know who is
+ interested in the selection. Therefore we may create new views that depend on
+ the selection of an existing view – without changing a single line of
+ code in that view.
+</p>
+
+<p>
+ The next sections explain <a href="#provider">who</a> provides
+ <a href="#what">what</a> kind of selections to <a href="#listener">whom</a>.
+</p>
+
+
+<h2><a name="what">What can be selected?</h2>
+
+<p>
+ From the users point of view a selection is a set of highlighted entries in a
+ viewer like a table or tree widget. A selection can also be a piece of text in
+ an editor. Behind the scene each visual element in the workbench is
+ represented by a Java object. The MVC implementation of JFace maps
+ between the domain model objects and the visual representations.
+</p>
+
+<p>
+ Internally a selection is a data structure holding the model objects which
+ corresponds to the graphical elements selected in the workbench. As pointed
+ out before there are two fundamental different kinds of selections:
+</p>
+
+<ul>
+ <li>A list of objects</li>
+ <li>A piece of text</li>
+</ul>
+
+<p>
+ Both can be empty, i.e. a empty list or a text string with zero length.
+ Following the typical Eclipse philosophy these data structures are properly
+ defined by interfaces:
+</p>
+
+<img src="images/diagram2.gif" width="445" height="270" title="Diagram 2">
+
+
+<p>
+ The
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/IStructuredSelection.html"><code>IStructuredSelection</code></a>
+ refers to a list of objects. A special form of this is the
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/ITreeSelection.html"><code>ITreeSelection</code></a>
+ where each object in the list is described by a path. A path is a list of
+ objects, for example the objects from the root to the selected object in a tree view.
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/ITextSelection.html"><code>ITextSelection</code></a>
+ and
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/IMarkSelection.html"><code>IMarkSelection</code></a>
+ describe a piece of selected text.
+</p>
+
+<p>
+ For convenience there are default implementations for these interfaces:
+</p>
+
+<ul>
+ <li><a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/StructuredSelection.html"><code>org.eclipse.jface.viewers.StructuredSelection</code></a></li>
+ <li><a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/TreeSelection.html"><code>org.eclipse.jface.viewers.TreeSelection</code></a></li>
+ <li><a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/TextSelection.html"><code>org.eclipse.jface.text.TextSelection</code></a></li>
+ <li><a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/MarkSelection.html"><code>org.eclipse.jface.text.MarkSelection</code></a></li>
+</ul>
+
+<p>
+ These implementations are used internally within the viewer when transforming
+ low-level SWT events to
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/ISelection.html"><code>ISelection</code></a>
+ objects. The implementations are also useful when elements should be selected
+ programmatically by some application code, for example:
+</p>
+
+<pre>
+ ISelection sel = new StructuredSelection(presetElement);
+ treeviewer.setSelection(sel);
+</pre>
+
+<blockquote>
+ <p>
+ <img src="images/tryit.gif" width="61" height="13">
+ Install the provided <a href="#example">sample plug-in</a> and check what
+ kind of selections occur in different views. The
+ <i>"Workbench Selection"</i> view shows the
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/ISelection.html"><code>ISelection</code></a>
+ implementation class and the selected elements or text itself.
+ </p>
+</blockquote>
+
+
+
+<h2><a name="provider">Telling the Workbench Window about Selections</h2>
+
+<p>
+ All JFace viewers are so called <i>selection providers</i>. A selection
+ provider implements the interface
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/ISelectionProvider.html"><code>ISelectionProvider</code></a>:
+</p>
+
+<img src="images/diagram3.gif" width="345" height="108" title="Diagram 3">
+
+<p>
+ The different JFace viewers accept and propagate different kind of selections:
+</p>
+
+<table>
+ <tr>
+ <td><b>Viewer</b></td>
+ <td><b>Selection Type</b></td>
+ </tr><tr>
+ <td><code>ComboViewer</code></td>
+ <td><a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/IStructuredSelection.html"><code>IStructuredSelection</code></a></td>
+ </tr><tr>
+ <td><code>ListViewer</code></td>
+ <td><a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/IStructuredSelection.html"><code>IStructuredSelection</code></a></td>
+ </tr><tr>
+ <td><code>TreeViewer</code></td>
+ <td><a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/IStructuredSelection.html"><code>IStructuredSelection</code></a>,
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/ITreeSelection.html"><code>ITreeSelection</code></a></td>
+ </tr><tr>
+ <td><code> +- CheckboxTreeViewer</code></td>
+ <td><a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/IStructuredSelection.html"><code>IStructuredSelection</code></a>,
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/ITreeSelection.html"><code>ITreeSelection</code></td>
+ </tr><tr>
+ <td><code>TableViewer</code></td>
+ <td><a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/IStructuredSelection.html"><code>IStructuredSelection</code></a></td>
+ </tr><tr>
+ <td><code> +- CheckboxTableViewer</code></td>
+ <td><a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/IStructuredSelection.html"><code>IStructuredSelection</code></a></td>
+ </tr><tr>
+ <td><code>TextViewer</code></td>
+ <td><a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/ITextSelection.html"><code>ITextSelection</code></a>,
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/IMarkSelection.html"><code>IMarkSelection</code></a></td>
+ </tr><tr>
+ <td><code> +- SourceViewer</code></td>
+ <td><a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/ITextSelection.html"><code>ITextSelection</code></a>,
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/IMarkSelection.html"><code>IMarkSelection</code></a></td>
+ </tr><tr>
+ <td><code> +- ProjectionViewer</code></td>
+ <td><a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/ITextSelection.html"><code>ITextSelection</code></a>,
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/IMarkSelection.html"><code>IMarkSelection</code></a></td>
+ </tr>
+</table>
+
+<p>
+ Also custom viewers may serve as selection providers and implement the
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/ISelectionProvider.html"><code>ISelectionProvider</code></a>
+ interface.
+</p>
+
+<p>
+ Any workbench part that holds a viewer should register this viewer as the
+ selection provider with the respective view site:
+</p>
+
+<pre>
+ getSite().setSelectionProvider(tableviewer);
+</pre>
+
+<p>
+ Even if you don't see a need for propagating your selection right now, this
+ opens your plug-in for future extensions by you or by other plug-in
+ implementers. If your view defines actions that depend on the current
+ selection, setting a selection provider is also necessary to allow dynamic
+ enablement of these actions.
+</p>
+
+
+<blockquote>
+ <p>
+ <img src="images/tip.gif" width="61" height="13">
+ Use the <a href="#example">sample plug-in</a> to check whether your views
+ properly register selection providers.
+ </p>
+</blockquote>
+
+
+<h2><a name="listener">Tracking the Current Selection</h2>
+
+<p>
+ The workbench window is typically assembled in many parts, each coming with at
+ least one viewer. The workbench keeps track about the currently selected part
+ in the window and the selection within this part. Here starts the interesting
+ part of the story: Plug-in implementations can access this information or
+ register for notifications on selection changes.
+</p>
+
+<p>
+ Each workbench window has an
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/ISelectionService.html"><code>ISelectionService</code></a> implementation
+ which allows tracking the current selection. A view part can obtain a
+ reference to it through its site:
+</p>
+
+<pre>
+ getSite().getWorkbenchWindow().getSelectionService()
+</pre>
+
+<p>
+ The selection service knows the current selection of the active part or of a
+ part with a particular id:
+</p>
+
+<pre>
+ ISelection getSelection()
+ ISelection getSelection(String partId)
+</pre>
+
+<p>
+ Typically views react on selection changes in the workbench window. In this
+ case they better register an
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/ISelectionListener.html"><code>ISelectionListener</code></a>
+ to get notified when the window's current selection changes:
+</p>
+
+<pre>
+ void addSelectionListener(ISelectionListener listener)
+ void removeSelectionListener(ISelectionListener listener)
+</pre>
+
+<p>
+ Listeners registered in this way are notified when the selection in the active
+ part is changed or when a different part is activated. Only selections within
+ the active part are propagated. If the application is only interested in the
+ selection of a particular part (independently of its actual activation) one
+ may register the listener only for the respective part id:
+</p>
+
+<pre>
+ void addSelectionListener(String partId, ISelectionListener listener)
+ void removeSelectionListener(String partId, ISelectionListener listener)
+</pre>
+
+<p>
+ This works even if there is currently no part with such a id. As soon as the
+ part is created its initial selection will be propagated to the listeners
+ registered for it. When the part is disposed, the listener is passed a
+ <code>null</code> selection if the listener implements
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/INullSelectionListener.html"><code>INullSelectionListener</code></a>
+ (see <a href="#nullselection">section below</a>).
+</p>
+
+<h3>Implementing a Selection Listener</h3>
+
+<p>
+ The
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/ISelectionListener.html"><code>ISelectionListener</code></a>
+ is a simple interface with just one method. A typical implementation
+ looks like this:
+</p>
+
+<pre>
+ private ISelectionListener mylistener = new ISelectionListener() {
+ public void selectionChanged(IWorkbenchPart sourcepart, ISelection selection) {
+<img src="images/tag_1.gif" height="13" width="24" align="center"> if (sourcepart != MyView.this &&
+<img src="images/tag_2.gif" height="13" width="24" align="center"> selection instanceof IStructuredSelection) {
+<img src="images/tag_3.gif" height="13" width="24" align="center"> doSomething(((IStructuredSelection) selection).toList());
+ }
+ }
+ };
+</pre>
+
+<p>
+ Depending on your requirements your listener implementation probably needs to
+ deal with the following issues as shown in the code snippet above:
+</p>
+
+<ul>
+ <li>In case we also provide selections (e.g. a view or editor) we should
+ <img src="images/tag_1.gif" height="13" width="24" align="center">
+ exclude our own selection events from processing. This avoids unexpected
+ results when the user selects elements within our part.
+ </li>
+ <li>Check whether we can handle this kind of selection
+ (<img src="images/tag_2.gif" height="13" width="24" align="center">).
+ </li>
+ <li>Get the selected content from the selection and process it.
+ (<img src="images/tag_3.gif" height="13" width="24" align="center">).
+ </li>
+</ul>
+
+
+<blockquote>
+ <p>
+ <img src="images/tip.gif" width="61" height="13">
+ Don't mix the
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/ISelectionListener.html"><code>ISelectionListener</code></a>
+ interface up with
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/ISelectionChangedListener.html"><code>ISelectionChangedListener</code></a>
+ used by JFace viewers to notify about selection changes.
+ </p>
+</blockquote>
+
+
+<h3>Removing the Selection Listener</h3>
+
+<p>
+ Don't forget to remove your selection listener when you can't handle events
+ any more, e.g. when your view has been closed. The <code>dispose()</code>
+ method is a good place to
+ <img src="images/tag_1.gif" height="13" width="24" align="center"> remove your
+ listener:
+</p>
+
+<pre>
+ public void dispose() {
+ ISelectionService s = getSite().getWorkbenchWindow().getSelectionService();
+<img src="images/tag_1.gif" height="13" width="24" align="center"> s.removeSelectionListener(mylistener);
+ super.dispose();
+ }
+</pre>
+
+
+
+
+<h2>More Selection Issues</h2>
+
+<p>
+ Up to now we focused on the core functionality of the selection service, which covers most
+ of the use cases. There are additional issues that might come into picture in implementation
+ projects.
+</p>
+
+<h3>Post Selection</h3>
+
+<p>
+ When navigating views the selection changes frequently - especially when the keyboard is
+ used to scroll through long lists or the mouse is dragged over some text. This will lead
+ to many unnecessary updates of the viewers registered as listeners to the selection service
+ and may make your application less responsive.
+</p>
+
+<p>
+ So called post selection events will be send-out with a slight delay. All intermediate
+ selections during the delay time are ignored; just the final selection is propagated.
+ The <code>ISelectionService</code> has additional methods to register listeners for the
+ delayed selection events:
+</p>
+
+<pre>
+ void addPostSelectionListener(ISelectionListener listener)
+ void removePostSelectionListener(ISelectionListener listener)
+ void addPostSelectionListener(String partId,
+ ISelectionListener listener)
+ void removePostSelectionListener(String partId,
+ ISelectionListener listener)
+</pre>
+
+<p>
+ To avoid performance issues viewers should typically register selection listeners this way.
+</p>
+
+<p>
+ The selection providers are responsible for sending out the delayed events and have to
+ implement the <code>IPostSelectionProvider</code> interface if they support it – all
+ JFace viewers do so.
+</p>
+
+<blockquote>
+ <p>
+ <img src="images/tryit.gif" width="61" height="13">
+ Change the <a href="#example">sample plug-in</a> to listen to post selection events and
+ check when they are sent.
+ </p>
+</blockquote>
+
+<h3><a name="nullselection">INullSelectionListener</h3>
+
+<p>
+ The call-back method <code>selectionChanged()</code> defined in
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/ISelectionListener.html"><code>ISelectionListener</code></a>
+ get the new selection as well as the originating part passed in as parameters:
+</p>
+
+<pre>
+ public void selectionChanged(IWorkbenchPart part, ISelection selection);
+</pre>
+
+<p>
+ The
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/INullSelectionListener.html"><code>INullSelectionListener</code></a>
+ interface extends
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/ISelectionListener.html"><code>ISelectionListener</code></a>
+ but does not declare any additional methods. It is a pure marker interface to
+ indicate that implementers of the <code>selectionChanged()</code> method wants
+ to bet notified even with <code>null</code> parameters. This is usefull when
+ you need to know that there is no current selection simply due to the fact
+ that there is no one who provides a selection. You step into this when:
+</p>
+
+<ul>
+ <li>The active part has not set a selection provider.</li>
+ <li>The specific part we have registered our listener for has not set a selection provider.</li>
+ <li>There is no active part in the workbench window, all parts are closed.</li>
+ <li>The specific part we have registered our listener for has been closed.</li>
+</ul>
+
+
+<h3>Which Selection Service: Page or Window?</h3>
+
+<p>
+ If you study the workbench API carefully you will find out that there
+ are two selection services: The
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/IWorkbenchPage.html"><code>IWorkbenchPage</code></a>
+ is a
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/ISelectionService.html"><code>ISelectionService</code></a>.
+ On the other hand the
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/IWorkbenchWindow.html"><code>IWorkbenchWindow</code></a>
+ has a method <code>getSelectionService()</code>. Therefore e.g. registering
+ a listener within a part implementation is possible in two ways:
+</p>
+
+<pre>
+ getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(l);
+</pre>
+
+<p>
+ or
+</p>
+
+<pre>
+ getSite().getPage().addSelectionListener(l);
+</pre>
+
+<p>
+ Actually this is totally equivalent because since Eclipse 2.0 a workbench
+ window is limited to a single page only. Just don't mix both selection
+ services when adding and removing a listener as two different implementations
+ sit behind it.
+</p>
+
+
+<h3>Multiple Selection Providers Within a Part</h3>
+
+
+<p>
+ Be aware that the part's site accepts a single selection provider only,
+ which should be registered within the <code>createPartControl()</code>
+ method only:
+</p>
+
+<pre>
+ getSite().setSelectionProvider(provider);
+</pre>
+
+<p>
+ Replacing the selection provider during the lifetime of the part is not
+ properly supported by the workbench. If a part contains multiple viewers
+ providing selections, like the <i>"Java Hierarchy"</i> view does, a intermediate
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/ISelectionProvider.html"><code>ISelectionProvider</code></a>
+ implementation has to be provided that allows dynamically delegating to the
+ currently active viewer within the part. As a starting point you may look into
+ <a href="SelectionProviderIntermediate.java"><code>SelectionProviderIntermediate.java</code></a>
+ provided with this article.
+</p>
+
+
+
+<h3>What to do With the Selected Objects?</h3>
+
+<p>
+ This article claims that the <i>selection service</i> helps to decouple
+ views reacting on each others selection. But the view handling a selection
+ still needs to deal with the selected objects to provide any useful
+ functionality. Check out the
+ <a href="http://wiki.eclipse.org/FAQ_How_do_I_use_IAdaptable_and_IAdapterFactory%3F">adapter pattern</a>
+ provided by the Eclipse runtime core, which allows attaching new functionality
+ to existing model objects or the other way round providing required
+ functionality for newly contributed objects.
+</p>
+
+<p>
+ Actually our <a href="#example">example plug-in</a> does exactly this by using the workbench label
+ provider which in turn relies on the
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/model/IWorkbenchAdapter.html"><code>IWorkbenchAdapter</code></a>
+ to retrieve icons and text labels for the listed objects. The same mechanism
+ is utilized by the <i>"Properties"</i> view, see article
+ <a href="http://www.eclipse.org/articles/Article-Properties-View/properties-view.html">"Take control of your properties"</a>
+ for details.
+</p>
+
+
+
+<h2><a name="example">Example Plug-in </h2>
+
+<p>
+ This article comes with a small example plug-in that demonstrates the
+ explained techniques. Additionally the plug-in may serve for debugging your
+ selection providers. The example contributes a new view
+ <i>"Workbench Selection"</i> which simply mirrors the current selection in the
+ workbench. It works for element selections as well as for text selections.
+</p>
+
+<h3>Getting and Running the Example</h3>
+
+<p>
+ Download the plug-in
+ <a href="com.mountainminds.eclipse.selectionsample_1.1.0.jar"><code>com.mountainminds.eclipse.selectionsample_1.1.0.jar</code></a>
+ and import it into your workspace via the <i>"Import..."</i> wizard from the
+ <i>"File"</i> menu. Select <i>"Existing Project into Workspace"</i> on the
+ first wizard page. On the second page simply use the option
+ <i>"Select archive file"</i> to import the downloaded archive. The fastest way
+ to launch the example is right-clicking the plug-in project and select
+ <a>"Run As"</a> → <a>"Eclipse Application"</a> in the context menu.
+</p>
+
+<p>
+ If don't want to play with the source code you can also drop the bundle into
+ an Eclipse installation and use it directly.
+</p>
+
+<p>
+ From the menu of the launched workbench activate
+ <a>"Window"</a> → <a>"Show View"</a> → <a>"Other..."</a> and select
+ our view <i>"Workbench Selection"</i> in the category <a>"Other"</a>. Now you
+ can play around with selections in various workbench parts and see how our
+ <i>"Workbench Selection"</i> view reflects these selections:
+</p>
+
+<img src="images/screen2.gif" width="344" height="333" title="Screen 2">
+
+<p>
+ The same works for text selections:
+</p>
+
+<img src="images/screen3.gif" width="401" height="333" title="Screen 3">
+
+<p>
+ The example is implemented in a single class
+ <a href="SelectionView.java"><code>SelectionView.java</code></a> applying the
+ techniques discussed in this article. When reading through this short piece
+ of code you may note that:
+</p>
+
+<ul>
+ <li>
+ The <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/ISelectionListener.html"><code>ISelectionListener</code></a>
+ implementation makes sure that we do not react on our own selections.
+ </li>
+ <li>
+ The title of the source part of the current selection as well as the
+ implementation class of
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/ISelection.html"><code>ISelection</code></a>
+ is shown in the view description (the optional grey bar at the top).
+ </li>
+ <li>
+ The view uses two viewers: One for object lists and one for text blocks.
+ Switching between the viewers is implemented done with a
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/part/PageBook.html"><code>PageBook</code></a>.
+ <li>
+ </li>
+ The viewer for object lists itself registeres as a selection provider.
+ Check it out: If you select a element listed in our
+ <i>"Workbench Selection"</i> view its properties are shown in turn in the
+ <i>"Properties"</i> view.
+ </li>
+</ul>
+
+
+
+
+<h2>Conclusion</h2>
+
+<p>
+ The mechanisms provided by the Eclipse workbench are simple to use and
+ powerful. Not using this mechanisms result in plug-ins that poorly integrate
+ with the rest of the workbench and will be hard to extend. To avoid such
+ pitfalls simply follow these rules when selections come into picture:
+</p>
+
+<ul>
+ <li>
+ Avoid direct hard-wired inter-view communication. If one view needs to react
+ on the selection in another view use the <code>ISelectionService</code>.
+ </li>
+ <li>
+ Be cooperative and open for future extensions: Always register your viewers
+ as selection providers with the part site.
+ </li>
+ <li>
+ Use existing selection specific views like the <i>"Properties"</i> view when
+ appropriate instead of creating new ones.
+ </li>
+</ul>
+
+
+<h2>References</h2>
+
+<ul>
+ <li>
+ OTI Inc., Eclipse Platform Technical Overview, 2003<br>
+ <a href="http://www.eclipse.org/whitepapers/eclipse-overview.pdf">http://www.eclipse.org/whitepapers/eclipse-overview.pdf</a>
+ </li>
+ <li>
+ eclipse.org, JFace Viewer Package, 2005<br>
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/package-summary.html">http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/package-summary.html</a>
+ </li>
+ <li>
+ eclipse.org, Workbench UI Package, 2005<br>
+ <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/package-summary.html">http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/package-summary.html</a>
+ </li>
+ <li>
+ wiki.eclipse.org, FAQ How do I find out what object is selected?, 2006<br>
+ <a href="http://wiki.eclipse.org/FAQ_How_do_I_find_out_what_object_is_selected%3F">http://wiki.eclipse.org/FAQ_How_do_I_find_out_what_object_is_selected%3F</a>
+ </li>
+ <li>
+ wiki.eclipse.org, FAQ How do I make a view respond to selection changes in another view?, 2006<br>
+ <a href="http://wiki.eclipse.org/FAQ_How_do_I_make_a_view_respond_to_selection_changes_in_another_view%3F">http://wiki.eclipse.org/FAQ_How_do_I_make_a_view_respond_to_selection_changes_in_another_view%3F</a>
+ </li>
+ <li>
+ wiki.eclipse.org, FAQ How do I use IAdaptable and IAdapterFactory?, 2006<br>
+ <a href="http://wiki.eclipse.org/FAQ_How_do_I_use_IAdaptable_and_IAdapterFactory%3F">http://wiki.eclipse.org/FAQ_How_do_I_use_IAdaptable_and_IAdapterFactory%3F</a>
+ </li>
+ <li>
+ Dicky Johan, Take control of your properties, 2003<br>
+ <a href="http://www.eclipse.org/articles/Article-Properties-View/properties-view.html">http://www.eclipse.org/articles/Article-Properties-View/properties-view.html</a>
+ </li>
+</ul>
+
+<p>
+ To discuss or report problems in this article see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=112193">bug 112193</a>.
+</p>
+
+<h2>Resources</h2>
+
+<p>
+ This article come with the following resources:
+</p>
+
+
+<ul>
+ <li>
+ Example plug-in providing the <i>"Workbench Selection"</i> view<br>
+ <a href="com.mountainminds.eclipse.selectionsample_1.1.0.jar">com.mountainminds.eclipse.selectionsample_1.1.0.jar</a>
+ </li>
+ <li>
+ Selection provider implementation for delegating to multiple other selection providers<br>
+ <a href="SelectionProviderIntermediate.java">SelectionProviderIntermediate.java</a>
+ </li>
+</ul>
+
+</body>
+</html>
diff --git a/Article-WorkbenchSelections/com.mountainminds.eclipse.selectionsample_1.1.0.jar b/Article-WorkbenchSelections/com.mountainminds.eclipse.selectionsample_1.1.0.jar
new file mode 100644
index 0000000..8bc4699
--- /dev/null
+++ b/Article-WorkbenchSelections/com.mountainminds.eclipse.selectionsample_1.1.0.jar
Binary files differ
diff --git a/Article-WorkbenchSelections/images/diagram2.gif b/Article-WorkbenchSelections/images/diagram2.gif
index 0765b99..574cf2b 100644
--- a/Article-WorkbenchSelections/images/diagram2.gif
+++ b/Article-WorkbenchSelections/images/diagram2.gif
Binary files differ