The Object Teams Blog

Adding team spirit to your objects.

Posts Tagged ‘ui

Follow-up: Object Teams Tutorial at EclipseCon 2011

leave a comment »

At our EclipseCon tutorial we mentioned a bonus excercise, for which we didn’t have the time at the tutorial.

Now it’s time to reveal the solution.


Implement the following demo-mode for the JDT:

• When creating a Java project let the user select:
❒ Project is for demo purpose only
• When creating a class in a Demo project:
insert class name as “Foo1”, “Foo2” …”

So creating classes in demo mode is much easier, and you’ll use the names “Foo1″… anyway 🙂
(See also our slides (#39)).

Granted, this is a toy example, yet it combines a few properties that I frequently find in real life and which cause significant pains without OT/J:

  • The added behavior must tightly integrate with existing behavior.
  • The added behavior affects code at distant locations,
    here two plug-ins are affected: org.eclipse.jdt.ui and org.eclipse.jdt.core.
  • The added behavior affects execution at different points in time,
    here creation of a project plus creation of a class inside a project.
  • The added behavior requires to maintain more state at existing objects,
    here a JavaProject must remember if it is a demo project.

Despite these characteristics the task can be easily described in a few English sentences. So the solution should be similarly concise and delivered as a single coherent piece.


With a little knowledge about the JDT the solution can be outlined as this

  • Add a checkbox to the New Java Project wizard
  • When the wizard creates the project mark it as a demo project if the box is checked.
  • Let the project also count the names of Foo.. classes it has created.
  • When the new class wizard creates a class inside a demo project pre-set the generated class name and make the name field unselectable.

From this we conclude the need to define 4 roles, playedBy these existing types:

  • org.eclipse.jdt.ui.wizards.NewJavaProjectWizardPageOne.NameGroup:
    the wizard page section where the project name is entered and where we want to add the checkbox.
  • org.eclipse.jdt.ui.wizards.NewJavaProjectWizardPageTwo:
    the part of the wizard that triggers setup of the JavaProject.
  • org.eclipse.jdt.core.IJavaProject:
    this is where we need to add more state (isDemoProject and numFooClasses).
  • org.eclipse.jdt.ui.wizards.NewTypeWizardPage:
    this is where the user normally specifies the name for a new class to be created.

Note, that 3 classes in this list resided in org.eclipse.jdt.ui, but IJavaProject is from org.eclipse.jdt.core, which leads us to the next step:

Plug-in configuration

Our solution is developed as an OT/Equinox plug-in, with the following architecture level connections:

This simply says that the same team demohelper.ProjectAdaptor is entitled to bind roles to classes from both org.eclipse.jdt.ui and org.eclipse.jdt.core.
One more detail in these extensions shouldn’t go unmentioned: Don’t forget to set “activation: ALL_THREADS” for the team (otherwise you won’t see any effect …).

Now we’re ready to do the coding.

Implementing the roles

protected class DialogExtender playedBy NameGroup {
        protected SelectionButtonDialogField isDemoField;
        void createControl(Composite parent) <- after Control createControl(Composite composite)
                with { parent <- (Composite) result }
        private void createControl(Composite parent) {
                isDemoField= new SelectionButtonDialogField(SWT.CHECK);
                isDemoField.setLabelText("Project is for demo purpose only");
                isDemoField.doFillIntoGrid(parent, 4);

Our first role adds the checkbox. The implementation of createControl is straight-forward UI business. Lines 22,23 hook our role method into the one from the bound base class NameGroup. After the with keyword, we are piping the result from the base method into the parameter parent of the role method (with a cast). This construct is a parameter mapping.

Here’s the result:

Next we want to store the demo-flag to instances of IJavaProject, so we write this role:

protected class EnhancedJavaProject playedBy IJavaProject {
        protected boolean isDemoProject;
        private int numFooClasses = 1;
        protected String getTypeName() {
                return "Foo"+(numFooClasses++);

Great, now any IJavaProject can play the role EnhancedJavaProject which holds the two additional fields, and we can automatically serve an arbitrary number of class names Foo1 …
In the IDE you will actually see a warning, telling you that binding a role to a base interface currently imposes a few restrictions, but these don’t affect us in this example.

Next comes a typical question: how to transfer the flag from role DialogExtender to role EnhancedJavaProject?? The roles don’t know about each other nor do the bound base classes. The answer is: use a chain of references.

protected class FirstPage playedBy NewJavaProjectWizardPageOne {
        DialogExtender getFNameGroup() -> get NameGroup fNameGroup;
        protected boolean isDemoProject() {
                return getFNameGroup().isDemoField.isSelected();
protected class WizardExtender playedBy NewJavaProjectWizardPageTwo {
        FirstPage getFFirstPage() -> get NewJavaProjectWizardPageOne fFirstPage;
        markDemoProject <- after initializeBuildPath;
        private void markDemoProject(EnhancedJavaProject javaProject) {
                if (getFFirstPage().isDemoProject())
                        javaProject.isDemoProject = true;

Role WizardExtender intercepts the event when the wizard initializes the IJavaProject (line 46). Method initializedBuildPath receives a parameter of type IJavaProject but the OT/J runtime transparently translates this into an instance of type EnhancedJavaProject (this – statically type safe – operation is called lifting). Another indirection is needed to access the checkbox: The base objects are linked like this:

NewJavaProjectWizardPageTwo —fFirstPage—> NewJavaProjectWizardPageOne —fNameGroup—> NameGroup

This link structure is lifted to the role level by the callout bindings in lines 35 and 44.

We’re ready for our last role:

protected class NewTypeExtender playedBy NewTypeWizardPage {                                                              
        void setTypeName(String name, boolean canBeModified) -> void setTypeName(String name, boolean canBeModified);                                                                      
        void initTypePage(EnhancedJavaProject prj) <- after void initTypePage(IJavaElement element)
                with { prj <- element.getJavaProject() }
        private void initTypePage(EnhancedJavaProject prj) {
                if (prj.isDemoProject)
                        setTypeName(prj.getTypeName(), false);

Here we intercept the initialization of the type page of a New Java Project wizard (lines 66,67). Another parameter mapping is used to perform two adjustments in one go: fetch the IJavaProject from the enclosing element and lift it to its EnhancedJavaProject role. This follows the rule-of-thumb that base-type operations (like navigating from IJavaElement to IJavaProject) should happen at the right hand side, so that we are ready to lift the IJavaProject to EnhancedJavaProject when the data flow enters the team.

The EnhancedJavaProject can now be asked for its stored flag (isDemoProject) and it can be asked for a generated class name (getTypeName()). The generated class name is then inserted into the dialog using the callout binding in line 64. Looks like this:

See this? No need to think of a good class name 🙂


So that’s it. All these roles are collected in one team class and here is the fully expanded outline:

All this is indeed one concise and coherent module. In the tutorial I promised to do this no more than 80 LOC, and indeed the team class has 74 lines including imports and white space.

Or, if you are interested just in how this module connects to the existing implementation, you may use the “binding editor” in which you see all playedBy, callout and callin bindings:

The full sources are also available for download.

have fun


Written by Stephan Herrmann

April 14, 2011 at 21:14

Meta Feedback

leave a comment »

Last Friday I received some wonderful meta-feedback. What’s that you’ll say?
It’s feedback on feedback, or, second order feedback.

First Order Feedback

Initially, I’m thinking of feedback whereby a tool tells its user what s/he’s done wrong and where to go in order to improve. As I mentioned earlier, I’m not interested in a tool that just works when it works, as that might require its users to get everything 100% correct right from the beginning. In our business I’m interested in tools that help the user to get it to work, from initial buggy attempts towards a full working solution.

So, when working on the Object Teams Development Tooling, how can we make the tool speak to the user in really helpful ways?

First we really care to give precise error messages and warnings regarding all kinds of situations that look funny, strange or plain bogus. Last time I counted the OT/J compiler featured 314 messages specific to OT/J. This is excellent for a seasoned OT/J developer but someone still trying to learn the language might be a little bit puzzled by messages like:

Fragile callin binding: base method requires a result of type {0}, which is not provided in this binding. If no base call is issued, the result will be missing, causing a ResultNotProvidedException to be thrown (OTJLD 4.3(e)).

The clue on how to help the puzzled users lies in the suffix “OTJLD 4.3(e)”: that’s exactly the paragraph in the OT/J Language Definition, that defines what’s going on here. But what’s a reference like “§4.3(e)” good for? So the next thing we added to the OTDT was a context menu action on any OT/J related problem in the Problems view:

What do you see:

  • At the top you see an editor with an underlined, buggy piece of code
  • Next you see the Problems view with the corresponding error message
  • Next you see a context menu on the problem with an entry “Go to Language Definition“.
  • At the bottom finally you see a small extract from the language definition, exactly that paragraph that is violated by the buggy code. If that doesn’t provide sufficient context there are plenty of hyperlinks and breadcrumbs that help to find the required explanation

This is our specific feedback system and I think its already quite nice, however …

Second Order Feedback

Last Friday I presented Object Teams at the Vienna Helios Demo Camp. When I showed the “Go to Language Definition” action Peter Kofler gave some excellent feedback on our feedback system. He must have feeled the too-much-stuff syndrome you can easily see when looking at the screenshot above. So he requested that the same action be available even without the Problems view. So once back home I file bug 318071. In the most recent build you now have two more options:

Use the context menu of the left gutter:

Use the toolbar of the problem hover

Need I say that adding a button to the problem hover is not normally possible? With the action already in place the following OT/J code is all we need to integrate into the JDT/UI’s implementation of that hover:

 * Add OT-Support to hovers for java problems.
 * @author stephan
 * @since 0.7.0 (Incubation at
@SuppressWarnings({ "restriction", "decapsulation" })
public team class HoverAdaptor {
        /** Add the "Go to Language Definition" action to the hover's toolbar. */
        protected class ProblemHoverAdaptor playedBy ProblemInfo {
                void addAction(ToolBarManager manager, Annotation annotation) <- after void fillToolBar(ToolBarManager manager, IInformationControl infoControl)
                        base when (isOTJProblem(base.annotation))
                        with {  manager    <- manager,
                                        annotation <- base.annotation }
                void addAction(ToolBarManager manager, Annotation annotation) 
                        manager.add(ShowOTJLDAction.createAction(null/*site*/, annotation.getText()));
                static boolean isOTJProblem(Annotation annotation) {
                        if (annotation instanceof IJavaAnnotation) {
                                int problemId = ((IJavaAnnotation) annotation).getId();
                                return problemId > IProblem.OTJ_RELATED && problemId < IProblem.TypeRelated;
                        return false;

Thanks Peter, I think your RFE made a clear point for usability of the OTDT!

Written by Stephan Herrmann

June 28, 2010 at 16:38

Posted in Eclipse, Object Teams, OTDT, OTJLD

Tagged with ,