Reputation: 5099
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?
Upvotes: 2
Views: 500
Reputation: 5099
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 [email protected]
*/
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:
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.
Upvotes: 2