<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>TechJava&#187; TechJava &#8211; Articles tagged by common navigator framework</title>
	<atom:link href="http://www.techjava.de/topics/tag/common-navigator-framework/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.techjava.de</link>
	<description>Journal on Java Technology</description>
	<lastBuildDate>Thu, 17 Jun 2010 10:41:29 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Eclipse CNF: Navigator Content Extensions</title>
		<link>http://www.techjava.de/topics/2009/08/eclipse-common-navigator-framework-2/</link>
		<comments>http://www.techjava.de/topics/2009/08/eclipse-common-navigator-framework-2/#comments</comments>
		<pubDate>Mon, 17 Aug 2009 20:55:11 +0000</pubDate>
		<dc:creator>Simon Zambrovski</dc:creator>
				<category><![CDATA[eclipse]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[rcp]]></category>
		<category><![CDATA[cnf]]></category>
		<category><![CDATA[common navigator framework]]></category>
		<category><![CDATA[navigator content extension]]></category>
		<category><![CDATA[NCE]]></category>
		<category><![CDATA[plug-in]]></category>

		<guid isPermaLink="false">http://www.techjava.de/?p=471</guid>
		<description><![CDATA[Abstract
 After 
providing the basic example of how the Eclipse Common Navigator Framework (CNF) can be used to display custom content, this article focuses on the main feature of the CNF &#8211; the contribution of content to the same navigator by several independent plug-ins. First of all, I will explain some minor changes introduced to [...]]]></description>
			<content:encoded><![CDATA[<h2>Abstract</h2>
<p><img class="alignnone size-thumbnail wp-image-501" style="float:right; margin:10px;" title="compass" src="http://www.techjava.de/wp-content/uploads/compass2-150x150.jpg" alt="compass" width="150" height="150" /> After 
<a  href="http://www.techjava.de/topics/2009/04/eclipse-common-navigator-framework/">providing the basic example</a> of how the Eclipse Common Navigator Framework (CNF) can be used to display custom content, this article focuses on the main feature of the CNF &#8211; the contribution of content to the same navigator by several independent plug-ins. First of all, I will explain some minor changes introduced to the CNF in the Gallileo Edition, then I will focus on the content itself and finally provide an overview of how the action contributions can be provided. In the end of the post, some ideas on control of dynamic content are explained.</p>
<h2>Gallileo Changes</h2>
<p>There are two noticeable changes in the CNF that have been added with 
<a  href="http://www.techjava.de/topics/2009/06/galileo-has-arrived/">Eclipse Galileo</a>. The return type of the method <span id="more-471"></span><code>CommonNavigator#getInitialInput()</code> has been changed to <code>Object</code> (which is important for the RCP usage of the CNF) and the call of the method <code>org.eclipse.ui.internal.ide.model.WorkbenchAdapterBuilder#registerAdapters()</code> has been replaced by the <code>org.eclipse.ui.ide.IDE.registerAdapters();</code> which should be executed in the <code>initialize</code> method of the <code>ApplicationWorkbenchAdvisor</code> of your RCP if you are using resources with the CNF.</p>
<pre class="brush: java;">
public class CommonNavigator ...
{
  /**
   * Used to provide the initial input for the {@link CommonViewer}.
   * By default getSite().getPage().getInput() is used.
   * Subclass this to return your desired input.
   * @return The initial input for the viewer.
   * Defaults to getSite().getPage().getInput()
   * @since 3.4
   */
  protected Object getInitialInput() {...}
}
</pre>
<h2>Content contribution</h2>
<p>The main advantage of the use of the CNF over a simple tree view is the ability to contribute content to the view from several plug-ins. Thus, the plug-in that contains the view does not depend on the contributing plug-ins. If you are not familiar with the CNF, please review the 
<a  href="http://www.techjava.de/topics/2009/04/eclipse-common-navigator-framework/">previous post</a>, since the example provided there will be extended. The data model used previously will be extended by an additional layer: along with parents and children, the pets are introduced. Let&#8217;s assume that pets are owned by children.</p>
<pre class="brush: java;">
/**
 * Represents a pet
 * @author Simon Zambrovski
 */
public class Pet
{
    private String name;
    private Child owner;

    public Pet(String name, Child owner)
    {
        super();
        this.name = name;
        this.owner = owner;
    }
    ...
    // getter and setter
}
</pre>
<p>First of all create a new plug-in project called <code>de.techjava.rcp.cnf.subcontent</code>, add a plug-in dependency to the <code>de.techjava.rcp.cnf</code> and to the <code>org.eclipse.ui.navigator</code>. Then add two extensions <code>org.eclipse.ui.navigator.navigatorContent</code> and <code>org.eclipse.ui.navigator.viewer</code>. The first extension defines the new Navigator Content Extension (NCE) and the second one is used to bind it to the existing viewer.</p>
<pre class="brush: xml;">
   &lt;extension
         point=&quot;org.eclipse.ui.navigator.navigatorContent&quot;&gt;
      &lt;navigatorContent
            activeByDefault=&quot;true&quot;
            contentProvider=&quot;de.techjava.rcp.cnf.subcontent.provider.CNFSubContentProvider&quot;
            id=&quot;de.techjava.rcp.cnf.subcontent.navigatorContent&quot;
            labelProvider=&quot;de.techjava.rcp.cnf.subcontent.provider.CNFSubLabelProvider&quot;
            name=&quot;Sub Content&quot;
            priority=&quot;normal&quot;
            providesSaveables=&quot;false&quot;&gt;
         &lt;enablement&gt;
            &lt;instanceof value=&quot;de.techjava.rcp.cnf.data.Child&quot; /&gt;
         &lt;/enablement&gt;
      &lt;/navigatorContent&gt;
   &lt;/extension&gt;
   &lt;extension
         point=&quot;org.eclipse.ui.handlers&quot;&gt;
      &lt;handler
            class=&quot;de.techjava.rcp.cnf.subcontent.handler.RenameHandler&quot;
            commandId=&quot;org.eclipse.ui.edit.rename&quot;&gt;
         &lt;activeWhen&gt;
            &lt;reference definitionId=&quot;de.techjava.rcp.cnf.subcontent.petSelected&quot; /&gt;
         &lt;/activeWhen&gt;
         &lt;enabledWhen&gt;
            &lt;reference definitionId=&quot;de.techjava.rcp.cnf.subcontent.petSelected&quot;/&gt;
         &lt;/enabledWhen&gt;
      &lt;/handler&gt;
   &lt;/extension&gt;
</pre>
<p>The Sub Content is defined following the same scheme as the content in the previous article of this series.  Its <code>contentProvider</code> and <code>labelProvider</code> attributes point to the corresponding classes. The label provider implementation is straight forward. The content provider has to be able to return a list of children, if the instance of the <code>Child</code>-class is selected in the Navigator. The <code>enablement</code> is defined in this way respectively. An important thing to understand at this point is that the CNF will <strong>join</strong> contributions of all NCEs triggered on the element selection. This means, that even if the NCE of the first plug-in does not provide any children for the <code>Child</code> element, there will be children contributed by the second plug-in&#8217;s content provider. Here is the example content provider, which returns the number of pets depending on the last digit in a child&#8217;s name:</p>
<pre class="brush: java;">
public class CNFSubContentProvider implements ITreeContentProvider
{
    ...
    public Object[] getChildren(Object parentElement)
    {
        if (parentElement instanceof Child
                &amp;&amp; !(parentElement instanceof Parent))
        {
            Child child = ((Child) parentElement);
            char lastDigit = child.getName().charAt(child.getName().length() - 1);
            if (Character.isDigit(lastDigit))
            {
                int petCount = Integer.parseInt(String.valueOf(lastDigit));
                Pet[] pets = new Pet[petCount];
                for (int i = 0; i &gt; petCount; i++)
                {
                    pets[i] = new Pet(child.getName() + &quot;'s pet &quot; + (i + 1), child);
                }
                return pets;
            }
            return EMPTY_ARRAY;
        } else
        {
            return EMPTY_ARRAY;
        }
    }
    ...
}
</pre>
<p>After this trivial configuration and the inclusion of the new plug-in into the example product, the resulting Navigator should show pets as sub-elements of the child-elements.<br />
<img class="alignnone size-full wp-image-484" title="CNF2" src="http://www.techjava.de/wp-content/uploads/CNF2.png" alt="CNF2" width="400" height="300" /></p>
<h2>Shared commands</h2>
<p>If the Navigator displays content from several plug-ins, the contributed commands should be handled carefully. The commands (contributed to the pop-up menu shown upon right-click on the corresponding item) should appear only on items they belong to. In order to achieve this, let us first look at the standard way of the command contribution. The CNF developer is strongly recommend to use the declarative contribution techniques instead of the Action Contribution Provider. For this purpose, the extension point <code>org.eclipse.ui.navigator.viewer</code> allows to contribute a <code>popupMenu</code> element as a child element of the <code>viewer</code>. The pop-up menu element defines the structure (in terms of separators) of the pop-up menu. There is a standard pop-up menu structure defined, which is default if a user-specific definition is ommited. In the example, the user-specific pop-up menu is defined:</p>
<pre class="brush: xml;">
   &lt;extension
         point=&quot;org.eclipse.ui.navigator.viewer&quot;&gt;
      &lt;viewer
            viewerId=&quot;de.techjava.rcp.cnf.view&quot;&gt;
         &lt;popupMenu
               allowsPlatformContributions=&quot;true&quot;
               id=&quot;de.techjava.rcp.cnf.view.popup&quot;&gt;
            &lt;insertionPoint
                  name=&quot;group.new&quot;
                  separator=&quot;false&quot;&gt;
            &lt;/insertionPoint&gt;
            &lt;insertionPoint
                  name=&quot;group.open&quot;
                  separator=&quot;false&quot;&gt;
            &lt;/insertionPoint&gt;
            &lt;insertionPoint
                  name=&quot;group.edit&quot;
                  separator=&quot;true&quot;&gt;
            &lt;/insertionPoint&gt;
            ...
         &lt;/popupMenu&gt;
      &lt;/viewer&gt;
      ...
    &lt;/extension&gt;
</pre>
<p>Using the 
<a  href="http://wiki.eclipse.org/index.php/Platform_Command_Framework" onclick="javascript:pageTracker._trackPageview('/external/wiki.eclipse.org/index.php/Platform_Command_Framework');" >Eclipse Command Framework</a>, the commands can be contributed to the defined pop-up menu in the following way. Using the <code>org.eclipse.ui.menus</code> extension point one or several <code>menuContribution</code> elements can be defined. Each menu contribution defines a set of commands, controls, menus, tool bars or dynamic contributions (or any combination) which are added to a specific separator addressed in a special way (see Command Framework Documentation). In this example the set of commands is contributed:</p>
<pre class="brush: xml;">
   &lt;extension
         point=&quot;org.eclipse.ui.menus&quot;&gt;
      &lt;menuContribution
            locationURI=&quot;popup:de.techjava.rcp.cnf.view.popup?after=group.edit&quot;&gt;
         &lt;command
               commandId=&quot;org.eclipse.ui.edit.delete&quot;
               id=&quot;cnf.popupmenu.delete&quot;
               label=&quot;Delete&quot;
               mnemonic=&quot;D&quot;
               style=&quot;push&quot;&gt;
         &lt;/command&gt;
         &lt;command
               commandId=&quot;org.eclipse.ui.edit.rename&quot;
               id=&quot;cnf.popupmenu.rename&quot;
               label=&quot;Rename&quot;
               mnemonic=&quot;R&quot;
               style=&quot;push&quot;&gt;
         &lt;/command&gt;
      &lt;/menuContribution&gt;
      ....
    &lt;/extension&gt;
</pre>
<p>Please note that the <code>commandId</code> must point to an existing command, which is either user-defined, or defined by the Eclipse platform. A <code>command</code> is an abstraction of a user command which is referenced from the User Interface on one hand and has assigned handlers (which execute the command) on the other hand. The representation of the command is shown in the UI only if a handler is assigned to it. The idea of using shared commands is to have multiple handlers for the same command, which are activated depending on the selected element.</p>
<p>In order to enable and disable handlers in a declarative way, the 
<a  href="http://wiki.eclipse.org/Command_Core_Expressions" onclick="javascript:pageTracker._trackPageview('/external/wiki.eclipse.org/Command_Core_Expressions');" >Eclipse Core Expressions</a> are used. Core expressions can be written in the <code>enabledWhen</code> and <code>activeWhen</code> child elements of the handler definition. The core expressions can also be defined and referenced externally using the <code>org.eclipse.core.expressions.definitions</code> extension point. Here is an example definition of the handler assigned to the Rename command:</p>
<pre class="brush: xml;">
   &lt;extension
         point=&quot;org.eclipse.ui.handlers&quot;&gt;
      &lt;handler
            class=&quot;de.techjava.rcp.cnf.handler.RenameHandler&quot;
            commandId=&quot;org.eclipse.ui.edit.rename&quot;&gt;
         &lt;activeWhen&gt;
            &lt;reference definitionId=&quot;de.techjava.rcp.cnf.elementSelected&quot; /&gt;
         &lt;/activeWhen&gt;
         &lt;enabledWhen&gt;
            &lt;reference definitionId=&quot;de.techjava.rcp.cnf.elementSelected&quot; /&gt;
         &lt;/enabledWhen&gt;
      &lt;/handler&gt;
   &lt;/extension&gt;
</pre>
<p>The handler is enabled and active if the expression <code>de.techjava.rcp.cnf.elementSelected</code> is triggered. The definition of the expression is as follows. It defines the <code>with</code>-scope on the current selection, <code>iterates</code> over the elements and applies the <code>instance of</code> operator on the elements using the OR-conjunction. In doing so, the expression will trigger if among the currently selected elements is at least one <code>Child</code> element.</p>
<pre class="brush: xml;">
   &lt;extension
         point=&quot;org.eclipse.core.expressions.definitions&quot;&gt;
      &lt;definition id=&quot;de.techjava.rcp.cnf.elementSelected&quot;&gt;
         &lt;with variable=&quot;selection&quot;&gt;
            &lt;iterate ifEmpty=&quot;false&quot; operator=&quot;or&quot;&gt;
               &lt;instanceof value=&quot;de.techjava.rcp.cnf.data.Child&quot; /&gt;
            &lt;/iterate&gt;
         &lt;/with&gt;
      &lt;/definition&gt;
   &lt;/extension&gt;
</pre>
<p><img class="alignnone size-full wp-image-486" title="CNF2-rename-child" src="http://www.techjava.de/wp-content/uploads/CNF2-rename-child.png" alt="CNF2-rename-child" width="384" height="239" /><br />
In order to use the same action (the Rename item of the pop-up menu) in the Pet plug-in, the handler enabled on the Pet element has to be provided. The code is analogous to the code before:</p>
<pre class="brush: xml;">
   &lt;extension
         point=&quot;org.eclipse.ui.handlers&quot;&gt;
      &lt;handler
            class=&quot;de.techjava.rcp.cnf.subcontent.handler.RenameHandler&quot;
            commandId=&quot;org.eclipse.ui.edit.rename&quot;&gt;
         &lt;activeWhen&gt;
            &lt;reference
                  definitionId=&quot;de.techjava.rcp.cnf.subcontent.petSelected&quot;&gt;
            &lt;/reference&gt;
         &lt;/activeWhen&gt;
         &lt;enabledWhen&gt;
            &lt;reference definitionId=&quot;de.techjava.rcp.cnf.subcontent.petSelected&quot; /&gt;
         &lt;/enabledWhen&gt;
      &lt;/handler&gt;
   &lt;/extension&gt;
   &lt;extension
         point=&quot;org.eclipse.core.expressions.definitions&quot;&gt;
      &lt;definition
            id=&quot;de.techjava.rcp.cnf.subcontent.petSelected&quot;&gt;
         &lt;with variable=&quot;selection&quot;&gt;
            &lt;iterate ifEmpty=&quot;false&quot; operator=&quot;or&quot;&gt;
               &lt;instanceof value=&quot;de.techjava.rcp.cnf.subcontent.data.Pet&quot; /&gt;
            &lt;/iterate&gt;
         &lt;/with&gt;
      &lt;/definition&gt;
   &lt;/extension&gt;
</pre>
<p>This should enable the Rename action on the Pet elements, too.<br />
<img class="alignnone size-full wp-image-487" title="CNF2-rename-pet" src="http://www.techjava.de/wp-content/uploads/CNF2-rename-pet.png" alt="CNF2-rename-pet" width="384" height="239" /></p>
<h2>Dynamic content change</h2>
<p>Finally, the last topic, which is covered in this article is the control of which content is shown in the Common Navigator. The developer can define the initial behaviour by setting the <code>activeByDefault</code> attribute of the <code>NavigatorContent</code> element. The user can customize the visible NCEs in the special dialog:<br />
<img class="alignnone size-full wp-image-489" title="CNF2-available-customizations" src="http://www.techjava.de/wp-content/uploads/CNF2-available-customizations.png" alt="CNF2-available-customizations" width="407" height="339" /><br />
Of course there is a way to change the content shown in the Common Navigator at run-time. The following section describes how this can be done.</p>
<p>Responsible for loading the NCEs is the NavigatorContentService, which can be retrieved from the running Navigator instance. Using it is straight forward.</p>
<pre class="brush: java;">
    /**
     * Sets the status of a NCE of the current viewer if any
     */
    public static void setToolboxNCEActive(final String extensionId, final boolean active)
    {
        CommonNavigator instance = findCommonNavigator(CNFNavigator.VIEW_ID);
        if (instance != null)
        {
            INavigatorContentService contentService = instance.getNavigatorContentService();
            boolean isActive = contentService.getActivationService().isNavigatorExtensionActive(extensionId);
            if (active &amp;&amp; !isActive)
            {
                contentService.getActivationService().activateExtensions(new String[] { extensionId }, false);
            } else if (!active &amp;&amp; isActive)
            {
                contentService.getActivationService().deactivateExtensions(new String[] { extensionId }, false);
            } else
            {
                // do nothing, just quit
                return;
            }
            contentService.getActivationService().persistExtensionActivations();
            contentService.update();
        }
    }
</pre>
<p>The method <code>findCommonNavigator(String viewId)</code> is responsible for delivering the instance of the CNF. For example it could query the view for visible viewers and compare them with the requested Id:</p>
<pre class="brush: java;">
    public static CommonNavigator findCommonNavigator(String navigatorViewId)
    {
        IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
        if (page != null)
        {
            IViewPart view = page.findView(navigatorViewId);
            if (view != null &amp;&amp; view instanceof CommonNavigator)
                return ((CommonNavigator) view);
        }
        return null;
    }
</pre>
<p>After the NCE status is changed the viewer has to be updated. Please note, that retrieving the instance of the <code>INavigatorContentService</code> via the Factory (<code>NavigatorContentServiceFactory</code>) will not work for this scenario (see 
<a  href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=284650" onclick="javascript:pageTracker._trackPageview('/external/bugs.eclipse.org/bugs/show_bug.cgi');" >Bug 284650</a>).</p>
<p>Making a step back and thinking about the usage of the method above, I realized that it can be reduced to the usage of core expressions instead of the simple boolean <code>activeByDefault</code> attribute. Maybe this enhancement could be contributed to the CNF at some point&#8230;</p>
<p>The source code to this post is available for 
<a  href="http://www.techjava.de/wp-content/uploads/rcp-cnf2.zip" onclick="javascript:pageTracker._trackPageview('/downloads/wp-content/uploads/rcp-cnf2.zip');" >download</a>. It includes two plug-in projects (the CNF and the child content) which are packaged into a small RCP application. Just launch the product included in the CNF plug-in.</p>
<h3>References</h3>
<ul>
<li>
<a  href="http://wiki.eclipse.org/index.php/Common_Navigator_Framework" onclick="javascript:pageTracker._trackPageview('/external/wiki.eclipse.org/index.php/Common_Navigator_Framework');" >http://wiki.eclipse.org/index.php/Common_Navigator_Framework</a></li>
<li>
<a  href="http://wiki.eclipse.org/Command_Core_Expressions" onclick="javascript:pageTracker._trackPageview('/external/wiki.eclipse.org/Command_Core_Expressions');" >http://wiki.eclipse.org/Command_Core_Expressions</a></li>
<li>
<a  href="http://wiki.eclipse.org/index.php/Platform_Command_Framework" onclick="javascript:pageTracker._trackPageview('/external/wiki.eclipse.org/index.php/Platform_Command_Framework');" >http://wiki.eclipse.org/index.php/Platform_Command_Framework</a></li>
</ul>
<p>The compass image used in the post is taken from the 
<a  href="http://www.flickr.com/photos/bio_inc/484534267/" onclick="javascript:pageTracker._trackPageview('/external/www.flickr.com/photos/bio_inc/484534267/');" >FlickR gallery</a> of Jean Franco Castro.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.techjava.de/topics/2009/08/eclipse-common-navigator-framework-2/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Eclipse Common Navigator Framework</title>
		<link>http://www.techjava.de/topics/2009/04/eclipse-common-navigator-framework/</link>
		<comments>http://www.techjava.de/topics/2009/04/eclipse-common-navigator-framework/#comments</comments>
		<pubDate>Tue, 28 Apr 2009 01:13:02 +0000</pubDate>
		<dc:creator>Simon Zambrovski</dc:creator>
				<category><![CDATA[eclipse]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[rcp]]></category>
		<category><![CDATA[cnf]]></category>
		<category><![CDATA[common navigator]]></category>
		<category><![CDATA[common navigator framework]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[resource]]></category>

		<guid isPermaLink="false">http://www.techjava.de/?p=302</guid>
		<description><![CDATA[
Abstract
This article describes some efforts to use the Common Navigator Framework (CNF). In doing so it incorporates the information already covered in different articles, but also focuses on the specific use case of providing a view of something completely unrelated to the platform resources. So the aim is not to add some content to the [...]]]></description>
			<content:encoded><![CDATA[<p><img style="margin: 10px; float:right;" title="compas" src="http://www.techjava.de/wp-content/uploads/compas.jpg" alt="compas" width="240" height="160" /></p>
<h2>Abstract</h2>
<p>This article describes some efforts to use the Common Navigator Framework (CNF). In doing so it incorporates the information already covered in different articles, but also focuses on the specific use case of providing a view of something completely unrelated to the platform resources. So the aim is not to add some content to the &#8220;Project Explorer&#8221; which is an example of resource-oriented CNF usage, but to provide a view on a completely own data model.</p>
<h2>Introduction</h2>
<p><img style="margin: 10px; float:left;" title="Project Explorer" src="http://www.techjava.de/wp-content/uploads/pe_01.png" alt="Project Explorer" width="272" height="179" /><br />
A very common UI element to represent data is a tree view. In SWT this UI element is implemented using the <code>Tree</code> widget. Following the MVC design pattern in the <code>TreeViewer</code>, JFace simplifies the usage of the Tree widget by delegating the task of content adoption to the ContentProvider and the label production to the LabelProvider (and using Sorters and Filters for sorting and filtering). Still for a single representation one has to construct a viewer and configure it with a corresponding Label- and ContentProvider. Further code reduction can be achieved by the use of <code>WorkbenchContentProvider</code> and <code>WorkbenchLabelProvider</code> if the elements can be made adaptable (implement <code>IAdaptable</code> interface and making them first-class workbench citizens). This approach is helpful, if the elements has to be displayed in several different viewers (e.G. Table). Finally, <strong>the Common Navigator Framework (CNF)</strong> is a facility provided by the Eclipse Platform which allows the usage of multiple Label- and ContentProvider on the same view. The providers are activated and used dynamically and can be configured declarative or programmatically. The advantage of CNF approach is the ability to combine elements in one view which have different origins(e.G. contributed by different plugins). CNF is used in Eclipse IDE: e.G. &#8220;ProjectExplorer&#8221; and &#8220;CVS Synchrnoize&#8221; are both instances of the CNF.</p>
<p>The usage of the CNF in your own application for purposes of representation of resource-based (and usually file-based) content is discussed in 
<a  href="http://scribbledideas.blogspot.com/2006/07/pdf-versions-now-available.html" onclick="javascript:pageTracker._trackPageview('/external/scribbledideas.blogspot.com/2006/07/pdf-versions-now-available.html');" >articles of Micael Elder</a> in detail. The main idea is to instantiate the view, declare the default content and UI interface and make some additions where needed. This post has a different aim: we start from scratch and represent completely resource unrelated content. Before diving in the implementation details, some overview is provided.</p>
<h2>UI Overview</h2>
<p><img style="margin: 10px; float:right;" title="Project Explorer with default options" src="http://www.techjava.de/wp-content/uploads/pe_02.png" alt="Project Explorer with default options" width="380" height="215" /> There are many things which can be configured by the usage of CNF and it is beyond the scope of this post to cover all of them. Still there are several things to understand before the actual code can be written. The user interacts with a View which shows the data elements. Which elements are shown is configured using the navigation content extensions. Shown elements can be filtered with Filters and sorted using Sorters on behalf of the user. There are some predefined actions and their positions in the UI and corresponding extension points to contribute to. <img style="margin: 10px; float:right;" title="Project Explorer Pop-up" src="http://www.techjava.de/wp-content/uploads/pe_031.png" alt="Project Explorer Pop-up" width="293" height="174" />. The actions for <strong>Working sets</strong>, <strong>Customize View</strong>, <strong>Link with editor</strong> belong to this category. The user can also right-click on particular element in the tree and sees a popup-menu. This menu is configured based on the content element and can be (is) contributed by several plugins. The action contribution is also covered in the article series from 
<a  href="http://scribbledideas.blogspot.com/2006/07/pdf-versions-now-available.html" onclick="javascript:pageTracker._trackPageview('/external/scribbledideas.blogspot.com/2006/07/pdf-versions-now-available.html');" >Michael Elder</a>.<br />
<br />
<span id="more-302"></span></p>
<h2>Minimal non-resource based CNF viewer</h2>
<p>The following example provide a set of minimal steps required to create a non-resource based CNF viewer. Your plug-in requires at least a dependency to <code>org.eclipse.ui.navigator</code>, <code>org.eclipse.ui</code>. </p>
<h3>Data model</h3>
<p>Let us assume a simple data model that should be represented in the view. There are two kinds of elements: parents and children (see Composite design pattern). Both Child and Parent are POJOs:</p>
<pre class="brush: java;">
public class Child
{
    private String name;
    private Parent parent;

    public Child(String name)
    {
        super();
        this.name = name;
    }

    // getters and setter
...
}
</pre>
<p>Every child stores information about its parent, and every parent knows its children. In order to maintain the model in-sync the <code>setChildren()</code> method of the <code>Parent</code> class takes care of unsetting on all previous children and setting the parent on new children. This is just a sample code and there are different ways to implement this more elegantly (like e.G. holding the parent-child relation externally).</p>
<pre class="brush: java;">
public class Parent extends Child
{
    private Child[] children = new Child[0];
    private Object rootElement;

    public Parent(String name)
    {
        super(name);
    }

    public void setChildren(Child[] children)
    {
        if (children != null)
        {
            setChildrensParent(null, this.children);
        }
        this.children = children;
        setChildrensParent(this, this.children);
    }

    /**
     * Sets children's parent
     * @param parent parent to be set
     * @param children children to set the parent
     */
    private static void setChildrensParent(Parent parent, Child[] children)
    {
        for (int i = 0; i &lt; children.length; i++)
        {
            children[i].setParent(parent);
        }
    }

    // getter and setter
...
}
</pre>
<p>Please note, that nothing more is assumed about the parent and the child. It is a good idea to make such elements implement <code>IAdaptable</code>, which simplifies a lot of issues later, but this is another topic. You may have noticed the <code>rootElement</code> member of the Parent. Again, this is only used in order to keep the object tree structure as simple as possible and provide a hook to the root of the tree. The final tree structure contains one root object, several parent objects containing several child objects each.</p>
<pre class="brush: java;">
public class Root extends PlatformObject
{
}
</pre>
<h3>Declaring the viewer</h3>
<p>In order to contribute a view to RCP/IDE the <code>org.eclipse.ui.views</code> extension point is used:</p>
<pre class="brush: xml;">
   &lt;extension
         point=&quot;org.eclipse.ui.views&quot;&gt;
      &lt;view
            class=&quot;de.techjava.rcp.cnf.provider.CNFNavigator&quot;
            id=&quot;de.techjava.rcp.cnf.view&quot;
            name=&quot;Virtual CNF&quot;
            restorable=&quot;true&quot;&gt;
      &lt;/view&gt;
   &lt;/extension&gt;
</pre>
<p>The two important things here are the <code>class</code> attribute pointing to the class of the CNF Navigator and the <code>id</code> attribute that will be used later in order to identify the view. Instead of pointing to the <code>org.eclipse.ui.navigator.CommonNavigator</code><br />
the reference to <code>ParentChildNavigator</code> is provided which is a subclass of the <code>CommonNavigator</code>. The reason for that is, that CommonNavigator gets its initial input (during initialization) from the Workbench by calling <code>getSite().getPage().getInput()</code>. In the IDE scenario, the default page input is <code>IWorkspaceRoot</code>, in the RCP scenario it is <code>null</code> and can be configured in the <code>WorkbenchAdvisor</code>. Instead, another implementation of <code>getInitialInput()</code> can be provided, passing the dummy Root object, which indicates the root of the tree. </p>
<pre class="brush: java;">
public class CNFNavigator extends CommonNavigator
{
    protected IAdaptable getInitialInput()
    {
        return new Root();
    }
}
</pre>
<h3>Defining viewer content</h3>
<p>In order to see something in the freshly-defined viewer, the information about the content has to be provided. The extension point <code>org.eclipse.ui.navigator.navigatorContent</code> is defined for this purpose. The main element responsible for the content is called <code>navigatorContent</code> and contains the following information:</p>
<ul>
<li><code>id</code> &#8211; the id of the content, to be referenced in the viewer</li>
<li><code>name</code> &#8211; the name of the content, which is seen in the <strong>Customize View</strong> dialog using the content tab, which can be activated or deactivated there by the user.</li>
<li><code>contentProvider</code> &#8211; the contentProvider class responsible for providing content elements</li>
<li><code>labelProvider</code> &#8211; the labelProvider class responsible for rendering a content element in the view</li>
</ul>
<pre class="brush: xml;">
   &lt;extension
         point=&quot;org.eclipse.ui.navigator.navigatorContent&quot;&gt;
      &lt;navigatorContent
            activeByDefault=&quot;true&quot;
            contentProvider=&quot;de.techjava.rcp.cnf.provider.CNFContentProvider&quot;
            id=&quot;de.techjava.rcp.cnf.content.VirtualContent&quot;
            labelProvider=&quot;de.techjava.rcp.cnf.provider.CNFLabelProvider&quot;
            name=&quot;Virtual content&quot;
            priority=&quot;normal&quot;&gt;
         &lt;triggerPoints&gt;...&lt;/triggerPoints&gt;
         &lt;possibleChildren&gt;...&lt;/possibleChildren&gt;
      ...
      &lt;/navigatorContent&gt;
   &lt;/extension&gt;
</pre>
<p>In addition, nested elements <code>triggerPoints</code> and <code>possibleChildren</code> describe when the current content is activated. This means that a CNF Viewer can compose the content coming from multiple providers and needs to know what content to display. These will be covered in the following sections. </p>
<h3>How the platform uses the viewer</h3>
<p>Before diving into the code section, it is worth spending a small section on the topic, how the platform uses the CNF viewer. In general, if an element is selected in the viewer, the CNF consults <code>triggerPoints</code> of all <b>Navigation Content Extensions (NCEs)</b> provided and tries to match the element to the trigger point expression. If the expression matches, the NCE is activated by the platform and the corresponding <code>contentProvider</code> is responsible for delivering content. If the element is activated by other means than in the viewer (e.G. in the Editor), the platform consults <code>possibleChildren</code> list and tries to match the corresponding expression. For resource-based approaches, the NCE with id <code>org.eclipse.ui.navigator.resourceContent</code> is usually provided. This NCE is enabled / triggered on any element that is instance of <code>IResource</code>. By this means e.G. the Project Explorer in the IDE passes the workspace root to the <code>ResourceExtensionContentProvider</code> which is responsible for delivering the children of the workspace root &#8211; the projects. In a non-resource based approach, the NCE must be triggered by the initial input of the viewer, in this example by the <code>Root</code> object. If the selected element is a <code>Parent</code> node, the NCE should also be triggered. The following definition of the trigger point accomplishes this task:</p>
<pre class="brush: xml;">
         &lt;triggerPoints&gt;
            &lt;or&gt;
               &lt;instanceof value=&quot;de.techjava.rcp.cnf.data.Root&quot; /&gt;
               &lt;instanceof value=&quot;de.techjava.rcp.cnf.data.Parent&quot; /&gt;
            &lt;/or&gt;
         &lt;/triggerPoints&gt;
</pre>
<p>Since the children delivered by the content provider on <code>Root</code> as parent element are instances of <code>Parent</code> and on <code>Parent</code> as parent element are instances of <code>Child</code>, the <code>possibleChildren</code> code looks as follows:</p>
<pre class="brush: xml;">
         &lt;possibleChildren&gt;
            &lt;or&gt;
               &lt;instanceof value=&quot;de.techjava.rcp.cnf.data.Parent&quot; /&gt;
               &lt;instanceof value=&quot;de.techjava.rcp.cnf.data.Child&quot; /&gt;
            &lt;/or&gt;
         &lt;/possibleChildren&gt;
</pre>
<h3>Label and Content providers</h3>
<p>After the way how the navigation content is being activated is discussed, the Content and Label providers can be addressed. The label provider implementation is straight-forward. Its task is to produce a textual and graphical representation of every element. In addition, it implements the <code>IDescriptionProvider</code> interface to provide description in the status bar when an element is selected. Please note, that this section is not CNF-specific but is related to JFace ContentProvider and JFace LabelProvider, as usual for any Viewer. It is provided here only for completion and if the user is not familiar with it in detail.</p>
<pre class="brush: java;">
public class CNFLabelProvider extends LabelProvider implements ILabelProvider, IDescriptionProvider
{
    public String getText(Object element)
    {
        if (element instanceof Parent)
        {
            return ((Child)element).getName() + &quot; [ &quot; +((Parent)element).getChildren().length + &quot; ]&quot;;
        } else if (element instanceof Child)
        {
            return ((Child)element).getName();
        }
        return null;
    }

    public String getDescription(Object element)
    {
        String text = getText(element);
        return &quot;This is a description of &quot; + text;
    }

    public Image getImage(Object element)
    {
        if (element instanceof Parent)
        {
            return PlatformUI.getWorkbench().getSharedImages()
              .getImage(ISharedImages.IMG_OBJ_FOLDER);
        } else if (element instanceof Child)
        {
            return PlatformUI.getWorkbench().getSharedImages()
              .getImage(ISharedImages.IMG_OBJ_FILE);
        }
        return null;
    }
}
</pre>
<p>The methods above are self-describing. For any element the text and image is selected based on element type. For children, the name is shown, for parents the number of children is displayed, additionally. The platform built-in icons of folder and file are used for convenience. The methods for the Label/Content provider usually follow this pattern of a <code>instanceof</code> cascade. </p>
<p>The content provider is responsible for the following tasks:</p>
<ul>
<li>At requested of <code>Root</code> it should deliver the list of <code>Parent</code> elements</li>
<li>At requested of <code>Parent</code> it should deliver the list of its children (<code>Child</code> elements)</li>
<li>At requested of <code>Child</code> it should deliver an empty list</li>
</ul>
<p>Since no real data model is available, its creation is hooked to the first access (that is, of course, for demonstration purposes only)</p>
<pre class="brush: java;">
public class CNFContentProvider implements ITreeContentProvider
{

    private static final Object[] EMPTY_ARRAY = new Object[0];
    private Parent[] parents;

    public Object[] getChildren(Object parentElement)
    {
        if (parentElement instanceof Root)
        {
            if (parents == null)
            {
                initializeParents(parentElement);
            }
            return parents;
        } else if (parentElement instanceof Parent)
        {
            return ((Parent) parentElement).getChildren();
        } else if (parentElement instanceof Child)
        {
            return EMPTY_ARRAY;
        } else
        {
            return EMPTY_ARRAY;
        }
    }

    public Object getParent(Object element)
    {
        if (element instanceof Child)
        {
            return ((Child) element).getParent();
        } else if (element instanceof Parent)
        {
            return ((Parent) element).getRoot();
        }
        return null;
    }

    public boolean hasChildren(Object element)
    {
        return (element instanceof Root || element instanceof Parent);
    }

    public Object[] getElements(Object inputElement)
    {
        return getChildren(inputElement);
    }

    public void dispose()
    {
        this.parents = null;
    }

    public void inputChanged(Viewer viewer, Object oldInput, Object newInput)
    { /* ... */
    }
    ...
}
</pre>
<p>The class has three important methods: <code>getChildren(Object)</code>, <code>getParent(Object)</code> and <code>hasChildren(Object)</code>. The <code>getChildren(Object)</code> is responsible for delivering children elements to a given parent element. The <code>getParent()</code> delivers a parent for a given child element (e.G. when the child is selected using the editor and the viewer is requested to show the element in it). The <code>hasChildren(Object)</code> is a way of providing a more efficient implementation than <code>(getChildren(element).length == 0)</code>. The <code>getElements(Object)</code> method is usually delegated to <code>getChildren(Object)</code>. The difference between these methods is that <code>getElements(Object)</code> is called to obtain the tree viewer&#8217;s root elements, whereas <code>getChildren(Object)</code> is used to obtain the children of a given parent element in the tree (including a root). Since there is only one root (the not shown <code>IWorkspaceRoot</code>), it is OK to delegate. Finally, the <code>parents</code> member variable needs to be initialized on the first access, which can be done using the following code:</p>
<pre class="brush: java;">
    /**
     * Init code for empty model
     */
    private void initializeParents(Object parentElement)
    {
        this.parents = new Parent[3];
        for (int i = 0; i &lt; this.parents.length; i++)
        {
            this.parents[i] = new Parent(&quot;Parent &quot; + i);
            this.parents[i].setRoot(parentElement);
            Child[] children = new Child[3];
            for (int j = 0; j &lt; children.length; j++)
            {
                children[j] = new Child(&quot;Child &quot; + i + j);
            }
            this.parents[i].setChildren(children);
        }
    }
</pre>
<h3>Binding the content to the viewer</h3>
<p>The last remaining piece in the puzzle is to bind the content defined in the navigation content extension to the view defined in the view extension. The extension point <code>org.eclipse.ui.navigator.viewer</code> is responsible for that. It consists of several parts: the <code>viewer</code> element, that references the <code>id</code> of the view and the <code>viewerContentBinding</code> element that one one hand specifies the view to bind the content to and on the other hand provides a reference to the content definition id.</p>
<pre class="brush: xml;">
   &lt;extension
         point=&quot;org.eclipse.ui.navigator.viewer&quot;&gt;
      &lt;viewer
            viewerId=&quot;de.techjava.rcp.cnf.view&quot;&gt;
      &lt;/viewer&gt;
      &lt;viewerContentBinding
            viewerId=&quot;de.techjava.rcp.cnf.view&quot;&gt;
         &lt;includes&gt;
            &lt;contentExtension
                  isRoot=&quot;false&quot;
                  pattern=&quot;de.techjava.rcp.cnf.content.VirtualContent&quot;&gt;
            &lt;/contentExtension&gt;
         &lt;/includes&gt;
      &lt;/viewerContentBinding&gt;
   &lt;/extension&gt;
</pre>
<p>Please note, that the content id is provided in the <code>pattern</code> attribute. Instead of pointing to particular content id, the regex can be used (e.G. <code>de.techjava.rcp.cnf.content.*</code>). That&#8217;s it, look at the result.<br />
<img style="margin: 10px;" title="RCP virtual CNF" src="http://www.techjava.de/wp-content/uploads/rcp_cnf.png" alt="RCP virtual CNF" width="402" height="302" /><br />
Under <strong>&#8220;Custimize View&#8221;</strong> the content tab allows to show the defined &#8220;virtual content&#8221;. Since no filters are defined, the filter section is empty.<br />
<img style="margin: 10px;" title="RCP virtual CNF content selection" src="http://www.techjava.de/wp-content/uploads/rcp_cnf_content.png" alt="RCP virtual CNF content selection" width="406" height="416" /> </p>
<h2>Conclusion</h2>
<p>To my opinion, for almost every application using a tree/list view to represent entities the CNF should serve as a basis for the implementation. Thus, CNF documentation should be improved and get to the level &#8220;for beginners&#8221; rather than &#8220;for experts&#8221;. In this post, I have tried to provide an introduction for non-expert RCP/PDE developers. I&#8217;m interested in your comments.</p>
<h2>Further directions</h2>
<p>Currently, neither filters, sorters nor actions or pop-up menu are defined for the viewer. This can be a subject of the follow-up post, if requested, but is partly covered in the 
<a  href="http://scribbledideas.blogspot.com/2006/07/pdf-versions-now-available.html" onclick="javascript:pageTracker._trackPageview('/external/scribbledideas.blogspot.com/2006/07/pdf-versions-now-available.html');" >articles of Michael Edler.</a> Especially, the application of the new command framework has to be described.</p>
<h2>Resources</h2>
<h3>Eclipse</h3>
<ul>
<li>
<a  href="http://wiki.eclipse.org/index.php/Common_Navigator_Framework" onclick="javascript:pageTracker._trackPageview('/external/wiki.eclipse.org/index.php/Common_Navigator_Framework');" >CNF EclipseWiki page</a></li>
<li>
<a  href="http://dev.eclipse.org/blogs/francis/" onclick="javascript:pageTracker._trackPageview('/external/dev.eclipse.org/blogs/francis/');" >Common Navigator and Other Things by Francis Upton</a></li>
</ul>
<h3>Digital Paper Napkin by Michael D. Elder</h3>
<p>A basic set of introduction articles written in 2006. The articles introduce contribution to the resource-based CNF viewer displaying the content of the property files. A good overview to get into the subject. The blog seems to be dead, according to many spam comments.</p>
<ul>
<li>
<a  href="http://scribbledideas.blogspot.com/2006/05/building-common-navigator-based-viewer.html" onclick="javascript:pageTracker._trackPageview('/external/scribbledideas.blogspot.com/2006/05/building-common-navigator-based-viewer.html');" >Part 1 &#8211; Defining the Viewer</a></li>
<li>
<a  href="http://scribbledideas.blogspot.com/2006/05/building-common-navigator-based-viewer_22.html" onclick="javascript:pageTracker._trackPageview('/external/scribbledideas.blogspot.com/2006/05/building-common-navigator-based-viewer_22.html');" >Part 2 &#8211; Adding Content</a></li>
<li>
<a  href="http://scribbledideas.blogspot.com/2006/06/building-common-navigator-based-viewer.html" onclick="javascript:pageTracker._trackPageview('/external/scribbledideas.blogspot.com/2006/06/building-common-navigator-based-viewer.html');" >Part 3 &#8211; Configuring Menus</a></li>
<li>
<a  href="http://scribbledideas.blogspot.com/2006/06/building-common-navigator-based-viewer_18.html" onclick="javascript:pageTracker._trackPageview('/external/scribbledideas.blogspot.com/2006/06/building-common-navigator-based-viewer_18.html');" >Part 4 &#8211; Object Contribution</a></li>
<li>
<a  href="http://scribbledideas.blogspot.com/2006/06/building-common-navigator-_115067357450703178.html" onclick="javascript:pageTracker._trackPageview('/external/scribbledideas.blogspot.com/2006/06/building-common-navigator-_115067357450703178.html');" >Part 5 &#8211; Action Providers</a></li>
<li>
<a  href="http://scribbledideas.blogspot.com/2006/06/what-does-common-navigator-framework.html" onclick="javascript:pageTracker._trackPageview('/external/scribbledideas.blogspot.com/2006/06/what-does-common-navigator-framework.html');" >High Level Requirement on CNF</a></li>
<li>
<a  href="http://scribbledideas.blogspot.com/2006/05/where-do-we-go-from-here.html" onclick="javascript:pageTracker._trackPageview('/external/scribbledideas.blogspot.com/2006/05/where-do-we-go-from-here.html');" >Further directions</a></li>
<li>
<a  href="http://scribbledideas.blogspot.com/2006/07/pdf-versions-now-available.html" onclick="javascript:pageTracker._trackPageview('/external/scribbledideas.blogspot.com/2006/07/pdf-versions-now-available.html');" >PDF Versions</a></li>
<li>
<a  href="http://scribbledideas.blogspot.com/2006/07/label-decorators-in-common-navigator.html" onclick="javascript:pageTracker._trackPageview('/external/scribbledideas.blogspot.com/2006/07/label-decorators-in-common-navigator.html');" >Label decorators</a></li>
</ul>
<h3>Eclipse from the bottom up by Michael Valenta</h3>
<p>A good hint is to look on the implementation of the 
<a  href="http://eclipselowdown.blogspot.com/2006/05/common-navigator-and-synchronize-view.html" onclick="javascript:pageTracker._trackPageview('/external/eclipselowdown.blogspot.com/2006/05/common-navigator-and-synchronize-view.html');" >CVS Synchronize View</a>. Pretty old content, but still valid.</p>
<h3>vAAni by Aashish Patil</h3>
<p>Weakly formatted article, providing some hints on how to implement a not &#8220;resource only&#8221;-based CNF viewer. Still, the information from here helped me to create a complete 
<a  href="http://aashishpatil.blogspot.com/2006/07/displaying-non-resource-content-using.html" onclick="javascript:pageTracker._trackPageview('/external/aashishpatil.blogspot.com/2006/07/displaying-non-resource-content-using.html');" >non-resource based CNF viewer described here.</a></p>
<h3>Other</h3>
<p>Thanks to 
<a  href="http://dev.eclipse.org/blogs/francis/" onclick="javascript:pageTracker._trackPageview('/external/dev.eclipse.org/blogs/francis/');" >Francis Upton</a>, who reviewed the post and corrected some mistakes and misconceptions.</p>
<p>Special thanks to 
<a  href="http://bairdphotos.com/" onclick="javascript:pageTracker._trackPageview('/external/bairdphotos.com/');" >Michael &#8220;Mike&#8221; L. Baird</a> for the beautiful 
<a  href="http://www.flickr.com/photos/mikebaird/3009401040/" onclick="javascript:pageTracker._trackPageview('/external/www.flickr.com/photos/mikebaird/3009401040/');" >picture of the compass</a>. I found the picture on Google Image Search and became a big fan of his pictures (some of you know about 
<a  href="http://www.flickr.com/photos/sza/" onclick="javascript:pageTracker._trackPageview('/external/www.flickr.com/photos/sza/');" >my photo passion</a>). It is funny that from all places in the world, the picture is shot in Morro Bay, about 200 Miles away from where I&#8217;m located now. It is also funny that Mike is a computer science guy, even if retired&#8230;<br />
</code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.techjava.de/topics/2009/04/eclipse-common-navigator-framework/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
	</channel>
</rss>
