简体   繁体   中英

Eclipse RCP - add a Listener right after a View has been created

Greetings fellow Stackoverflowians,

I am developing an Eclipse RCP application, and must add a SelectionListener to the Project Explorer view the moment after it's created.

I've realized that I cannot do this in the Activator of my contributing plug-in, whereas in order to get the SelectionService via PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService() I must have an active workbench window (which is null when the Activator start() is called)

So my question: When can I get the SelectionService so that the Project Explorer view has been created and is visible, but the user has not yet been able to 'push any buttons'?

Any opinions and suggestions are appreciated!

When you really want to track user selection from startup without having a UI (like a view) that can register an ISelectionListener on creation, you can us a startup hook.

Eclipse provides the extension point org.eclipse.ui.startup . It accepts a class that implements the interface org.eclipse.ui.IStartup . It will be called after the UI has been created, so the ISelectionService is already available then:

public class StartupHook implements IStartup, ISelectionListener {

    @Override
    public void earlyStartup() {
        final IWorkbench workbench = PlatformUI.getWorkbench();
        workbench.addWindowListener(new IWindowListener() {

            @Override
            public void windowOpened(IWorkbenchWindow window) {
                addSelectionListener(window);
            }

            @Override
            public void windowClosed(IWorkbenchWindow window) {
                removeSelectionListener(window);
            }
            /* ... */
        });

        workbench.getDisplay().asyncExec(new Runnable() {
            public void run() {
                for (IWorkbenchWindow window : workbench.getWorkbenchWindows()) {
                    addSelectionListener(window);
                }
            }
        });
    }

    private void addSelectionListener(IWorkbenchWindow window) {
        if (window != null) {
            window.getSelectionService().addSelectionListener("org.eclipse.ui.navigator.ProjectExplorer", this);
        }
    }

    private void removeSelectionListener(IWorkbenchWindow window) {
        if (window != null) {
            window.getSelectionService().removeSelectionListener("org.eclipse.ui.navigator.ProjectExplorer", this);
        }
    }

    @Override
    public void selectionChanged(IWorkbenchPart part, ISelection selection) {
        // TODO handle selection changes
        System.out.println("selection changed");
    }
}

Note that it is discouraged to use this UI startup hook as it forces OSGi to activate your bundle very early (and so all dependent bundles too!) and slows down system startup. So please make sure that your bundle is neat and slim. Reduce bundle dependencies to a minimum. Sometimes it is necessary move the startup hook code into a separate bundle to achieve that.

You could add your selection listener in the ApplicationWorkbenchWindowAdvisor.postWindowOpen() method (at this point you can be sure workbench is already created). If you want to add it, when 'Project explorer view' gets visible, then it is possible to do something like this:

PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().addPartListener(new PartAdapter() {

    @Override
    public void partVisible(IWorkbenchPartReference partRef) {
        if ("org.eclipse.ui.navigator.ProjectExplorer".equals(partRef.getId())) {
            // add selection listener
        }
    }
});

UPD: OK, if you don't have access to AppliationWorkbenchWindowAdvisor (which is weird, if you are developing Eclipse RCP product), then ASAIK, there is no clean solution to get notified about availability of the UI. So one of such solutions could be adding a job, which would wait for the UI to be initializd. In your plugin Activator.start() method consider adding following job (sure you can extract it to separate class and improve in many ways, but for the beginning it should be sufficient):

Job j = new Job("") {

    @Override
    protected IStatus run(IProgressMonitor monitor) {
        final boolean[] workbenchAvailable = new boolean[] { false };
        Display.getDefault().syncExec(new Runnable() {

            @Override
            public void run() {
                if (PlatformUI.isWorkbenchRunning() && PlatformUI.getWorkbench().getActiveWorkbenchWindow() != null) {
                    workbenchAvailable[0] = true;
                }

            }
        });
        if (workbenchAvailable[0]) {
            System.out.println("Workbench is available");
            Display.getDefault().asyncExec(new Runnable() {

                @Override
                public void run() {
                    ISelectionService selectionService =
                        PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService();

                    System.out.println(selectionService);
                }
            });
        } else {
            System.out.println("Waiting for the Workbench ...");
            schedule(1000);
        }
        return Status.OK_STATUS;
    }
};

j.schedule();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM