Using Perspectives in the Workbench

From mitk.org
Revision as of 15:48, 1 June 2016 by JasminMetzger (talk | contribs) (Refactor nightly docu link)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

This article is inspired by this Eclipse Corner Article written by Dave Springgay.


Summary

In the BlueBerry Platform a Perspective determines the visible actions and views within a window. Perspectives also go well beyond this by providing mechanisms for task oriented interaction with resources, multi-tasking and information filtering. In this article the concepts behind perspectives are examined. The process for perspective definition, extension and instantiation will also be covered in detail with coding examples and sample scenarios.


Introduction

In this article the perspective concept will be explored in detail. In particular, we'll look at how it relates to task oriented interaction, multi-tasking and information filtering. We'll also look at the techniques to define a new perspective, extend an existing perspective, or instantiate a new perspective at runtime within the workbench. Coding samples are provided for each technique.


What is a Perspective?

A perspective is a visual container for a set of views and editors (parts). It exists within a window along with any number of other perspectives and, like a page within a book, only one perspective is visible at any time.


Adding a New Perspective

Within the workbench a new perspective can be defined in two ways. A programmer can add a new perspective using the perspective extension point in the plug-in registry. A user can add a new perspective or override an existing perspective by using the customization and persistence features built in to the workbench user interface. This section will focus on the programmer scenario.

The definition of a new perspective is a three step process.

  1. Create a plug-in (or use your existing one)
  2. Add a perspective extension to the plugin.xml file.
  3. Define a perspective class for the extension within the plug-in.
  4. Export your perspective class in your manifest.cpp file.

This process will be illustrated by defining a plugin with a perspective called "Test". The Test Perspective will contain a fictive Navigator View, Outline View, and an editor area. The layout for the perspective is illustrated in the quick sketch below.


For the fist step, we suppose that we already have a plug-in called org.blueberry.ui.articles.perspective.

The org.blueberry.ui plug-in defines a single extension point for perspective contribution: org.blueberry.ui.perspectives. A new perspective is added to the workbench by defining an extension for this point. In the example below a perspective extension is defined for the Test Perspective, inside the plugin.xml of our org.blueberry.ui.articels.perspective plug-in. This declaration contains the basic elements: id, name and class.

<syntaxhighlight lang="cpp"> <extension point="org.blueberry.ui.perspectives">

 <perspective name="Test"
              class="TestPerspective"
              id="org.blueberry.ui.articles.perspective.Test">
 </perspective>

</extension> </syntaxhighlight>

A complete description of the extension point and the syntax can be found here. The attributes are described as follows.

  • id - a unique name that will be used to identify this perspective.
  • name - a translatable name that will be used in the workbench window menu bar to represent this perspective.
  • class – a fully qualified name of the class that implements berry::IPerspectiveFactory interface.
  • icon - a relative name of the icon that will be associated with this perspective.

Perhaps the most important attribute in the perspective declaration is class. This attribute names a class that will define the initial layout for the perspective. In this example the layout for the Test perspective is defined by TestPerspective. The implementation of TestPerspective will be examined in a few paragraphs.

When CreateInitialLayout is called on an berry::IPerspectiveFactory the page layout consists of an editor area with no additional views. Within CreateInitialLayout you can add views, folders, and view place holders to the page layout. A folder is a stack of views. A place holder marks the position of a view within the page. The view itself is not initially open, but when opened will occupy the position marked by the place holder.

In the example below you can see how CreateInitialLayout is implemented in the TestPerspective class. When CreateInitialLayout is called the page layout consists of an editor area with no additional views. Additional views are added using the editor area as the initial point of reference. The factory gets the id of the editor area and creates a folder to the left of this area. It then adds the Navigator view and Outline view to this folder.

<syntaxhighlight lang="cpp"> void TestPerspective::CreateInitialLayout(IPageLayout::Pointer layout) {

 // Editors are placed for free.
 std::string editorArea = layout->GetEditorArea();
 // Place navigator and outline to left of
 // editor area.
 IFolderLayout::Pointer left =
     layout->CreateFolder("left", IPageLayout::LEFT, 0.26f, editorArea);
 left->AddView(IPageLayout::ID_RES_NAV);
 left->AddView(IPageLayout::ID_OUTLINE);

} </syntaxhighlight>

The CreateFolder method adds a new folder to the page layout. The position and relative size of the folder are expressed as a fraction of an existing part. In the example above a folder is created with the name "left". It is positioned to the left of the editor area and occupies 26% of the original space of the editor area. The positioning constants are defined on berry::IPageLayout, and include TOP, BOTTOM, LEFT and RIGHT.

Finally, you have to export your TestPerspective class, by adding the proper code to your manifest.cpp file.

<syntaxhighlight lang="cpp">

  1. include "TestPerspective.h"

POCO_BEGIN_NAMED_MANIFEST(berryIPerspectiveFactory, berry::IPerspectiveFactory)

 POCO_EXPORT_CLASS(TestPerspective)

POCO_END_MANIFEST </syntaxhighlight>


The Test perspective is now ready to use.


Why is Layout Declaration done in Code Rather than XML?

During the design of perspectives both options were considered. Within BlueBerry XML is typically used to declare the presence of an extension and the circumstances under which it should be loaded. The information is used to load the extension and its plug-in lazily for better startup performance. Now let's apply this logic to perspectives. When a perspective is selected from the user interface the load conditions are met, so we can load the extension and move forward using C++. C++ code provides the benefits of code completion and error detection at development time.


Can I Remove the Editor Area Completely?

In some scenarios the ideal layout for a perspective may be made up of one or more views with no editor area. To achieve this you can invoke IPageLayout::SetEditorAreaVisible(bool) to hide or show the editor area. This state will be honored unless the user decides to override it.

As a philosophical point, wouldn't it be great if you could punt the editor area completely? In fact, the workbench user interface favours the user more than the programmer. While the programmer may wish to define a closed environment with a fixed set of views, the user may always have the possibility to show any view from a "Show View" menu. If the user can show any view they can also open any resource in an editor, and this necessitates an editor area. This underscores a very important point. A perspective definition is just a suggestion. The user can override it at any time and probably will. For more information on this idea see User Customization and Persistence.


Do I Need a Perspective?

The temptation to create a new perspective is strong. The dark side beckons. As a plug-in provider, if you add a view extension to the platform you'd like some way to make it visible. One way to do that is to copy an existing perspective and add your view to the factory class. If every plug-in took this approach the user would soon be overwhelmed by perspective choices. In all likelihood the user would ignore them all and create their own.

In general, a perspective should only be created when there is a certain group of related tasks which would benefit from a predefined configuration of actions and views.

In some situations it may be better to augment an existing perspective. For instance, if you want to extend a collaboration software with an "Address Book" view, which already has a "Mail" perspective defined, it is probably better to add that view to the Mail perspective rather than defining a new perspective. This strategy provides better integration with the existing platform. For more information on this process check out Extending an Existing Perspective.