Friday, May 8, 2009

Context Sensitive Help in Eclipse (Version 3.4 - Ganymede)

Introduction:

This article will explain and walk you through on how to add context sensitive help to your Eclipse application. Also, it touches upon how to implement programmatic help in Eclipse.

Adding context extension:

Open plugin.xml of your help plugin (or your source plugin, if you have help files in your source plugin itself) . Go to extensions and add org.eclipse.help.contexts extension point. Create contexts element inside it which has two attributes - file and plugin. The file attribute points to your contexts.xml (we will discuss the details of contexts.xml below) and the plugin attribute points to the plugin for which context sensitive help is needed. The plugin attribute is very useful, and allows any plugin to contribute to the context help of other plugins. This provides extensibility. Below is an example of this extension point:

<extension
point="org.eclipse.help.contexts">
<contexts
file="contexts.xml"
plugin="com.mycompany.xyz">
</contexts>
</extension>

Contexts.xml:

This file lists the various context ids. The root element is contexts and it can have many context elements. Each context has id and title attributes and it has description and topic elements. A context can have multiple topics each pointing to a html location. PDE has support for editing contexts xml file. You should be able to right click on contexts and add context, edit attributes of context etc., using the PDE editor. Below is an example of a sample contexts xml file:

<contexts>
<context id="package_explorer_view" title="Package Explorer View">
<description>Short description of package explorer view
<topic href="html/views/packageExplorer.html" label="Package Explorer View"/>
</context>
<context id="java_editor" title="Java Editor">
<description>Short description of java editor
<topic href="html/editors/javaEditor.htmll" label="Java Editor"/>
</context>
</contexts>

Setting context ids in the code:

Now that we have defined the contexts file and the context ids, it is time to associate the views and editors in the application to those context ids. You can set the context ids for your control using this:

IWorkbenchHelpSystem helpSystem = PlatformUI.getWorkbench().getHelpSystem();
helpSystem.setHelp(control, "com.mycompany.xyz.package_explorer_view");

Note that context id has the plugin name prefixed to it. The contex id in itself (i.e without the prefix) should not have whitespaces or periods.

Also, context id's are inherited by the child controls. You can override by setting the context id for each of your child control. If not, they would use the parent context id.

Invoking Help:

Now, whenever you press F1, it will display context sensitive help. It can either appear in infopopup or the Help view. You can control that using the preference in
Window->Preferences->Help. It has option to show context sensitive help in either the help view or in the infopopup. The bottom of the infopopup also has option to show the context in help view.

Adding Dynamic Help menu item:

Dynamic Help view is the same help view which appears when F1 is pressed. If you wish, you can add it to your Help menu (like in Eclipse IDE) by adding org.eclipse.ui.help.dynamicHelp command under your menu. Also, don't forget to register this action in your ApplicationActionBarAdvisor class.

action = ActionFactory.DYNAMIC_HELP.create(window);
this.register(action);

The dynamic help view changes content based on the active selection. For example, if you are in package explorer, it will show help for that view and then when you move selection from there to java editor, it will display the contents related to the java editor.

Programmatic Help:

Eclipse also provides API to access the help system programmatically. For example, if you want to open the global help or the context help for a particular editor upon pressing a button, you can do so by using the API. IWorkbenchHelpSystem has various methods to access help. Some of the common useful ones are:

displayHelp();

displayHelp(String contextId);

displayHelpResource(String htmlUrl);

setHelp(Control control, String contextId);

Below is a code snippet for displaying the context help when help button is pressed:

Button help = new Button(buttonsComposite, SWT.PUSH);
help.setText("Help");
GridData gridData = new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false);
help.setLayoutData(gridData);
help.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent evt) {
IWorkbenchHelpSystem helpSystem = PlatformUI.getWorkbench().getHelpSystem();
helpSystem.displayHelp("com.mycompany.xyz.java_editor");
}
});

Conclusion:

We saw how to add the required contexts extension, details of contexts xml file and how to associate context ids in the code. We also discussed about adding dynamic help, how to add it to the menu and how to access the help system programmatically. Hope this article helps you in implementing context sensitive help in your eclipse application.

Tuesday, May 5, 2009

Working with Eclipse Help System (Version 3.4 - Ganymede)

Introduction:

Almost any application we work with needs a help system. The help system can be set up for normal workbench mode, remote infocenter mode (help via web) and standalone mode (for users who do not use eclipse). This article will guide you through how to add help menu, how to set up the help system using the workbench mode.

Adding help menu items:

Under your help menu, create a new command with commandId org.eclipse.ui.help.helpContents to add Help->HelpContents menu item. To add Search menu item, create a new command with commandId org.eclipse.ui.help.helpSearch. To add index menu item, create a new command with commandId org.eclipse.help.ui.indexcommand. You also need to make sure that the actions are registered. Add this block of code to makeActions(window) method in your ApplicationActionBarAdvisor to register them:

IWorkbenchAction action = ActionFactory.HELP_CONTENTS.create(window);
this.register(action);

action = ActionFactory.HELP_SEARCH.create(window);
this.register(action);

Generating sample help content:

The help content can either go with your source plugin or in a separate documentation plugin. I personally prefer to have it in a separate documentation plugin. Help is contributed by documentation plugins by using org.eclipse.help.toc extension point. The easiest way to add some help content is using the help content template which comes with Eclipse. Open plugin.xml and go to Extensions tab. Click on "Add" and type in org.eclipse.help.toc in extension point filter and in the available templates select Help Content and click Next. Make sure to select Primary checkbox, if you wish to contribute a main book to the help content. This will generate a bunch of toc xml files and sample html pages under html directory. Now, if you do Help->Help Contents you should be able to see the sample content.

Understanding help content:

If you look at plugin.xml, you will see that all of the toc* points to xml file. The primary toc.xml has several topics inside it and each topic can either specify link or anchor. In this case, you can see that all of the them are specifying anchors and not an actual link. These anchors can actually be used by any plugin to contribute help under that section. The primary toc would look like this:

<toc label="Sample Table of Contents" topic="html/toc.html">
<topic label="Getting Started">
<anchor id="gettingstarted"/>
</topic>
<topic label="Concepts">
<anchor id="concepts"/>
</topic>
<topic label="Tasks">
<anchor id="tasks"/>
</topic>
<topic label="Reference">
<anchor id="reference"/>
</topic>
<topic label="Samples">
<anchor id="samples"/>
</topic>
</toc>

If you see tocconcepts.xml, it uses anchor to contribute help i.e all topics inside this toc would go under the main topic which has this anchor. The link_to attribute takes care of this.

<toc label="Concepts" link_to="toc.xml#concepts">
<topic label="Main Topic" href="html/concepts/maintopic.html">
<topic label="Sub Topic" href="html/concepts/subtopic.html" />
</topic>
<topic label="Main Topic 2">
<topic label="Sub Topic 2" href="html/concepts/subtopic2.html" />
</topic>
</toc>

This is bottom-up composition. For top-down nesting, instead of defining anchors, the primary toc can instead create the links directly. Below is an example of top-down nesting, where links are directly used:

<toc label="Sample Table of Contents" topic="html/toc.html">
<topic label="Getting Started">
<link toc="toc_gettingStarted.xml"/>
</topic>
<topic label="Concepts">
<link toc="toc_concepts.xml"/>
</topic>
<topic label="Tasks">
<link toc="toc_tasks.xml"/>
</topic>
<topic label="Reference">
<link toc="toc_reference.xml"/>
</topic>
<topic label="Samples">
<link toc="toc_samples.xml"/>
</topic>
</toc>

Now, the secondary toc files (i.e tocconcepts.xml or toctasks.xml) do not need link_to attribute anymore.

Top down nesting is easier to understand but bottom up composition is preferred since it is very flexible and other plugins can contribute content to that section dynamically.

The actual help content is actually html pages. So, it does not matter how they are generated i.e using docbook or DITA or FrameMaker. As long as the html files are valid and they are structured properly, help will show up fine. You can also use XHTML to generate dynamic content.

Localization of help content:

By default, the toc files are in the base directory and the html pages reside under the html directory. For localizing the content, the content needs to be under nl/<languageCode> or nl/<languageCode>/<countryCode>. For example, for help content in german, the contents need to be in nl/de/DE directory. The content is first searched in nl/<languageCode>/<countryCode>. If it is not found, then it is searched in nl/<languageCode>. If it is not found there also, then it looks in the default base directory of the plugin.

The amount of documentation can quickly grow as your application gets bigger. Eclipse allows the documentation to be bundled in doc.zip file so that you can compress your documentation files. But, this works only when the plugin is deployed in unpacked form. Also, if you have localized help content, you cannot have one big doc.zip which has content for all languages. Instead, you need to have doc.zip for each of the languages under it's own nl directory.

Help Index:

To set up the help index, you need to use org.eclipse.help.index extension point. This extension point takes a index xml file and it looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<index version="1.0">
<entry keyword="Eclipse Concepts">
<entry keyword="Views">
<topic href="html/concepts/views.html" />
</entry>
<entry keyword="Editors">
<topic href="html/concepts/editors.html" />
</entry>
</entry>
</index>

This shows up in the help index page. Basically, this is similar to book keyword index. Here Eclipse concepts is shown as a folder under which you have two keywords - Views and Editors.

Don't confuse this with search index. Talking about search index, the index is built by eclipse, whenever user first does search on the help. If you have large number of help files and do not want your user to wait for a long time, then you also have the option of pre building index files and ship it along with your plugin. Basically, this is a tradeoff between time and space.

Customization:

The help contents window is very rich and offers lot of functionalities including searching, printing, bookmarking, moving between search results to table of contents etc., We can also customize some of the help contents window UI using the preferences defined in org.eclipse.help plugin. Some of the preferences are:

banner - To specify new banner at the top of the help
banner_height - To specify the height of the banner
help_home - To specify the custom html help home page, when help opens up
page_not_found - The page to show when the help topic html page is not found
windowTitlePrefix - To specify whether the help window show have "Help - " string prefixed
always_external_browser - Set this to true, if you want help to always open in external browser
bookmarksView - Set this to true or false to control the visibility of bookmarks view

Conclusion:

We saw how to add help to your menu, how to generate and understand help content, how to create index pages, how to localize and customize help functionality. Eclipse also supports context sensitive help, programmatic help and active help. I purposefully left them out for simplicity purpose. I will cover them in a separate article. Hope this article helps you in understanding and getting started with the Eclipse help system.