|  | <!doctype html public "-//w3c//dtd html 4.0 transitional//en"> | 
|  | <html> | 
|  | <head> | 
|  | <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> | 
|  | <meta name="Author" content="Build"> | 
|  | <meta name="GENERATOR" content="Mozilla/4.5 [en] (WinNT; I) [Netscape]"> | 
|  | <title>Using Perspectives in the Eclipse UI</title> | 
|  | <link rel="stylesheet" href="../default_style.css"> | 
|  | </head> | 
|  | <body> | 
|  |  | 
|  | <div align=right>  <font face="Times New Roman, Times, serif"><font size=-1>Copyright | 
|  | © 2001 Object Technology International, Inc.</font></font></div> | 
|  |  | 
|  | <table BORDER=0 CELLSPACING=0 CELLPADDING=2 WIDTH="100%" > | 
|  | <caption><TBODY> | 
|  | <br></TBODY></caption> | 
|  |  | 
|  | <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> | 
|  |  | 
|  | <h1> | 
|  | <img SRC="Idea.jpg" height=86 width=120 align=CENTER></h1> | 
|  |  | 
|  | <center> | 
|  | <h1> | 
|  | Using Perspectives in the Eclipse UI</h1></center> | 
|  |  | 
|  | <h3> | 
|  | Summary</h3> | 
|  | In the Eclipse 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 in the Eclipse | 
|  | Platform, 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. | 
|  | <p><b>By Dave Springgay, OTI</b> | 
|  | <br>August 27, 2001 | 
|  | <h3> | 
|  |  | 
|  | <hr WIDTH="100%"></h3> | 
|  |  | 
|  | <h3> | 
|  | Introduction</h3> | 
|  | In the Eclipse Platform there are two main layers: the model layer and | 
|  | the user interface layer.  The underlying model, known as the Workspace, | 
|  | is a collection of resources (projects, folders and files).  The user | 
|  | interface, or Workbench, defines the presentation for those resources.  | 
|  | Within the workbench the Perspective feature is used to control the visibility | 
|  | of items in the model and the user interface.  It controls what you | 
|  | see in the model (which project, folder or files) and what you see in the | 
|  | user interface (which actions or views).  These controls make it possible | 
|  | to navigate through and modify the workspace in a way which suits the user | 
|  | task. | 
|  | <p>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. | 
|  | <h3> | 
|  | What is a Perspective?</h3> | 
|  | A perspective is a visual container for a set of views and editors (parts).  | 
|  | These parts exist wholly within the perspective and are not shared.  | 
|  | A perspective is also like a page within a book.  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. | 
|  | <p>Each perspective has an <i>input</i> and a <i>type</i>.  The <i>input</i> | 
|  | attribute is used to define which resources are visible in the workspace | 
|  | and the | 
|  | <i>type</i> attribute is used to define which actions and views | 
|  | are visible in the user interface.  This design is a reflection of | 
|  | 3 key concepts. | 
|  | <br>  | 
|  | <ol> | 
|  | <li> | 
|  | Information Filtering</li> | 
|  |  | 
|  | <li> | 
|  | Task Oriented Interaction with Your Information</li> | 
|  |  | 
|  | <li> | 
|  | Two is Always Better than One</li> | 
|  | </ol> | 
|  |  | 
|  | <p><br>Each of these will be covered in detail below.  But before | 
|  | getting into the details, let's explore the idea of input and type. | 
|  | <p>On startup the workbench will most likely consist of one window with | 
|  | one perspective.  For instance, the window may contain a Resource | 
|  | perspective on the entire workspace.  This perspective has<i> input | 
|  | = the Workspace</i> and <i>type = Resource</i>.  If you select a project | 
|  | or folder in the Navigator you can open a new perspective by invoking Open | 
|  | Perspective > Java™ from the object context menu.  This new perspective | 
|  | has a different input and type: <i>input = the Project</i> and <i>type | 
|  | = Java</i>.  Now there are two perspectives.  The visible resources | 
|  | in the second perspective are a subset of those in the first.  Each | 
|  | perspective contains a set of views and editors which exist wholly within | 
|  | the perspective and are not shared with the other.  These parts define | 
|  | the presentation for a shared, underlying model. | 
|  | <h4> | 
|  | Information Filtering</h4> | 
|  | In a large, real world project the Eclipse Workspace may contain hundreds | 
|  | or thousands of resources.  For instance, consider the following project | 
|  | in Eclipse.  It may be small, but this project represents a typical | 
|  | three tier B2C web application.  There are three folders: ClientSide, | 
|  | MiddleTier and DatabaseServer.  Each folder represents a different | 
|  | tier in the application.  The files types in each folder are also | 
|  | different. | 
|  | <pre>WebApplicationProject | 
|  |         ClientSide | 
|  |                 index.html | 
|  |                 link1.html | 
|  |                 image1.html | 
|  |                 ... | 
|  |         MiddleTier | 
|  |                 script1.jsp | 
|  |                 script2.cgi | 
|  |                 script3.perl | 
|  |                 Main.java | 
|  |                 DataBase.java | 
|  |                 ... | 
|  |         DatabaseServer | 
|  |                 sqlScripts.script | 
|  |                 serverConguration.config | 
|  |                 ...</pre> | 
|  | The contents of this project are very typical of application development | 
|  | in the Internet age.  No single language or technology can do it all, | 
|  | and software development involves the application of many technologies | 
|  | rather than just one. | 
|  | <p>An important tool for comprehension is information filtering.  | 
|  | In other words, remove the irrelevant so you can see the relevant.  | 
|  | In Eclipse this is performed in two ways, by using the inherent structure | 
|  | of the information (the resource tree) and the unstructured attributes | 
|  | of the information (file name, nature, resource type, etc.).  For | 
|  | this discussion only the first style of information filtering is relevant. | 
|  | <p>In a large project the resources are usually structured within a hierarchy.  | 
|  | The workspace contains many projects containing many folders containing | 
|  | many files.  It's a tree, and each subtree within the whole defines | 
|  | a physical subset of information. This idea is the basis for information | 
|  | filtering within the workbench.  The user can open a perspective on | 
|  | any resource subtree within the workspace.  In the resulting perspective | 
|  | only the children of the subtree root are visible.  The subtree root | 
|  | is known as the <i>input</i>.  For example, if you open a perspective | 
|  | on MiddleTier within the WebApplicationProject only the children of MiddleTier | 
|  | are visible within the resulting perspective.  The <i>input = MiddleTier</i>. | 
|  | <h4> | 
|  | Task Oriented Interaction with Your Information</h4> | 
|  | As a development platform Eclipse was designed to fulfill the needs of | 
|  | a large product development team, from product manager to content developer | 
|  | to product tester.  It is fully extensible and may be configured with | 
|  | hundreds of action, wizard, view and editor extensions for any number of | 
|  | languages, tasks, roles, and phases within the development life cycle.  | 
|  | In other words, it may contain a lot of junk you'll never use.  To | 
|  | avoid the visual overload and confusion which would occur if everything | 
|  | was visible in the UI some mechanism is required to filter the user interface. | 
|  | <p>In Eclipse a task oriented approach was taken to filtering. Consider | 
|  | a Java developer.  Within a single development cycle a Java developer | 
|  | may iterate through the following phases: Analysis and Design, Implementation, | 
|  | Debug, Testing and Documentation.  In one phase the developer may | 
|  | use a UML modeling tool.  In another you use a Problem Reporting tool.  | 
|  | The time spent in each phase will vary but rapid transition between phases | 
|  | may occur several times a day.  If we say that each phase is a "task" | 
|  | then it is possible to say there is rapid transition between tasks.  | 
|  | In addition, the preferred way to look at resources in the workspace will | 
|  | change with the active task. | 
|  | <p>In Eclipse task orientation is embodied by perspective type.  A | 
|  | perspective determines the visible actions, views, and view layout within | 
|  | the window.  There are many types of perspective, and each one defines | 
|  | the layout in a different way.  Ideally, the layout should be tailored | 
|  | to suit a particular set of related tasks.  For instance, the standard | 
|  | Eclipse platform includes a Java perspective and a Team perspective.  | 
|  | The Java perspective defines a layout containing the Package, Hierarchy, | 
|  | Outline and Tasks view.  This is useful for java development.  | 
|  | The Team perspective defines a layout containing the Repositories and Synchronize | 
|  | view.  This is useful for code sharing and versioning.  In Eclipse | 
|  | the user can open a new perspective with a particular type, switch from | 
|  | one perspective to another with different type, or change the type (layout) | 
|  | of an existing perspective as they move from one task to another. | 
|  | <h4> | 
|  | Two is Always Better than One</h4> | 
|  | In an earlier section we saw how information filtering can be used to limit | 
|  | information overload.  When information filtering is implemented a | 
|  | new need develops: the need to see information which is not visible.  | 
|  | For instance, a Java developer may explore one class hierarchy while they | 
|  | modify code in another.  In Eclipse this functionality is provided | 
|  | by opening a second perspective on the information required.  The | 
|  | ability to create two separate perspectives (or more) makes it possible | 
|  | to switch between information without loss of context. | 
|  | <p>The ability to open more than one perspective is also crucial for multi-tasking | 
|  | support.  Developers often multi-task without even knowing it.  | 
|  | For instance, in a team environment a coworker may walk into your office | 
|  | to ask a question.  In response, you open up a class hierarchy and | 
|  | explore the code for a few minutes.  This is a new task and it should | 
|  | have no impact upon your previous task.  It demands good task separation.  | 
|  | In Eclipse the creation of the second task can be accomplished by just | 
|  | opening a new perspective.  When the task is complete you can close | 
|  | the perspective and return to the old task without loss of context. | 
|  | <h3> | 
|  | Moving from Concept to Implementation</h3> | 
|  | At a conceptual level a perspective is quite simple.  A perspective | 
|  | is a visual container for a set of views and editors.  It has an input | 
|  | and type.  A perspective is also like a page within a book.  | 
|  | 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. | 
|  | <p>At the implementation level things become more complex.  The platform | 
|  | user interface is exposed through a series of interfaces in <tt>org.eclipse.ui</tt>.  | 
|  | The root of the user interface is accessed by invoking <tt>PlatformUI.getWorkbench( | 
|  | )</tt>.  This returns an object of type <tt>IWorkbench</tt>.  | 
|  | A workbench has one or more windows of type <tt>IWorkbenchWindow</tt>.  | 
|  | And each window has a collection of pages of type <tt>IWorkbenchPage</tt>.  | 
|  | In the user interface a page is known as a "perspective".  Within | 
|  | each window there is at most one active and visible page. | 
|  | <p>The structure of the workbench is exposed within the following diagram.  | 
|  | The workbench window is outlined in red.  Within this window there | 
|  | is a single open perspective.  It's purple.  But to be truly | 
|  | accurate, the user calls it a "perspective".  At the implementation | 
|  | level it is an <tt>IWorkbenchPage</tt>. | 
|  | <center> | 
|  | <p><img SRC="workbench_decomposed.jpg" height=578 width=480 align=ABSCENTER></center> | 
|  |  | 
|  | <p>While the workbench is running new windows and pages can be created | 
|  | interactively by invoking Open Perspective from the window menu or from | 
|  | the Navigator context menu.  A page can also be created programmatically | 
|  | using public API on <tt>IWorkbenchWindow</tt>.  For instance, the | 
|  | following code demonstrates the creation of a new page. | 
|  | <pre>// fWindow is an IWorkbenchWindow. | 
|  | fWindow.openPage("org.eclipse.ui.resourcePerspective", ResourcesPlugin.getWorkspace());</pre> | 
|  | In this example the two parameters to <tt>openPage</tt> identify the perspective | 
|  | type and input, in that order.  The perspective type is identified | 
|  | by a string.  Each perspective has a unique id.  In this case | 
|  | <tt>"org.eclipse.ui.resourcePerspective"</tt> | 
|  | identifies the Resource perspective.  The perspective input may be | 
|  | any object of type <tt>IAdaptable</tt>.  In this case the input is | 
|  | the entire workspace. | 
|  | <p>The <tt>openPage</tt> method creates and returns an object of type <tt>IWorkbenchPage</tt>.  | 
|  | Given a page, you can get the input and perspective type by using the following | 
|  | methods. | 
|  | <pre>public IAdaptable getInput(); | 
|  | public IPerspectiveDescriptor getPerspective();</pre> | 
|  | There is an interesting twist here.  When a new page is created you | 
|  | identify the perspective type by id.  In the <tt>openPage</tt> method | 
|  | the id is mapped to a perspective descriptor within a list of known perspectives | 
|  | types and the result is stored within the return page.  The <tt>getPerspective</tt> | 
|  | method on <tt>IWorkbenchPage</tt> returns an object of type <tt>IPerspectiveDescriptor</tt>.  | 
|  | This object has accessor methods for the perspective id, label and icon. | 
|  | <p>The page input determines which resources are visible in the page.  | 
|  | In practice, resource visibility in a page is implemented through collaboration | 
|  | between the page and the views within that page.  The page itself | 
|  | is a visual container for views and editors.  It doesn't provide any | 
|  | presentation for resources. That is delegated to the parts within the page.  | 
|  | The hand-off usually occurs during part creation.  In the early stages | 
|  | of part life cycle a part can obtain a handle to the containing <tt>IWorkbenchPage</tt> | 
|  | and from this it may call <tt>getInput</tt>.  The result will be used | 
|  | as the initial input for this view.  For instance, if a new perspective | 
|  | containing the Navigator is opened the Navigator will use the page input | 
|  | as its own input.  The Packages view does the same.  In some | 
|  | cases the view may provide additional actions to dynamically change the | 
|  | view input.  In the Navigator the Go Into, Go Up, Go Back, and Go | 
|  | Forward actions can be used to navigate around the workspace tree. | 
|  | <p>The perspective determines which views are visible in a page.  | 
|  | For instance, if you open a new page with the Resource perspective the | 
|  | Navigator, Outline, and editor area will be visible.  If you open | 
|  | a new page with the Java perspective the Packages, Hierarchy, Tasks, and | 
|  | editor area will be visible.  The visible views are determined by | 
|  | the perspective type. The type also influences the visible action sets | 
|  | within a page.  For instance, the Java and Debug Action Sets are typically | 
|  | visible in the Java perspective but not in the Team perspective.  | 
|  | This influence will be discussed in greater detail in <a href="#Adding a New Perspective">Adding | 
|  | a New Perspective</a>. | 
|  | <h3> | 
|  | <a NAME="Adding a New Perspective"></a>Adding a New Perspective</h3> | 
|  | Within the workbench a new perspective can be defined in two ways.  | 
|  | An ISV 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 Eclipse user interface.  This section will focus on | 
|  | the ISV scenario. | 
|  | <p>The definition of a new perspective is a three step process. | 
|  | <br>  | 
|  | <ol> | 
|  | <li> | 
|  | Create a plug-in.</li> | 
|  |  | 
|  | <li> | 
|  | Add a perspective extension to the plugin.xml file.</li> | 
|  |  | 
|  | <li> | 
|  | Define a perspective class for the extension within the plug-in.</li> | 
|  | </ol> | 
|  |  | 
|  | <p><br>This process will be illustrated by defining a plugin with a perspective | 
|  | called "Test".  The Test Perspective will contain the Navigator View, | 
|  | the Outline View, and an editor area.  The layout for the perspective | 
|  | is illustrated in the quick sketch below. | 
|  | <center> | 
|  | <p><img SRC="TestPerspectiveSketch.jpg" height=281 width=374></center> | 
|  |  | 
|  | <p>In the first step a new plug-in is created.  The process of plug-in | 
|  | creation is explained in detail in <a href="http://www.eclipsecorner.org/articles/Your%20First%20Plug-in.html">Your | 
|  | First Plugin</a>, by Jim Amsden, so I won't go into the details here.  | 
|  | For this article I created a Perspective Plugin with following plugin.xml | 
|  | file. | 
|  | <pre><plugin | 
|  |    id="org.eclipse.ui.articles.perspective" | 
|  |    name="Perspective Article Plugin" | 
|  |    version="1.0.0"></pre> | 
|  |  | 
|  | <pre><requires> | 
|  |    <import plugin="org.eclipse.core.runtime"/> | 
|  |    <import plugin="org.eclipse.core.resources"/> | 
|  |    <import plugin="org.eclipse.ui"/> | 
|  | </requires></pre> | 
|  |  | 
|  | <pre><runtime> | 
|  |    <library name="perspective.jar"/> | 
|  | </runtime></pre> | 
|  |  | 
|  | <pre></plugin></pre> | 
|  | The <tt>org.eclipse.ui</tt> plug-in defines a single extension point for | 
|  | perspective contribution: <tt>org.eclipse.ui.perspectives</tt>.  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.  This declaration contains the basic elements: | 
|  | id, name and class. | 
|  | <pre><extension point="org.eclipse.ui.perspectives"> | 
|  |    <perspective | 
|  |          name="Test" | 
|  |          class="org.eclipse.ui.articles.perspective.TestPerspective" | 
|  |          id="org.eclipse.ui.articles.perspective.Test"> | 
|  |    </perspective> | 
|  | </extension></pre> | 
|  | A complete description of the extension point and the syntax are available | 
|  | in the developer documentation for <tt>org.eclipse.ui</tt>. The attributes | 
|  | are described as follows. | 
|  | <br>  | 
|  | <ul> | 
|  | <li> | 
|  | <b>id</b> - a unique name that will be used to identify this perspective.</li> | 
|  |  | 
|  | <li> | 
|  | <b>name</b> - a translatable name that will be used in the workbench window | 
|  | menu bar to represent this perspective.</li> | 
|  |  | 
|  | <li> | 
|  | <b>class</b>  – a fully qualified name of the class that implements | 
|  | <tt>org.eclipse.ui.IPerspectiveFactory</tt> | 
|  | interface.</li> | 
|  |  | 
|  | <li> | 
|  | <b>icon</b> - a relative name of the icon that will be associated with | 
|  | this perspective.</li> | 
|  | </ul> | 
|  |  | 
|  | <p><br>Perhaps the most important attribute in the perspective declaration | 
|  | is <i>class</i>.  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 <tt>org.eclipse.ui.articles.perspective.TestPerspective</tt>.  | 
|  | The implementation of <tt>TestPerspective</tt> will be examined in a few | 
|  | paragraphs. | 
|  | <p>Once a perspective extension has been declared for the Test Perspective | 
|  | it will appear in the Perspective > Open menu and in the Open Perspective | 
|  | menu of the Navigator.  If the user invokes either of these actions | 
|  | a new workbench page will be created.  During this process the following | 
|  | steps are taken. | 
|  | <br>  | 
|  | <ol> | 
|  | <li> | 
|  | A new <tt>IWorkbenchPage</tt> object is created with perspective id = "org.eclipse.ui.articles.perspective.Test".</li> | 
|  |  | 
|  | <li> | 
|  | The perspective id is used to lookup the actual perspective extension in | 
|  | the plugin registry.  Within the workbench a list of the registered | 
|  | perspective extensions are stored within the <tt>IPerspectiveRegistry</tt> | 
|  | (available from the <tt>IWorkbench</tt> interface).  The <tt>findPerspectiveWithId</tt> | 
|  | method is called to get a complete description of the perspective.  | 
|  | This method returns an object of type <tt>IPerspectiveDescriptor</tt>.</li> | 
|  |  | 
|  | <li> | 
|  | The perspective class is retrieved from the <tt>IPerspectiveDescriptor</tt>.  | 
|  | This class must implement <tt>IPerspectiveFactory</tt>.</li> | 
|  |  | 
|  | <li> | 
|  | An instance of the perspective class is created, yielding a <tt>IPerspectiveFactory</tt>.</li> | 
|  |  | 
|  | <li> | 
|  | The <tt>createInitialLayout</tt> method is called on the <tt>IPerspectiveFactory</tt>.  | 
|  | This method defines the initial layout for a page. Implementors may add | 
|  | views, folders, actions and action sets to the page layout.</li> | 
|  |  | 
|  | <li> | 
|  | The <tt>IPerspectiveFactory</tt> is dereferenced and is not used again | 
|  | during the life cycle of the page.</li> | 
|  |  | 
|  | <li> | 
|  | The <tt>IWorkbenchPage</tt> is activated.</li> | 
|  | </ol> | 
|  |  | 
|  | <p><br>In the next few paragraphs we'll concentrate on point # 5.  | 
|  | When <tt>createInitialLayout</tt> is called on an <tt>IPerspectiveFactory</tt> | 
|  | the page layout consists of an editor area with no additional views.  | 
|  | Within <tt>createInitialLayout</tt> you can add views, folders, and view | 
|  | place holders to the page layout.  A <i>folder</i> is a stack of views.  | 
|  | A <i>place holder</i> 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. | 
|  | <p>In the example below you can see how <tt>createInitialLayout</tt> is | 
|  | implemented in the <tt>TestPerspective</tt> class.  For clarity the | 
|  | algorithm has been split into two parts which define the actions and layout: | 
|  | <tt>defineActions</tt> | 
|  | and <tt>defineLayout</tt>. | 
|  | <pre>public void createInitialLayout(IPageLayout layout) { | 
|  |     defineActions(layout); | 
|  |     defineLayout(layout); | 
|  | }</pre> | 
|  | In <tt>defineActions</tt> a number of items and action sets are added to | 
|  | the window.  A perspective may add items to the File > New, Show View, | 
|  | or Perspective > Open menus of the window.  You can also add complete | 
|  | action sets to the menu or toolbar of the window.  In this example | 
|  | a few File > New and Show View items are added. | 
|  | <pre>public void defineActions(IPageLayout layout) { | 
|  |         // Add "new wizards". | 
|  |         layout.addNewWizardShortcut("org.eclipse.ui.wizards.new.folder"); | 
|  |         layout.addNewWizardShortcut("org.eclipse.ui.wizards.new.file"); | 
|  |  | 
|  |         // Add "show views". | 
|  |         layout.addShowViewShortcut(IPageLayout.ID_RES_NAV); | 
|  |         layout.addShowViewShortcut(IPageLayout.ID_BOOKMARKS); | 
|  |         layout.addShowViewShortcut(IPageLayout.ID_OUTLINE); | 
|  |         layout.addShowViewShortcut(IPageLayout.ID_PROP_SHEET); | 
|  |         layout.addShowViewShortcut(IPageLayout.ID_TASK_LIST); | 
|  | }</pre> | 
|  | In <tt>defineLayout</tt> the TestPerspective factory adds two views to | 
|  | the layout.  When <tt>createInitialLayout</tt> 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.  | 
|  | In <tt>defineLayout</tt> the factory gets the id of the editor area.  | 
|  | Then it creates a folder to the left of this area and adds the Navigator | 
|  | view and Outline view to this folder. | 
|  | <pre>public void defineLayout(IPageLayout layout) { | 
|  |         // Editors are placed for free. | 
|  |         String editorArea = layout.getEditorArea(); | 
|  |  | 
|  |         // Place navigator and outline to left of | 
|  |         // editor area. | 
|  |         IFolderLayout left = | 
|  |                 layout.createFolder("left", IPageLayout.LEFT, (float) 0.26, editorArea); | 
|  |         left.addView(IPageLayout.ID_RES_NAV); | 
|  |         left.addView(IPageLayout.ID_OUTLINE); | 
|  | }</pre> | 
|  | The <tt>createFolder</tt> 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 <tt>IPageLayout</tt>, and include <tt>TOP, BOTTOM, | 
|  | LEFT </tt>and<tt> RIGHT</tt>. | 
|  | <p>In some situations a perspective within one plug-in may be referenced | 
|  | by another plug-in.  For convenience, the unique id for each perspective | 
|  | should be declared on a public interface in the source plug-in.  The | 
|  | unique id is usually derived by concatenating the plug-in id with some | 
|  | plug-in unique perspective id.  For instance, the following approach | 
|  | was used for the Perspective plugin and perspective. | 
|  | <pre>public interface IPerspectivePlugin { | 
|  |         /** | 
|  |          * Plugin id. | 
|  |          */ | 
|  |         public final static String PLUGIN_ID = "org.eclipse.ui.articles.perspective"; | 
|  |          | 
|  |         /** | 
|  |          * Test perspective id. | 
|  |          */ | 
|  |         public final static String TEST_PERSPECTIVE_ID = PLUGIN_ID + ".Test"; | 
|  | }</pre> | 
|  | The Test perspective is now ready to use.  To test the new perspective | 
|  | I installed the Perspective plugin in the Eclipse plugins directory and | 
|  | then restarted Eclipse.  From the Perspective > Open > Other... dialog | 
|  | I selected the Test perspective.  After pressing OK the following | 
|  | page appeared within my window. | 
|  | <center> | 
|  | <p><img SRC="TestPerspective.jpg" height=406 width=559></center> | 
|  |  | 
|  | <h4> | 
|  | Why is Layout Declaration done in Code Rather than XML?</h4> | 
|  | During the design of perspectives both options were considered.  Within | 
|  | Eclipse 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 plugin lazily for better startup | 
|  | performance.  Now let's apply this logic to perspectives.  When | 
|  | a perspective is selected from the Open Perspective menu the load conditions | 
|  | are met, so we can load the extension and move forward using Java.  | 
|  | Java code provides the benefits of code completion and error detection | 
|  | at development time. | 
|  | <h4> | 
|  | Can I Remove the Editor Area Completely?</h4> | 
|  | 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 | 
|  | <tt>IPageLayout.setEditorAreaVisible(boolean)</tt> to hide or show the | 
|  | editor area.  This state will be honored unless the user decides to | 
|  | override it from the Perspective menu. | 
|  | <p>As a philosophical point, wouldn't it be great if you could punt the | 
|  | editor area completely?  In fact, the workbench user interface favors | 
|  | the user more than the ISV.  While the ISV may wish to define a closed | 
|  | environment with a fixed set of views, the user always has the ability | 
|  | to show any view from the Perspective > 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 <a href="#User Customization and Persistance">User Customization and | 
|  | Persistence</a>. | 
|  | <h4> | 
|  | Do I Need a Perspective?</h4> | 
|  | The temptation to create a new perspective is strong.  The dark side | 
|  | beckons.  As an ISV, 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, say the Resource perspective, and add your view to | 
|  | the factory class.  If every ISV 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. | 
|  | <p>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.  For instance, the Java Perspective is a good | 
|  | context for the completion of Java related tasks.  It contains a Packages | 
|  | view and Hierarchy view for class navigation.  The Tasks view is good | 
|  | for problem navigation.  And the Outline view is useful for navigation | 
|  | within an editor.  Together, these views are useful for many Java | 
|  | oriented tasks and the creation of a Java Perspective is justified. | 
|  | <p>In some situations it may be better to augment an existing perspective.  | 
|  | For instance, if you create a single view which is Java centric it is probably | 
|  | better to add that view to the standard Java perspective rather than defining | 
|  | a new perspective.  This strategy provides better integration with | 
|  | the existing platform.  For more information on this process check | 
|  | out <a href="#Extend an Existing Perspective">Extending an Existing Perspective</a>. | 
|  | <h3> | 
|  | <a NAME="User Customization and Persistance"></a>User Customization and | 
|  | Persistence</h3> | 
|  | In the previous section we examined the techniques an ISV would use to | 
|  | add a perspective to the workbench.  The user can also add a new perspective | 
|  | to the Eclipse user interface or override an existing perspective.  | 
|  | This section will focus on those aspects of user customization. | 
|  | <p>When Eclipse is installed the plug-in registry contains a number of | 
|  | perspective extensions.  These extensions are contributed by plug-ins | 
|  | from various ISV's and form the initial set of perspectives available to | 
|  | the user.  In my own experience the perspectives contributed by an | 
|  | ISV usually fail to completely meet my needs, so I quickly customize them.  | 
|  | I add views, remove views, add action sets, customize the menus, etc., | 
|  | until the user interface reflects the way I work.  Then I save the | 
|  | new layout to the original perspective. | 
|  | <p>The initial layout for a page is determined by the perspective.  | 
|  | To be more precise, it is determined by an <tt>IPerspectiveFactory</tt> | 
|  | as explained in <a href="#Adding a New Perspective">Adding a New Perspective</a>.  | 
|  | Once a page is open the user may modify the part layout or the visible | 
|  | action sets within the page.  If this page is closed the new layout | 
|  | is discarded.  However, if this page is open when the workbench is | 
|  | closed the state of the page (and in fact every window, page and part) | 
|  | is saved to an XML file in the <tt>org.eclipse.ui</tt> plug-in.  This | 
|  | file is used to restore the state of the page when the workbench is restarted | 
|  | and contains every important attribute of the page: the visible views, | 
|  | their layout, the visible action sets and other state attributes.  | 
|  | In fact, the <tt>IPerspectiveFactory</tt> which defined the initial layout | 
|  | for the page is not consulted when the page is restored. | 
|  | <p>The user can also create a new perspective by invoking Perspective > | 
|  | Save.  In response a dialog appears where the user can type a user | 
|  | friendly name for the new perspective.  Depending on the option chosen | 
|  | by the user, this action will create a new perspective with the layout | 
|  | of the current page or override the layout for an existing perspective.  | 
|  | The resulting perspective has all of the privileges of an ISV perspective.  | 
|  | The user can open a page with the custom perspective, use it as the default | 
|  | perspective, or delete it.  The layout of the custom perspective is | 
|  | saved as an XML file using the same mechanism described above for workbench | 
|  | session persistence, so there is no <tt>IPerspectiveFactory</tt>. | 
|  | <h3> | 
|  | Opening a New Perspective</h3> | 
|  | In the workbench a new perspective can be created interactively by the | 
|  | user or programmatically through public API on <tt>IWorkbench, IWorkbenchWindow | 
|  | or IWorkbenchPage</tt>.  For instance, the user may select a container | 
|  | in the Navigator and invoke Open Perspective > Java.  This is an explicit | 
|  | command from the user to the view to create a new perspective.  A | 
|  | new perspective may also be created as a step within some other action.  | 
|  | For instance, if Project > Open Type is invoked an option exists to open | 
|  | a new Hierarchy Perspective.  In this section the implementation of | 
|  | both will be discussed. | 
|  | <p>In the Navigator a user may open a new perspective with specific input | 
|  | and type by invoking Open Perspective from the context menu.  This | 
|  | ability is an important element of information filtering and should be | 
|  | included in any view where the resource tree is visible.  This will | 
|  | lead to user interface consistency and ease of use. | 
|  | <p>The easiest way to add Open Perspective functionality to a view or menu | 
|  | is with the <tt>OpenPerspectiveMenu</tt>.  This class is supplied | 
|  | in | 
|  | <tt>org.eclipse.ui.actions</tt> and can be included in any popup menu.  | 
|  | For instance, the following code demonstrates its use within the Navigator. | 
|  | <pre>/** | 
|  |  * Add "open to" actions to the context sensitive menu. | 
|  |  * @param menu the context sensitive menu | 
|  |  * @param selection the current selection in the project explorer | 
|  |  */ | 
|  | void fillOpenToMenu(IMenuManager menu, IStructuredSelection selection)  | 
|  | { | 
|  |         // If one file is selected get it. | 
|  |         // Otherwise, do not show the "open with" menu. | 
|  |         if (selection.size() != 1) | 
|  |                 return; | 
|  |         IAdaptable element = (IAdaptable) selection.getFirstElement(); | 
|  |         if (!(element instanceof IContainer)) | 
|  |                 return; | 
|  |  | 
|  |         // Create a menu flyout. | 
|  |         MenuManager submenu = new MenuManager(ResourceNavigatorMessages.getString("ResourceNavigator.openPerspective")); //$NON-NLS-1$ | 
|  |         submenu.add(new OpenPerspectiveMenu(getSite().getWorkbenchWindow(), element)); | 
|  |         menu.add(submenu); | 
|  |  | 
|  | }</pre> | 
|  | In this example the popup menu for the navigator is populated dynamically | 
|  | just before the menu is about to show.  The <tt>fillOpenToMenu</tt> | 
|  | method is called from within <tt>menuAboutToShow</tt>.  If the selection | 
|  | is a container (project or folder) the Open Perspective submenu is created | 
|  | and then populated automatically using the <tt>OpenPerspectiveMenu</tt>.  | 
|  | The contents of this submenu are determined by the customized settings | 
|  | of the active perspective.  For instance, if the Perspective > Open | 
|  | menu contains "Resource, Java, and Team" your context menu will also contain | 
|  | "Resource, Java, and Team". | 
|  | <p>In the workbench the behavior of Open Perspective in flexible.  | 
|  | In fact, the user can configure this behavior in the workbench preferences.  | 
|  | The "Open a New Perspective" behavior may be defined as "Open in Same Window", | 
|  | "Open in New Window", or "Replace Current".   The meaning of | 
|  | "Open in Same Window" and "Open in New Window" are obvious.  The meaning | 
|  | of "Replace Current" is less so.  Each page has a perspective.  | 
|  | If "Replace Current" is invoked the active perspective within the page | 
|  | is replaced by a new perspective.  This causes the view layout and | 
|  | visible action sets within the page to change, and is equivalent to changing | 
|  | the layout in MS Studio. | 
|  | <p>The <tt>OpenPerspectiveMenu </tt>class implements the preferred behavior | 
|  | for "Open Perspective" and supports the selection of alternate behaviors | 
|  | when the Control or Shift keys are pressed.  After the addition of | 
|  | an <tt>OpenPerspectiveMenu</tt> object to the context menu no other action | 
|  | is required to implement the Open Perspective behavior. | 
|  | <p>A new perspective may also be created as a step within some other action.  | 
|  | For instance, if Project > Open Type is invoked the implementing action | 
|  | will open a new page with the Hierarchy perspective.   In this | 
|  | scenario a new IWorkbenchPage must be created explicitly using the API's | 
|  | available on <tt>IWorkbenchWindow</tt>.  The following code illustrates | 
|  | this process. | 
|  | <pre><tt>// Open the page. | 
|  | try { | 
|  |    getWindow().openPage(IPerspectivePlugin.TEST_PERSPECTIVE_ID, pageInput); | 
|  | } catch (WorkbenchException e) { | 
|  |    MessageDialog.openError(getWindow().getShell(), | 
|  |        "Problem Opening Perspective", | 
|  |        e.getMessage()); | 
|  | }</tt></pre> | 
|  | In the code above the active workbench window is retrieved and then <tt>openPage</tt> | 
|  | is invoked with a perspective type and input.  As we saw in <a href="#Adding a New Perspective">Adding | 
|  | a New Perspective</a>, the id of each perspective should be exposed on | 
|  | a public interface in the source plug-in for convenient access by other | 
|  | plug-ins in Java code.  In this example the Test perspective id is | 
|  | referenced from the <tt>IPerspectivePlugin</tt> class.  The perspective | 
|  | id is mapped to an <tt>IPerspectiveDescriptor</tt> within the perspective | 
|  | registry.  Then the page is opened.  If any problems occur during | 
|  | the creation of the page an exception will be thrown. | 
|  | <p>As a philosophical point, should a hard coded constant be used to specify | 
|  | perspective type?  In my own experience it is difficult to predict | 
|  | the usage pattern for any perspective.  For instance, one user may | 
|  | prefer to develop java code in the Java perspective.  Another may | 
|  | prefer to develop java code in the Resource perspective.  If a hard | 
|  | coded constant is used to specify a perspective type the user may become | 
|  | frustrated if the wrong perspective is chosen.  It may be better to | 
|  | let the user choose the perspective type or disable this behavior completely. | 
|  | <p>If you need to open a perspective from within an action there is one | 
|  | detail to be aware of: the user may change the default behavior for Open | 
|  | Perspective in the workbench preferences.  In most scenarios your | 
|  | action should honor this preference. | 
|  | <p>To demonstrate the use of the Open Perspective preference I created | 
|  | an Action Set containing one action: "Open Test Perspective".  When | 
|  | this action is invoked a new Test Perspective is opened using the preferred | 
|  | behavior.   At the implementation level the action implements | 
|  | <tt>IWorkbenchWindowActionDelegate</tt>.  | 
|  | Within the <tt>run</tt> method the preference is retrieved from the workbench | 
|  | plugin and then the perspective is opened.  Here is an snippet containing | 
|  | the relevant details of my action delegate class. | 
|  | <pre>public void run(IAction action) { | 
|  |         openPerspective(IPerspectivePlugin.TEST_PERSPECTIVE_ID, | 
|  |                 ResourcesPlugin.getWorkspace()); | 
|  | } | 
|  |  | 
|  | /**  | 
|  |  * Implements Open Perspective.  | 
|  |  */ | 
|  | private void openPerspective(String perspId, IAdaptable input) { | 
|  |         // Get "Open Behavior" preference. | 
|  |         AbstractUIPlugin plugin = (AbstractUIPlugin)Platform.getPlugin(PlatformUI.PLUGIN_ID); | 
|  |         IPreferenceStore store = plugin.getPreferenceStore(); | 
|  |         String pref = store.getString(IWorkbenchPreferenceConstants.OPEN_NEW_PERSPECTIVE); | 
|  |                          | 
|  |         // Implement open behavior. | 
|  |         try { | 
|  |                 if (pref.equals(IWorkbenchPreferenceConstants.OPEN_PERSPECTIVE_WINDOW)) | 
|  |                         workbench.openWorkbenchWindow(perspId, input); | 
|  |                 else if (pref.equals(IWorkbenchPreferenceConstants.OPEN_PERSPECTIVE_PAGE)) | 
|  |                         window.openPage(perspId, input); | 
|  |                 else if (pref.equals(IWorkbenchPreferenceConstants.OPEN_PERSPECTIVE_REPLACE)) { | 
|  |                         IPerspectiveRegistry reg = workbench.getPerspectiveRegistry(); | 
|  |                         window.getActivePage().setPerspective(reg.findPerspectiveWithId(perspId)); | 
|  |                 } | 
|  |         } catch (WorkbenchException e) { | 
|  |                 e.printStackTrace(); | 
|  |         } | 
|  | }</pre> | 
|  |  | 
|  | <h3> | 
|  | <a NAME="Extend an Existing Perspective"></a>Extending an Existing Perspective</h3> | 
|  | In many scenarios the extension of an existing perspective is a good way | 
|  | to introduce new action sets, wizards, or views into the workbench.  | 
|  | For instance, as an ISV you may create a new Java centric view to the workbench.  | 
|  | Rather than defining a new perspective to show off your view, you can extend | 
|  | the standard Java perspective.  This strategy provides better integration | 
|  | with the existing platform.  In this section the details of perspective | 
|  | extension will be covered. | 
|  | <p>The extension of an existing perspective is a three step process. | 
|  | <br>  | 
|  | <ol> | 
|  | <li> | 
|  | Create a plug-in for your extensions.</li> | 
|  |  | 
|  | <li> | 
|  | Define an action set or view extension in the plugin.xml file.</li> | 
|  |  | 
|  | <li> | 
|  | Add a perspectiveExtension extension to the plug-in registry.</li> | 
|  | </ol> | 
|  |  | 
|  | <p><br>This process will be illustrated using the Test Perspective which | 
|  | was defined in a <a href="#Adding a New Perspective">Adding a New Perspective</a>. | 
|  | <p>The first step is to create a plug-in with an action set or view extension.  | 
|  | In this example I chose to reuse a few extensions which already exist within | 
|  | <tt>org.eclipse.jdt.ui</tt> | 
|  | (the Java plug-in).  This plug-in defines a Java Action Set, a New | 
|  | Java Project Wizard, a Packages View and a Hierarchy View. | 
|  | <p>The <tt>org.eclipse.ui</tt> plug-in defines an extension point for perspective | 
|  | extension: <tt>org.eclipse.ui.perspectiveExtensions</tt>.  This extension | 
|  | point can be used to contribute any of the following objects to an existing | 
|  | extension perspective. | 
|  | <br>  | 
|  | <ul> | 
|  | <li> | 
|  | Action Sets</li> | 
|  |  | 
|  | <li> | 
|  | File New Items</li> | 
|  |  | 
|  | <li> | 
|  | Show View Items</li> | 
|  |  | 
|  | <li> | 
|  | Open Perspective Items</li> | 
|  |  | 
|  | <li> | 
|  | Views</li> | 
|  | </ul> | 
|  |  | 
|  | <p><br>In the following example the extension point is used to add the | 
|  | Java extensions discussed above to the Test perspective.  In the first | 
|  | two lines of XML the target perspective extension is declared: <tt>org.eclipse.ui.articles.perspective.TestPerspective</tt>.  | 
|  | Following this the specific extensions for this perspective are declared.  | 
|  | An action set is added.  Then menu items for Show View, File > New, | 
|  | and Open Perspective are added.  And then the Packages view is stacked | 
|  | on top of the Navigator. | 
|  | <pre><extension point="org.eclipse.ui.perspectiveExtensions"> | 
|  |           <perspectiveExtension targetID="org.eclipse.ui.articles.perspective.Test"> | 
|  |                <actionSet id="org.eclipse.jdt.ui.JavaActionSet"/> | 
|  |                <viewShortcut id="org.eclipse.jdt.ui.PackageExplorer"/> | 
|  |                <newWizardShortcut | 
|  |                     id="org.eclipse.jdt.ui.wizards.NewProjectCreationWizard"/> | 
|  |                <perspectiveShortcut id="org.eclipse.jdt.ui.JavaPerspective"/> | 
|  |                <view id="org.eclipse.jdt.ui.PackageExplorer" | 
|  |                     relative="org.eclipse.ui.views.ResourceNavigator" | 
|  |                     relationship="stack"/> | 
|  |           </perspectiveExtension> | 
|  | </extension></pre> | 
|  | In the next few paragraphs a brief description of each element within the | 
|  | perspectiveExtensions extension point is provided.  A complete description | 
|  | of the extension point and the syntax are available in the developer documentation | 
|  | for org.eclipse.ui. | 
|  | <p>In the example an <tt>actionSet</tt>, <tt>viewShortcut</tt>, <tt>newWizardShortcut</tt> | 
|  | and <tt>perspectiveShortcut</tt> extension are demonstrated.  The | 
|  | format of these elements is very simple.  There is one attribute, | 
|  | <tt>id</tt>, which identifies an existing extension which should be added | 
|  | to the perspective.  It must identify an action set, view, wizard, | 
|  | or perspective which has been registered using the standard extension point | 
|  | for each. | 
|  | <p>The XML for view extension is a little more complicated.  A new | 
|  | view may be stacked on or placed relative to an existing view.  Minimally, | 
|  | you must define an <tt>id</tt> (of the view being added), <tt>relative</tt> | 
|  | id, and <tt>relationship</tt> ( <tt>left, right, bottom, top, stack</tt> | 
|  | ).  If the relationship is not <tt>stack</tt> a <tt>ratio</tt> must | 
|  | also be supplied.  This will be interpreted using the same heuristics | 
|  | as <tt>IPageLayout.addView(id, relationship, ratio, refID)</tt>. | 
|  | <p>In the current implementation of perspective extension there is one | 
|  | limitation.  Perspective extension is only possible when the user | 
|  | has not modified the default layout for a perspective.  If modification | 
|  | has occurred perspective extensions will be ignored. However, given the | 
|  | customizable nature of the workbench the user can always introduce an action | 
|  | set or view into the perspective by invoking the Perspective > Customize | 
|  | action or by opening a view from the Perspective > Show View menu. | 
|  | <h3> | 
|  | Conclusion</h3> | 
|  | In this article we have examined the role of perspectives within the workbench | 
|  | and their implementation.  Perspectives are complex and will certainly | 
|  | evolve over time.  Hopefully this article will get you started.  | 
|  | Further information is available in the Platform Plug-in Developer Guide | 
|  | and in the javadoc for <tt>org.eclipse.ui</tt>. | 
|  |  | 
|  | <p><small>Java and all Java-based trademarks and logos are trademarks or registered | 
|  | trademarks of Sun Microsystems, Inc. in the United States, other countries, or | 
|  | both.</small></p> | 
|  |  | 
|  | </body> | 
|  | </html> |