Ley
Ley

Reputation:

Eclipse RCP application - Create a window programmatically

In an RCP application, how I can programmatically define and open a new window? I want to open several window - each window show different data. How can I set different input for each window?

I want to simulate the same functionality of Eclipse IDE (Window --> New Window), but I want each new opened window to have different input. I'm trying to use : IWorkbenchPage newPage = window.openPage(inputObject); How can I programmatically define the "inputObject" that identifies the data shown in the window?

Upvotes: 3

Views: 14415

Answers (6)

hps72
hps72

Reputation: 11

This opens a new Window aside of the main application window:

package any.pack;

import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.basic.MTrimmedWindow;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.e4.ui.model.application.ui.basic.impl.PartImpl;
import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
import org.eclipse.e4.ui.workbench.IPresentationEngine;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.swt.SWT;

public class WindowOpener {

    private MWindow createWindow(EModelService modelService, MApplication application) {
        MWindow window = modelService.createModelElement(MTrimmedWindow.class);
        window.setElementId("com.ubs.cqe.ui.window.aside.1");
        window.setLabel("Second Window");
        window.getPersistedState().put(IPresentationEngine.STYLE_OVERRIDE_KEY, "" + SWT.SHELL_TRIM);
        window.setVisible(true);
        window.setX(20);
        window.setY(20);
        window.setWidget(700);
        window.setHeight(500);
        application.getChildren().add(window); // Add window to application
        return window;
    }
    
}

Upvotes: 0

hps72
hps72

Reputation: 11

The following Handler - each time its @Execute method is invoked - creates a new TrimmedWindow with data content independent from each other:

package com.vogella.tasks.ui.handlers;

import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.e4.ui.model.application.ui.basic.impl.TrimmedWindowImpl;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.e4.ui.workbench.modeling.EPartService.PartState;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.WorkbenchException;

import com.vogella.tasks.ui.parts.DynamicPart;

public class OpenAdditionalWindowHandler {
    private static final String PART_DESCRIPTOR_ID = "com.vogella.tasks.ui.partdescriptor.static.part";
    static int posX = 20;
    static int posY = 20;
    static int counter = 0;

    /**
     * Opens a new TrimmedWindow based on the (template) definition. Each time invoked a separate window is opened with independent data content.
     */
    @Execute
    public void execute(EPartService partService, MWindow window, MApplication application, EModelService modelService) throws WorkbenchException {

        // Get the predefined TrimmedWindow and clone it
        MUIElement element = modelService.find("com.vogella.tasks.ui.trimmedwindow.zusatz", application);
        TrimmedWindowImpl clonedWindow = (TrimmedWindowImpl) modelService.cloneElement(element, application);
        application.getChildren().add(clonedWindow);
        modelService.bringToTop(clonedWindow);
        clonedWindow.setToBeRendered(true);

        // Shift the new windows a little bit each time a new one is created
        shiftWindowPositionSoTheyDontExactlyOverlay(clonedWindow);

        // Derive new Part Descriptor Id with counter & create new part
        final String dynamicallyCreatedPartId = PART_DESCRIPTOR_ID + counter++;
        MPart dynamicallyCreatedPart = partService.createPart(PART_DESCRIPTOR_ID);

        if (dynamicallyCreatedPart != null) {
            // Add the part to the newly cloned trimmed window
            clonedWindow.getChildren().add(dynamicallyCreatedPart);

            dynamicallyCreatedPart.setElementId(dynamicallyCreatedPartId);
            dynamicallyCreatedPart.setLabel("My part nbr " + counter);

            final DynamicPart staticPseudoAspect = (DynamicPart) dynamicallyCreatedPart.getObject();
            staticPseudoAspect.setContent("Dynamic part content nbr " + counter);
            clonedWindow.getChildren().get(0).setVisible(true);
            clonedWindow.getChildren().get(0).setToBeRendered(true);

        }

    }

    private void shiftWindowPositionSoTheyDontExactlyOverlay(TrimmedWindowImpl clonedWindow) {
        posX = posX + 20;
        posY = posY + 20;
        clonedWindow.setX(posX);
        clonedWindow.setY(posY);
    }

}

The Trimmed window is defined in the application model as a template. The same with the Part which is described in the application model in the form of a PartDescriptor.

enter image description here

Upvotes: 1

user85259
user85259

Reputation: 225

A workbench window in Eclipse terminology is a window that contains, typically, a menu, a toolbar, an editor area, and views. Eclipse RCP applications generally contain a single window but some applications allow multiple windows to be created. For example, in the Eclipse IDE one may open another window by selecting 'New Window' from the window menu. Perspectives can be set independently into each window.

Although multiple windows can be confusing, they can also be very useful. For example, if a user may be working on two different datasources but have multiple editors and views open against each datasource then it would be useful to have two windows open. The same effect could be achieved by opening two instances of the RCP application. However that would require multiple copies of code and other resources to be loaded, it would require a full initialization of the application for each datasource, and it would make cross-communications between the windows more difficult.

To allow users of your RCP application to open another window, you have two choices.

You can include the 'New Window' menu item in your RCP application. This can be done by adding to your RCP application the action supplied by the workbench. Modify your ActionBarAdvisor class:

add to the field declarations:

private IWorkbenchAction newWindowAction;

add to the code where you make the actions (typically a method called makeActions):

newWindowAction = ActionFactory.OPEN_NEW_WINDOW.create(window);
register(newWindowAction);

add to the code where you create the menus:

menu.add(newWindowAction);

where menu is typically the Window menu. If you don't have a Window menu already in your application and would like to create one, the following line will work:

MenuManager menu = new MenuManager( "&Window", IWorkbenchActionConstants.M_WINDOW);

This will give you a menu item that will create a new window in the same way as the Window->New Window menu item in the Eclipse IDE.

However this gives no control over the input. The second window may have a different set of views and editors open, and may have a different perspective set, but it will still have the same 'input'. For example, in the Eclipse IDE you can open a second window but if you switch workspaces then that will apply to all windows.

A second way to create a new window is to do so programatically by creating pages. This allows you to set an 'input' to a window. So opening a view in one window may result in different data being shown than if you opened the same view in another window.

Technically, a window does not have input. Pages have input. A window can contain at most one page. In may seem from some of the method names that a window can have multiple pages (e.g. getActivePage implies there are inactive pages). Those method names are holdovers from Eclipse 2.0 days when multiple pages were supported.

To open a new page programatically:

        IWorkbenchPage newPage = window.openPage(myInput);

This method will create a new page in the given window if the window does not already contain a page, otherwise a new window will be created to contain the page.

If you support multiple windows with different input then you should set a title in each window that distinguishes each window:

        newPage.getWorkbenchWindow().getShell().setText("My App - " + myInput.getName());

There are situations in which you may want to change the input to a window. You cannot change the input to a page, so you must do this by closing the existing page and creating a new page. The following code will close the existing page:

        IWorkbenchPage activePage = window.getActivePage();
        activePage.close();

Note that some views provided by Eclipse use the page input. For example, the Common Navigator view will use the page input as the root element of the navigation tree.

To access the page input from your own view, you would call site.getPage().getInput(). If you have no site context to start from, calling the following will get you the input:

PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getInput();

Note that the 'input' is an Object. It can be an object of any class you like. When you get it back from Page::getInput(), cast it back to the appropriate class. You should not usually create a new class to be the input. You can almost always use an existing class. This is generally the top level object of your object model. The Eclipse framework does nothing with this input except to store it and to pass it back when Page::getInput() is called.

Upvotes: 4

Andrew Eidsness
Andrew Eidsness

Reputation: 1621

You should make sure that you really want to open a bunch of other windows. Maybe you could achieve the same thing by opening some new views or editors in the existing window? Using multiple views is usually easier for the user to understand since they are no presented with several windows that look nearly the same. It also makes is easier for you to show the relationships among the views.

That being said, you can call IWorkbench.openWorkbenchWindow to create an entirely new Window. A good example of this is the code for Window --> New Window, which is in OpenNewWindowMenu.

Upvotes: 1

Dr. Faust
Dr. Faust

Reputation: 1021

You need to understand how to implement views in the Eclipse plug-in model. This can be achieved either by adding extension points and configuring properties or through code. Configuring properties is the preferred approach. Both are explained at:

http://www.vogella.de/articles/RichClientPlatform/article.html#views

That site has lots of good articles on Eclipse development:

http://www.vogella.de/eclipse.html

Anyway, as PSU_Kardi suggested, it would be a good idea to read through the entire article.

Upvotes: 2

ist_lion
ist_lion

Reputation: 3209

I think you'll need to better define a 'window' for me or someone else to answer this question.

Are you creating a plug-in that you want to be open multiple times, in which case you might want an editor and need to assure you're not using the Singleton pattern - which is something you can specify in the manifest file.

Or are you trying to create a window that you want to display data? Like a View? If you're doing that you'll want to read up on how to create a ViewPart and make sure you extend everything properly.

Might I suggest going to my two favorite RCP sites

http://www.vogella.de/articles/RichClientPlatform/article.html

http://www.java2s.com/Code/Java/SWT-JFace-Eclipse/CatalogSWT-JFace-Eclipse.htm

Upvotes: 1

Related Questions