173
ECLIPSE PLUGIN DEVELOPMENT TUTORIAL Eclipse Plugin Development Tutorial website to teach you how to develop eclipse plugins using simple examples to a complex eclipse rcp over time. This chapter will give you a detailed insight into Eclipse Architecture and we will develop a simple but fully functional eclipse plug-in so as to give you a quick start with eclipse plug-in development. Overview Eclipse isn’t a huge single java program, but rather a small program which provides the functionality of typical loader called plug-in loader. Eclipse (plug-in loader) is surrounded by hundreds and thousands of plug-ins. Plug-in is nothing but another java program which extends the functionality of Eclipse in some way. Each eclipse plug-in can either consume services provided by other plug-in or can extend its functionality to be consumed by other plug-ins. These plug-in are dynamically loaded by eclipse at run time on demand basis. An Open Platform Eclipse is an open platform. It is designed to be easily and infinitely extensible by third parties. At the core is the eclipse SDK, we can build various products/tools around this SDK. These products or tools can further be extended by other products/tools and so on. For example, we can extend simple text editor to create xml editor. Eclipse architecture is truly amazing when it comes to extensibility. This extensibility is achieved by creating these products/tools in form of plug-ins. Figure 1-1

Eclipse Plugin Development TUTORIAL

Embed Size (px)

Citation preview

Page 1: Eclipse Plugin Development TUTORIAL

ECLIPSE PLUGIN DEVELOPMENT TUTORIAL

Eclipse Plugin Development Tutorial website to teach you how to develop eclipse plugins using simple examples to a complex eclipse rcp over time. This chapter will give you a detailed insight into Eclipse Architecture and we will develop a simple but fully functional eclipse plug-in so as to give you a quick start with eclipse plug-in development.

Overview

Eclipse isn’t a huge single java program, but rather a small program which provides the functionality of typical loader called plug-in loader. Eclipse (plug-in loader) is surrounded by hundreds and thousands of plug-ins. Plug-in is nothing but another java program which extends the functionality of Eclipse in some way. Each eclipse plug-in can either consume services provided by other plug-in or can extend its functionality to be consumed by other plug-ins. These plug-in are dynamically loaded

by eclipse at run time on demand basis.

An Open Platform

Eclipse is an open platform. It is designed to be easily and infinitely extensible by third parties. At the core is the eclipse SDK, we can build various products/tools around this SDK. These products or tools can further be extended by other products/tools and so on. For example, we can extend simple text editor to create xml editor. Eclipse architecture is truly amazing when it comes to extensibility. This extensibility is achieved by creating these products/tools in form of plug-ins.

Figure 1-1

Inside the Eclipse SDK

Page 2: Eclipse Plugin Development TUTORIAL

Figure 1-2

RCP: On the bottom is RCP which provides the architecture and framework to build any rich client application.

IDE: It is a tools platform and a rich client application itself. We can build various form of tooling by using IDE for example Database tooling.

JDT: It is a complete java IDE and a platform in itself.

PDE: It provides all tools necessary to develop plug-ins and RCP applications. This is what we will concentrate on the course of this tutorial.

Plug-ins everywhere

All the layers in eclipse SDK are made up of plug-ins. If you see all the way, you will notice that everything is a plug-in in eclipse sdk.

Page 3: Eclipse Plugin Development TUTORIAL

Figure 1-3

Plug-in Architecture

A plugin is a small unit of Eclipse Platform that can be developed separately. It must be noted that all of the functionality of eclipse is located in different plugins (except for the kernel)

A plug-in can be delivered as a jar file. A plug-in is self-contained bundle in a sense that it contains the code and resources that it needs to run for ex: code, image files, resource bundles etc. A plug-in is self describing - when I say it is self describing it means that it describes who it is and what it contributes to the world. It also declares what it requires from the world.

Page 4: Eclipse Plugin Development TUTORIAL

ECLIPSE PLUG IN DEVELOPMENT (PAGE 2)

A Mechanism For Extensibility

Figure 1-7

We all know that eclipse is extensible. In order to achieve this extensibility eclipse uses the concept of extension points and extension. Think of extension point as Electric socket and think of extension as a plug. Plug-in A exposes a extension point (electric socket) which Plug-in B extends by providing an extension (an electric plug). Plug-in A knows nothing about plug-in B. If we think about it this is very similar to concept of Inheritance – we extend functionality of base class to provide more specific implementation. Think of Plug-in A as a text editor and Plug-in B as xml editor. Text editor declares extension point thereby declaring to the world that it is open for extension and xml editor extends text editor by using its extension point to customize it in its own way. It is important to understand that each extension point essentially declares a contract. An extension point provider only accepts those extensions which abide by the contract.

These extension points and extensions are declared in plugin.xml (discussed earlier). The runtime is able to wire extensions and extension points and form a registry using markup alone.

Plug-in Example

Now that we have covered good amount of architecture basics, its time to get our hands dirty with some actual plug-in coding. The process for creating a plug-in is best demonstrated by implementing a plug-in on which discussion and examples can be based. Here we will take a step-by-step approach to create a simple but fully operational plug-in. This example will try to give you an feel of eclipse plug-in development. However, don’t try to grab all the details at this point. It is fine if you are not able to understand much of the details in this example. Rest of the tutorial will cover all the topics in great depth.

We will build a simple Resource Manager plug-in. Features of this plug-in are as follows:

Ability to add/remove resources (essentially files in workspace) to resource manager. Display list of resources which were added to resource manager.

Ability to open up associated editor whenever resource is clicked.

Note: All Examples in this tutorial have been implemented using Eclipse version 3.1.2

Creating a Plug-in

1. Launch Eclipse.

Page 5: Eclipse Plugin Development TUTORIAL

2. From File menu, select New Project. This will open up New Project wizard.3. Now select Plug-in Project and click on the next button. (see Figure 1-8)

Figure 1-8

4. On next page of the wizard (see Figure 1-9), enter the name of the project "com.myplugin.rmp"

Page 6: Eclipse Plugin Development TUTORIAL

Figure 1-9

5. Fill in the other fields as shown and then click the Next button. The next wizard page displays options for generating plug-in Java class. Fill all the fields as shown below. Do not fill anything in classpath field - This has been removed in eclipse 3.4. Plug-in Activator is required if we want to do anything on plug-in start up or shut down. For example we want to acquire some resources at plug-in start up and perform clean up when plug-in is shutdown. It is important to note that Eclipse startup does not essentially means that your plug-in is starting up. Plug-ins are loaded/started only when they are demanded or required. So activator is used when plug-in startup/shutdown happens.

Page 7: Eclipse Plugin Development TUTORIAL

Figure 1-10

6. Click Next, select Plug-in with a view and then click the Next button.

Page 8: Eclipse Plugin Development TUTORIAL

Figure 1-11

7. Next, Enter the values for this page (see Figure 1-12), and click the Next button.

Page 9: Eclipse Plugin Development TUTORIAL

Figure 1-12

8. Finally, uncheck all the options (see Figure 1-13). and click Finish button.

Page 10: Eclipse Plugin Development TUTORIAL

ECLIPSE PLUGIN TUTORIAL (PAGE 3)

After completing New plug-in Project wizard following directory structure will be created (Figure 1-14).

Page 11: Eclipse Plugin Development TUTORIAL

Figure 1-14

Four important files to look for are:

RmpPlugin.java – This is the main plug-in class. When plug-in is activated, startup method of this class is called. This class can be used to initialize plugin specific resources.

ResourceManagerView.java – This is the View class which gets generated. This class contributes to the UI of our example Resource manager plug-in.

MANIFEST.MF – defines runtime information of the plugin

Plugin.xml – defines the extension information of the plug-in.

In order to open up plug-in manifest editor double click on MANIFEST.MF or plugin.xml file. Browse through the tabs shown at the bottom of editor. Don’t worry if you are unable to understand all of the content in this editor, it will be discussed during course of this tutorial.

Manifest Editor - Dependencies Tab

Figure 1-15

In This section a plug-in must list all the dependent plug-ins which are required so that our plug-in compiles. As you know that we build our plug-ins on top of other plug-ins, so this section essentially declares all those dependencies.

Page 12: Eclipse Plugin Development TUTORIAL

It must be noted that all above plug-in dependencies must be met before plug-in is resolved. It is always good to scan your dependencies from time to time and remove unused dependencies. In order to know unused dependencies use Dependency Analysis section.

Manifest Editor – Runtime Tab

Figure 1-16

On this page plug-in declares what all it exposes to the outside world. Lets understand this concept with an example. Say you are building Plug-in A. Now if plug-in B wants to extend plug-in A or wants to use plug-in A in any way it will be required that Plug-in A exposes its API’s. It is here that Plug-in A would declare all the packages which it wants to expose to outside world. You can use Add.. button to see all your plug-in packages and then select all Packages which you would like to export.

Another important section on this page is the Classpath. If your plug-in is using some external jars then it is important to add such jars to runtime classpath. Note that simply adding such jars to project classpath will only help you in compiling your source code. In order to make these jars available to runtime environment use Classpath section.

Manifest Editor – Extensions Page

Page 13: Eclipse Plugin Development TUTORIAL

Figure 1-17

Extensions page is a viewer on top of plugin.xml. This is one of the most frequently used page in plug-in development. This page makes it easy to create extensions as this page is aware of all the extension points. Eclipse provides around 213 extension points where clients can contribute functionality. Extension points are available for virtually every thing for ex: builders, editors, preferences, help contents, markers, views, perspective and so on. Basically we select some extension point and then use these to build our own extensions.

Manifest Editor – Extension Points

Page 14: Eclipse Plugin Development TUTORIAL

Figure 1-18

This page is also a viewer on top of plugin.xml. This page is used to define our own extension points. Such extension points define a contract which other plug-ins may agree to abide by and extend plug-ins functionality in some way.

Test New Plug-in

There are two ways to test this plug-in. First, we can build a product which will essentially create a plugin bundle, this bundle is then dumped into plug-in folder of eclipse installation. Second, launching new plug-in from within Overview tab of manifest editor. At this time we will take second approach to test this plug-in. This is also the preferable choice when we are developing eclipse plug-ins and need to test them from time to time. In order to test this plug-in click on Overview tab followed by clicking on link Launch an Eclipse Application. See figure 1-19

Page 15: Eclipse Plugin Development TUTORIAL

Figure 1-19

This will launch another instance of eclipse application. However, this new instance will have our plug-in registered with it, So we will be able to see resource manager view. After New Eclipse has started, from the Window menu, select Show View > Other... to open the Show View dialog (see Figure 1-20). In the dialog, expand the Resource Manager Category, select Resource Manager View, and then click the OK button. This causes the Resource Manager view to open (see figure 1-21).

Page 16: Eclipse Plugin Development TUTORIAL

Figure 1-20

Figure 1-21

ECLIPSE SWT DEVELOPMENT

Working With Standard Widget Toolkit

Page 17: Eclipse Plugin Development TUTORIAL

Standard Widget Toolkit (SWT) is the foundation on which entire Eclipse UI is based. SWT provides easy to use widgets and API's which are helpful in building rich user interfaces. SWT is designed in a way so as to give us access to the underlying operation system resources. It uses native (OS) widgets which gives an native look and feel, similar to what is provided by operating system (See figures below). SWT includes many different type of controls for ex: tree, table, button, label etc. This tutorial introduces SWT by describing some of the basic concepts and classes.

SWT Widgets

SWT provides a rich set of widgets that can be used to create either stand-alone Java applications or Eclipse plug-ins. We will start by implementing a small SWT example before getting into details about each of the widgets you are likely to use. In order to create this standalone version of swt program we will start by creating new java Project in eclipse.

Before you can start using SWT, the SWT libraries need to be added to your project's classpath. To add SWT support, do the following:

1. Download SWT library. For 3.1.2 version of eclipse, SWT library is available at http://archive.eclipse.org/eclipse/downloads/drops/R-3.1.2-200601181600/index.php Look for the section titled SWT Binary and Source. 2. From main menu tool bar, select "File" followed by "Import". Doing so will bring up the "Import wizard" dialog.3. Now select "Existing Projects into Workspace" and click on "Next" button.4. Click on "Select archive file" followed by "Browse" button. Now locate the SWT archive that you downloaded in step 1.5. Click the Finish button to finish importing the SWT project into your workspace.6. Create new java project from File > New Java Project.

Page 18: Eclipse Plugin Development TUTORIAL

7. Right-click on the project and select the Properties command to open the Properties dialog.8. Select the Java Build Path followed by Projects tab and click the Add button.9. Select the org.eclipse.swt project and click OK to finish adding the SWT libraries to your project's classpath

Create a new Standalone SWT Program

Create a new java class as follows:

1 import org.eclipse.swt.*;2 import org.eclipse.swt.graphics.*;3 import org.eclipse.swt.widgets.*;

4 public class FirstExample {5 public static void main(String[] args){6 Display firstDisplay = new Display();7 Shell firstShell = new Shell(firstDisplay);8 firstShell.setText("First Example");9 firstShell.setSize(200,100);10 firstShell.open ();11 while (!firstShell.isDisposed()) {12 if (!firstDisplay.readAndDispatch())13 firstDisplay.sleep ();14 }15 firstDisplay.dispose ();16 }17 }

Lines 1-3: SWT classes are contained in different packages which begin with org.eclipse.swt. The package org.eclipse.swt is the main package and contains SWT class and exception/error classes. All the SWT widgets are contained in org.eclipse.swt.widgets package. Refer to online help for more information about these packages

Line 6: Every SWT program has a Display. Display acts like a bridge between program and underlying operating system

Lines 7-9: Next, in the program we have created a shell. All the Top level windows are created by the class Shell and shell's are contained in Display.

Line 10: When a shell is created it is invisible by default. Shell becomes visible only when method open() is called on shell instance. open() method not only makes shell visible but also brings it to the front so that all user input can be intercepted by the shell.

Lines 11-14: SWT supports an event based user interface. Event driven user interface essentially means that user interaction events are generated which are then intercepted by eclipse application to perform various actions. Not surprisingly, any event driven UI requires an event loop that continously listens to user interface events and then broadcasts the events to interested parties. Example of such event could be "Button click", "Minimize Window" etc. The condition when this event loop ends depend upon the application For ex: in some cases user might close the window OR clicks on the exit button provided by the application.

Line 15: Next, we are disposing the Display. Disposing display will release all resources that were acquired by the running program in its lifetime.

In order to run this example program use the Run As > "SWT Application". This will open up new window with title “First Example”.

Events

Page 19: Eclipse Plugin Development TUTORIAL

As discussed earlier, SWT supports an event based user interface. These events are generated by user actions. User actions could be keyboard entry, button click, mouse drag etc. We can trap or listen to these events by adding/attaching listeners to various SWT controls. Following listing shows an example to attach selection listener to button widgetfinal Button myButton = new Button(shell, SWT.PUSH);

SelectionAdapter adapter = new SelectionAdapter() {public void widgetSelected(SelectionEvent event) {myButton.setText("You clicked me!");

}};myButton.addSelectionListener(adapter);myButton.setText("Click");For complete listing of events, listeners refer to online help

In order to know more about events and widgets which support each of these events refer to online Platform Plug-in Developer Guide. Look for headings Low level events and High level events.

SWT ECLIPSE PLUGIN DEVELOPMENT TUTORIAL (PAGE 2)

Most Commonly Used Widgets

All the widgets have been defined in org.eclipse.swt.widgets package. In This section we will discuss most commonly used widgets. Most likely you will use these widgets during eclipse plug-in development. Best way to learn these widgets is through examples, so ill focus this discussion based on examples. You can refer to SWT API document for further reading. All API’s are self explanatory and quite simple.

1. Label Widget

Labels are used to display text messages/labels. Labels do not take part in event model and hence do not generate user interaction events.

public static void main(String[] args) { Display myDisplay = new Display(); Shell myShell = new Shell(myDisplay); myShell.setText("This is a label"); myShell.setBounds(100, 100, 200, 50); myShell.setLayout(new FillLayout());  Label label = new Label(myShell, SWT.CENTER); label.setText("Hello World"); Color red = new Color(myDisplay, 255, 0, 0); label.setForeground(red); myShell.open(); while (!myShell.isDisposed()) { if (!myDisplay.readAndDispatch()) myDisplay.sleep();    } red.dispose(); myDisplay.dispose();}

2. Button Widget

Page 20: Eclipse Plugin Development TUTORIAL

Buttons are used to generate special event called selection event when pressed or released. While creating a button we can use different styles so that this control represent different type of UI element. For example, we can use SWT.ARROW to create arrow button widget or SWT.CHECK to create checkbox.

public class MYButton { public static void main(String[] args) { Display myDisplay = new Display(); Shell myShell = new Shell(myDisplay); myShell.setText("This is my button"); myShell.setBounds(120, 120, 220, 120); myShell.setLayout(new FillLayout()); final Button button = new Button(myShell, SWT.PUSH); button.setText("Click"); button.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { button.setText("You clicked me!"); } }); myShell.open(); while (!myShell.isDisposed()) { if (!myDisplay.readAndDispatch()) myDisplay.sleep(); } myDisplay.dispose(); }}

3.  Text Widget

Eclipse plugin text field widget is used to take user input. It automatically shows scroll bar if provided text is more then control’s length.

public class MYText { public static void main(String[] args) { Display myDisplay = new Display(); Shell myShell = new Shell(myDisplay); myShell.setText("My Text Box"); myShell.setBounds(120, 120, 220, 120); myShell.setLayout(new FillLayout()); final Text text = new Text(myShell, SWT.MULTI); myShell.open(); while (!myShell.isDisposed()) { if (!myDisplay.readAndDispatch()) myDisplay.sleep(); } myDisplay.dispose(); }}

4. Combo Widget

Eclipse plugin Combo widget helps in displaying multiple options to user. User is allowed to select single option from the list of options.

Page 21: Eclipse Plugin Development TUTORIAL

public class MyCombo { public static void main(String[] args) { Display myDisplay = new Display(); Shell myShell = new Shell(myDisplay); myShell.setText("My Combo"); myShell.setBounds(120, 120, 220, 120); myShell.setLayout(new FillLayout(SWT.VERTICAL)); final Combo myCombo = new Combo(myShell,SWT.READ_ONLY); myCombo.setItems(new String[] {"option1", "option2", "option3", "option4", "option5"}); myCombo.setText("option5"); myCombo.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { System.out.println("you selected me: " + myCombo.getText()); } }); myShell.open(); while (!myShell.isDisposed()) { if (!myDisplay.readAndDispatch()) myDisplay.sleep(); } myDisplay.dispose(); }}

5. Table Widget

Table widget is used to display items in rows and columns. The columns of a table are defined by TableColumn.

public class MyTable { public static void main(String[] args) { Display myDisplay = new Display(); Shell myShell = new Shell(myDisplay); myShell.setText("My Table"); myShell.setBounds(120, 120, 220, 120); myShell.setLayout(new FillLayout()); final Table myTable = new Table(myShell, SWT.SINGLE | SWT.FULL_SELECTION); TableColumn col1 = new TableColumn(myTable, SWT.NULL); col1.setText("First Column"); col1.pack();  TableColumn col2 = new TableColumn(myTable, SWT.NULL); col2.setText("Second Column"); col2.pack(); TableItem tableItem1 = new TableItem(myTable, SWT.NULL); tableItem1.setText(new String[] {"A1", "A2"}); TableItem tableItem2 = new TableItem(myTable, SWT.NULL); tableItem2.setText(new String[] {"B1", "B2"}); myShell.open(); while (!myShell.isDisposed()) { if (!myDisplay.readAndDispatch()) myDisplay.sleep();

Page 22: Eclipse Plugin Development TUTORIAL

} myDisplay.dispose(); }}

6. Tree Widget

The tree widget is used to display data in a hierarchical manner. Typically tree has many tree items. For understanding purposes you can call tree item an "Tree Parent" if this item contains other items. Tree parent can contain other Tree Parents. or simply leaf nodes. A user navigates through a tree by expanding and collapsing items.

public class MyTree { public static void main(String[] args) { Display myDisplay = new Display(); Shell myShell = new Shell(myDisplay); myShell.setText("My Tree"); myShell.setBounds(120, 120, 220, 220); myShell.setLayout(new FillLayout()); final Tree tree = new Tree(myShell, SWT.SINGLE); for (int i = 1; i < 4; i++) { TreeItem parent1 = new TreeItem(tree, 0); parent1.setText("Paren1 - " + i); for (int j = 1; j < 4; j++) { TreeItem parent2 = new TreeItem(parent1,0); parent2.setText("Parent2 - " + j); for (int k = 1; k < 4; k++) { TreeItem child = new TreeItem(parent2, 0); child.setText("Child - " + k); } } } myShell.open(); while (!myShell.isDisposed()) { if (!myDisplay.readAndDispatch()) myDisplay.sleep(); } myDisplay.dispose(); }}

7. Menu Widget

The Menu widget is used to display user set of actions. Typical example of menu is the file menu on top of this browser window. Menu can further contain submenu’s and so on.

public class MyMenu { public static void main(String[] args) { Display myDisplay = new Display(); final Shell myShell = new Shell(myDisplay); myShell.setText("My Menu");     myShell.setBounds(110, 110, 210, 110); Menu myBar = new Menu(myShell, SWT.BAR); myShell.setMenuBar(myBar);

Page 23: Eclipse Plugin Development TUTORIAL

MenuItem fileMenuItem = new MenuItem(myBar, SWT.CASCADE); fileMenuItem.setText("&This is my Menu"); Menu subMenuItem = new Menu(myShell, SWT.DROP_DOWN); fileMenuItem.setMenu(subMenuItem); MenuItem selectMenuItem = new MenuItem( subMenuItem, SWT.NULL); selectMenuItem.setText("&Hello\tCtrl+S"); selectMenuItem.setAccelerator(SWT.CTRL + 'S'); selectMenuItem.addSelectionListener( new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { System.out.println("Hello Selected!"); } }); MenuItem thisIsSeperator = new MenuItem(subMenuItem, SWT.SEPARATOR); MenuItem exitMenuItem = new MenuItem(subMenuItem, SWT.NULL); exitMenuItem.setText("&Bye"); exitMenuItem.addSelectionListener(new SelectionAdapter(){ public void widgetSelected(SelectionEvent event) { myShell.dispose(); } }); myShell.open(); while (!myShell.isDisposed()) { if (!myDisplay.readAndDispatch()) myDisplay.sleep(); } myDisplay.dispose(); }}

8. Composite Widget

This is a very important widget since it is used to group together all other widgets. Composite widget can be used as a container for other widgets. We can use layout managers (Discussed next) for positioning and placement of other widgets inside composite widget.

public class MyComposite { public static void main(String[] args) { Display myDisplay = new Display(); Shell myShell = new Shell(myDisplay); myShell.setText("My Composite"); myShell.setBounds(120, 120, 220, 220); Composite composite = new Composite( myShell,SWT.BORDER); composite.setBounds(35, 35, 155, 127); final Button button = new Button(composite,SWT.PUSH); button.setBounds(30, 30, 110, 85); button.setText("ClickMe"); myShell.open(); while (!myShell.isDisposed()) { if (!myDisplay.readAndDispatch()) myDisplay.sleep(); } myDisplay.dispose();

Page 24: Eclipse Plugin Development TUTORIAL

}}SWT ECLIPSE PLUGIN DEVELOPMENT TUTORIAL (PAGE 3)

SWT Layout Managers

SWT defines many different types of layouts which are helpful in positioning and sizing of child widgets in a composite. In the following SWT Layout Tutorial Next we will discuss four type of layouts available in SWT.

1. Fill Layout

Fill layout is the simplest layout. It is used to layout widgets in a single row or column forcing them to be of same size.

public class MyFillLayout { Display myDisplay = new Display(); Shell myShell = new Shell(myDisplay);

public MyFillLayout() { FillLayout fillLayout = new FillLayout(SWT.VERTICAL); fillLayout.marginHeight = 5; fillLayout.marginWidth = 5;  fillLayout.spacing = 1;

myShell.setLayout(fillLayout);

Button button1 = new Button(myShell, SWT.PUSH); button1.setText("button1");

Button button2 = new Button(myShell, SWT.PUSH); button2.setText("button2");

Button button3 = new Button(myShell, SWT.PUSH); button3.setText("button3");

myShell.pack(); myShell.open();

while (!myShell.isDisposed()) { if (!myDisplay.readAndDispatch()) { myDisplay.sleep(); } }

myDisplay.dispose(); }

public static void main(String[] args) { new MyFillLayout(); }}

Page 25: Eclipse Plugin Development TUTORIAL

2. Row Layout

Row Layout provides more options as compared to fill layout, which provide more control Row Layout has a number of configuration fields which can be used to control placement of the widget. In addition, the height and width of each control in a RowLayout can be specified by setting a RowData object into the control using setLayoutData()

public class MyRowLayout { public static void main(String[] args) { Button myButton; Display myDisplay = new Display(); Shell myShell = new Shell(myDisplay); myShell.setText("MyRowLayout"); myShell.setBounds(120, 120, 420, 120); RowLayout myLayout = new RowLayout();  myShell.setLayout(myLayout); myLayout.spacing = 15; myLayout.marginTop = 15; myLayout.marginRight = 15; myLayout.marginLeft = 15; myLayout.marginBottom = 15; for (int i = 1; i <= 10; i++) { myButton = new Button(myShell, SWT.PUSH); myButton.setText("" + i); } myShell.open(); while (!myShell.isDisposed()) { if (!myDisplay.readAndDispatch()) myDisplay.sleep(); } myDisplay.dispose(); }}

3. Grid Layout

SWT Gridlayout is to arrange children in a grid of rows and columns, We have many options to control the sizing of each child widget.

public class MyGridLayout { public static void main(String[] args) { // Gridlayout swt image tutorial

Display myDisplay = new Display(); Shell myShell = new Shell(myDisplay); myShell.setText("My GridLayout"); myShell.setBounds(120, 120, 220, 120); GridLayout myLayout = new GridLayout(); myLayout.numColumns = 2; myShell.setLayout(myLayout);

Label myLabel = new Label(myShell, SWT.LEFT); myLabel.setText("Please enter your age and birthdate"); GridData gridData = new GridData();

Page 26: Eclipse Plugin Development TUTORIAL

gridData.horizontalSpan = 2; myLabel.setLayoutData(gridData);

myLabel = new Label(myShell, SWT.LEFT); myLabel.setText("Age:");

Text myText = new Text(myShell, SWT.SINGLE | SWT.BORDER); gridData = new GridData(); gridData.horizontalAlignment = GridData.FILL; gridData.grabExcessHorizontalSpace = true; myText.setLayoutData(gridData);

myLabel = new Label(myShell, SWT.LEFT);  myLabel.setText("BirthDate"); myText = new Text(myShell, SWT.SINGLE | SWT.BORDER); gridData = new GridData(); gridData.horizontalAlignment = GridData.FILL; gridData.grabExcessHorizontalSpace = true; myText.setLayoutData(gridData);

  myShell.open(); while (!myShell.isDisposed()) { if (!myDisplay.readAndDispatch()) myDisplay.sleep(); } myDisplay.dispose(); }}

4. Form Layout

Instances of this class control the position and size of the children of a composite control by using FormAttachments to optionally configure the left, top, right and bottom edges of each child. It is one of the most powerful layout managers.

public class MyFormLayout { public static void main(String[] args) {

Display myDisplay = new Display(); final Shell myShell = new Shell(myDisplay); myShell.setText("My FormLayout"); myShell.setBounds(120, 120, 240, 200); myShell.setLayout(new FormLayout()); Button myCancelButton = new Button(myShell, SWT.PUSH); myCancelButton.setText("This is Cancel Button"); FormData myFormData = new FormData(); myFormData.right = new FormAttachment(100,-10); myFormData.bottom = new FormAttachment(100,-10); myCancelButton.setLayoutData(myFormData); Button myOKButton = new Button(myShell, SWT.PUSH); myOKButton.setText("This is OK Button"); myFormData = new FormData(); myFormData.right = new FormAttachment(myCancelButton,-10); myFormData.bottom = new FormAttachment(100,-10); myOKButton.setLayoutData(myFormData); Text myTextBox = new Text(myShell, SWT.MULTI | SWT.BORDER);

Page 27: Eclipse Plugin Development TUTORIAL

myFormData = new FormData(); myFormData.top = new FormAttachment(0,10); myFormData.bottom = new FormAttachment( myCancelButton,-10); myFormData.left = new FormAttachment(0,10); myFormData.right = new FormAttachment(100,-10); myTextBox.setLayoutData(myFormData); myShell.open(); while (!myShell.isDisposed()) { if (!myDisplay.readAndDispatch()) myDisplay.sleep(); } myDisplay.dispose(); }}

ECLIPSE JFACE TUTORIAL

Working With JFace Viewers We have already seen SWT in action. It helps in rapid application development by providing ready made widgets like Tree, Table etc. However, there is a severe limitation in using these widgets directly. Let me explain it with an example. Consider the table example in SWT chapter. Following lines of code were used to populate Table with one row of data.

TableItem tableItem1 = new TableItem(myTable, SWT.NULL);tableItem1.setText(new String[] {"A1", "A2"});

You can see that we have used String Literals "A1" and "A2" respectively while creating a row in table. If you think from object oriented perspective it is a severe limitation. In object oriented world we talk in terms of Objects. In order to build above table we will have to get Strings out of those objects and then supply it to Table to form every single row. Isn’t there a way in which we can simply map objects to tables so that table can itself use those objects and populate itself? This is where JFace viewers step in to provide OO wrappers around their associated SWT widgets. JFace provides two types of Viewers, Text Viewers and List Viewers. First we will discuss about list viewers. List Viewers

JFace list viewers, such as TableViewer and TreeViewer, allow you to directly use your business objects (Employee, Customer, User, Business etc.) without. The trick is to provide adapters for things such as retrieving an item's name/label OR for retrieving an Tree parent's children (tree widget). So we will talk about these adaptors first before moving onto implementing Table/Tree Viewers. 1. Label Providers

A label provider maps an element of the viewer's model to an optional image and optional text string used to display the element in the viewer's control.

The two most frequently used label providers are ILabelProvider and ITableLabelProvider In order to display elements name and label we can use getImage and getText methods provided by ILabelProvider Similarly in case of ITableLabelProvider, in order to display label image and label text for any column in a table we can use getColumnImage and getColumnText. We can use setLabelProvider() method to attach/associate provider with the viewer. 2. Content Providers

Page 28: Eclipse Plugin Development TUTORIAL

A content provider is another common adapter type used in list viewers. This provider is used to feed the actual content to the viewer. Viewer then uses its internal logic to display these input elements with its internal controls.

The two most frequently used content providers are IStructuredContentProvider and ITreeContentProvider. These adapters provide convienient methods to retrive child elements for a given element. We can use setContentProvider() method to attach/associate provider with the viewer. A intial domain/business model of the application can be associated with the viewer with the help of setInput() method. 3. Viewer Sorters

A viewer sorter is a adapter which is called by viewer before the elements/contents are displayed to the user. We can use this provider to sort the elements which are provided by the content provider. We can use setSorter() method on the viewer to attach sorter.

4. Viewer Filters Providers

As the name suggests a viewer filter is used to filter out some of the elements from original list of elements provided by the content provider. For example: Original list of Employees consist of employees with two type of roles Admin, Non admin. We can use filters to display only admin role users. We can attach viewer filter by using the setFilter() method on the viwer itself. Table Viewers

The TableViewer class acts as a OO wrapper around the Table widget. Table Viewer is capable of displaying data in rows and cloumns with the help of adapters like label provider and content provider.

Table Viewer provides many useful APIs, Please refer to online Eclipse Platform API Specification

Following example creates a table viewer

public static void main(String[] args) { Display exampleDisplay = new Display(); Shell exampleShell = new Shell(exampleDisplay);   exampleShell.setBounds(120, 120, 345, 220); exampleShell.setLayout(new FillLayout());

final TableViewer myTableViewer = new TableViewer( exampleShell, SWT.SINGLE);

final Table myTable = myTableViewer.getTable();

String[] myColumns = new String[] { "Hello", "Bye"};

for (int i = 0; i < columnNames.length; i++) { TableColumn tableColumn = new TableColumn(myTable);       tableColumn.setText(myColumns[i]); }

myTableViewer.setLabelProvider( new ExampleLabelProvider());

Page 29: Eclipse Plugin Development TUTORIAL

myTableViewer.setContentProvider( new ArrayContentProvider());          myTableViewer.setInput(Example.getInput());

exampleShell.open();

while (!exampleShell.isDisposed()) { if (!exampleDisplay.readAndDispatch()) exampleDisplay.sleep(); }

exampleDisplay.dispose(); }

In Above listing we are creating table viewer Then we are creating two columns namely "Hello" and "Bye" The header of each column is set using setText() method. There after label provider and content providers are being attached with the viewer. Following listing shows how the label provider looks like

public class PersonTableLabelProvider extends LabelProvider implements ITableLabelProvider { public Image getColumnImage( Object element, int) { return null; }

public String getColumnText(Object element, int index) { Example ex = (Example) element; switch (index) { case 0 : return ex.hello; case 1 : return ex.bye; } }}

public class Example{String hello;

String bye;

Example(String hello, String bye){this.hello = hello;this.bye=bye;

}

public static Example[] getInput(){ return new Example[]{ new Example("FirstHello","FirstBye"),new

Example("SecondHello","SecondBye") };

Page 30: Eclipse Plugin Development TUTORIAL

}}

Tree Viewers

The treeViewer class acts as a OO wrapper around the Tree widget. Tree Viewer is capable of displaying data in hierarchical manner with the help of adapters like label provider and content provider.

Tree Viewer provides many useful APIs, Please refer to online Eclipse Platform API Specification

The following listing creates a tree viewer

public static void main(String[] args) { Display exampleDisplay = new Display(); Shell exampleShell = new Shell(exampleDisplay);

exampleShell.setBounds(120, 120, 220, 220); exampleShell.setLayout(new FillLayout());

final TreeViewer myTreeViewer = new TreeViewer(exampleShell, SWT.SINGLE);          myTreeViewer.setLabelProvider( new MyTreeLabelProvider());

myTreeViewer.setContentProvider( new MyTreeContentProvider());

myTreeViewer.setInput(Example1.getInput());

exampleShell.open();

while (!exampleShell.isDisposed()) {  if (!exampleDisplay.readAndDispatch()) exampleDisplay.sleep(); } exampleDisplay.dispose(); }

In above code listing we are creating the tree viewer. There after we are configuring label and content adapters. Following listing shows the rest of code:

public class MyTreeContentProvider extends ArrayContentProvider implements ITreeContentProvider {

public Object[] getChildren(Object parent) { Example1 ex1 = (Example1) parent; return ex1.children; }

Page 31: Eclipse Plugin Development TUTORIAL

public Object getParent(Object element) { Example1 ex1 = (Example1) element; return ex1.parent; }

public boolean hasChildren(Object element) { Example1 ex1 = (Example1) element; return ex1.children.length > 0; }}

public class MyTreeLabelProvider extends LabelProvider { public Image getImage(Object element) { return null; } public String getText(Object element) { Example1 ex1 = (Example1) element; return ex1.name; }}

public class Example1{String name;

Example1[] children = new Example1[0];

Example1 parent = null;

Example1(String name){this.name = name;

}

Example1(String name,Example1[] children){this.name = name;this.children = children;for (int i = 0; i < children.length; i++) { children[i].parent = this;

}}

public static Example1[] getInput(){ return new Example1[]{ new Example1("First",new Example1[] {new Example1("Child1"), new

Example1("Child2")}), new Example1("Second",new Example1[]{ new Example1("Child3"),new

Example1("Child4")} ) };}

}

Page 32: Eclipse Plugin Development TUTORIAL

ECLIPSE PERSPECTIVE TUTORIAL

As most of you who are Eclipse users will know, you can easily organize your views around in each perspective to make yourself comfortable with development related tasks. As an Eclipse user the first thing you do when you launch eclipse application is to select a perspective which is most suitable for the job in hand. In this chapter we will create a new perspective which will open up Resource manager view when selected. Since our plug-in is very small with only one view, creating a perspective for the purpose of opening up single view might look overburden. However, in real world Plug-in applications Views can grow real big in terms of number, so creating a perspective and managing views become almost a necessity.

What is a Perspective?

A perspective is useful in organizing various eclipse views around the editor area, these are also helpful in managing menus and toolbars We can save perspectives and these can be switched to in future. As an eclipse plugin developer we can either create a new perspective from scratch or enhance existing perspective. Enhancing existing perspective essentially means to accommodate your view in an existing perspective for example: we can add our resource manager view to existing Resource perspective, so that it opens up when ever user selects resource perspective.

Eclipse comes with many inbuilt perspectives (Some of them are listed below):

Resource - This perspective shows various workspace resources irrespective of file extension.

Java/Java Browsing - This is useful for Java development

Debug - This is useful for debugging Java Applications.

Plug-in Development - This is useful while developing Eclipse Plugin Applications

Following figure shows how Java Browsing perspective looks like. Notice how different views Projects view, Packages view etc. are organized in screen below. So the whole purpose of creating perspective can be to organize your screens according to ease of use.

Page 33: Eclipse Plugin Development TUTORIAL

Figure 4-1

Creating a Perspective

We can create a new perspective by extending the org.eclipse.ui.perspectives extension point.

Perspective extension point

In order to create perspective, open the Resource Manager’s Eclipse plugin manifest editor, Now select the Extensions tab. In Extensions tab click the Add button. Now select org.eclipse.ui.perspectives from the list in the New Extension wizard. Click the Finish button.

Page 34: Eclipse Plugin Development TUTORIAL

Figure 4-2

Again go to the Extensions page in the plug-in manifest editor, open mouse right click context menu on the org.eclipse.ui.perspectives extension followed by selecting New > perspective. This will add a new perspective called “com.myplugin.rmp.perspective1”. Modify properties on right side as shown in the figure below.

Page 35: Eclipse Plugin Development TUTORIAL

Figure 4-3

Perspective factories

Now we will create perspective factory which will be used to define the layout of our newly created perspective Click on the "class" link on the right side of the class property and use Java Attribute Editor to create a new class.

Page 36: Eclipse Plugin Development TUTORIAL

Figure 4-4

Open the ResourceManagerPerspectiveFactory class and modify it as follows so that the Resource Manager view will appear below the editor area and the standard Outline view will be shown to its left.

package com.myplugin.rmp;import org.eclipse.ui.IPerspectiveFactory;import org.eclipse.ui.IPageLayout;import org.eclipse.ui.IFolderLayout;

public class ResourceManagerPerspectiveFactory implements IPerspectiveFactory {

private static final String VIEW_ID = "com.myplugin.rmp.views.ResourceManagerView";

Page 37: Eclipse Plugin Development TUTORIAL

private static final String BOTTOM = "bottom";

public void createInitialLayout(IPageLayout myLayout) {

myLayout.addView(IPageLayout.ID_OUTLINE,IPageLayout.LEFT,0.30f,

myLayout.getEditorArea());

IFolderLayout bot = myLayout.createFolder(BOTTOM,IPageLayout.BOTTOM,0.76f,

myLayout.getEditorArea()); bot.addView(VIEW_ID);

} }

Lets test the new Perspective

Open Manifest editor if not already open. Select Overview tab > Launch an eclipse application. It will launch separate eclipse application.Open our new perspective from Window > Open Perspective > Other (as shown below)

Figure 4-5

This will open up Select Perspective dialog (as shown below)

Page 38: Eclipse Plugin Development TUTORIAL

Figure 4-6

Select Resource Manager perspective and click ok button. This will switch the perspective to our newly created perspective as shown below

Page 39: Eclipse Plugin Development TUTORIAL

Figure 4-7

Enhancing an already existing Perspective

As discussed earlier, in addition to creating new perspective we can also use already existing perspectives and add our views to it. For example we may want to open Resource Manager view whenever Java Perspective or Resource Perspective is opened up. In this section we will discuss how to enhance an existing perspective such that it accommodates our view in its existing view arrangement.

First, open the Resource Manager’s plug-in manifest editor, Next, click on the Extensions tab followed by clicking the "Add" button. Now select org.eclipse.ui.perspectiveExtensions (as shown below) from the list extension points. Next, Click the Finish button

Page 40: Eclipse Plugin Development TUTORIAL

Figure 4-8

Next, again go to the Extensions page of manifest editor, Open right click context menu on the org.eclipse.ui.perspectiveExtensions. Select New > perspectiveExtension. This will add a perspective extension named “com.myplugin.rmp.perspectiveExtension1”. Modify Properties as shown in the figure below.

Page 41: Eclipse Plugin Development TUTORIAL

Figure 4-9

On the Extensions page, click on the org.eclipse.ui.resourcePerspective extension and select New > view. Modify Extension element details as shown in figure below.

Page 42: Eclipse Plugin Development TUTORIAL

Figure 4-10

Lets test the Resource Perspective

Open Manifest editor if not already open. Select Overview tab > Launch an eclipse application. It will launch separate eclipse application.

Open Resource Perspective and you will see that Resource Manager view is shown.

Page 43: Eclipse Plugin Development TUTORIAL

Figure 4-11

GETTING STARTED WITH ACTIONS

Actions

Action represent user actions such as “Run”, “Debug”, “Save to file”, “Search” or “Go to marker”. Actions are attached to buttons, tool/menu bars in an eclipse application. Actions run method is called whenever end user clicks on menu item or button. This chapter covers all this with examples that show how to use actions and action sets in the example Resource Manager plug-in. Following figure shows the many areas where a plug-in can contribute actions. It includes Context menu of a view or editor, to local toolbar and pull down menu of a view, to the main toolbar and menu bar of the workbench window. In course of this tutorial we will add actions to various places in workbench window. However, at this time some of these actions may not do anything useful other then displaying some pop up message or opening up resource manager view. During the course of this tutorial we will re-visit these actions to add more meaningful implementation.

Page 44: Eclipse Plugin Development TUTORIAL

Figure 5-1

Adding actions to Main Menu bar and Main Toolbar

Now we will add a menu to the main menu bar and a button to the main toolbar. Both of these open the Resource manager view when clicked by the user. Open the Resource Manager plug-in manifest editor, Next navigate to Extensions page followed by clicking on the "Add" button.

Select org.eclipse.ui.actionSets from the list an then Click on the Finish button.

Page 45: Eclipse Plugin Development TUTORIAL

Figure 5-2

Navigate back to the Extensions page. Open right click context menu on the org.eclipse.ui.actionSets item and select New > actionSet (See Image below).

Page 46: Eclipse Plugin Development TUTORIAL

Figure 5-3

Once new com.myplugin.rmp.actionSet1 is added, Select this action set and modify its properties as shown below.

Page 47: Eclipse Plugin Development TUTORIAL

Figure 5-4

Next, add a menu to the main menu bar by opening up the right click context menu on on the action set followed by selecting New > menu (As shown below)

Page 48: Eclipse Plugin Development TUTORIAL

Figure 5-5

Next, Select the menu and modify its properties as shown below. Notice the path attribute, we have specified its value as “additions”. For now don’t worry about this attribute, we will discuss it in section to follow.

Page 49: Eclipse Plugin Development TUTORIAL

Figure 5-6

Working With Groups

When working with menu’s we often define groups. So we will have menu’s - which will have groups and actions will be added to groups. So first some groups need to be defined. Two types of groups are available – Separator and groupMarker. A separator group displays a horizontal line. We will now create both of these groups. First we create a groupMarker by opening up right click context menu on Resource Manager menu and select New followed by groupMarker. Select the groupMarker and change its name to "content" Next define second group to the Resource Manager menu; by selecting New followed by separator and change its name to "additions".

Page 50: Eclipse Plugin Development TUTORIAL

Figure 5-7

We will use this groups when we create actions discussed next. Take a minute to look back at path attribute which we provided at the time of creating menu inside action set. We defined “additions” in the path attribute, this is nothing but a predefined group.

Next, we will define the action itself. Open right click context menu on the Resource Manager ActionSet and select New followed by action. Modify action properties as shown below:

Page 51: Eclipse Plugin Development TUTORIAL

Figure 5-8

Almost every attribute is self descriptive, However following attributes require special attention:

menubarPath: We have entered “com.myplugin.rmp.workbenchMenu/content” in this attribute. Notice that the first part is same as the id attribute of Resource Manager menu created earlier and the second part i.e. content is the name of the group created earlier. So this full statement means that we want to add this action to Resource Manager Menu under content group.

toolbarPath: We have entered "Normal/additions" to this attribute. The first part is the id of toolbar where we would like to add this action. Note that eclipse has only single toolbar and its id is “Normal”. Second part is again a predefined group in toolbar. So the complete statement specifies that we would like to add this action to Normal toolbar under additions group.

Working with action delegate

Action delegate is a class which implements the behavior associated with the action. All above steps have no meaning until we specify the behavior associated with the action. When we say behavior, it

Page 52: Eclipse Plugin Development TUTORIAL

essentially means what action will be triggered when user clicks on the menu item or toolbar button. Next, we will create a action delegate class.

Click on the "class" link on the left of the class Text Box.

Figure 5-9

Clicking the class label will open up the Java Attribute Editor for the action's class.In Package text box, provide "com.myplugin.rmp.actions" and "OpenResourceManagerViewActionDelegate" as Name. Click on the Finish button.

Page 53: Eclipse Plugin Development TUTORIAL

Figure 5-10

Modify the class as shown below:

package com.myplugin.rmp.actions;import org.eclipse.jface.action.IAction;import org.eclipse.jface.viewers.ISelection;import org.eclipse.ui.IWorkbenchPage;import org.eclipse.ui.IWorkbenchWindow;import org.eclipse.ui.IWorkbenchWindowActionDelegate;import org.eclipse.ui.PartInitException;

public class OpenResourceManagerViewActionDelegate implements

Page 54: Eclipse Plugin Development TUTORIAL

IWorkbenchWindowActionDelegate {

private IWorkbenchWindow window; public static final String ID = "com.myplugin.rmp.views.ResourceManagerView";

public void init(IWorkbenchWindow window) { this.window = window; // cache the window object in which action delegate is operating } public void dispose() {}

public void run(IAction action) {

IWorkbenchPage page = window.getActivePage();

try {

page.showView(ID); // use the Resource Manager View id to open up view.

} catch (PartInitException e) { } } public void selectionChanged(IAction action, ISelection selection) {}}

Testing the new action

launch the Runtime Workbench. You will see that action have been added to main menu bar and a push button has been added to main toolbar. Clicking on anyone of these will open up Resource Manager View.

Page 55: Eclipse Plugin Development TUTORIAL

Figure 5-11

GETTING STARTED WITH ACTIONS (PAGE 2)

Adding actions to View Toolbar

In this section we will add actions to out Resource Manager View. In order to add these actions, open the Resource Manager plug-in manifest editor, navigate to Extensions tab and click the "Add" button.

Select org.eclipse.ui.viewActions from the list. Click the Finish button to add this extension to the plug-in manifest.

Page 56: Eclipse Plugin Development TUTORIAL

Figure 5-12

Next, right click and add viewActions > New > viewContribution.

Page 57: Eclipse Plugin Development TUTORIAL

Figure 5-13

Next, modify the viewContribution attributes as shown below, Notice that the targetID attribute points to the ID of the view to which we are adding this action. In this example the target view is Resource Manager View.

Page 58: Eclipse Plugin Development TUTORIAL

Figure 5-14

Next, Right click on the ResourceManagerViewContribution > New > Action to create a new action which will be associated with the View toolbar. Provide action attributes as shown below.

Page 59: Eclipse Plugin Development TUTORIAL

Figure 5-15

Creating an action delegate

Action delegate is a class which implements the behavior associated with the action. Next, we will create a action delegate class.

Click on the class: label that appears to the left of the class field to create a new action delegate class. We will modify the class so that it opens up a pop up when action is clicked on the View tool bar.

package com.myplugin.rmp;import org.eclipse.jface.action.IAction;import org.eclipse.jface.viewers.ISelection;import org.eclipse.swt.SWT;import org.eclipse.swt.widgets.MessageBox;import org.eclipse.ui.IViewActionDelegate;import org.eclipse.ui.IViewPart;

Page 60: Eclipse Plugin Development TUTORIAL

public class ResourceManagerViewActionDelegate implements IViewActionDelegate { private IViewPart view;

public void init(IViewPart view) { this.view = view; }

public void run(IAction action) { MessageBox box = new MessageBox(view.getSite().getShell(),SWT.ICON_INFORMATION); box.setMessage("Hello! You clicked view action!"); box.open(); } public void selectionChanged(IAction action, ISelection selection) {}}

Testing the new action

Launch the Runtime Workbench. You will see a new push button has been added to Resource Manager View tool bar. It will open up a Message box when clicked (See Below).

Page 61: Eclipse Plugin Development TUTORIAL

Figure 5-16

Dialogs

Dialogs are almost always used in every application. Dialogs are used to either inform user or to take user input. In Eclipse dialogs can be broadly classified into two categories i.e. SWT dialogs and JFace Dialogs. We will discuss how to create dialogs in eclipse plugins starting with Introduction to SWT Dialogs.

SWT Dialogs

Page 62: Eclipse Plugin Development TUTORIAL

Figure 6-1

Dialog class is an abstract class from which you can derive concrete native dialogs. The SWT already contains some concrete subclasses of dialog, such as shown in table below:

Subclass Description

ColorDialog Dialog for selecting a color

DirectoryDialog Dialog for selecting a directory in host file system

FileDialogDialog for selecting a file in host file system. Supported styles are SWT.OPEN and SWT.SAVE

FontDialog Dialog for selecting text font

MessageBox

Dialog for displaying a message. Various style parameters govern which buttons will be displayed to the user For ex: SWT.OK, SWT.CLOSE etc. Icon to be displayed with the message can be governed by styles such as SWT.ICON_ERROR, SWT.ICON_QUESTION etc.

PrintDialog Dialog for selecting printer and for printer settings

JFace Dialogs

Page 63: Eclipse Plugin Development TUTORIAL

Figure 6-2

The package org.eclipse.jface.dialogs provides classes that implement standard Dialog. All these classes are subclasses of abstract class Dialog which itself is a subclass of abstract class Window. Following table describes some of the most commonly used subclasses of Jface Dialog.

Subclass Description

IconAndMessageDialogsuperclass of dialogs with an icon and a message.

SelectionDialog superclass for displaying a selection

StatusDialog superclass for dialogs with status bar

TitleAreaDialog dialog having a title area.

ErrorDialog A dialog to display errors

MessageDialog dialog class for showing messages to the user.

ListDialogA dialog which prompts for one element out of a list.

ProgressMonitorDialogA modal dialog to display progress of a operation.

WizardDialog A dialog to show a wizard to the end user.

InputDialogA simple input dialog for getting an input from the user.

Page 64: Eclipse Plugin Development TUTORIAL

Lets try out a simple dialog example

We will modify ResourceManagerViewActionDelegate to try out some dialogs. Here is new code listing.

package com.myplugin.rmp;

import org.eclipse.core.runtime.IStatus;import org.eclipse.jface.action.IAction;import org.eclipse.jface.dialogs.InputDialog;import org.eclipse.jface.viewers.ISelection;import org.eclipse.swt.SWT;import org.eclipse.swt.widgets.MessageBox;import org.eclipse.ui.IViewActionDelegate;import org.eclipse.ui.IViewPart;

public class ResourceManagerViewActionDelegate implements IViewActionDelegate { private IViewPart view;

public void init(IViewPart view) { this.view = view; // cache the view part, this will be used in run action // to fetch the parent shell for dialog }

public void run(IAction action) { InputDialog dialog = new InputDialog(view.getSite().getShell(),"Lets try!", "Please enter your name","",null); // new input dialog if( dialog.open()== IStatus.OK){ // open dialog and wait for return status code. // If user clicks ok display message box String value = dialog.getValue(); // fetch the value entered by the user. MessageBox box = new MessageBox(view.getSite().getShell(),SWT.ICON_INFORMATION); box.setMessage("Hey there! You entered : " + value); box.open(); }else{ MessageBox box = new MessageBox(view.getSite().getShell(),SWT.ICON_INFORMATION); box.setMessage("Bye!"); box.open(); } }

public void selectionChanged(IAction action, ISelection selection) {}}

Page 65: Eclipse Plugin Development TUTORIAL

Wizards 

If you use Eclipse IDE for java development then you must have used Wizards extensively for example, while creating Java class or while new Projects etc.

Wizards are helpful in performing repetitive tasks for ex: New Java Class wizard takes information from user and create java class template. Depending upon user input it is also generate main method, abstract methods from super class etc.

JFace has two interface's org.eclipse.jface.wizard.IWizard and org.eclipse.jface.wizard.IWizardPage which are useful in creating wizards. So each wizard consists of one or more pages. In order to take huge data as input we can divide the input data into logical sets and display each such set on every page of the wizard. For example: We want to take employee information, On first page we can take personal information such as first name, last name, age etc. On second page we can gather address information and so on. In order to make things simple for us JFace also provides corresponding abstract classes which we will use in our examples. First we will see how to construct an wizard and thereafter we will move on to understand how we can open up wizards.

Creating Wizard Pages

Open Resource Manager plugin project and create a new java class as described in steps below:

1. Create new package in project name it com.myplugin.rmp.wizards

2. Create a new Wizard Page (PersonalInformationPage) by creating java class as shown in figure below

Page 66: Eclipse Plugin Development TUTORIAL

Figure 6-3

3. Modify the above generated class as shown below:

package com.myplugin.rmp.wizards;import org.eclipse.jface.wizard.WizardPage;import org.eclipse.swt.SWT;import org.eclipse.swt.layout.GridData;import org.eclipse.swt.layout.GridLayout;import org.eclipse.swt.widgets.Composite;import org.eclipse.swt.widgets.Label;import org.eclipse.swt.widgets.Text;public class PersonalInformationPage extends WizardPage { Text firstNameText; Text secondNameText;

Page 67: Eclipse Plugin Development TUTORIAL

protected PersonalInformationPage(String pageName) { super(pageName); setTitle("Personal Information"); setDescription("Please enter your personal information"); } public void createControl(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.numColumns = 2; composite.setLayout(layout); setControl(composite); new Label(composite,SWT.NONE).setText("First Name"); firstNameText = new Text(composite,SWT.NONE); new Label(composite,SWT.NONE).setText("Last Name"); secondNameText = new Text(composite,SWT.NONE); }}

4. Create another Wizard page (AddressInformationPage) class and modify it as follows:

package com.myplugin.rmp.wizards;import org.eclipse.jface.wizard.WizardPage;import org.eclipse.swt.SWT;import org.eclipse.swt.layout.GridLayout;import org.eclipse.swt.widgets.Composite;import org.eclipse.swt.widgets.Label;import org.eclipse.swt.widgets.Text;

public class AddressInformationPage extends WizardPage { Text street; Text city; Text State;

protected AddressInformationPage(String pageName) { super(pageName); setTitle("Address Information"); setDescription("Please enter your address information"); } public void createControl(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout();  layout.numColumns = 2; composite.setLayout(layout); setControl(composite); new Label(composite,SWT.NONE).setText("Street"); street = new Text(composite,SWT.NONE); new Label(composite,SWT.NONE).setText("City");

Page 68: Eclipse Plugin Development TUTORIAL

city = new Text(composite,SWT.NONE); new Label(composite,SWT.NONE).setText("State"); state = new Text(composite,SWT.NONE); }}

5. Create a new Wizard name it CaptureEmployeeInfomrationWizard as shown below:

Figure 6-4

6. Modify the above created class as shown below:

package com.myplugin.rmp.wizards;import org.eclipse.jface.wizard.Wizard;public class CaptureEmployeeInfomrationWizard extends Wizard {

Page 69: Eclipse Plugin Development TUTORIAL

PersonalInformationPage personalInfoPage; AddressInformationPage addressInfoPage;

public void addPages() { personalInfoPage = new PersonalInformationPage("Personal Information Page"); addPage(personalInfoPage); addressInfoPage = new AddressInformationPage("Address Information"); addPage(addressInfoPage); } public boolean performFinish() { return false; }}

Test newly created wizard

In order to test this wizard Modify run method of com.myplugin.rmp.ResourceManagerViewActionDelegate created in earlier chapter to open up the wizard when user clicks on View tool bar action

public void run(IAction action) { CaptureEmployeeInfomrationWizard wizard = new CaptureEmployeeInfomrationWizard(); WizardDialog dialog = new WizardDialog(view.getSite().getShell(), wizard); dialog.create(); dialog.open();}

From Overview tab of Manifest editor - launch eclipse to test your changes. Open Resource Manager Perspective and click on toolbar action to open up wizard (See image below).

Page 70: Eclipse Plugin Development TUTORIAL

Figure 6-5

ECLIPSE VIEWS

Working with Views

In eclipse the entire workbench contains one or more workbench windows. Each workbench window may further contain one or more workbench pages and each page may contain one or more editor or views. An editor is typically used to edit/modify a workspace resource whereas Views are arranged around editors and provide assistance to editors in some way (though this is not always true). Views are used to display hierarchy of information, open up an editor or display properties for an active editor. Classic example of view is Package explorer and outline view. Package explorer is used to display workspace resources in a hierarchy and is used to open up associated editor whenever user performs double click action on the resource. Outline view is used to display information about the java resource for ex: package declaration, imports etc. (See figure below)

Page 71: Eclipse Plugin Development TUTORIAL

One of the key difference between editors and view is that editors are resource based i.e. they work on underlying resources in workspace. For ex: XML editor requires “.xml” file in workspace. Whereas, views may not be resource based. They can be used to show any kind of information. It is also important that we can make views which may display information irrespective of resources opened up in editor window (that’s why I said its not always true that view plays role of assistant window around editor area).

Resource Manager View

Page 72: Eclipse Plugin Development TUTORIAL

In first chapter of this tutorial we created a Resource Manager view as part of plug-in creation. We have been playing around with our resource manager view for quite some time for ex: we added this view to our own customized perspective, added actions to Resource Manager view. However, Resource Manager view itself does not do anything useful – every time it is opened it just displays static model as shown below:

Let’s Manage Workspace Property Files

In this chapter, we will create Property File Manager View so that it does something useful and more meaningful rather then just displaying static data.

Property File Manager View will search the entire workspace for all the projects. In each project it will search for "Property Files" folder, In each such folder it will look out for all the files with ".properties" extension and display it to the user. This way we will end up with a view as shown in the figure below. Please note that a property file gets displayed in the Property File Manager view only when it is created inside Property Files folder.

Page 73: Eclipse Plugin Development TUTORIAL

Property File Manager View

In order to create a new view, open up manifest editor – click on extensions tab. Right click on “org.eclipse.ui.views” extension and click on new > view (See figure below)

It will immediately open up Extension element details page. Edit the element details as shown below

Page 74: Eclipse Plugin Development TUTORIAL

In order to create “com.myplugin.rmp.views.PropertyManagerView” class click on the class link to open up Java attribute editor as shown below:

Page 75: Eclipse Plugin Development TUTORIAL

Click finish to generate the Property Manager View class.

Complete Listing of the Property Manager View Class

What follows is the complete listing of Property Manager View class. However, before we move ahead to show this listing we will need to add two dependencies (if not already added) in the plug-in manifest editor.

First dependency (org.eclipse.core.resources) is required since property manager needs to access workspace resources.

Second dependency (org.eclipse.ui.ide) is required since we will open up associated editor whenever user clicks on listed property files in property manager view.

Page 76: Eclipse Plugin Development TUTORIAL

In order to add the dependencies, open up manifest editor – click on dependencies tab and add above two dependencies as shown in fig below:

Once the dependencies have been added following code listing will compile successfully.

1. package com.myplugin.rmp.views;2. import java.util.ArrayList;3. import org.eclipse.core.resources.IFile;4. import org.eclipse.core.resources.IFolder;5. import org.eclipse.core.resources.IProject;6. import org.eclipse.core.resources.IResource;7. import org.eclipse.core.resources.IWorkspace;8. import org.eclipse.core.resources.ResourcesPlugin;9. import org.eclipse.core.runtime.IAdaptable;10. import org.eclipse.jface.action.Action;11. import org.eclipse.jface.action.MenuManager;12. import org.eclipse.jface.dialogs.MessageDialog;

Page 77: Eclipse Plugin Development TUTORIAL

13. import org.eclipse.jface.viewers.DoubleClickEvent;14. import org.eclipse.jface.viewers.IDoubleClickListener;15. import org.eclipse.jface.viewers.ISelection;16. import org.eclipse.jface.viewers.IStructuredContentProvider;17. import org.eclipse.jface.viewers.IStructuredSelection;18. import org.eclipse.jface.viewers.ITreeContentProvider;19. import org.eclipse.jface.viewers.LabelProvider;20. import org.eclipse.jface.viewers.TreeViewer;21. import org.eclipse.jface.viewers.Viewer;22. import org.eclipse.swt.SWT;23. import org.eclipse.swt.graphics.Image;24. import org.eclipse.swt.widgets.Composite;25. import org.eclipse.swt.widgets.Menu;26. import org.eclipse.ui.ISharedImages;27. import org.eclipse.ui.IWorkbenchPage;28. import org.eclipse.ui.PlatformUI;29. import org.eclipse.ui.ide.IDE;30. import org.eclipse.ui.part.ViewPart;

31. public class PropertyManagerView extends ViewPart {32. private TreeViewer viewer;33. private TreeParent invisibleRoot;

34. class TreeObject implements IAdaptable {

35. private String name;36. private TreeParent parent;37. private IResource resouce;

38. public TreeObject(String name) {39. this.name = name;40. }

41. public String getName() {42. return name;43. }

44. public void setParent(TreeParent parent) {45. this.parent = parent;46. }

47. public TreeParent getParent() {48. return parent;49. }

50. public String toString() {51. return getName();52. }

53. public Object getAdapter(Class key) {54. return null;55. }56. protected IResource getResouce() {57. return resouce;

Page 78: Eclipse Plugin Development TUTORIAL

58. }59. protected void setResouce(IResource resouce) {60. this.resouce = resouce;61. }62. }63. class TreeParent extends TreeObject {64. private ArrayList children;65. public TreeParent(String name) {66. super(name);67. children = new ArrayList();68. }

69. public void addChild(TreeObject child) {70. children.add(child);71. child.setParent(this);72. }

73. public void removeChild(TreeObject child) {74. children.remove(child);75. child.setParent(null);76. }

77. public TreeObject[] getChildren() {78. return (TreeObject[]) children.toArray(new TreeObject[children.size()]);79. }

80. public boolean hasChildren() {81. return children.size() > 0;82. }

83. }84. class ViewContentProvider implements ITreeContentProvider {

85. public void inputChanged(Viewer v, Object oldInput, Object newInput) {86. }

87. public void dispose() {88. }

89. public Object[] getElements(Object parent) {90. if (parent.equals(getViewSite())) {91. if (invisibleRoot == null)92. initialize();

93. return getChildren(invisibleRoot);94. }

95. return getChildren(parent);96. }

97. public Object getParent(Object child) {98. if (child instanceof TreeObject) {99. return ((TreeObject) child).getParent();100. }

Page 79: Eclipse Plugin Development TUTORIAL

101. return null;102. }

103. public Object[] getChildren(Object parent) {

104. if (parent instanceof TreeParent) {105. return ((TreeParent) parent).getChildren();106. }

107. return new Object[0];108. }

109. public boolean hasChildren(Object parent) {110. if (parent instanceof TreeParent)111. return ((TreeParent) parent).hasChildren();112. return false;113. }

114. }

115. class ViewLabelProvider extends LabelProvider {116. public String getText(Object obj) {117. return obj.toString();118. }

119. public Image getImage(Object obj) {120. String imageKey = ISharedImages.IMG_OBJ_ELEMENT;

121. if (obj instanceof TreeParent)122. imageKey = ISharedImages.IMG_OBJ_FOLDER;123. return PlatformUI.getWorkbench().getSharedImages().getImage(imageKey);124. }

125. }

126. public void initialize() {127. TreeParent root = new TreeParent("WorkSpace Property Files");128. try {129. IWorkspace workspace = ResourcesPlugin.getWorkspace();

130. IProject[] projects = workspace.getRoot().getProjects();

131. for (int i = 0; i < projects.length; i++) {132. IResource[] folderResources = projects[i].members();

133. for (int j = 0; j < folderResources.length; j++) {

Page 80: Eclipse Plugin Development TUTORIAL

134. if (folderResources[j] instanceof IFolder) {135. IFolder resource = (IFolder) folderResources[j];136. if (resource.getName().equalsIgnoreCase("Property Files")) {137. IResource[] fileResources = resource.members();138. for (int k = 0; k < fileResources.length; k++) {139. if (fileResources[k] instanceof IFile && fileResources[k].getName().endsWith(".properties")){140. TreeObject obj = new TreeObject(fileResources[k]

.getName());141. obj.setResouce(fileResources[k]);142. root.addChild(obj);143. }144. }145. }146. }147. }148. }149. }catch (Exception e) { // log exception150. }151. invisibleRoot = new TreeParent("");152. invisibleRoot.addChild(root);153. }

154. public PropertyManagerView() {155. }

156. public void createPartControl(Composite parent) {157. viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);158. viewer.setContentProvider(new ViewContentProvider());159. viewer.setLabelProvider(new ViewLabelProvider());160. viewer.setInput(getViewSite());161. hookContextMenu();162. hookDoubleCLickAction();163. }

164. private void hookDoubleCLickAction() {165. viewer.addDoubleClickListener(new IDoubleClickListener() {166. public void doubleClick(DoubleClickEvent event) {167. ISelection selection = event.getSelection();168. Object obj = ((IStructuredSelection) selection).getFirstElement();

Page 81: Eclipse Plugin Development TUTORIAL

169. if (!(obj instanceof TreeObject)) {170. return;171. }else {172. TreeObject tempObj = (TreeObject) obj;173. IFile ifile = ResourcesPlugin.getWorkspace().getRoot().

getFile(tempObj.getResouce().getFullPath());174. IWorkbenchPage dpage = PropertyManagerView.this.getViewSite()

.getWorkbenchWindow().getActivePage();175. if (dpage != null) {176. try {177. IDE.openEditor(dpage, ifile,true);178. }catch (Exception e) {179. // log exception180. }181. }182. }183. };184. });185. }

186. private void hookContextMenu() {187. MenuManager menuMgr = new MenuManager("#PopupMenu");188. Menu menu = menuMgr.createContextMenu(viewer.getControl());189. viewer.getControl().setMenu(menu);190. Action refresh =new Action() {191. public void run() {192. initialize();193. viewer.refresh();194. }195. };196. refresh.setText("Refresh");197. menuMgr.add(refresh);198. } 199. public void setFocus() {200. viewer.getControl().setFocus();201. }202. }

GETTING STARTED WITH VIEWS (PAGE 2)

You might face issues understanding above code if you have not gone through JFace Viewers chapter. I would briefly discuss main points of complete listing below – for detailed information on SWT/JFace viewers please read respective chapters.

Lines 32 - 125: Nothing special here - Most of the SWT/JFace concepts have been put to practice.

Page 82: Eclipse Plugin Development TUTORIAL

TreeObject and TreeParent represents the model objects for our TreeViewer class. We have used TreeViewer class here because we need to show property files under “WorkSpace Property Files” folder, so it is more like tree rather then a table.

TreeParent represent Folders whereas TreeObject represent Files in specific folder. These two classes are essentially wrappers/adapters over the IResource objects. In our example we will use TreeParent to represent “WorkSpace Property Files” folder and TreeObject to represent various property files.

ViewContentProvider: A content provider is another common adapter type used in viewers. This provider is used to map a domain model object used as the input to the viewer and the internal structure needed by the viewer itself. We have implemented ITreeContentProvider interface. This interface adds support for retrieving an item's parent or children within a tree. Special attention is required for the method.

89. public Object[] getElements(Object parent) {90. if (parent.equals(getViewSite())) {91. if (invisibleRoot == null)92. initialize();

93. return getChildren(invisibleRoot);94. }

95. return getChildren(parent);96. }

getElements method is defined in the interface IStructuredContentProvider as shown below

This method returns the elements to display in the viewer. This method is called internally by the viewer and reference to the parent object is passed as an argument. In line 90, we are comparing parent with the ViewSite returned by getViewSite() method. Views are contained in a view site (org.eclipse.ui.IViewSite) and ViewSite is in turn contained in a workbench page (org.eclipse.ui.IWorkbenchPage). Basically at this time we want to know whether the elements are demanded by View itself or TreeParent object(folder). If it is demanded by View itself then we will initialize our model object and return it to viewer. ViewLabelProvider: This provider is used to map a domain model object into one or more images and text strings displayable in the viewer's widget. We will use this provider to display names of property files as well as folder. Also, we have used this provider to display images in the view.

Line 126: Initialize method is used to initialize our domain model.

Page 83: Eclipse Plugin Development TUTORIAL

Line 127: We have created TreeParent to represent “WorkSpace Property Files” folder which will act as a parent folder for all property files in workspace.

Line 129: he handle of workspace through Resources plug-in. Resource plugin is used for any workspace/resource modifications problems.

Line 130: workspace.getRoot() returns the root resource of this workspace. It is basically container of all projects in the workspace. IWorkspaceRoot.getProjects() returns the collection of projects which exist under this root. The projects can be open or closed.

126. public void initialize() {127. TreeParent root = new TreeParent("WorkSpace Property Files");128. try {129. IWorkspace workspace = ResourcesPlugin.getWorkspace();

130. IProject[] projects = workspace.getRoot().getProjects();

131. for (int i = 0; i < projects.length; i++) {132. IResource[] folderResources = projects[i].members();

133. for (int j = 0; j < folderResources.length; j++) {

134. if (folderResources[j] instanceof IFolder) {135. IFolder resource = (IFolder) folderResources[j];136. if (resource.getName().equalsIgnoreCase("Property Files")) {137. IResource[] fileResources = resource.members();138. for (int k = 0; k < fileResources.length; k++) {139. if (fileResources[k] instanceof IFile && fileResources[k].getName().endsWith(".properties")) {140. TreeObject obj = new TreeObject(fileResources[k]

.getName());141. obj.setResouce(fileResources[k]);142. root.addChild(obj);143. }144. }145. }146. }147. }148. }149. }catch (Exception e) {

Page 84: Eclipse Plugin Development TUTORIAL

// log exception150. }151. invisibleRoot = new TreeParent("");152. invisibleRoot.addChild(root);153. }

Line 131 – 151: Here we are iterating over projects in a workspace. For each project we are looking for folder named “Property Files”. In this folder we are looking for files with extension “.properties” and if they exist we create our domain model TreeObject and add this object to TreeParent created above by using root.addChild(obj) method. Following figure shows the hierarchy of IResource interface. For complete API listing refer Eclipse Platform Documentation.

Lines 151 - 152. Basically we have created an invisible node (TreeParent) which will act as a root node of tree but it will not be visible to user. This node will also act as a parent node for all the folders in the tree. We are adding root node which represents “Workspace Property Files” folder as child to invisible node.

Lines 156 – 163: we are overriding createPartControl (Composite) method defined in WorkbenchPart Class. This method is responsible for creating SWT/Jface components for our properties view. In this method we are creating TreeViewer and providing content , label providers to the viewer. For more information on this refer to Jface viewer chapter. Viewer.setInput method is used to provide the initial input to the viewer. We have used getViewSite method to get site reference which is passed to viewer as initial input. That is the reason that we are checking for parent.equals(viewsite) at line 90. We could have very well used invisibleroot in setinput method instead. Point is that our domain model gets to meet viewer control with the help of setInput method.

156. public void createPartControl(Composite parent) {157. viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);158. viewer.setContentProvider(new ViewContentProvider());159. viewer.setLabelProvider(new ViewLabelProvider());160. viewer.setInput(getViewSite());161. hookContextMenu();162. hookDoubleCLickAction();

Page 85: Eclipse Plugin Development TUTORIAL

163. }

Next we have called to methods to provide context menu and doubleclick action to our property view.

Lines 164 – 185: Here we are using viewer.addDoubleClickListener method to provide doubleclickListener. On line 167, we are using event object to retrieve current selection. IStructuredSelection represent multiple selected elements. It is possible that user has selected more then one element in the view.

164. private void hookDoubleCLickAction() {165. viewer.addDoubleClickListener(new IDoubleClickListener() {166. public void doubleClick(DoubleClickEvent event) {167. ISelection selection = event.getSelection();168. Object obj = ((IStructuredSelection) selection)

.getFirstElement();169. if (!(obj instanceof TreeObject)) {170. return;171. }else {172. TreeObject tempObj = (TreeObject) obj;173. IFile ifile = ResourcesPlugin.getWorkspace().getRoot()

.getFile(tempObj.getResouce().getFullPath());174. IWorkbenchPage dpage = PropertyManagerView.this.getViewSite()

.getWorkbenchWindow().getActivePage();175. if (dpage != null) {176. try {177. IDE.openEditor(dpage, ifile,true);178. }catch (Exception e) {179. // log exception

Page 86: Eclipse Plugin Development TUTORIAL

180. }181. }182. }183. };184. });185. }

On line 168, we are retrieving first element from the structured selection. Next we are checking if current selection is a property file by comparing it to TreeObject. Remember that TreeObject is our domain model which we have created in the initialize method and it represents the property file. Next we are retrieving Ifile handle with the help of TreeObject. Remember TreeObject saves the instance of corresponding Resource Object. On line 177, we are opening up the editor with the help of IDE.openEditor method.

public static IEditorPart openEditor(IWorkbenchPage page, IFile input,boolean activate) throws PartInitException

The above method opens the editor for the given file resource. This method will attempt to resolve the editor based on content-type bindings as well as traditional name/extension bindings. * If the page already has an editor open on the target object then that editor is brought to front; otherwise, a new editor is opened. If activate == true the editor will be activated.

Lines 186 – 198 : Nothing special here, your knowledge about actions have been put to practice here. Essentially we have created new action which will perform viewer.refresh() – This will refresh the tree starting from invisible node. We can also use public void refresh (final Object element) to perform refresh action on a particular folder by passing TreeParent object.

186. private void hookContextMenu() {187. MenuManager menuMgr = new MenuManager("#PopupMenu");188. Menu menu = menuMgr.createContextMenu(viewer.getControl());189. viewer.getControl().setMenu(menu);190. Action refresh =new Action() {191. public void run() {192. initialize();193. viewer.refresh();194. }195. };196. refresh.setText("Refresh");197. menuMgr.add(refresh);198. }

Lines 199 – 201: We have overridden setFocus method defined in WorkbechPart class. This method asks view to take focus within the workbench.

199. public void setFocus() {200. viewer.getControl().setFocus();201. }

Lets Test Properties View

Testing the modifications you have just made involves launching the Runtime Workbench. Open up Property Manager View (Window > ShowView > Other)

Page 87: Eclipse Plugin Development TUTORIAL

It will open up Property Manager View as shown below.

Page 88: Eclipse Plugin Development TUTORIAL

Next, create a new project as shown below

Page 89: Eclipse Plugin Development TUTORIAL

Click Next, Name it Testing and click finish

Page 90: Eclipse Plugin Development TUTORIAL

Now create a new Folder inside the project

Page 91: Eclipse Plugin Development TUTORIAL

Make sure that you name this folder “Property Files”

Page 92: Eclipse Plugin Development TUTORIAL

Next, create some property files inside the Property Files Folder

Page 93: Eclipse Plugin Development TUTORIAL

Make sure that you provide right extension for these files:

Page 94: Eclipse Plugin Development TUTORIAL

Once you have created a property file, Right click on WorkSpace Property Files Folder in the property manager view and click refresh.

Page 95: Eclipse Plugin Development TUTORIAL

You will notice that newly created file(s) is listed in property view as shown in figure below.

Page 96: Eclipse Plugin Development TUTORIAL

ECLIPSE TRACKING CHANGES

How to Track resource changes

In Last chapter (Views) we created a property manager view. Whenever user click refresh action, this view searches for all the property files in the workspace and displays it to the user. Wouldn’t it be cool if this view can refresh automatically whenever a property file is added to workspace? If you answer yes, then you are at right place.

Page 97: Eclipse Plugin Development TUTORIAL

Eclipse provides IResourceChangeListener to keep track of resource changes in the workspace. Eclipse generates resource change events indicating that the files and folders that have been added, modified, and removed from the workspace. Interested parties can subscribe to these events and take necessary action. The interface org.eclipse.core.resources.IResourceChangeListener defines single method:public void resourceChanged (IResourceChangeEvent event). In this chapter we will modify PropertyManagerView so as to implement IResourceChangeListener and use IResourceChangeEvent to update itself. Before we move on it is important to understand IResourceChangeEvent.

Note about IResourceChangeEvent

According to Eclipse API Specification there are currently five different types of resource change events:

PRE_BUILD POST_BUILD

POST_CHANGE

PRE_CLOSE

PRE_DELETE

Please refer to online Eclipse API Specification to know more about these events.

Note about IResourceDelta

A resource delta represents changes in the state of a resource tree between two discrete points in time OR we can say it is through delta object that we come to know about the changes taking place in workspace. Whenever resource modification is performed by the user delta of modification is prepared by eclipse and interested parties can use this delta to update themselves. This interface declares many constants describing the kind of change.

Please refer to online Eclipse API Specification to know about methods provided by IResourceDelta.

Let’s Modify Property Manager View

Best way to learn above mentioned theory is to practice with concrete example. In this section we will take step by step approach to modify Property Manager View so that it can keep itself updated with resource modifications in workspace. Lets start by implementing IResourceChangeListener. Open com.myplugin.rmp.views.PropertyManagerView in java editor and implement resource change listener as shown below.

public class PropertyManagerView extends ViewPart implements IResourceChangeListener

Next, register PropertyManagerView with Work Space so that this view is notified whenever work space modification event is generated.Modify createPartControl method as shown below:

public void createPartControl(Composite parent) { viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); viewer.setContentProvider(new ViewContentProvider()); viewer.setLabelProvider(new ViewLabelProvider());

Page 98: Eclipse Plugin Development TUTORIAL

viewer.setInput(getViewSite()); ResourcesPlugin.getWorkspace().addResourceChangeListener(this); hookContextMenu(); hookDoubleCLickAction(); }

Next, Override dispose method of view to remove Listener. Dispose method of View is called every time the View Part is destroyed.

public void dispose() { super.dispose(); ResourcesPlugin.getWorkspace().removeResourceChangeListener(this); }

Next, Override resourceChanged method from IResourceChangeListener as shown below:

1. public void resourceChanged(IResourceChangeEvent event) {2.   try{3. if(event.getType() == IResourceChangeEvent.POST_CHANGE){4. event.getDelta().accept(new IResourceDeltaVisitor(){5. public boolean visit(IResourceDelta delta) throws CoreException {6. if(delta.getResource().getName().endsWith(".properties")){7. initialize();8. Display.getDefault().asyncExec(new Runnable() {9. public void run() {10. viewer.refresh();11. viewer.expandAll();13. }14 });15. }16. return true;17. }18. });19. }20. }catch(CoreException e){21. // log it22. e.printStackTrace();23. }24.  }

Line 3: We are only interested in Post change events. So here we are checking the event type. If the event is a POST_CHANGE event then we proceed ahead.

Line 4: getDelta() method in IResourceChangeEvent returns the delta i.e. information about the

Page 99: Eclipse Plugin Development TUTORIAL

modifications which triggered this event.

Line 5: IResourceDeltaVisitor is an object that visits (visitor pattern) resource deltas. It visits resource deltas that are ADDED, CHANGED, or REMOVED. In case visitor returns true - the resource delta's children are also visited.

Line 6: Here we are retrieving the resource which has been modified and checking if it is a .properties file.

Line 7: If the modified resource is a .properties file then we are initializing our model object again.

Line 8 – 13: Next we want to refresh viewer so that it updates itself and resource changes are visible in Property Manager View. The code Display.getDefault().asyncExec(new Runnable(){… makes sure that we don’t get illegal thread access exception. If we try to refresh viewer outside of this code (say immediately after initialize is called) then we will get illegal thread access exception. Reason? Basically the resourceChanged Method is called in a non UI thread and when we try to modify UI by calling viewer.refresh() in this non UI thread it throws exception. In order to overcome this problem we have redirected the execution to UI Thread by using Display object.

Let’s Test Property Manager View

Launch eclipse application from plug-in manifest editor. Open up Property manager View (Window > show view > other). Create property files in Project under folder (Property Files) and notice that Property manager View Refreshes on every addition/deletion of property file resource.

Page 100: Eclipse Plugin Development TUTORIAL

GETTING STARTED WITH PREFERENCE PAGES

Preference Pages

As an eclipse user you must have used preferences on many occasions. A Preference is a data which is persisted between workspace sessions. Preferences are used in Eclipse to take preferences from user on the fly rather then hard cording them in plug-in itself. In order to view preferences go to window > preferences. Following figure show how preferences dialog look like.

Page 101: Eclipse Plugin Development TUTORIAL

In this chapter we will create a new preference page which will take Folder name preference from user. This folder name will be used in Properties view instead of hard coding “Workspace Property Files”.

Property File Manager Preference Page

Eclipse provide a wizard for creating preference pages. Open plugin.xml. Navigate to the Extensions page followed by clicking "Add" button then click on org.eclipse.ui.preferencePages. Now select Preference Page in list of available templates as shown below.

Page 102: Eclipse Plugin Development TUTORIAL

Click next button and provide values as shown in figure below and click finish.

Page 103: Eclipse Plugin Development TUTORIAL

After you click finish, open up com.myplugin.rmp.preferences.PropertyManagerPreferencePage class to see the default implementation. We will discuss default implementation in sections to follow. At this time we will launch new runtime workbench to see how Property Manager Preference page looks like. Once you launch new Runtime workbench, open preference dialog (Window > preferences) and you will see something as shown in figure below.

Page 104: Eclipse Plugin Development TUTORIAL

Note about FieldEditor and FieldEditorPreferencePage

Field editors are basically used to make UI of a preference page. A field editor can be thought of as an item which is used to show the user with the value of a preference. FieldEditor is mostly used together with a FieldEditorPreferencePage, Eclipse provides many ready-to-use field editors as shown in figure below.

Page 105: Eclipse Plugin Development TUTORIAL

FieldEditorPreferencePage is a special abstract preference page to host field editors. Our preference page extends FieldEditorPreferencePage, which, along with the various editor classes helps in capturing preferences. Following figure shows complete hierarchy of FieldEditorPreferencePage. Please refer to Eclipse API Specification to know about methods available in this class.

Reviewing the generated code

Armed with the knowledge of field editors and FieldEditorPreferencePage we are now ready to review the generated code. Open com.myplugin.rmp.preferences.PropertyManagerPreferencePage class. Notice that the default implementation (generated by wizard) extends FieldEditorPreferencePage and implements IWorkbenchPreferencePage interface.

1. public class PropertyManagerPreferencePage2. extends FieldEditorPreferencePage3. implements IWorkbenchPreferencePage {4. public PropertyManagerPreferencePage() {5. super(GRID);6. setPreferenceStore(RmpPlugin.getDefault().getPreferenceStore());7. setDescription("A demonstration of a preference page implementation");8. }9. public void createFieldEditors() {

Page 106: Eclipse Plugin Development TUTORIAL

10. addField(new DirectoryFieldEditor(PreferenceConstants.P_PATH,11. "&Directory preference:", getFieldEditorParent()));12. addField(13. new BooleanFieldEditor(14. PreferenceConstants.P_BOOLEAN,15. "&An example of a boolean preference",16. getFieldEditorParent()));

17. addField(new RadioGroupFieldEditor(18. PreferenceConstants.P_CHOICE,19. "An example of a multiple-choice preference",20. 1,21. new String[][] { { "&Choice 1", "choice1" }, {22. "C&hoice 2", "choice2" }23. }, getFieldEditorParent()));

24. addField(25. new StringFieldEditor(PreferenceConstants.P_STRING,

"A &text preference:", getFieldEditorParent()));26. }27. public void init(IWorkbench workbench) {28. }29.}

Line 5: GRID is a layout constant defined in FieldEditorPreferencePage. Layout constant (value 1) indicates that the field editors' basic controls are put into a grid layout. Read SWT chapter for more on layouts.

Line 6: Sets the preference store for this preference page. We are using RmpPlugin.getDefault().getPreferenceStore() to retrieve the preference store for this Resource Manager Plugin. getDefault method returns the shared instance of plug-in. every plug-in has its own preference store. Preferences are stored in a <runtimeworkspace>\.metadata\.plugins\<pluginid>\pref_store.ini file.

Line 7: Set Description method is used to set the description title on the top of preference window.

Line 9 -26: createFieldEditors method is used to create GUI of the preference page. In this method we are creating four field editors (Directory, Boolean, Radio and String). AddField method is used to add the filed editor to preference page.

DirectoryFieldEditor

This editor is used to create a directory filed with in the preference page. First argument to constructor is the name of this field. This name is defined as a constant in com.myplugin.rmp.preferences.PreferenceConstants which was generated by preference page

Page 107: Eclipse Plugin Development TUTORIAL

creation wizard. These names are also used to retrieve values of a specific preference from preference store. Last argument specifies the parent of the field editor's control. We are using getFieldEditorParent() defined in FieldEditorPreferencePage to retrieve the parent control.

BooleanFieldEditor

This editor is used to create a Boolean field. It creates a checkbox in the preference page. Arguments are same as described in directory filed editor.

RadioFieldEditor

This editor is used to create a radio button field. Third argument is the numColumns - the number of columns for the radio button presentation.In our case it is one. Next argument is the labelAndValues list of radio button [label, value] entries. The value is returned when the radio button is selected

StringFieldEditor

This editor is used to create a Text box which takes a String as input. Arguments are same as described in DirectoryFieldEditor.

Lines 27 – 28: We have not used this method. However, it can be used to Initialize this preference page for the given workbench.

GETTING STARTED WITH PREFERENCE PAGES (PAGE 2)

Lets Customize Preference Pages

In this section we will modify the preference page so as to create a single String Text Box where user can set his preference for the name of folder which will be displayed in the Property Manager View.

Modify the PreferenceConstants class to add another constant FOLDER_NAME as shown in bold below.

public class PreferenceConstants { public static final String P_PATH = "pathPreference"; public static final String P_BOOLEAN = "booleanPreference"; public static final String P_CHOICE = "choicePreference"; public static final String P_STRING = "stringPreference"; public static final String FOLDER_NAME = "folderName";}

Page 108: Eclipse Plugin Development TUTORIAL

Next, Modify the createFieldEditors() in PropertyManagerPreferencePage class to create String filed editor. Provide FOLDER_NAME constant as the name of this field editor (as shown below). Also declare class level reference variable to hold String Field Editor object.

private StringFieldEditor fieldEditor; public void createFieldEditors() {

fieldEditor = new StringFieldEditor(PreferenceConstants.FOLDER_NAME, "Folder Name: ", getFieldEditorParent());

addField(fieldEditor); }

Following figure shows, how preference page will look like after above customization.

Next, Override checkState() method defined in FieldEditorPreferencePage for the purpose of customized validations. I could have very well use fieldEditor.setEmptyStringAllowed to perform same validation. However, I am manually checking it here so that you can get an idea as to how to use this method for complex validations.

protected void checkState() { super.checkState();

Page 109: Eclipse Plugin Development TUTORIAL

if(fieldEditor.getStringValue()!= null && !fieldEditor.getStringValue().equals("")){ setErrorMessage(null); setValid(true); }else{ setErrorMessage("Folder name cannot be blank!"); setValid(false); }}

The FieldEditorPropertyPage listens for FieldEditor.IS_VALID property change events and then calls checkState() and setValid() as necessary. The String field editors are never in an invalid state and thus do not issue FieldEditor.IS_VALID property change events, only FieldEditor.VALUE property change events. You must override the FieldEditorPreferencePage propertyChange() method to call the checkState() method when the FieldEditor.VALUE property change event is received.

public void propertyChange(PropertyChangeEvent event) { super.propertyChange(event); if (event.getProperty().equals(FieldEditor.VALUE)) { checkState(); } }

With above change an error message is displayed across the top of the preference page and the Apply and OK buttons are disabled (as shown below)

Page 110: Eclipse Plugin Development TUTORIAL

Next, Modify com.myplugin.rmp.preferences. PreferenceInitializer (Generated by create preference page wizard) to set the default value for folder name. In general Initializers are used to initialize default preference values. Modify initializeDefaultPreferences() as shown below

public void initializeDefaultPreferences() { IPreferenceStore store = RmpPlugin.getDefault() .getPreferenceStore(); store.setDefault(PreferenceConstants.FOLDER_NAME,"WorkSpace Property Files");}

With above change, folder name will be defaulted to “WorkSpace Property Files” whenever user clicks on default button in preferences dialog (as shown below)

Page 111: Eclipse Plugin Development TUTORIAL

Next Modify PropertyManagerView class so as to use preference rather than hard coded folder name. Modify initialize method as follows:

public void initialize() { IPreferenceStore store = RmpPlugin.getDefault() .getPreferenceStore(); String folderName = store.getString(PreferenceConstants.FOLDER_NAME); TreeParent root = new TreeParent(folderName); try { IWorkspace workspace = ResourcesPlugin.getWorkspace(); IProject[] projects = workspace.getRoot().getProjects();rest method is sameWith above mentioned change, On every refresh on root node of Properties view – folder name will be picked up from preferences.

Page 112: Eclipse Plugin Development TUTORIAL

GETTING STARTED WITH PROPERTIES

Working with Properties

Eclipse plugin Properties are used to assign additional information to resources and objects. Additional information could be anything. For Example, we may want to attach author name property with the java file resource in eclipse. There are two ways to access resource property. First, right click on resource and select properties option from context menu (as shown in figure below)

Page 113: Eclipse Plugin Development TUTORIAL

Another way to access properties for a resource is to open up the properties view from Window > Show View > Properties (as shown in figure below)

In this chapter we will learn how to create property on a particular resource and display it's properties in properties dialog as well as properties view. For the purpose of our example we will associate properties with property files displayed in Property Manager View. We will create a context menu option to open properties dialog. Later on we will see how to display properties in property view when ever user selects a property file in Property Manager View.

Let’s create a property dialog

We will first create a property page through plug-in manifest editor. This preference page will be shown in properties dialog. In order to create property page open plugin.xml in manifest editor. Navigate to extension page. Click on Add… button. Select org.eclipse.ui.propertyPages and click finish.

Page 114: Eclipse Plugin Development TUTORIAL

Next, In the extensions page right click on org.eclipse.ui.propertyPages and select new > page. Click on new page declaration and edit its properties as shown in figure below. We need to provide TreeObject class in object Class because we will be showing property dialog on selection of property files in Property Manager View and model class for property files in our view is TreeObject class.

Note: In order to access TreeObject class in below mentioned properties change access modifier from default to public. Also change the getResource() method in TreeObject to public from protected. It will be accessed from outside in coming sections.

Page 115: Eclipse Plugin Development TUTORIAL

Next, generate the com.myplugin.rmp.propertyPage class by clicking on class link in manifest editor(extensions page) with the help of java attribute dialog. Modify the com.myplugin.rmp.propertyPage as shown in the listing below.

1. package com.myplugin.rmp;2. import org.eclipse.core.resources.IResource;3. import org.eclipse.core.runtime.CoreException;4. import org.eclipse.core.runtime.QualifiedName;5. import org.eclipse.swt.SWT;6. import org.eclipse.swt.layout.GridData;7. import org.eclipse.swt.layout.GridLayout;8. import org.eclipse.swt.widgets.Composite;9. import org.eclipse.swt.widgets.Control;10. import org.eclipse.swt.widgets.Label;11. import org.eclipse.swt.widgets.Text;12. import org.eclipse.ui.IWorkbenchPropertyPage;13. import org.eclipse.ui.dialogs.PropertyPage;14. import com.myplugin.rmp.views.PropertyManagerView.TreeObject;

15. public class propertyPage extends PropertyPage implements

Page 116: Eclipse Plugin Development TUTORIAL

16. IWorkbenchPropertyPage {

17. private Text textField;18. public static QualifiedName AUTHOR_PROP_KEY = new QualifiedName("Author", "Author");

19. public propertyPage() {20. super();21. }

22. protected Control createContents(Composite parent) {23. Composite myComposite = new Composite(parent, SWT.NONE);24. GridLayout mylayout = new GridLayout();25. mylayout.marginHeight = 1;26. mylayout.marginWidth = 1;27. myComposite.setLayout(mylayout);28. Label mylabel = new Label(myComposite, SWT.NONE);29. mylabel.setLayoutData(new GridData());30. mylabel.setText("Author");31. textField = new Text(myComposite, SWT.BORDER);32. textField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));33. textField.setText(getAuthor());34.   return myComposite;35. }

36. protected String getAuthor() {37. IResource resource =38. ((TreeObject) getElement()).getResouce();39. try {40. String value =41. resource.getPersistentProperty(42. AUTHOR_PROP_KEY);43. if (value == null)44. return "";45. return value;46. }47. catch (CoreException e) {48. return e.getMessage();49. }50. }

51. protected void setAuthor(String author) {52.  IResource resource =53. ((TreeObject) getElement()).getResouce();54. String value = author;55. if (value.equals(""))56. value = null;57. try {58. resource.setPersistentProperty(

Page 117: Eclipse Plugin Development TUTORIAL

59.   AUTHOR_PROP_KEY,60. value);61. }62. catch (CoreException e) {63. }64. }

65. public boolean performOk() {66. setAuthor(textField.getText());67. return super.performOk();68. }69. }

Lines 15 -16: We are extending abstract base class PropertyPage. This class is Abstract base implementation of a workbench property page (IWorkbenchPropertyPage). Subclasses of this base class should implement the createContents method in order to provide the property page's main control. Following figure shows the hierarchy of this class.

Lines 22 – 35: Here we are implementing createContents method defined in PreferencePage class. This method creates and returns the SWT control. Nothing special here we are just using SWT controls to create the GUI of properties dialog. At line 33 we are calling getAuthor() method discussed next to get the existing author property.

Lines 37 - 38: In our properties dialog we will be showing single property named author for every “.properties” file. getAuthor() method is used to fetch the existing property saved in workspace. getElement() returns the object that owns the properties shown in the dialog. In our example case this dialog will open up whenever user right clicks on “.property” file in Property Manager View. Since our model object behind tree viewer is TreeObject we are casting getElement with TreeObject. Finally we are fetching corresponding resource object from treeObject.

Lines 39 – 50: There are two types of properties: persistent and session. Methods in IResource provide both session properties, which are discarded when Eclipse exits, and persistent properties, which are preserved across multiple workspace sessions. Following are the four methods provided by IResource implementation

getPersistentProperty(QualifiedName)

getSessionProperty(QualifiedName)

Page 118: Eclipse Plugin Development TUTORIAL

setPersistentProperty(QualifiedName, String)

setSessionProperty(QualifiedName, Object)

Please follow the link to know more about these methods. In order to retrieve property we use qualified name. Qualified names are two-part names: qualifier and local name. AUTHOR_PROP_KEY(QualifiedName) is defined on line 18.

Lines 51 – 64: All concepts are similar to what we discussed above with exception that we are using setPersistentProperty to set the author property for every object.

Lines 65 – 68: finally we are overriding perform ok method to fetch author name from dialog and calling the setAuthor() method which will persist the preference.

In order to open properties dialog we will modify hookContextMenu() method in com.myplugin.rmp.views.PropertyManagerView as shown below.We have used Eclipse inbuilt action “PropertyDialogAction to open up Properties Dialog Below.

private void hookContextMenu() { MenuManager menuMgr = new MenuManager("#PopupMenu"); Menu menu = menuMgr.createContextMenu(viewer.getControl()); viewer.getControl().setMenu(menu); Action refresh =new Action() { public void run() { initialize(); viewer.refresh(); } }; refresh.setText("Refresh"); menuMgr.add(refresh); menuMgr.add(new Separator()); menuMgr.add(new PropertyDialogAction(getSite(), viewer));}

Page 119: Eclipse Plugin Development TUTORIAL

GETTING STARTED WITH PROPERTIES

Lets display properties in properties View

Object properties are shown in Properties view if selected object implements org.eclipse.ui.views.properties.IPropertySource interface. In our example we will show Author property in the properties view whenever “.properties” file is selected in the com.myplugin.rmp.views.PropertyManagerView. Since TreeObject is the model object behind “.properties” file – TreeObject needs to implement “org.eclipse.ui.views.properties.IPropertySource” interface. Also, com.myplugin.rmp.views.PropertyManagerView should emit selection changed events so that the Properties View can listen to them and decide whether properties are to be displayed for selected object. Before we get into details it will be good to look at the IPropertySource interface and its methods. Please refer to Eclipse API Specification to know about this interface Property descriptors objects are used to create a property editor in the Properties view. Eclipse provides some implementations of the IPropertyDescriptor interface as shown in figure below.

Confused! Let’s start with real coding If you are not able to understand above mentioned details then don’t worry!! What follows is the step by step approach of integrating properties View with our own Property Manager View (similar names!! Don’t get confused, Property Manager View is our example view where in we are displaying all the property files in workspace whereas Properties View is provided by eclipse to display properties of object selected in workbench).  Step 1: Modify com.myplugin.rmp.views.PropertyManagerView such that it starts broadcasting selection changed events. Remember Property View listens to selection change events in order to display properties of selected object. Modify createPartControl method in com.myplugin.rmp.views.PropertyManagerView as shown below (in bold).

public void createPartControl(Composite parent) { viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); viewer.setContentProvider(new ViewContentProvider()); viewer.setLabelProvider(new ViewLabelProvider()); viewer.setInput(getViewSite());

Page 120: Eclipse Plugin Development TUTORIAL

ResourcesPlugin.getWorkspace().addResourceChangeListener(this); getSite().setSelectionProvider(viewer); hookContextMenu(); hookDoubleCLickAction();}Step 2: With above step, PropertyManagerView will start broadcasting selection changed events. Whenever user selects/deselects “.properties” file in view an event will be generated. Eclipse Properties View listen to these selection change events and display properties of currently selected object. BUT HOW???? How does it know which properties to display?? What are the values for these properties. Can it display properties for any type of objects?? The short answer is NO… Eclipse Properties View will display properties for only those objects which implement org.eclipse.ui.views.properties.IPropertySource Interface.In our case “.properties” files are essentially TreeObject. So we need to modify TreeObject class so that it implements IPropertySource Interface. However, in order to use org.eclipse.ui.views.properties.IPropertySource you need to add org.eclipse.ui.views in plug-in dependencies as shown in figure below.

Next, add following three lines in com.myplugin.rmp.views.PropertyManagerView class.

private static final String AUTHOR_ID = "RMP.author";

Page 121: Eclipse Plugin Development TUTORIAL

private static final TextPropertyDescriptor AUTHOR_PROP_DESC = new

TextPropertyDescriptor(AUTHOR_ID,"author");private static final IPropertyDescriptor[] DESCRIPTORS = { AUTHOR_PROP_DESC };Next, modify com.myplugin.rmp.views.PropertyManagerView$TreeObject as shown below (notice changes in bold): public class TreeObject implements IAdaptable,IPropertySource { private String name; private TreeParent parent; private IResource resouce;

public TreeObject(String name) { this.name = name; }  public String getName() { return name; }  public void setParent(TreeParent parent) { this.parent = parent; }  public TreeParent getParent() { return parent; }  public String toString() { return getName(); }  public Object getAdapter(Class key) { return null; }  public IResource getResouce() { return resouce; }  public void setResouce(IResource resouce) { this.resouce = resouce; }  public Object getEditableValue() { return null; }  public IPropertyDescriptor[] getPropertyDescriptors() { return DESCRIPTORS; }  public Object getPropertyValue(Object id) { try{ if(AUTHOR_ID.equals(id)){

Page 122: Eclipse Plugin Development TUTORIAL

return resouce.getPersistentProperty(propertyPage.AUTHOR_PROP_KEY); } }catch(Exception e){

} return null; }  public boolean isPropertySet(Object id) { return false; }  public void resetPropertyValue(Object id) {

}  public void setPropertyValue(Object id, Object value) { try{ if(AUTHOR_ID.equals(id)){ resouce.setPersistentProperty(propertyPage.AUTHOR_PROP_KEY,(String)value); } }catch(Exception e){

} }  }Now, whenever a “.properties” file is selected in Property Manager View. Its properties are shown in Eclipse Properties View as shown in figure below.

Page 123: Eclipse Plugin Development TUTORIAL

ECLIPSE PLUGIN EDITORS TUTORIAL

Working with Editors

Editors are used to create/modify workspace resources. As an Eclipse user you must have used editors all the time. Famous example of editor is the Java Editor. It provides many capabilities like Content assist, color coding and so on. There is no specific implementation of an editor because editors essentially cater to application specific behavior.

Once the implementation model for an editor is determined, implementing the editor is much like programming a standalone JFace or SWT application.

Workbench Editors

Although the implementation of a workbench editor will be specific to your plug-in and the content that

Page 124: Eclipse Plugin Development TUTORIAL

you want to edit, the workbench provides a general structure for building an editor. Editors should implement org.eclipse.ui.IEditorPart interface. In Eclipse, Editors rests inside org.eclipse.ui.IEditorSite, which in turn rests in org.eclipse.ui.IWorkbenchPage.

Thankfully, Eclipse provides two important base implementations of IEditorPart interface namely EditorPart and MultiPageEditorPart (discussed next). Major difference between the two type of editors is that MultiPageEditorPart provides the functionality of displaying multiple pages on same editor in tabbed fashion – similar to what we see in plug-in manifest editor (Overview tab, extensions tab, dependency tab etc.)

EditorPart

This is the Abstract base implementation of all workbench editors. Subclasses must implement the following methods:

IEditorPart.init - to initialize editor when assigned its site IWorkbenchPart.createPartControl - to create the editor's controls (SWT/JFace controls)

IWorkbenchPart.setFocus - to accept focus

IEditorPart.isDirty - to decide whether a significant change has occurred

IEditorPart.doSave - to save contents of editor

IEditorPart.doSaveAs - to save contents of editor

IEditorPart.isSaveAsAllowed - to control Save As

MultiPageEditorPart

A multi-page editor is an editor with multiple pages, each of which may contain an editor or an arbitrary SWT control. Subclasses must implement the following methods:

CreatePages - to create the required pages by calling one of the addPage methods (pages will be subclasses of EditorPart discussed above)

IEditorPart.doSave - to save contents of editor

IEditorPart.doSaveAs - to save contents of editor

IEditorPart.isSaveAsAllowed - to enable Save As

Page 125: Eclipse Plugin Development TUTORIAL

IEditorPart.gotoMarker - to scroll to a marker.

Creating Editor by using inbuilt editor template

In order to understand editor concepts we will use one of the templates available in eclipse itself. This template creates a multi-page editor. The editor has three pages: Edit where you enter text, Properties that allows you to change font of the result and Preview that shows sorted words from the Edit page using the font set in Properties.

In order to create multi-page editor, open plug-in.xml file. Navigate to extensions tab and click on Add. Select “Extension Wizards” tab followed by Multi-page Editor as shown in figure below.

Next, click on “Next” button and provide values as shown below:

Page 126: Eclipse Plugin Development TUTORIAL

Java Package Name: is the package in which editor class will be generated.

Editor Class Name: is the name of multi page editor class which will be generated after this wizard finishes

Editor Contributor Class: is an instance of org.eclipse.ui.IEditorActionBarContributor which manages the installation and removal of global menus, menu items, and toolbar buttons for one or more editors. The platform sends the some events to the contributor, indicating when an editor has become active or inactive, so that the contributor can install or remove menus and buttons as appropriate.

Editor Name: Human readable name of editor.

File Extension: This attribute specifies the file extensions with which we would like to associate this particular editor.

Next, Click finish. Save the Plugin manifest file. We will first look how newly created editor looks like before reviewing the generated code. In order to view the editor in action launch eclipse runtime application. Create a new file from right click context menu as shown below:

Page 127: Eclipse Plugin Development TUTORIAL

Name the new file anything but keep the extension of the “.mpe” because this is the extension with which newly created editor is associated with. Once you have created the file – Sample Multi-Page editor will open up with three tabs namely <filename>.mpe, Properties and Preview. Play around with the editor before we get onto reviewing generated code.

Page 128: Eclipse Plugin Development TUTORIAL

Let’s Review the generated code

Let’s start with plug-in manifest editor.

Page 129: Eclipse Plugin Development TUTORIAL

In order to create a new editor we need to extend org.eclipse.ui.editors extension point. Following are some of attributes (with brief description) which need special attention.

Extensions: every editor typically understands only special file extensions. For ex: XML editor understands only .xml extension. You can provide file extensions (comma separated) understood by editor.

Command: We can specify command here to launch an external editor. For example: I may like to open XML SPY (external editor) when user clicks on xml file inside eclipse.

Launcher: class that implements org.eclipse.ui.IEditorLauncher and is used to launch an external editor.

contributerClass: a class that implements org.eclipse.ui. IEditorActionBarContributor . This class us useful in adding actions to various parts of eclipse whenever editor is opened. We will discuss Contributor class in coming sections when we review its generated code.

Default: If true, this editor will be used as the default editor for the file extension

Filenames: if we want to open our editor for specific filenames

Page 130: Eclipse Plugin Development TUTORIAL

Let’s review com.myplugin.rmp.editors.MultiPageEditor class.

As discussed earlier that implementation of editor is much like programming a standalone JFace or SWT application. So we will not get into details of how to build an editor with help of SWT/JFACE. We will just concentrate on the lifecycle of editor. In Coming sections ill discuss various editor specific methods. We will discuss the order in which these method get called (in editor lifecycle) and what is the purpose of these methods.

public MultiPageEditor() { super(); ResourcesPlugin.getWorkspace().addResourceChangeListener(this);}

Whenever user clicks on a “.mpe” file constructor of MultiPageEditor will be called. This class implements IResourceChangeListener (discussed in resource change tracking chapter). In editor constructor we are registering this instance of editor with the workspace so that editor is notified for any resource changes in the workspace.

public void init(IEditorSite site, IEditorInput editorInput) throws PartInitException { if (!(editorInput instanceof IFileEditorInput)) throw new PartInitException("Invalid Input: Must be IFileEditorInput"); super.init(site, editorInput);}

Next in the editor lifecycle init method is called, we are overriding init method defined in EditorPart class. This method is the first method to be called when editor is created In this method we are verifying whether the editor input is acceptable (it should be instance of IFileEditorInput) otherwise throwing an exception. IEditorInput is a light weight descriptor of editor input, like a file name but more abstract. It is a object which can be queried to know more about the input which is coming to editor.

protected void createPages() { createPage0(); createPage1(); createPage2();} void createPage0() { try { editor = new TextEditor(); int index = addPage(editor, getEditorInput()); setPageText(index, editor.getTitle()); } catch (PartInitException e) { ErrorDialog.openError( getSite().getShell(), "Error creating nested text editor", null, e.getStatus()); }}

...

...

Page 131: Eclipse Plugin Development TUTORIAL

Next in the editor lifecycle createPages() method is called, This method creates the pages of this multipage editor. Typically, this method simply calls more finely grained methods such as createPage0(To create eclipse plugin text editor), createPage1(To create composite) etc. So this method is used to create the GUI for our editor. Next, in createPage0() we are creating a new TextEditor. This is a inbuilt standard text editor for file resources (we could have created our own editor by extensing EditoPart Directly). addPage method is used to add a new page containing the given editor to this multipage editor. addPage returns the index where this page is added. Next setPageText is used to set the title for the page index.

public boolean isSaveAsAllowed() { return true;}

isSaveAsAllowed() returns whether the "Save As" operation is supported by this editor part. This method calculates whether save action should be disabled or enabled whenever editor is opened.

protected void pageChange(int newPageIndex) { super.pageChange(newPageIndex); if (newPageIndex == 2) { sortWords(); }}

pageChange(int) method is called whenever user toggles the page tab on bottom of multi page editor. This method is used to calculate the contents of selected page.

public void doSave(IProgressMonitor monitor) { getEditor(0).doSave(monitor);} public void doSaveAs() { IEditorPart editor = getEditor(0); editor.doSaveAs(); setPageText(0, editor.getTitle()); setInput(editor.getEditorInput());}

doSave() and doSaveAs() methods are called whenever user clicks “Save” or “Save As” actions. We are using editor at index zero i.e. the Text Editor to save the file. On save, the editor should generate a property changed event (PROP_DIRTY). doSaveAs() is used to open a Save As dialog

public void gotoMarker(IMarker marker) { setActivePage(0); IDE.gotoMarker(getEditor(0), marker);}

gotoMarker() sets the cursor and selection state for this editor as specified by the given marker. We will discuss about markers in chapters to follow.

Note About Marking Editors Dirty

In above example we have not covered process to mark editors dirty so that Save and Save As buttons can be enabled. Whenever user makes some modification to editor file we can mark editor as dirty by calling firePropertyChange(IEditorPart.PROP_DIRTY). We can also use isDirty() method to see if editor is marked as dirty at any point in editor.

Let’s review com.myplugin.rmp.editors.MultiPageEditorContributor class.

Page 132: Eclipse Plugin Development TUTORIAL

This class is responsible for Managing the installation/deinstallation of global actions for multi-page editors. In our example editor, you will notice that “Editor Menu” action is displayed on top menu whenever editor is opened (as shown in figure below). This action is removed from workbench menu bar whenever multi page editor is closed.

The EditorActionBarContributor class implements the IEditorActionBarContributor interface, which caches the action bar and workbench page, and provides two new accessor methods.

getActionBars() : it returns the contributor's action bars provided to the contributor when it was initialized.

getPage(): it returns the contributor's workbench page provided to the contributor when it was initialized.

contributeToMenu(): Contributes to the given menu. In our example we are adding new “Editor &Menu” to the workbench menu.

contributeToToolBar(): Contributes to the given tool bar.

The MultiPageEditorActionBarContributor class extends EditorActionBarContributor, providing a new method to override instead of the setActiveEditor(IEditorPart) method.

setActivePage(IEditorPart part): This method is called whenever the page changes. This method Sets the active page of the multipage editor to the given editor. If there is no active page, or if the active page does not have a corresponding editor, the argument is null. We are calling

ECLIPSE BUILDERS, NATURES AND MARKERS

In this chapter we will talk about builders, natures and markers.

Builders: If you are using Eclipse IDE for java development then you are not new to Builders. Inside Eclipse builders are used to take java source as input and generate corresponding class files. So you can define builders as an engine which generates some output based on your input. Incremental Builders - These contribute to performance improvement by rebuilding only the delta since last full build.

Page 133: Eclipse Plugin Development TUTORIAL

Markers: Markers are used mark locations in editor. Java editor uses these markers to mark error locations, warnings, book marks etc.

Natures: Natures are used to link project with various functionalities such as builders in a project. For ex: if we add java nature to a project inside eclipse. It associates project with incremental java compiler.

Creating Builders Nature using existing templates

In order to understand builder nature and marker concepts we will use one of the templates available in eclipse itself. This template will create an builder (incremental). In addition, it will also create a project nature. Name of this builder is "sample builder" and it basically validates XML file and if required adds a problem marker to problematic xml files. The builder will run only for projects which have declared themselves as having sample nature projects. Select Add/Remove Sample Nature action from a project context menu, to toggle the nature on a project.

In order to create project builder and nature, open plug-in manifest editor. Navigate to extensions page followed by clicking on "Add" button. Now select Extension Wizards tab followed by Project Builder and nature template as shown in figure below.

Page 134: Eclipse Plugin Development TUTORIAL

Click next and use default values as shown below.

Click finish and save the plug-in manifest file. Before we move onto discuss the generated code let’s first see the builder in action. Launch eclipse runtime application. Create a new xml file in existing project (create new project if workspace is new). Edit newly created xml file such that it is not well formed. Right click on project and click Add/Remove sample Nature. Notice that the marker will appear inside the editor (as shown in figure below).

Page 135: Eclipse Plugin Development TUTORIAL

Eclipse Builders

Let’s review the plug-in manifest file to see what it takes to create a new project builder. New builder is created by extending the org.eclipse.core.resources.builders extension point. ID and name are used to give builder a datavalue and name respectively. Point is nothing but the extension point which we have extended.

Page 136: Eclipse Plugin Development TUTORIAL

Next, is the builder element. The hasNature attribute flags whether this builder is associated with any nature.

Page 137: Eclipse Plugin Development TUTORIAL

Next, is the run element (class attribute). Here we specify the actual java class which provides the functionality of the builder.

Page 138: Eclipse Plugin Development TUTORIAL

IncrementalProjectBuilder

The java class (com.myplugin.rmp.builder.SampleBuilder) discussed above needs more attention as this is the class which is doing the actual work. Any builder class must be a subclass of IncrementalProjectBuilder. All builders must subclass this class according to the following guidelines:

Subclasses should implement the build method of this class Subclasses may implement remaining methods

Subclasses should supply a public and no arg constructor

Please refer to Eclipse API Specification to find details of all the methods provided by this Class.

The build method requires special attention here. This method of the builder is called whenever build is required (for ex: user saves java file and automatic build preference is checked)

build(int kind, Map args, IProgressMonitor monitor)

kind: What kind of build is required?? Kind parameter could be a FULL_BUILD, INCREMENTAL_BUILD, and AUTO_BUILD.

Page 139: Eclipse Plugin Development TUTORIAL

Args: A map to pass arguments/information to builder.

Monitor: A progress monitor

Let’s review generated code related to builders

In this section we will review generated class (com.myplugin.rmp.builder.SampleBuilder) and will discuss builder/marker related code segments.

We will not go into details of IResourceDelta, IResourceDeltaVisitor or IResourceVisitor in this chapter. For more details on these topics refer to resource change tracking chapter.

protected IProject[] build(int kind, Map args, IProgressMonitor monitor) throws CoreException { if (kind == FULL_BUILD) { fullBuild(monitor); } else { IResourceDelta delta = getDelta(getProject()); if (delta == null) { fullBuild(monitor); } else { incrementalBuild(delta, monitor); } } return null;}Eclipse will call build method of the builder whenever any type of build is required. In above code segment we are using kind parameter to understand the kind of build request. We have implemented two methods for each kind of build full build/ incremental build discussed next.protected void fullBuild(final IProgressMonitor monitor) throws CoreException { try { getProject().accept(new SampleResourceVisitor()); } catch (CoreException e) { }} protected void incrementalBuild(IResourceDelta delta, IProgressMonitor monitor)

throws CoreException { // the visitor does the work. delta.accept(new SampleDeltaVisitor());}

In both of above methods we are delegating calls to Visitors. Visitor will visit all the resources (in case of delta only the modified resources since last build). For each resource we are calling checkXML() method. CheckXML method essentially delegates call to XMLErrorHandler defined in builder class which will check if XML document is well formed or not. In case it is not well formed it will create a marker (as shown below). I am not going into details of SAX parsing or SAX event handlers (it is out of scope for this tutorial). We are using Sample builder’s addMarker method to create a marker on line number where the exception occurred.

private void addMarker(SAXParseException e, int severity) { SampleBuilder.this.addMarker(file, e.getMessage(), e .getLineNumber(), severity);

Page 140: Eclipse Plugin Development TUTORIAL

BUILDERS, NATURES AND MARKERS (PAGE 2)

Markers

As described earlier, Markers are used mark locations in editor. Java editor uses these markers to mark error locations, warnings, book marks etc.

There are many types of predefined markers defined as constants in IMarker interface.

org.eclipse.core.resources.bookmarkIMarker.BOOKMARK org.eclipse.core.resources.markerIMarker.MARKER org.eclipse.core.resources.problemmarker IMarker.PROBLEM org.eclipse.core.resources.taskmarkerIMarker.TASK org.eclipse.core.resources.textmarkerIMarker.TEXT

Let’s review the plug-in manifest file to see what it takes to create a new marker. New marker is created by extending org.eclipse.core.resources.markers extension point. ID and Name are datavalue and name respectively. Point is nothing but the extension point we are using to create this marker.

Page 141: Eclipse Plugin Development TUTORIAL

Next, we need to define the super type marker for new marker. Since we want to show errors in Problems View we are using org.eclipse.core.resources.problemmarker as supertype.

Next is the persistent element. Since we want this markers to persist across eclipse sessions we are setting this property to true.

Page 142: Eclipse Plugin Development TUTORIAL

Reviewing the generated code

addMarker method in SampleBuilder class is used to show above defined marker in the editor whenever problem/error occurs.

private static final String MARKER_TYPE = "com.myplugin.rmp.xmlProblem";private void addMarker(IFile file, String message, int lineNumber, int severity) { try { IMarker marker = file.createMarker(MARKER_TYPE); marker.setAttribute(IMarker.MESSAGE, message); marker.setAttribute(IMarker.SEVERITY, severity); if (lineNumber == -1) { lineNumber = 1; } marker.setAttribute(IMarker.LINE_NUMBER, lineNumber); } catch (CoreException e) { }}

Page 143: Eclipse Plugin Development TUTORIAL

IMarker is the main interface when we are dealing with eclipse markers. Please refer to Eclipse API Specification to know more about IMarker Interface.

BUILDERS, NATURES AND MARKERS (PAGE 3)

Natures

Natures are used to link project with various functionalities such as builders in a project. For ex: if we add java nature to a project inside eclipse. It associates project with incremental java compiler. natures are added in .project file of the project. Natures are not only used to associate builders but are also used to define many other functionalities for ex: only java nature projects are shown in Package Explorer. Some of the predefined natures are org.eclipse.jdt.core.javanature,org.eclipse.pde.PluginNature

Reviewing the generated code

Let’s review the plug-in manifest file to see what it takes to create a nature. Nature is created by extending org.eclipse.core.resources.natures extension point. ID is the unique identifier for this nature. Name is the human readable name of the nature.

Page 144: Eclipse Plugin Development TUTORIAL

Next element is the builder. Here we will add a builder to this nature. We have associated SampleBuilder created earlier with this nature. So that projects with SampleNature use SampleBuilder whenever an XML file is saved.

Page 145: Eclipse Plugin Development TUTORIAL

Next elements which we are going to discuss are runtime and run. Here we will specify a class named Sample Nature which will be used to configure/deconfigure project with Sample Nature. With the help of this class we will be able to configure non Sample Nature project to Sample Nature project at run time. OR we will be able to convert Sample Nature Project to non Sample Nature project. Repercussions of making a Project as Sample Nature project will be that a Sample builder will be attached to project which will run whenever an XML file is saved and will look for any errors in XML.

Page 146: Eclipse Plugin Development TUTORIAL

IProjectNature

Class com.myplugin.rmp.builder.SampleNature declared above implements IProjectNature interface. It can configure a project with the project nature, or de-configure it. Please refer to Eclipse API Specification to know more about this class.

In our example, user is provided with toggle action to convert non Sample Nature project to Sample Nature project. Following method from SampleNature class will be called to associate the project with SampleNature.

public void configure() throws CoreException { IProjectDescription desc = project.getDescription(); get the description of the project basically .project file information ICommand[] commands = desc.getBuildSpec(); // get the build commands already associated with project. for (int i = 0; i < commands.length; ++i) {

Page 147: Eclipse Plugin Development TUTORIAL

if (commands[i].getBuilderName().equals(SampleBuilder.BUILDER_ID)) { return; // Do nothing if Sample builder is already associated with project } }

ICommand[] newCommands = new ICommand[commands.length + 1]; // create a new build command System.arraycopy(commands, 0, newCommands, 0, commands.length); ICommand command = desc.newCommand(); command.setBuilderName(SampleBuilder.BUILDER_ID); // attach it to sample builder newCommands[newCommands.length - 1] = command; desc.setBuildSpec(newCommands); project.setDescription(desc, null); // write to .project file}Every workbench project contains a .project file that contains build commands. Executing above method causes the following to appear in the buildSpec section of the project's .project file. Also Sample nature is added in natures section.<buildSpec> <buildCommand> <name>com.myplugin.rmp.sampleBuilder</name> <arguments> </arguments> </buildCommand></buildSpec><natures> <nature>com.myplugin.rmp.sampleNature</nature></natures> 

Eclipse Help System

 Help in eclipse is accessed by using Help > Help Contents menu. Once you done with development of your plug-in and before you are ready to ship it as a product, one thing which you would like to do is create help contents. No matter how simple or complex your plugin is, users would like to see get started documents. Also help provide us with opportunity to describe functionalities available with the plugin.

Page 148: Eclipse Plugin Development TUTORIAL

Creating New Help Eclipse has support for many formats like HTML, PDF, XHTML to name a few. We can create help within the main plugin or create altogether a new plugin project for help.  Creating new help project We will start by creating a new Plug in project. In order to create new project click on File > New Project > Select Plug in project (as shown below)

Page 149: Eclipse Plugin Development TUTORIAL

Click next button, Provide “com.myplugin.rmp.help” in Project Name field.

Page 150: Eclipse Plugin Development TUTORIAL

Click next button, Provide values as shown in figure below.

Page 151: Eclipse Plugin Development TUTORIAL

Click finish, this will create a new plug in project and will generate minimal code for the project. Till this point project is empty. Now we will use Existing extension templates to generate necessary files for creating help. Navigate to Extensions page, click on "Add" button and select Extensions Wizard tab followed by selecting Help Content template. This template creates a Help table of contents. If this table is set to primary, it can be standalone, or integrated into pre-set categories. If this is not set as primary then it can be attached with the primary toc for testing purposes.

Page 152: Eclipse Plugin Development TUTORIAL

Click Next button and provide values as shown below: Check the Primary Option. This will create a primary table of content file. We will select only Getting Started and Reference categories for this example.

Page 153: Eclipse Plugin Development TUTORIAL

Click Finish and save the manifest file.  Let’s Review the generated code

Once you have finished creating the extension points you will notice that many files have been generated by the Help Template Wizard. It also creates html files in a new folder.In order to create eclipse help org.eclipse.help.toc extension point is used. Next, we have to create various toc’s and mark them primary/secondary depending on the type of help we are creating. Every toc is represented by XML file.

Page 154: Eclipse Plugin Development TUTORIAL

Now let’s have a look at toc.xml file. Remember this file represents primary table of contents file.

<toc label="My Table of Contents" topic="html/toc.html"> <topic label="Getting Started"> <anchor id="gettingstarted"/> </topic> <topic label="Reference"> <anchor id="reference"/> </topic></toc>In above xml file, two subtopics have been defined i.e. "Getting Started" and "Reference". In the above xml file, labels are used to display human readable text on the help. and the topic is used to navigate to the real help page. Next, examine tocgettingstarted.xml :<toc label="Getting Started" link_to="toc.xml#gettingstarted"> <topic label="Main Topic" href="html/gettingstarted/maintopic.html"> <topic label="Sub Topic"

Page 155: Eclipse Plugin Development TUTORIAL

href="html/gettingstarted/subtopic.html" /> </topic> <topic label="Main Topic 2"> <topic label="Sub Topic 2" href="html/gettingstarted/subtopic2.html" /> </topic></toc>Above xml file has links to Help HTML files. This is all it takes to create a help with eclipse. In order to test recently created help, launch new eclipse runtime and open help window, you will see newly created help in the Eclipse help System.

GETTING STARTED WITH INTERNATIONALIZATION

In today’s world internationalization has become really important. Good news is that Eclipse has internationalization support. This is achieved by externalizing strings to a resource bundle. In Eclipse plug-in’s there are many files which can contain Strings (seen by end user) such as plugin.xml, Views, Editors and more specifically all the GUI labels.

In this chapter (eclipse plugin for internationalization) we will externalize strings (seen by end user) to a properties file called plugin.properties.

Externalizing Strings in plug-in manifest

In plug-in manifest file we need to externalize strings, such as the names of views, name of wizards and the labels of actions.

Externalizing strings from the plug-in manifest file very simple and straight forward. The file plugin.properties contains all the extracted strings.

Steps involved in externalizing strings are as follows:

1. create a plugin.properties file2. provide key value pairs in resource bundle. Key are the datavalues to be used in code and value is actual human readable string.

Step 1: Create a resource bundle

First step is to create a new properties file in plug-in project. Right click on project > select new file as shown below. Name this file “plugin.properties”. It must be noted that the translated files for each targeted language should be named plugin_<language>_<country>.properties, where <language> and <country> represent the language and country.

Page 156: Eclipse Plugin Development TUTORIAL

Edit the plugin.properties file and add following line to the file:

views.propertyviewname = Property Manager View

Next, open plug-in manifest editor and replace Property Manager View name with a descriptive key that starts with a percent (%) sign. These are the same keys that are used in the associated plugin.properties file. The only rule is that the keys need to be unique within the plug-in.

Page 157: Eclipse Plugin Development TUTORIAL

In order to test if strings have been externalized correctly you can play around by changing Property Manager View name and launch eclipse runtime. Note: If your changes are not reflected in the eclipse runtime then try clean build on your project followed by launch of eclipse runtime.

Externalizing Strings in plug-in classes

Eclipse has excellent inbuilt support for externalizing Strings. These can be used in any Java Project not necessarily plugin project. Here ill give you brief introduction on how to use this support (Please refer to eclipse help for complete details). We will externalize strings from com.myplugin.rmp.preferences.PropertyManagerPreferencePage class created earlier in this tutorial.

In order to externalize strings from this class, right click on Source > Externalize Strings when this class is open in java editor.

Page 158: Eclipse Plugin Development TUTORIAL

This will open up Externalize strings wizard. You will notice that list displays all the strings from java file.

In this wizard against each string - "Internalize" button can be used to mark the string as non-translatable using end-of-line comment.

Page 159: Eclipse Plugin Development TUTORIAL

On the bottom of the page you can specify properties file where these strings have to be externalized. Change it to refer to existing resource bundle file (if you already have one). Click next and you will be displayed following message.

Page 160: Eclipse Plugin Development TUTORIAL

Click Next, Last page will show you the summary of all the changes which will take place if you click finish. Verify your changes and press finish so that eclipse can automatically externalize strings into resource bundle.

Page 161: Eclipse Plugin Development TUTORIAL

Once you have finished review the generated code to see how eclipse have externalized all your strings into resource bundle.