Buildship on the mission to Mars

2286865364_900e1fe74e_z

Gradleware decided to implement their own tooling solution for building project within the Eclipse IDE and the Buildship project was born.

Selection_103

Since march there are currently 123 commits on the master branch of the GitHub project, which can be found here: https://github.com/eclipse/buildship

We from the vogella company will be working together with Gradleware and hopefully many other contributors as well.

Therefore we started a new tutorial concerning the Buildship project, which will be constantly updated, when new features will be available. See http://www.vogella.com/tutorials/EclipseGradle/article.html
Detailed information can also be found on GitHub: https://github.com/eclipse/buildship

Here is a little impression for you:

gradle_blog_teaser

As I already “println” in the build script, please help us by contributing to the Buildship project. So make your hands dirty, read the tutorial and give the Buildship project a try.

I’d also like to quote Wayne Beaton (Blog entry concerning Buildship):

Great Fixes for Buildship will qualify for the Great Fixes for Mars Skills Competition!

 

 

Posted in Eclipse, Simon Scholz, vogella | Tagged , , , , , | 1 Comment

Welcome Andrey Loskutov as a new eclipse.platform.ui Committer

I would like to welcome Andrey as new platform.ui committer. Andrey is a very active Eclipse tools developer who maintain popular Eclipse tools like the Eclipse Findbugs plug-in and AnyEdit. And now is is already the second most active developer of platform.ui takeling a bunch of critical and difficult issues.

andrey

Welcome Andrey!

See the message on the platform.ui mailing list. See also Andrey blog post about this topic.

Posted in Eclipse, Lars Vogel, Other | 1 Comment

Identifying the GTK version your Eclipse IDE is using

To identify which GKT version your Eclipse IDE under Linux is using go to Help -> About -> Installation Details and select the Configuration tab. Look there for
org.eclipse.swt.internal.gtk.version property. You can also use the “Copy to Clipboard” button so that you can copy the details into a text editor to search for it.

In my case it shows: org.eclipse.swt.internal.gtk.version=3.12.2 which obviously means that I’m using GKT3.

Thanks to Alexander Kurtakov for the tip.

Posted in Eclipse, Lars Vogel | Tagged | 1 Comment

Gerrit build trigger for eclipse.platform.runtime active

Based on an idea from Brian de Alwis, we (the Eclipse platform.ui team) were able to activate our Gerrit build trigger for eclipse.platform.runtime.

This means we now get build validation for the runtime component and that we can start including your tests into the Gerrit build trigger run. This hopefully accelerates the Gerrit review process for contributions, as the basic technical validation is done by Gerrit.

Posted in Eclipse, Lars Vogel | Tagged | Comments Off on Gerrit build trigger for eclipse.platform.runtime active

Dealing with whitespace legacy in Eclipse projects

One of most annoying things during Gerrit reviews are “unnecessary whitespaces” change discussion. This applies for the contributors and the reviewers.

As we in the Eclipse platform.ui project currently see a flow incoming Gerrit reviews from various people, I want to minimize these issues to keep everyone involved in this process happy. Therefore I started to cleanup the existing whitespaces and a activate the save actions on the project to avoid the creation of new whitespace.

If you also would like to do this use Source -> Clean-up on your source folder and activate afterwards the “Remove unnecessary whitespace” save action via the project setting.

Eclipse can be instructed to ignore these changes in its blame annotations via the “Ignore whitespace changes” preference setting in Team -> Git.

With these changes you bite the bullet once but afterwards the Gerrit review process becomes much more enjoyable.

Posted in Eclipse, Lars Vogel | 3 Comments

Gerrit plug-in to update Eclipse Bugzilla for Gerrit activities

I big thanks to the Eclipse webmaster Denis Roy who fixed Bug 434811. This Gerrit plug-in updates Bugzilla bugs automatically with Gerrit and commit references. See the bug for details and for the ongoing discussion how to improve the message format.

A great step to simplify our Eclipse committer workflow. Thanks again to Denis.

Posted in Eclipse, Lars Vogel | 1 Comment

Honored to become Platform UI co-lead

It is a great honor to help in the role of the Platform UI co-Lead together with Paul Webster. Paul was in the past a great mentor for me and I’m very happy to continue to work with him.

We at the vogella GmbH follow three goals, two of them apply in my option also for our platform work:

  • Improvement over initial perfection
  • Automation over manual work

As a platform.ui committer I’m contributing since a while a lot to the Platform UI project and I’m happy to extend this activity. Here are some of the work items which I think are important for the Eclipse Platform UI project:

  • Simplify the contribution process to the Eclipse platform
  • Clean up the platform code for ease maintenance in the future
  • Enable the existing tests during our Tycho build to ensure quality of the code
  • Ensure that the Eclipse IDE remains the best IDE out there
  • Make it easier to use the Eclipse 4 API for IDE plug-in development
  • Improve our CSS story
  • Improve the stability and the performance of the platform

The overall target is to extend the number of contributors and committers in the Eclipse platform project.

Thanks a lot to the former co-lead Daniel Rolka for his great work. I’m looking forward to help the platform UI project.

Posted in Eclipse, Lars Vogel | Tagged | 8 Comments

NatTable context menus with Eclipse menus

In this blog post I will explain how to add context menus to a NatTable instance and how it is possible to combine menus configured via Eclipse Application Model with NatTable menus. It is based on the enhancements added in NatTable 1.2.0, but I will also explain the differences to prior NatTable versions and the issues that lead to the enhancements.

I will also show some basics and the usage with Eclipse 3.x menus.

Basics

In SWT it is possible to attach a menu to a control by calling Control#setMenu(Menu). This menu will be shown when performing a right click on the rendered control.

Text input = new Text(parent, SWT.BORDER);

// create a simple Menu for the input text field
Menu menu = new Menu(input);
MenuItem item = new MenuItem(menu, SWT.PUSH);
item.setText("Open dialog");
item.addSelectionListener(new SelectionAdapter() {
    @Override
    public void widgetSelected(SelectionEvent e) {
        MessageDialog.openInformation(
            null, "Information", "Some information dialog");
    }
});

// set the menu to the input Text control
input.setMenu(menu);
}

Using the SWT default mechanism for registering a menu to a NatTable instance would cause showing the menu at every region of a NatTable composition. For example a menu that should only be attached to the column header would open by performing a right click on any region in a grid composition (column header, row header, corner, body). Because of that, and as NatTable comes with a lot of built in commands and a special label/region based concept to determine a context, it provides its own mechanism to register menus.

Via IUiBindingRegistry it is possible to register a binding in NatTable to perform an action on user interaction, e.g. open a menu on performing a right click in a configured grid region. The PopupMenuBuilder is a builder in NatTable to create a menu with menu items that perform NatTable commands. It has several methods for adding such menu items and initializes and returns the menu on calling PopupMenuBuilder#build().

To create a menu with NatTable commands you need to perform the following steps:

  1. Create an IConfiguration for the menu by extending AbstractUiBindingConfiguration
  2. Create a menu using the NatTable PopupMenuBuilder helper class
  3. Register a PopupMenuAction binding using the created menu
  4. Add the IConfiguration to the NatTable instance

The following code shows the DebugMenuConfiguration that is shipped with NatTable to add debugging capability in a rendered NatTable.

// [1] IConfiguration for registering a UI binding to open a menu
public class DebugMenuConfiguration
    extends AbstractUiBindingConfiguration {

    private final Menu debugMenu;

    public DebugMenuConfiguration(NatTable natTable) {
        // [2] create the menu using the PopupMenuBuilder
        this.debugMenu = new PopupMenuBuilder(natTable)
                    .withInspectLabelsMenuItem()
                    .build();
    }

    @Override
    public void configureUiBindings(
        UiBindingRegistry uiBindingRegistry) {
        // [3] bind the PopupMenuAction to a right click
        // using GridRegion.COLUMN_HEADER instead of null would
        // for example open the menu only on performing a right
        // click on the column header instead of any region
        uiBindingRegistry.registerMouseDownBinding(
                new MouseEventMatcher(
                    SWT.NONE,
                    null,
                    MouseEventMatcher.RIGHT_BUTTON),
                new PopupMenuAction(this.debugMenu));
    }

}
// [4] add the menu configuration to a NatTable instance
natTable.addConfiguration(new DebugMenuConfiguration(natTable));

In NatTable versions before 1.2.0, you also need to ensure that the created menu is disposed when the NatTable instance is disposed. Otherwise you run into a memory leak. The reason for this is, that the menu is not connected to the NatTable Control as SWT menu. So when the NatTable instance gets disposed, the connected menu is not known and therefore not disposed with the Control. This can be solved by adding a DisposeListener to the NatTable instance as shown below.

public DebugMenuConfiguration(NatTable natTable) {
    // [2] create the menu using the PopupMenuBuilder
    this.debugMenu = new PopupMenuBuilder(natTable)
                .withInspectLabelsMenuItem()
                .build();

    // ensure the created menu gets disposed
    // only necessary for NatTable < 1.2.0
    natTable.addDisposeListener(new DisposeListener() {
        public void widgetDisposed(DisposeEvent e) {
            if (debugMenu != null && !debugMenu.isDisposed())
                debugMenu.dispose();
        }
    });
}

Since NatTable 1.2.0 the necessary DisposeListener is added automatically when calling PopupMenuBuilder#build().

Combination with Eclipse 3.x menus

Using Eclipse it is possible to specify a menu declarative. In Eclipse 3.x this is done using the extension point org.eclipse.ui.menus. Create a new menuContribution for that extension point and set the locationURI to a value that starts with popup:, e.g. popup:myMenu.

Eclipse3menu

This menu can then be used as a NatTable menu by creating a MenuManager, registering the menu via id together with the MenuManager to the site and create a PopupMenuBuilder using the MenuManager instance.

// somewhere in the ViewPart, e.g. createPartControl(Composite)
MenuManager mgr = new MenuManager();
getSite().registerContextMenu("myMenu", mgr, null);
// in the menu configuration
public DebugMenuConfiguration(NatTable natTable, MenuManager mgr) {
    // extend the declarative menu provided by the MenuManager
    this.debugMenu = new PopupMenuBuilder(natTable, mgr)
                .withInspectLabelsMenuItem()
                .build();
}

Since NatTable 1.2.0 it is possible to create the PopupMenuBuilder using a MenuManager instance. By using the MenuManager it is possible to configure visibility and enablement constraints in the plugin.xml and extend the declarative menu with NatTable commands using the PopupMenuBuilder. Prior 1.2.0 it was only possible to create the PopupMenuBuilder using the Menu instance created via MenuManager#createContextMenu(Control). Menu items that are added via PopupMenuBuilder will be dismissed that way, since they are not of type IContributionItem.

Combination with Eclipse 4.x menus

In Eclipse 4.x you declare a popup menu for a SWT control in the application model, e.g. in the menus section of a part.

Eclipse4menu

The declared menu can then be retrieved via EMenuService. For this get the EMenuService via injection and call EMenuService#registerContextMenu(Object, String)

@Inject
EMenuService menuService;
menuService.registerContextMenu(
    natTable,
    "com.vogella.nebula.nattable.popupmenu.0");

Further informations on popup menus with Eclipse 4.x can be found here.

Using the EMenuService will directly register the menu as SWT menu to the NatTable control, which is violating the NatTable menu concepts. As explained above, the menu will be shown for the whole NatTable, and it is not possible to distinguish between regions in a grid for example.

Since it is not possible to retrieve the menu without registering it directly to the Widget, we need to retrieve and unregister it accordingly. After that we are able to create the PopupMenuBuilder instance using the created and retrieved menu.

// get the menu registered by EMenuService
final Menu e4Menu = natTable.getMenu();

// remove the menu reference from NatTable instance
natTable.setMenu(null);

natTable.addConfiguration(
		new AbstractUiBindingConfiguration() {

	@Override
	public void configureUiBindings(
			UiBindingRegistry uiBindingRegistry) {
		// add NatTable menu items
		// and register the DisposeListener
		new PopupMenuBuilder(natTable, e4Menu)
			.withInspectLabelsMenuItem()
			.build();

        // register the UI binding
        uiBindingRegistry.registerMouseDownBinding(
                new MouseEventMatcher(
                		SWT.NONE,
                		GridRegion.BODY,
                		MouseEventMatcher.RIGHT_BUTTON),
                new PopupMenuAction(e4Menu));
	}
});

As explained before, using the Menu instance directly would avoid adding additional menu items, because the MenuManager that created the Menu only handles IContributionItem correctly and is called on filling the menu. Fortunately, using Eclipse 4, the Menu that is created via MenuManager knows the MenuManager that created it. It can be retrieved via Menu#getData(), which is set by the MenuManagerRenderer. The PopupMenuBuilder checks that value and keeps the reference to the MenuManager in order to support extending the menu and adding visibility and enablement states as explained in a minute.

The MenuManager itself also adds the reference to itself to the created Menu via setData(). It uses the key org.eclipse.jface.action.MenuManager.managerKey which is defined as a constant in MenuManager. Unfortunately this constant is private and therefore not accessible from any other code, which seems to be the reason for the MenuManagerRenderer to add the reference via setData() without a key.

State configuration of menu items

Another advantage that comes with NatTable 1.2.0 is the support for visibility and enabled states. As explained above, the PopupMenuBuilder is now able to work with a MenuManager instead of the simple Menu instance. This way also the visibility constraints via core expressions will work correctly.

For NatTable commands it is also possible to specify a visible or enabled state via IMenuItemState. This can be done using the methods withEnabledState(String, IMenuItemState) and withVisibleState(String, IMenuItemState) on PopupMenuBuilder on building the menu. The addition of the visible and enabled states for NatTable menu items for example adds support to disable a menu item for specific columns or for a special state, like disabling the hide column menu item if it would lead to an empty table (hide last column issue). For this every default menu item can be identified via unique id, which are specified as constants in the PopupMenuBuilder.

The following code will extend the Eclipse 4 menu from above with the debug menu item and disable it for the first column in the body region of the grid.

new PopupMenuBuilder(natTable, e4Menu)
    .withInspectLabelsMenuItem()
    .withEnabledState(
        PopupMenuBuilder.INSPECT_LABEL_MENU_ITEM_ID,
        new IMenuItemState() {

            @Override
            public boolean isActive(NatEventData natEventData) {
                return natEventData.getColumnPosition() > 1;
            }
    })
    .build();

In order to be able to configure a visible or enabled state for custom menu items, the menu items need to be added specifying an id. This can be done using PopupMenuBuilder#withMenuItemProvider(String, IMenuItemProvider). Using the id that was used to add the menu item, it is possible to configure a IMenuItemState for that menu item.

Posted in Dirk Fauth, Eclipse | Comments Off on NatTable context menus with Eclipse menus

NatTable with custom scrollbars

When talking about styling a SWT control via CSS, one issue is raised quite early. The scrollbars can not be styled! Looking at a dark theme, the importance on that issue becomes obvious, as you can see in the following screenshot.

NatTable_dark_default_scrollbars

Using NatTable the scrolling capabilities are via the ViewportLayer. With NatTable 1.1 the possibility was added to set custom scrollbars to the ViewportLayer. This enables for example to have multiple ViewportLayer in a layer composition (split viewport) or to create UI layouts with special scrolling interactions.

With the possibility to use a custom scrollbar implementation, it is possible to style a NatTable completely with a dark theme. As an example for a stylable scrollbar we use the FlatScrollBar from Code Affine.

Since the scrollbars of the Canvas, which is the base class of NatTable, can’t be exchanged directly, we need to create a wrapper composite for the NatTable. This way the scrollbars can be attached beneath the NatTable instead of being part inside the NatTable.

NatTable_wrapper

To create the above layout, a GridLayout with two columns can be used, where the NatTable will take all the available space.

// NatTable and scrollbar container
Composite container = new Composite(parent, SWT.NONE);
GridLayoutFactory
    .swtDefaults()
    .numColumns(2)
    .margins(0, 0)
    .spacing(0, 0)
    .applyTo(container);

// NatTable as main control
NatTable natTable = new NatTable(container, viewportLayer);
GridDataFactory
    .fillDefaults()
    .grab(true, true)
    .applyTo(natTable);

The vertical scrollbar is attached to the right, and the horizontal scrollbar is attached to the bottom. To ensure that the layout doesn’t break, the FlatScrollBar is wrapped into a Composite. This way we are also able to set a fixed width/height, while telling the FlatScrollBar to fill the available space.

// vertical scrollbar wrapped in another composite for layout
Composite verticalComposite =
    new Composite(container, SWT.NONE);
GridLayoutFactory
    .swtDefaults()
    .margins(0, 0)
    .spacing(0, 0)
    .applyTo(verticalComposite);
GridData verticalData = GridDataFactory
    .swtDefaults()
    .hint(14, SWT.DEFAULT)
    .align(SWT.BEGINNING, SWT.FILL)
    .grab(false, true)
    .create();
verticalComposite.setLayoutData(verticalData);

FlatScrollBar vertical =
    new FlatScrollBar(verticalComposite, SWT.VERTICAL);
GridDataFactory
    .fillDefaults()
    .grab(true, true)
    .applyTo(vertical);

// horizontal scrollbar wrapped in another composite for layout
Composite horizontalComposite =
    new Composite(container, SWT.NONE);
GridLayoutFactory
    .swtDefaults()
    .margins(0, 0)
    .spacing(0, 0)
    .applyTo(horizontalComposite);
GridData horizontalData = GridDataFactory
    .swtDefaults()
    .hint(SWT.DEFAULT, 14)
    .align(SWT.FILL, SWT.BEGINNING)
    .grab(true, false)
    .create();
horizontalComposite.setLayoutData(horizontalData);

FlatScrollBar horizontal =
    new FlatScrollBar(horizontalComposite, SWT.HORIZONTAL);
GridDataFactory
    .fillDefaults()
    .grab(true, true)
    .applyTo(horizontal);

To be independent of the scrollbar implementation, the IScroller<T> interface was introduced in NatTable. The two default implementations ScrollBarScroller and SliderScroller are shipped with NatTable Core to be able to set custom scrollbars using SWT default implementations. Using this abstraction it is also possible to use another scrollbar implementation, like the FlatScrollBar. The following code shows the implementation of a FlatScrollBarScroller.

class FlatScrollBarScroller
    implements IScroller<FlatScrollBar> {

    private FlatScrollBar scrollBar;

    public FlatScrollBarScroller(FlatScrollBar scrollBar) {
        this.scrollBar = scrollBar;
    }

    @Override
    public FlatScrollBar getUnderlying() {
        return scrollBar;
    }

    @Override
    public boolean isDisposed() {
        return scrollBar.isDisposed();
    }

    @Override
    public void addListener(int eventType, Listener listener) {
        scrollBar.addListener(eventType, listener);
    }

    @Override
    public void removeListener(int eventType, Listener listener) {
        scrollBar.removeListener(eventType, listener);
    }

    @Override
    public int getSelection() {
        return scrollBar.getSelection();
    }

    @Override
    public void setSelection(int value) {
        scrollBar.setSelection(value);
    }

    @Override
    public int getMaximum() {
        return scrollBar.getMaximum();
    }

    @Override
    public void setMaximum(int value) {
        scrollBar.setMaximum(value);
    }

    @Override
    public int getPageIncrement() {
        return scrollBar.getPageIncrement();
    }

    @Override
    public void setPageIncrement(int value) {
        scrollBar.setPageIncrement(value);
    }

    @Override
    public int getThumb() {
        return scrollBar.getThumb();
    }

    @Override
    public void setThumb(int value) {
        scrollBar.setThumb(value);
    }

    @Override
    public int getIncrement() {
        return scrollBar.getIncrement();
    }

    @Override
    public void setIncrement(int value) {
        scrollBar.setIncrement(value);
    }

    @Override
    public boolean getEnabled() {
        return scrollBar.getEnabled();
    }

    @Override
    public void setEnabled(boolean b) {
        scrollBar.setEnabled(b);
    }

    @Override
    public boolean getVisible() {
        return scrollBar.getVisible();
    }

    @Override
    public void setVisible(boolean b) {
        scrollBar.setVisible(b);
    }

}

Using the above FlatScrollBarScroller, the created FlatScrollBar instances can be set to the ViewportLayer.

As the layout will always show the space for the scroller with the GridData instances above, we need to register a listener that hides the wrapper Composites of the FlatScrollBar instances in case the FlatScrollBar is hidden, and a listener that shows the Composites again in case the FlatScrollBar becomes visible again. This is done by setting a GridLayoutData with a matching exclude flag.

// create the vertical scroller
FlatScrollBarScroller verticalScroller =
    new FlatScrollBarScroller(vertical);

// register the hide/show listener
verticalScroller.addListener(SWT.Hide, new Listener() {
    @Override
    public void handleEvent(Event event) {
    	GridDataFactory
            .createFrom(verticalData)
            .exclude(true)
            .applyTo(verticalComposite);
    	GridDataFactory
            .createFrom(horizontalData)
            .span(2, 1)
            .applyTo(horizontalComposite);
    }
});
verticalScroller.addListener(SWT.Show, new Listener() {
    @Override
    public void handleEvent(Event event) {
    	verticalComposite.setLayoutData(verticalData);
    	horizontalComposite.setLayoutData(horizontalData);
    }
});

// create the horizontal scroller
FlatScrollBarScroller horizontalScroller =
    new FlatScrollBarScroller(horizontal);

// register the hide/show listener
horizontalScroller.addListener(SWT.Hide, new Listener() {
    @Override
    public void handleEvent(Event event) {
    	GridDataFactory
            .createFrom(verticalData)
            .span(1, 2)
            .applyTo(verticalComposite);
    	GridDataFactory
            .createFrom(horizontalData)
            .exclude(true)
            .applyTo(horizontalComposite);
    }
});
horizontalScroller.addListener(SWT.Show, new Listener() {
    @Override
    public void handleEvent(Event event) {
    	verticalComposite.setLayoutData(verticalData);
    	horizontalComposite.setLayoutData(horizontalData);
    }
});

// set the custom IScroller to the ViewportLayer
viewportLayer.setVerticalScroller(verticalScroller);
viewportLayer.setHorizontalScroller(horizontalScroller);

The last part is to set the style information to the NatTable and the FlatScrollBar instances.

// set a dark background to the wrapper container
container.setBackground(GUIHelper.COLOR_BLACK);

// set a dark styling to the scrollbars
vertical.setBackground(GUIHelper.COLOR_BLACK);
vertical.setPageIncrementColor(GUIHelper.COLOR_BLACK);
vertical.setThumbColor(GUIHelper.COLOR_DARK_GRAY);

horizontal.setBackground(GUIHelper.COLOR_BLACK);
horizontal.setPageIncrementColor(GUIHelper.COLOR_BLACK);
horizontal.setThumbColor(GUIHelper.COLOR_DARK_GRAY);

// set a dark styling to NatTable
natTable.setBackground(GUIHelper.COLOR_BLACK);
natTable.setTheme(new DarkNatTableThemeConfiguration());

Doing the steps described above it is possible to create a completely dark themed NatTable using custom scrollbars as shown in the picture below.

NatTable_dark_custom_scrollbars

At the time writing this blog post, there is no wrapper or adapter implementation in NatTable for creating a NatTable with custom scrollbars. But it might be added in the future, based on the above explanations.

The full example code is available here.

Posted in Dirk Fauth, Eclipse | Comments Off on NatTable with custom scrollbars

Welcome Sergey Prigogin as a new eclipse.platform.ui Committer

I would like to welcome Sergey working for Google as new platform.ui committer. Sergey is a very active contributor to several Eclipse projects and did recently the majority of the work to contribute the UI freeze monitor to Eclipse 4.5.

Welcome Sergey!

See the message on the platform.ui mailing list.

Posted in Eclipse, Lars Vogel | Tagged , | Comments Off on Welcome Sergey Prigogin as a new eclipse.platform.ui Committer