I discovered, perhaps unsurprisingly, that it's possible to create a module that defines window groups consisting of windows defined in other modules, even (and that's the most fun part) windows over which you normally have no control, e.g., the windows defined in the NetBeans Platform itself, such as the Properties window, the Favorites window, and the Output window. Once you have defined a window group consisting of some of your own windows, plus some windows from the NetBeans Platform itself, or from other modules over which you have no control, you can open and close those windows together.
Above, I have two Actions, the open action is like this:
@Override public void actionPerformed(ActionEvent e) { TopComponentGroup group = WindowManager.getDefault().findTopComponentGroup("testGroup"); if (group != null) { group.open(); } }
And the close action is the same as the above, except that "close" is called on the group.
Now, what does the group consist of? You can see "testGroup" as the name of the group, above. Here's where that name comes from, in the file "testGroupWsgrp.xml" shown in the screenshot above:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE group PUBLIC "-//NetBeans//DTD Group Properties 2.0//EN" "http://www.netbeans.org/dtds/group-properties2_0.dtd"><group version="2.0"> <module name="org.fwc" spec="1.0" /> <name unique="testGroup" /> <state opened="false" /></group>
And the above is registered in the layer.xml file (which, in turn, is registered in the manifest file), as follows:
<folder name="Windows2"> <folder name="Groups"> <file name="testGroup.wsgrp" url="testGroupWsgrp.xml"/> <folder name="testGroup"> <file name="output.wstcgrp" url="groups/output.xml"/> <file name="properties.wstcgrp" url="groups/properties.xml"/> <file name="favorites.wstcgrp" url="groups/favorites.xml"/> </folder> </folder></folder>
Each of the window system component group files above has content like this, here you see it for the "output.wstcgrp":
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE tc-group PUBLIC "-//NetBeans//DTD Top Component in Group Properties 2.0//EN" "http://www.netbeans.org/dtds/tc-group2_0.dtd"><tc-group version="2.0"> <module name="org.netbeans.core.io.ui" spec="1.0"/> <tc-id id="output" /> <open-close-behavior open="true" close="true" /></tc-group>
And here it is for the "properties.wstcgrp":
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE tc-group PUBLIC "-//NetBeans//DTD Top Component in Group Properties 2.0//EN" "http://www.netbeans.org/dtds/tc-group2_0.dtd"><tc-group version="2.0"> <module name="org.netbeans.core.ui" spec="1.0"/> <tc-id id="properties" /> <open-close-behavior open="true" close="true" /></tc-group>
And, finally, here it is for the "favorites.wstcgrp":
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE tc-group PUBLIC "-//NetBeans//DTD Top Component in Group Properties 2.0//EN" "http://www.netbeans.org/dtds/tc-group2_0.dtd"><tc-group version="2.0"> <module name="org.netbeans.modules.favorites" spec="1.0"/> <tc-id id="favorites" /> <open-close-behavior open="true" close="true" /></tc-group>
Note: It is very important that you get the "module name" and "tc-id name" to be 100% correct. And the value of "tc-id name" must be the same as the name of the file. That's the only information needed for the TopComponent to be found when the "open" and "close" are called on the group you have defined, since each of the above XML files is registered within the group in the layer file.
And that's how you can open (and close) foreign windows. Now that these windows are part of a group, whenever you open the group and then close one of the windows within the group, next time you open the group that window you closed will still be closed. I.e., this is the way you can provide workspaces for your users, that is, workspaces consisting of windows that adapt themselves automatically to the needs of the user.
PS: I've noticed that if your TopComponent is an "editor" TopComponent, it doesn't close when the "close" is called on the group of which it is a part. Seems like a bug.