Thursday, December 31, 2009

Writing an RCP application using e4 modeled UI - part II

Understanding what we did and why

In the previous post we wrote a very minimalistic RCP application using e4 modeled UI. Before adding more stuff to it, lets quickly revisit few steps and try to make sense of them.

In Step 1 we unchecked the Generate an activator button. This was because right now we don't want to do anything on bundle start or stop events. We will later add one if we find the need to do so.

In Step 2, we add a dependency to org.eclipse.core.runtime plug-in. This was to bring the extension org.eclipse.core.runtime.products in visible scope. If we don't add this dependency, we will get prompted to add it when we add the extension.

We also gave the value product to the extension id. This was to get the product registered as projectname.product. That is why we created a new product config in Step 5, the product org.example.e4.rcpapp.product was already available to us.

e4 provides an out of the box application which understands the modeled UI. This application is org.eclipse.e4.ui.workbench.swt.E4Application which is why we assigned it to the application property of our product.

The applicationXMI property is what points to the UI model which the E4Application will use to render the  UI. The format for the value is the plugin-name/project-relative-path. The file extension doesn't really matter. But an xmi extension will make it open the Toolkit Model Editor.

In Step 3, we had to manually add and modify the Application.xmi file. The New wizard doesn't have a option for it yet. Bug 284413 shall address the issue.

In Step 4, we gave proper shape to the model.

Application - this node represents the complete application. It will contain all UI elements plus their handlers, etc. Basically everything has to be child of this node.

Window - represents the visible window that will form the RCP application GUI. Whatever Label we give to it, is what we will see in the window title bar. Lets play with it a bit. Change the Label property to give it a new title. Give the X and Y property as 10 each. Save the editor and launch the application. You will see the application now has the new title and it shows up very close to the top-left corner of the screen. The X and Y properties represents the distance from the top-left corner of the screen.

Part Sash Container - is a container for our Part. In e4 both view and editor are treated equally as Part. All the children Parts will share the space among them.

Part Stack - is a collection of sibling Parts. Only one visible as a time - like we deck various views currently.
Part - represents a view or a editor. As usual, the Label property will control the name getting displayed on the view tab. We also added it a property URI and gave it a value platform:/plugin/org.example.e4.rcpapp/org.example.e4.rcpapp.views.MyView. This looks like a class name because it is a class name. We don't really need it as of now, but without it you will get a error and just to suppress it I added it. Getting an error on your first e4 RCP app won't look too elegant ;) In next post we will added this class and use it to create UI in the Part space.


Step 5 created a product configuration to help invoke the application. Nothing new here.


Step 6 created a run configuration using the product created in Step 5.
 
Step 7 simple launched this run config.Only point to note here would be the Plug-ins tab in Run configuration shall select all the target plug-ins. This is because the Add Required Plug-ins button can not yet cope with the Dependency Injection used by modeled UI. Not doing so will run you into NPE at org.eclipse.e4.workbench.ui.internal.E4Workbench.init(E4Workbench.java:93).

Next


We will add more Parts and render some useful UI in it.

Writing an RCP application using e4 modeled UI - part I

Prakash was couple of hours quicker on posting the same topic here. I have a slightly different approach and may be more to add. Lets see.

Step 1: Create a simple plug-in project.

Open the plug-in wizard and create a new plug-in project. Let's give a name org.example.e4.rcpapp. Be sure to uncheck the Generate an activator option. Click Finish. Do not go to template page (they are not yet updated for e4).


 

Step 2: Adding product extension.

Open the manifest editor and go to Dependencies tab. Add org.eclipse.core.runtime as required plug-in. Now open the Extensions page. Add a new extension org.eclipse.core.runtime.products.

Select the extension and give it a ID product in extension details section.

Right click the extension and select New -> Product. Select the product and give it a nice name - e4 RCP app. Change the application id to org.eclipse.e4.ui.workbench.swt.E4Application.

Now right click the product in extension section and add two new properties. In the extension section give the name and values like this

Name : appName
Value : Hello e4

Name : applicationXMI
Value : org.example.e4.rcpapp/Application.xmi

After this your plugin.xml will look like this


<plugin>
   <extension
         id="product"
         point="org.eclipse.core.runtime.products">
      <product
            application="org.eclipse.e4.ui.workbench.swt.E4Application"
            name="e4 RCP app">
         <property
               name="appName"
               value="Hello e4">
         </property>
         <property
               name="applicationXMI"
               value="org.example.e4.rcpapp/Application.xmi">
         </property>
      </product>
   </extension>
</plugin>


Step 3: Application.xmi

Create a new file to the root of the project and call it Application.xmi. It will open by default in a Toolkit model editor with errors (because it doesn't have the expected header). The editor will show a button Open with Text Editor. Click it and the file will open in a text editor. Add following skeleton to it. Save and close it.


<?xml version="1.0" encoding="ASCII"?>
<application:Application xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:application="http://www.eclipse.org/ui/2008/UIModel">
</application:Application>

Reopen the file and it will now open properly.





Step 4: Creating Modeled UI

When you right click any node in this editor, there will options to add a new Child and/or Siblings. The Properties view will show the properties of each node. If it is not already visible you can invoke it by selecting the node and choosing Show Properties View option from the context menu.

Select the Application node and add a new child Window to it. See its properties and give it a nice name in the Label property like Hello e4.

Select the Window node and add a child Part Sash Container.
Select PartSashContainer node and add a child Part Stack.
Finally select PartStack node and add a child Part to it. Visit the Properties view for the Part node and give it a name in the Label property like My view. And in the URI property give a path platform:/plugin/org.example.e4.rcpapp/org.example.e4.rcpapp.views.MyView

Save the editor and it shall now look like this.




To be sure that we did everything right, open the Application.xmi in text editor and its contents should look like this


<?xml version="1.0" encoding="ASCII"?>
<application:Application xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:application="http://www.eclipse.org/ui/2008/UIModel">
  <children xsi:type="application:Window" label="Hello e4">
    <children xsi:type="application:PartSashContainer">
      <children xsi:type="application:PartStack">
        <children xsi:type="application:Part" URI="platform:/plugin/org.example.e4.rcpapp/org.example.e4.rcpapp.views.MyView" label="My View"/>
      </children>
    </children>
  </children>
</application:Application>


Step 5: Product Configuration

Create a new Product Configuration. Select the product org.example.e4.rcpapp.product from the combo by enabling the Use an existing product option in the New Product Configuration wizard.



The product editor will now open and will look like this



Step 6: Creating a Run Configuration


Open the Run Configurations wizard and create a new Eclipse Application config. Name it rcpapp.product.
Choose the product org.example.e4.rcpapp.product in the Run a product option.



Go to Plug-ins tab and make sure all workspace and enabled target plug-ins option is selected in the Launch with combo.



Step 7: Launching the RCP Application

Click Run button in run configuration to execute the RCP application. Your first e4 RCP application will look like this

 


Next

In the following posts we will revisit what we did above and try to see why we did it so.

Note to e4 gurus and committers

This series is post is outcome of hit-and-trial self learning. Please do add you views or point out any mistakes you see.

Wednesday, December 23, 2009

LinkedIn IT Trends and Compensation Report (Aus-India) 2009

LinkedIn’s Technology Trends & Compensation Study Australia - India Report for 2009 was released recently. You may download the PDF from here. Apart from various trends, I found a couple for slides with a mention of Eclipse too.

1. Eclipse is the 4th most popular development tool.


I was expecting Eclipse to be in top 5 so being number 4 is not so disappointing. I feel some of the survey participants might have counted Eclipse under 'Other open source dev tools' which is at number 2.


2. 46% developers 'very satisfied' with Eclipse.


Eclipse got second highest votes for 'very satisfied'. Surprisingly second to Apple!! What can I say. May be because I don't have a iPhone :-) But even more shocking was SAP better than Apple and Eclipse in average scores. Now I have seen only one SAP application and that sucks bad. Perhaps they really are doing a fantastic job.

Since the report from Australia-India geo its a partial view. Am sure this pictures differs a lot from the one at global level.

Monday, December 7, 2009

Heap Status

If you wish to keep an eye on heap status of your eclipse instance then a quick way to do it is 'Heap Status' preference. You don't need any memory profiler for this.



This starts displaying the heap status in the status bar.



The garbage can icon is for running the Garbage Collection. It basically makes call to System.gc() and System.runFinalization()

Saturday, November 21, 2009

source.<library> and output.<library>

The source and output properties in build.properties control the folders to be compiled and where to place the resulting output. The eclipse help briefly talks about it.
    * source.<library> - lists source folders that will be compiled (e.g. source.xyz.jar=src/, src-ant/). If the library is specified in your plug-in.xml or manifest.mf, the value should match it;
    * output.<library> - lists the output folder receiving the result of the compilation;

Source Folders and Output Folders


Source and Output folder have already been discussed in this post. Only the source folders gets compiled and the generated class files get stored in the corresponding output folder. A project can have one or more source folder. If a source folder does not have a output folder attached to it explicitly, its output will go to the default output folder. The .classpath file stores all this information.

source.. and output..

The real syntax is source.<library> and output.<library> where <library> is generally the name of the jar. Here the second dot signifies the default library. Any source folder assigned to it gets it output reside in the root when the plug-in is build. The output.. entry tells the PDE Build where to pick the classes for source.. from.
Typical entries look like this
source.. = src/
output.. = bin/

When a plug-in with above entries is build the structure of the plug-in jar will look like this
org.example.sample_1.0.0
│   plugin.xml
│
├───icons
│       sample.gif
│
├───META-INF
│       MANIFEST.MF
│
└───org
    └───example
        └───sample
            │   Activator.class
            │
            └───actions
                    SampleAction.class

More complex plug-ins have more than one source folder. org.eclipse.pde.core is one such plug-in. It is good practice to assign separate output folder for separate source folders. This is not mandatory.
Lets assume src and src_an are the two source folders and their corresponding output folders are bin and bin_ant. Then a build.properties like
source.. = src/
output.. = bin/
source.ant_tasks/anttasks.jar = src_ant/
output.ant_tasks/anttasks.jar = bin_ant/
will create a plug-in which will look something like this
org.example.sample_1.0.0
│   plugin.xml
│
├───ant_tasks
│       anttasks.jar
│
├───icons
│       sample.gif
│
├───META-INF
│       MANIFEST.MF
│
└───org
    └───example
        └───sample
            │   Activator.class
            │
            └───actions
                    SampleAction.class
The contents of the src_ant folder will get compiled and jared in to anttasks.jar inside ant_tasks folder because of the source.ant_tasks/anttasks.jar = src_ant/ entry.

Classpath vs source/output entries

The source folder and output folder information is already available in class path then why source/output entries are needed? The classpath entries are used to compile source code. But the PDE Build relies on the source/output entries while building (or exporting) the plug-ins. Suppose a plug-in A refers to a class C in plug-in B. Then while building the plug-in A PDE Build will look into build.properties of plug-in B to locate the C.class.

Rules of using source. and output. entries
  1. Every source folder should appear in a source. entry.
  2. A source folder can appear in one and only one source. entry.
  3. The source and output folders are specified as their path relative to the root of the project.
  4. All source folders whose output folder is same should belong to same source. entry.
  5. The corresponding output folders should be mentioned in the corresponding output.entry.
Note that should in above rules means that rule is a good practice and not an obligation but if not followed the result of PDE Build might be unexpected.

Wednesday, October 21, 2009

Execution Environment and javac entries

Execution Environment
Execution Environments have been explained in detail in this article. And from PDE API tooling perspective it has been explained here. In one line, EE represents the JRE. It is a set of properties, each marking a level of compliance. I am reproducing this table from 'Setting the Compilation Environment' help page.


Environment
Source
Target
CDC-1.0/Foundation-1.0
1.3
1.1
CDC-1.1/Foundation-1.1
1.3
1.2
OSGi/Minimum-1.0
1.3
1.1
OSGi/Minimum-1.1
1.3
1.2
JRE-1.1
1.1
1.1
J2SE-1.2
1.2
1.1
J2SE-1.3
1.3
1.1
J2SE-1.4
1.3
1.2
J2SE-1.5
1.5
1.5
JavaSE-1.6
1.6
1.6
PersonalJava-1.1
1.1
1.1
PersonalJava-1.2
1.1
1.1
CDC-1.0/PersonalBasis-1.0
1.3
1.1
CDC-1.0/PersonalJava-1.0
1.3
1.1
CDC-1.1/PersonalBasis-1.1
1.3
1.2
CDC-1.1/PersonalJava-1.1
1.3
1.2

There are more properties and are provided by org.eclipse.jdt.core

org.eclipse.jdt.launching plug-in provides an extension point (id = org.eclipse.jdt.launching.executionEnvironments) for contributing EEs. JDT Launching plug-in also extends it and provides the EEs that are listed in the above table. If you really want to see the code then check out JavaCore.java and CompilerOptions.java in org.eclipse.jdt.core plug-in.

Manifest.MF

The execution environment for a bundle can be defined in the Manifest.MF file. A typical entry for Java 1.4 environment will look like this.

Bundle-RequiredExecutionEnvironment: J2SE-1.4

The manifest editor provides an easier way on the Overview tab.


Execution Environment section on Overview page of Manifest Editor

The Add button opens a selection dialog with the list of available execution environments (contributed to the extension point org.eclipse.jdt.launching.executionEnvironments). By default the list is same as those listed in the table above.

jre.compilation.profile
The execution environment in build.properties is mentioned using the jre.compilation.profile entry. It takes same value as BREE entry in manifest.MF. Thus, the entry for Java 1.4 will look like this.

jre.compilation.profile = J2SE-1.4

javacSource, javacTarget and javacWarnings
These entries can be used to override the jre.compilation.profile entry in build.properties. A certain EE mandates a particular version for Java source and generated class file compliance. These versions can be overridden using these entries. These entries can be used without jre profile entry as well. If you just want to specify the java source version then only javacSource entry will suffice.

Looking at the table above we can see that J2SE-1.4 is Java source at version 1.3 and class files version 1.2 compliant. This can be mentioned in build.properties as

javacSource = 1.3
javacTarget = 1.2

Please note that the above two entries are not equivalent to jre profile entry for J2SE-1.4. This is because an EE is other properties too like system packages, boot delegation, assert and enum identifiers. See the schema description for the EE extension point discussed above.

Eclipse uses batch compiler to build the plug-ins. It is located inside org.eclipse.jdt.core. Since version 3.2, it is also available as separate download - ecj.jar - Eclipse Compiler for Java. The batch compiler accepts many options and a list and details can be found here. The javacSource and javacTarget entries map to -source and -target options.

javacWarnings.<library> entry is used to pass the warning options (-warn) to the compiler. The entry to suppress warnings for assert and enum identifiers in library.jar will look like this

javacWarnings.library.jar = -assertIdentifer, -enumIdentifier


Thursday, October 15, 2009

Eclipse Demo Camp. Bangalore '09

This year's Eclipse Demo Camp at Bangalore will be held on November 5, 2009. Various demos have already been lined up on topics like GEF 3D, SWTBot, Jazz, XText, E4 and JSDT. If you are working on some cool stuff and want to share it with Eclipse community then this is your best chance. Do get in touch as there is still room for couple of more demos.

30 participants from 15 different companies like IBM, HP, Oracle, Nokia, Bosch, Infosys  and ThoughtWorks (to name a few) have already registered. There are limited seats available so hurry up if you want to catch all the cool stuff Eclipse community is doing. Registration is free and available on First-come-First-serve basis. Details at Eclipse Wiki.

See you there.

Sunday, October 11, 2009

Source folders and src.includes

Source Folders

A source folder is, of course, a folder which contains source code. But where it is identified is in .classpath file. This is how a typical .classpath file looks like.

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="src_samples"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.4"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="output" path="bin"/>
</classpath>

org.eclipse.pde.ui/.classpath

The kind="src" marks a folder as source folder. Similarly, the kind="output" marks a folder for output - where all the binaries will go after the build. In Eclipse you don't have to modify/manage the .classpath file manually. Various wizards are available to do all the work for us such that we never even have to look at .classpath file.

New Source Folder Wizard
Use New -> Source Folder from File or context menu to invoke the new source folder wizard. It's a very simple wizard. It asks for the project and the folder name. When you click Finish, it will create that folder and mark it as source folder.




New Source Folder Wizard
The way we can check that the folder has been marked as source folder is by opening .classpath file. But there is a simpler way. Check the Source tab on the project's Java Build Path properties page. This can be invoked as Project -> Properties or simple Alt + Enter on the project in Package Explorer view.


Java Build Path properties page
Source Folders and Output Folders

If you notice the check box towards the end "Allow output folders for source folders" is unchecked. This means the binaries for all the source folders will go to the default output folder (mentioned right below this checkbox, typically named as bin. The bin is for binaries and not like one in recycle bin).

However, we can select this check box and associate a specific output folder for every source folder. This will make the binaries for that particular source folder to get created in the associated folder. Note that this does not makes the associated folder an Output Folder. That is, no kind="output" entry in .classpath file. Only the source folder entry gets a output="foldername" attribute.


Java Build Path properties page with associated output folders

build.properties

The build path only brands the folders are source or otherwise. The actual build and output binaries are controlled by build.properties file.

src.includes
This entry in build.properties file specifies the folders whose contents also needs to be added to the source build. Source build is the source bundle or the source inside the exported plug-in. The emphasis on ALSO is to highlight the fact that the source folder are part of source build by default and they should not be added explicitly using src.includes. In fact, it only cause unwanted side effects as mentioned in bug #286808.

src.excludes

This entry explicitly removes a folder from source build. It is used when a parent folder is part of source build and only specific child folder has to be  excluded from the source build.

Both these entries take relative folder paths. The Build tab on the Manifest editor provides a very easy UI to deal with them so that we don't have to add them manually to build.properties.



Binary and Source build section on Build tab of Manifest editor
The corresponding build.properties will look like this.



build.properties

Similarly the bin.includes and bin.excludes are used to control the folders involved in the binary build. Again, notice that source folders and files like .classpath, MANIFEST.MF and plugin.xml have not been added to src.includes because they are not required in source build.


Saturday, September 19, 2009

[3.6 M2] Spelling check on help editor source pages

In 3.6 Milestone 2 spelling check will also be available on help editor source pages (bug 286203). By help editors I mean Context Help editor, Table of Contents editor and Cheat Sheet editor. These editors has a source page which reveals the actual XML contents of the files. The page will now check spelling for all the quoted strings (Text enclosed with single or double quotes). The XML comments, tags and attributes will be excluded from spell checking.



Cheat Sheet Editor - Source Page
The spelling errors are marked with usual annotations that you would find in any other place such as properties file. Quick fix will be available for these annotations, suggesting the possible correct spellings.



Quick fixing spelling errors
Customizing spelling check preferences

The spell check options can be controlled from the Spelling Preference page. See Windows -> Preferences -> General -> Editors -> Text Editors -> Spelling.



Spelling Preferences page
This page controls the dictionary and spell checking rules.
Few more enhancements are already planned specific to the XML format of these help files. See bug 289926. Feel free to add anything to it that you feel will make life easier.

Saturday, August 29, 2009

VM Arguments in Eclipse

Eclipse.ini
Eclipse.ini has been explained in detail here. It is used to control the Eclipse start up. This text file will contain the options that can also be provided from command line when invoking Eclipse.

Two of them are -vm and -vmargs. These and other such arguments have been explained here in detail.


-vm <path to java vm> (Executable, Main)
This is the path to the JRE/JDK which will be used to run Eclipse. Eclipse supports Java 1.42 and above. The path should be absolute. The path should point to the bin folder but can also point to java.exe, java lib folder or the Java VM execution environment description file (whatever that is). The path should follow  -vm and should one the separate line right after it.

-vm
C:\Program Files\IBM\Java50\bin

This path is copied to eclipse.vm and can be accessed at runtime using System.getProperty("eclipse.vm").


-vmargs [vmargs*] (Executable, Main)
These are arguments are passed as is to JVM. Used to configure JVM that would run Eclipse. This should be last argument in eclipse.ini as anything that follows it is passed to JVM and eclipse doesn't bothers about it. Again, the value is available as system property "eclipse.vmargs" at runtime.

A typical eclipse.ini will have -Xms and -Xmx following the -vmargs. They define the minimum and maximum heap size respectively. Again, each argument has to be defined on a separate line.


-vmargs
-Xms40m
-Xmx256m

This means the JVM launching Eclipse will have minimum heap size of 40 MB and a max of 256MB.

Target Definition
The target definition editor or wizard has an Arguments tab. This page has a section which deals with VM Arguments. The VM Arguments specified here are used to initialize the Run configurations. This section has an Import... button which produces an Import Arguments dialog. The import argument dialog scans the selected bundle containers and presents the VM Arguments from them. They do have no effect on build.

Run Configuration

The run configurations generally have an Arguments tab. This tab has a section for VM Arguments. Values specified here are sent to the JVM while launching.

The Eclipse Application Run Configuration defaults the VM Arguments from the active target platform.

Thursday, August 20, 2009

how do i install pde

PDE or Plug-in Development Environment is part of Eclipse SDK. If you have using Eclipde IDE for Java Developers or some other distribution like this then you will have only Eclipse Platform and not the SDK. The various distribution packages are listed here.

The SDK can be installed from the update site. The URL for Galeleo repository is Galileo - http://download.eclipse.org/releases/galileo. Use Help > Install new software... to install the new features to your existing eclipse installation.

Only PDE too can be installed. Open the Install (new software) wizard and use link mentioned above. Filter the results for "Eclipse plug-in development environment". The PDE will be available as "Eclipse plug-in development environment" under "General Purpose Tools" category.


Install wizard
And how to install Eclipse? Well, there is no installer. Just download it and unzip it wherever you wish on your hard disk. To uninstall, just delete it. Eclipse needs JRE (or JDK) 1.4.2 or above. So make sure one is available in your path settings.

Wednesday, August 19, 2009

Adding SpellChecking to custom editors

Eclipse provides a nice framework to use spell checking in dialog and editors. Chris has tipped about it here. However, if you are using a custom editor then you have to put few pieces together yourself. Consider an XML editor. We would want the spelling check only for the string in attribute values and not the XML Tags.

Let us try and implement this. We can start with the XML editor template provided by PDE.

1. Create a new plug-in using "Plug-in with an Editor" template.

New Plug-in Wizard
2.  This will create a simple XML Editor by extending TextEditor.

3. The XMLEditor uses XMLConfiguration to set the source viewer configuration.

public XMLEditor() {
 super();
 colorManager = new ColorManager();
 setSourceViewerConfiguration(new XMLConfiguration(colorManager));
 setDocumentProvider(new XMLDocumentProvider());
}

Modify the constructor for XMLConfiguration and pass the preference store. It will be needed by its super class.

public XMLEditor() {
 super();
 colorManager = new ColorManager();
 setSourceViewerConfiguration(new XMLConfiguration(colorManager, getPreferenceStore()));
 setDocumentProvider(new XMLDocumentProvider());
} 
 
4. The XMLConfiguration basically hooks various listeners, providers and assistants to the Editor. The template generated code will have it sub-classed from SourceViewerConfiguration. Change it to TextSourceViewerConfiguration. The TextSourceViewerConfiguration provides out of the box spell checker, spelling annotation, problem hover text, quick fixes, etc.

public class XMLConfiguration extends TextSourceViewerConfiguration { //SourceViewerConfiguration {
...
public XMLConfiguration(ColorManager colorManager, IPreferenceStore preferenceStore) {
 super(preferenceStore);
 this.colorManager = colorManager;
}
...

The preferenceStore will be used for checking dictionary and other preferences. They can be set from Window > Preferences > General > Editors > Text Editors > Spelling .

5. Override the getReconciler function. The implementation for getReconciler provided by TextSourceViewerConfiguration uses a SpellingReconcileStrategy. The SpellingReconcileStrategy will spell check the whole document. Since its an XML Editor, only quoted strings should be spell checked and the XML tags should be skipped.

/**
* Providing custom XMLSpellingReconcileStrategy to enable spell checking for only strings
*/
/* (non-Javadoc)
* @see org.eclipse.jface.text.source.SourceViewerConfiguration#getReconciler(org.eclipse.jface.text.source.ISourceViewer)
*/
public IReconciler getReconciler(ISourceViewer sourceViewer) {
 XMLSpellingReconcileStrategy strategy = new XMLSpellingReconcileStrategy(sourceViewer, EditorsUI.getSpellingService());
 Reconciler reconciler = new Reconciler();
 reconciler.setReconcilingStrategy(strategy, XMLStringPartitionScanner.XML_STRING);
 reconciler.setDocumentPartitioning(XMLStringPartitionScanner.XML_STRING);
 return reconciler;
}

6. XMLStringPartitionScanner will be our custom document partition scanner to identify the quoted string. The template generated code will make use of XMLPartitionScanner. This class specifies the rules for identifying the XML tags and comments. Since, the quoted string are part of XML Tag only, we can not use this partition scanner. Therefore, we write our custom document partition scanner and at supply it to the reconcile strategy.

public class XMLStringPartitionScanner extends RuleBasedPartitionScanner {

 public final static String XML_STRING = "__xml_string";

 public XMLStringPartitionScanner() {
  IToken stringToken = new Token(XML_STRING);
  IPredicateRule[] rules = new IPredicateRule[1];

  rules[0] = new MultiLineRule("\"", "\"", stringToken, '\\');
  setPredicateRules(rules);
 }
}

7. XMLSpellingReconcileStrategy will extend SpellingReconcileStrategy since it already knows how to collect spelling problem, etc. Only reconcile is what needs to be overridden.

public class XMLSpellingReconcileStrategy extends SpellingReconcileStrategy {

 public XMLSpellingReconcileStrategy(ISourceViewer sourceViewer, SpellingService spellingService) {
  super(sourceViewer, spellingService);
 }
 ...
 public void reconcile(IRegion region) {

  AbstractDocument document = (AbstractDocument) getDocument();
  IDocumentPartitioner docPartitioner = document.getDocumentPartitioner(XMLStringPartitionScanner.XML_STRING);

  IAnnotationModel model = getAnnotationModel();
  if (region.getOffset() == 0 && region.getLength() == document.getLength()) {
  //reconciling whole document
  super.reconcile(region);
  deleteUnwantedAnnotations();
  } else {
   //partial reconciliation
   //preserve spelling annotations first
   Iterator iter = model.getAnnotationIterator();
   Map spellingErrors = new HashMap(1);
   while (iter.hasNext()) {
    Annotation annotation = (Annotation) iter.next();
    if (annotation instanceof SpellingAnnotation) {
     SpellingAnnotation spellingAnnotation = (SpellingAnnotation) annotation;
     Position position = model.getPosition(spellingAnnotation);
     String contentType = docPartitioner.getContentType(position.getOffset());

     if (XMLStringPartitionScanner.XML_STRING.equalsIgnoreCase(contentType)) {
      spellingErrors.put(spellingAnnotation, model.getPosition(annotation));
     }
    }
   }

   //reconcile
   super.reconcile(region);

   //restore annotations
   model = getAnnotationModel();
   iter = spellingErrors.keySet().iterator();
   while (iter.hasNext()) {
    Annotation annotation = (Annotation) iter.next();
    model.addAnnotation(annotation, (Position) spellingErrors.get(annotation));
   }
   deleteUnwantedAnnotations();
  }

 }

 /**
 * Deletes the spelling annotations marked for XML Tags
 */
 private void deleteUnwantedAnnotations() {
  AbstractDocument document = (AbstractDocument) getDocument();
  IDocumentPartitioner docPartitioner = document.getDocumentPartitioner(XMLStringPartitionScanner.XML_STRING);
  IAnnotationModel model = getAnnotationModel();
  Iterator iter = model.getAnnotationIterator();

  while (iter.hasNext()) {
   Annotation annotation = (Annotation) iter.next();
   if (annotation instanceof SpellingAnnotation) {
    SpellingAnnotation spellingAnnotation = (SpellingAnnotation) annotation;
    Position position = model.getPosition(spellingAnnotation);
    String contentType = docPartitioner.getContentType(position.getOffset());
    if (!XMLStringPartitionScanner.XML_STRING.equalsIgnoreCase(contentType)) {
     model.removeAnnotation(spellingAnnotation);
    }
   }
  }
 }
}

8. Putting it all together

The XMLStringPartitionScanner is our document partition scanner. It uses the MultiLineRule to locate the quoted string. XMLDocumentProvider adds it to the XML document.

public class XMLDocumentProvider extends FileDocumentProvider {

 protected IDocument createDocument(Object element) throws CoreException {
  IDocument document = super.createDocument(element);
  if (document != null) {
   IDocumentPartitioner partitioner = new FastPartitioner(new XMLPartitionScanner(), new String[] {XMLPartitionScanner.XML_TAG, XMLPartitionScanner.XML_COMMENT});
   partitioner.connect(document);
   document.setDocumentPartitioner(partitioner);

   //Adding our string partition scanner to the document
   partitioner = new FastPartitioner(new XMLStringPartitionScanner(), new String[] {XMLStringPartitionScanner.XML_STRING});
   partitioner.connect(document);
   ((AbstractDocument) document).setDocumentPartitioner(XMLStringPartitionScanner.XML_STRING, partitioner);
  }
  return document;
 }
}

XMLPartitionScanner is generated by the template and it locates XML tags and comments. Since quoted strings are part of tags, we added XMLStringPartitionScanner too.

The XMLConfiguration finally wires all the content types to PresentationReconciler

9. After thoughts

All the infrastructure is already in place for enabling spell checking. But custom editors need some extra wiring. If finer control is needed on the quick fix assistant override getQuickAssistAssistant function and for controlling the hover message getTextHover will do the trick.

10. Source code


The archived project can be downloaded from here.

11. Disclaimer :-)

This code doesn't cover all the scenarios as it is just an example. These things I figured out while fixing the bug #286203. Feel free to add your suggestions and point out any mistakes you see.Eclipse provides a nice framework to use spell checking in dialog and editors. Chris has tipped about it here. However, if you are using a custom editor then you have to put few pieces together yourself. Consider an XML editor. We would want the spelling check only for the string in attribute values and not the XML Tags.

Sunday, July 26, 2009

Cheat Sheet for configuring API Tooling for existing projects

This topic are covered in previous post too. Here am providing a Cheat Sheet for easy access. Do feel free to post your feedback/suggestions/bugs in comments to this post.

The process of registering a cheat sheet in your Eclipse installation can be found in Eclipse help.

Sunday, July 19, 2009

Friday, July 17, 2009

System library validation

This is a new feature available in Eclipse 3.5.  API Tools can now validate the code against the Execution Environment mentioned in the bundle manifest.

Consider a scenario where the system JRE on developers machine (where Eclipse IDE is running) is version 1.5. But the bundle execution environment will be JVM 1.4. This is such cases, it is very easy to make the mistakes of accessing the functions that may not be available at runtime.

API Tooling can catch such errors easily if the Execution Environments are available.

Installing Execution Environments

Open the API Tooling preferences (Window > Preferences > Plug-in Development > API Errors/Warnings).


API Errors/Warnings
By default the severity level is set to Ignore. Change it to Warning or Error. Click the link install them now. This shall open the Install wizard.


Install wizard

Work with the Galileo release site Galileo - http://download.eclipse.org/releases/galileo. The execution environments are categorized under General Purpose Tools > PDE/API Tools Environment Descriptions. Install the ones you need.

Once installed the API preferences page will show the available execution environments.


API Errors/Warnings

System Library Validation in action

Consider a plug-in is execution environment marked as Java 1.4.


Execution Environment section on Overview page of Manifest Editor


Manifest File

If such a plug-in tries to access Java 1.5, there won't be any compilation errors (we will discuss the JDK Compliance level towards the end of this post).

For example, see the snippet below.

String name ="ankur";
name.contentEquals(new StringBuilder("ankur"));

This code will compile fine but will fail at runtime as contentEquals won't take StringBuilder in 1.4. That's an 1.5 API.

Once the API Preference for System Libraries is set to warning or error, same will be reported in the Problems view.



API Tooling validating against System Library

Compiler compliance level Vs System Library Validation

The problem we just discussed above can be also caught by setting the compiler compliance level appropriately. Where it differs is that the compiler setting are restricted to the JDK version. The API Tooling focuses on the execution environment from OSGi perspective. As you would have noticed there are non-Java specific environment descriptions too like CDC-Foundation and OSGi/Miminum.

Another major difference is that API Tooling does not need JRE/JDK. It checks the usage against the environment descriptions. The descriptions are just the environment API and thus occupy very less space. For example, the 1.5 JRE takes close to 50MB while the descriptions for the same takes less than 2 MB.

Thursday, June 25, 2009

Galileo is here!!

If you are reading this and you probably know Eclipse Galileo is out today!!. Have you downloaded it already? No? what are you waiting for? :-)

Tuesday, June 23, 2009

Configuring API Tooling for existing projects

API Tooling is not a new feature. It came out of incubation in 3.4 and has been explained nicely at developerworks and eclipse wiki. What I would cover below is how to do it for existing projects and the strategy to continue with it.
  1. Setting up API Tooling
  2. Note: API Tooling works only for plug-in projects. It can not be used for Java, Feature and Update site projects API Tooling for a project is setup by attaching an API Nature to the project. When completed you will be prompted to make a baseline.
  3. Baselining
  4. A baseline is a snapshot (set) of plug-ins. The AP Tooling expects not just the plug-ins you exported from your workspace, but also the dependent plug-ins. If the complete set is not available, the Compare with baseline will not work. If your plug-ins makes a product, then export the product configuration and point to it as baseline. If its a set of features then just exporting them will not be enough. The dependent plug-ins are required too. You pull them all by modifying your ant build script. I don't know any shortcut/simple way of achieving this.
  5. Comparing with baselines
  6. API Tooling is a new view available with3.5. It can be quick accessed through context menu (Compare with > API Baseline...) on a project, a folder, a package or any java resource in package explorer. Compare Baseline compares the selected resource with the selected baseline. Any changes are reported in the API. Note that you can compare two baseline with each other here. Its the code against the selected baseline.
  7. Going ahead
  8. Having a baseline on each minor version will be a overkill. I would have one for each major release and one for each milestone during the development cycle. API Tooling can also be integrated in the PDE Build. Look for Eclipse help contents PDE Guide > Reference > API Tools Ant Tasks. For a quick list type apitooling in build.xml and press Ctrl + Space (content assist). API Tooling view allows exporting the results as XML or HTML. Same can be automated using ant tasks.

Saturday, June 13, 2009

When a n00b met Galileo

First time I used Eclipse it was Europa. Completely missed Ganymede. And it was only early this year I saw Galileo taking shape. So this review comes from the perspective of a relatively novice plug-in developer.

Things I liked
  1. API Tooling
  2. This one is really impressing. I know its not new and had been around @since 3.4. But the new baseline compare feature is really lovely. I remember spending hours, sifting through the CVS history, to figure out who changed that function signature and when.
    With the new API Tooling view, we can now compare the code with any baseline and figure out what all got changed. Chris explains it in detail here.
  3. Hyperlinking
  4. Wow! Just Ctrl + Click on the variable, function, whatever....it takes you to the declaration. F3 is cool. Does the same trick. But when I am browsing the code, following the call stack, Ctrl + Click is my scout. And where it betters the F3 is if its a method from interface, it lets you choose where you wish to go - declaration or the implementation. Mostly its the later one we want, isn't it?
    Hyperlinking
  5. Export wizard enhancements
  6. The new "Use class file compiled in the workspace" option is such a time saver. I almost always have the "Build Automatically" checked. Glad that I don't have to wait for all the features to compile all over again when I export then. It just picks the class files from the bin directly. Also, its not very easy to export the plug-ins along with source bundles.
  7. P2
  8. It took a while to figure out just that P2 means Platform Provisioning (correct me if am still wrong). This is perhaps the next big thing in Eclipse, but frankly I have no clue how it works and will take some time to catch up. Then what  I like about it? Installation history and the fact that I can now actually 'revert' back the feature I installed for testing. Don't have to make a copy of eclipse to try it over it. If I don't like I can get rid of it.

Things I wish for
I feel the API tooling is yet to grow to its full potential. I'll like to see support for tentative API and better reports. The PDE UI need lot of working. Like Cheat Sheet editor is a PITA when you have to bulk update. P2 may have liberated the release engineers but I strongly feel it needs lot of help material to reduce the entry barrier for n00bs like me.

The wish-lists are always endless. With Galileo edition, Eclipse has come a really long way. And with E4 the vision reaches out farther than I can see. Glad to be part of Eclipse community.

Saturday, June 6, 2009

[New in Eclipse 3.5] Target Definition Editor make over

The new Target Platform story has resulted in a few changes to the Target Definition Editor.

The Environment page remains unchanged. The Overview page has been renamed to Definition page. The page is less confusing now. Earlier it had the workspace target topped with additional directories. But now its just a set of locations which can be any directory, eclipse (or eclipse based product) installation, features or can even be an update site.




Target Definition Editor - Definition Page

The Content page too as gone simpler. It not only shows the constituent plug-ins for the selected locations but also helps in choosing the individual plug-ins out of each location. The plug-ins can be filtered and also be grouped by their location or the file path. As before, the Add Required button adds the required plug-ins for the selected ones. And the good thing is that it searches for the required plug-ins in all the available locations.


Target Definition Editor - Content Page

Monday, June 1, 2009

[New in Eclipse 3.5] Plug-ins Import Wizard refurbished

The Import Plug-ins and Fragments wizard has gone under knife in Galileo release. It has been made simpler and consistent with the new target platform story.

Before & After






as seen in Eclipse 3.4.2                           new look in Eclipse 3.5
The import has been made simpler by providing three simple options to import from.
  1. Active Target Platform
  2. The Target Platform Preference page now allows you to maintain various target definitions.  However, only one can be active at a time (of course). It is this target that the workspace is built against. So this is option to be chosen if a plug-in has to be imported from the current target platform.
  3. Registered Target Definitions
  4. By 'Registered' Target Definitions I mean the local target definitions (using Target Platform Preference page) or any target definition file that exists in the open projects. Any external target definition file (outside workspace) that was opened in current session is also remembered.  Simply speaking, any target definition that appears on the Target Platform Preference page. Using this option, a plug-in from any of the these target can be selected for import.
  5. Directory
  6. This one is easy. Choose any plug-from the specified directory location. The option is smart enough to locate and pick  from the "plugins" directory also under the location mentioned.
The Features Import wizard remains the same. No changes to it.

Sunday, May 31, 2009

Target Platform State view : wish-list

In previous post we discussed the new Target Platform State view. I feel the view can be enhanced more and can be leveraged as a quick watch on the active Target. In 3.6 I would like to see
  1. the view displaying the name of the active Target (276981).
  2. acting as a quick launch to Edit Target Definition wizard.
  3. a "collapse all" button.
  4. How about color highlighting the plug-ins referred by workspace plug-ins?

Give it a try and let us know your wish-list.

Saturday, May 30, 2009

[New in Eclipse 3.5] Target Platform State view

The new target story in Eclipse 3.5 allows you to have multiple targets in your workspace. With this one really needs a means to see what constitutes the active target definition. For this reason, we now have a new view - Target Platform State (I don't like to call it TPS view :-)). It can be found in Window -> Show View -> Other... -> Plug-in Development -> Target Platform State.

This is how it looks like


Target Platform State view

What is it good for?
The target platform state view displays the bundles selected by the active target definition. And also their version and the location they are getting picked from. Thus, if you are facing an issue such as plug-in dependency not getting resolved as expected or wrong version of the plug-in getting picked up, the target platform state is where you should be looking.

It also displays, for each plug-in, the required plug-ins and the packages it imports and from where.



Required Plug-ins and Imported Packages
The view is a filtered one.



view filtered for org.eclipse.pde.ui

And when the "Show only unresolved plug-ins" menu choice from the view menu is used, the view only those plug-ins are shown whose dependencies can not be resolved. With all dependencies resolved this one should show a blank view. The "Show leaf plug-ins" will show only those plug-ins on whom no other plug-in depends. They are the leaf of the dependency tree.


Target with only Mylyn plug-ins without Eclipse SDK

Thursday, May 28, 2009

[New in Eclipse 3.5] VM Arguments can be now imported to Target Definition

The Target Definitions have environment settings which are used as template to create launch configurations. One such setting is the VM Arguments (discussed in more detail here). The VM Arguments are used to tune the JVM and one of the most commonly used arguments are -Xms and -Xmx (minimum and maximum heap size). Thus, if a heap size is specified, it will then be used to initialize the launch configurations. That is, the same VM arguments are copied.


Import Arguments wizard
In 3,5, the VM Arguments section comes with an Import Arguments wizard. It collects and displays VM arguments from all the bundle containers that form that particular target definition. A general assumption used to be that the VM arguments will be reflected in the target and launch configurations automatically. Because there could be conflicting values, Eclipse can not be sure which one to pick. That is why the arguments were left at developer's discretion. Since the expectation was to get the same values for arguments, we now have the import wizard that simplifies this copy-paste.

The Import Argument wizard is available both on Environment page of Target Editor as well as Arguments tab of  Edit Target Definition wizard.



Arguments section on Environment page of Target Editor
The Edit Target Definition wizard gets invoked when "Edit..." button is clicked on Target Preference page.


Import Arguments wizard

Clicking OK on Import Arguments wizard inserts the selected arguments in the arguments text box. It does not checks if they were already present.

Tuesday, May 26, 2009

Source Bundles

These links are good read to know more about the Source Bundles and a bit of history behind.