简体   繁体   中英

Creating window groups on Netbeans Platform with Annotations

There's a related question already answered, but so much has changed since then with the use of annotations.

I'm registering TopComponents with annotations. For example:

@TopComponent.Registration(mode = "explorer", openAtStartup = false,
        roles = "Test Role")

Later I tried to open the group like this, as a test:

    WindowManager.getDefault().invokeWhenUIReady(() -> {
        WindowManager.getDefault().getRegistry().getOpened().stream()
                .forEach((tc) -> {
                    tc.close();
                });
        TopComponentGroup group
                = WindowManager.getDefault()
                .findTopComponentGroup("Test Role");
        if (group != null) {
            group.open();
        }
    });

All components are closed but nothing opens. It doesn't work, so obviously some plumbing is missing.

Is this still the right way of doing it?

Is there a working example of this somewhere?

Here's how I was able to make it work for anyone stumbling on this question:

I created a class and registered as a service based on this code :

/**
 * Based on code from: http://www.smartcode.ch/netbeans-hide-show-topcomponent/
 *
 * @author Javier A. Ortiz Bultrón javier.ortiz.78@gmail.com
 */
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.openide.util.Lookup;
import org.openide.util.lookup.ServiceProvider;
import org.openide.windows.Mode;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;

@ServiceProvider(service = ViewManager.class)
public class ViewManager {

    private final Map<TopComponent, Mode> hiddenComponents;

    public ViewManager() {
        hiddenComponents = new HashMap<>();
    }

    public synchronized void showTopComponent(Class<? extends TopComponent> topComponentClass) {

        for (Map.Entry<TopComponent, Mode> hiddenComponentEntry : hiddenComponents.entrySet()) {
            TopComponent hiddenComponent = hiddenComponentEntry.getKey();

            if (hiddenComponent.getClass().equals(topComponentClass)) {
                Mode mode = hiddenComponentEntry.getValue();
                WindowManager.getDefault().findMode(mode.getName()).dockInto(hiddenComponent);
                hiddenComponent.open();
                hiddenComponents.remove(hiddenComponent);
                break;
            }

        }
    }

    public synchronized void hideTopComponent(Class<? extends TopComponent> topComponentClass) {

        Set<TopComponent> shownTopComponents = WindowManager.getDefault().getRegistry().getOpened();

        for (TopComponent shownTopComponent : shownTopComponents) {
            if (shownTopComponent.getClass().equals(topComponentClass)) {
                Mode mode = WindowManager.getDefault().findMode(shownTopComponent);

                hiddenComponents.put(shownTopComponent, mode);
                shownTopComponent.close();
            }
        }
    }

    public synchronized void showAll() {
        for (TopComponent tc : hiddenComponents.keySet()) {
            showTopComponent(tc.getClass());
        }
    }

    /**
     * Load a screen role.
     *
     * @param role Role to load.
     */
    public static void loadRole(String role) {
        //Open all components
        Lookup.getDefault().lookup(ViewManager.class).showAll();
        //Change role (this closes the ones not in this role)
        WindowManager.getDefault().setRole(role);
    }
}

Then in a module installer I do this:

@Override
    public void restored() {
        WindowManager.getDefault().invokeWhenUIReady(() -> {
            /**
             * All windows start opened. Populated the ViewManager. It is
             * important to configure all TopComponents with: 
             * persistenceType = TopComponent.PERSISTENCE_NEVER or TopComponent.PERSISTENCE_ONLY_OPENED
             * and openAtStartup = true
             */
            ViewManager manager = Lookup.getDefault().lookup(ViewManager.class);
            WindowManager.getDefault().getRegistry().getOpened().stream()
                    .forEach((tc) -> {
                        manager.hideTopComponent(tc.getClass());
                    });
            manager.loadRole(Tool.LOBBY);
        });
    }

The trick, as documented in the Installer code, is to mark all modules to open at start up and with the right persistence type.

This will open all windows on the application start, hide them (while registering them on the ViewManager) and then open the specified role.

Roles, as documented here , do the following:

The default implementation of this method does the following:

  1. Hide the main window.
  2. Save the current window layout of the current role.
  3. Load new window layout from the given role.
  4. Show the main window.

Another option would be overriding the WindowManager itself to do all of this but I found it to be way too invasive and dangerous as some methods are protected so it's not possible to wrap the WindowsManagerImpl (the default). Also is impossible to just extend WindowsManagerImpl as this it's package is private.

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