Geertjan's Blog

  • October 21, 2006

Creating a Window Group for External TopComponents

Geertjan Wielenga
Product Manager
In yesterday's window group, we used a TopComponent Group to manage two TopComponents. The two TopComponents belonged to the same module where I defined the group. However, it would also be cool if I could manage the windows provided by other modules. "Oh well," you might think, "That probably means you've got to hack the NetBeans sources, recompile various modules, find yourself in a world of confusion with conflicting dependencies, and tear all your hair out in frustration without reaching your goal."

Not at all. Membership of a window group is defined in an XML file. Registration of membership is done in the XML Layer. Therefore, including external TopComponents is as simple as creating a new membership XML file and then registering the XML file in the layer. The key to the puzzle is that each TopComponent has an ID. If you make use of that ID in the membership XML file, your file will override the file defined in the module that provides the TopComponent. Then you can change the state flags that determine whether the TopComponent opens and closes together with the group. Since you're not touching a single line of Java code, there's no need to recompile anything at all. So, without a single grain of Java knowledge, without ever having typed one line of code, you can completely redo the layout of your application, or even of the IDE itself.

Here, for example, I have defined an XML file called "runtimeWstcgrp.xml". This is the XML file that declares a TopComponent with the ID "runtime" as a window group member. We don't know what group it belongs to, because that is defined in the XML layer (hence the same group member could belong to multiple groups, without the window group membershop file needing to be changed):

<?xml version="1.0" encoding="UTF-8" ?>
"-//NetBeans//DTD Top Component in Group Properties 2.0//EN"
<tc-group version="2.0">
<tc-id id="runtime" />
<open-close-behavior open="true" close="true"/>

And now, in the XML layer, I just need to register the above file as a member of the group I defined yesterday (together with the two TopComponents in my own module):

<folder name="Groups">
<file name="MyGroup.wsgrp" url="groups/MyGroupWsgrp.xml"/>
<folder name="MyGroup">
<file name="OneTopComponent.wstcgrp" url="groups/MyGroup/OneTopComponentWstcgrp.xml"/>
<file name="TwoTopComponent.wstcgrp" url="groups/MyGroup/TwoTopComponentWstcgrp.xml"/><file name="runtime.wstcgrp" url="groups/MyGroup/runtimeWstcgrp.xml"/>

Now the TopComponent with the ID "runtime" (which is in a totally different module, deep in the NetBeans Sources somewhere) is part of the same window group as my own two TopComponents. Similarly, instead of working with window group membership files in this way, you can work with individual file's open/close state. Window group membership files end in .Wstcgrp.xml, while individual files end in Wsctref.xml. For example, maybe you don't want the Projects window, Files window, and Runtime window to open when the IDE starts. Instead of worrying about hacking the NetBeans sources, you can just add the necessary Wstcref.xml files and then change the state element from true to false.

As a result of all of the above, based on a neurotic need to want to control almost all the IDE's windows, my project now contains all the following XML files:

And in my XML layer, I now have this:

<folder name="Windows2">
<folder name="Components">
<file name="OneTopComponent.settings" url="OneTopComponentSettings.xml"/>
<file name="TwoTopComponent.settings" url="TwoTopComponentSettings.xml"/>
<folder name="Modes">
<folder name="editor">
<file name="OneTopComponent.wstcref" url="OneTopComponentWstcref.xml"/>
<folder name="explorer">
<file name="projectTabLogical_tc.wstcref" url="modes/explorer/projectTabLogical_tcWstcref.xml"/>
<file name="projectTab_tc.wstcref" url="modes/explorer/projectTab_tcWstcref.xml"/>
<file name="runtime.wstcref" url="modes/explorer/runtimeWstcref.xml"/>
<folder name="navigator">
<file name="navigatorTC.wstcref" url="modes/navigator/navigatorTCWstcref.xml"/>
<folder name="output">
<file name="TwoTopComponent.wstcref" url="TwoTopComponentWstcref.xml"/>
<folder name="Groups">
<file name="MyGroup.wsgrp" url="groups/MyGroupWsgrp.xml"/>
<folder name="MyGroup">
<file name="OneTopComponent.wstcgrp" url="groups/MyGroup/OneTopComponentWstcgrp.xml"/>
<file name="TwoTopComponent.wstcgrp" url="groups/MyGroup/TwoTopComponentWstcgrp.xml"/>
<file name="CommonPalette.wstcgrp" url="groups/MyGroup/CommonPaletteWstcgrp.xml"/>
<file name="output.wstcgrp" url="groups/MyGroup/outputWstcgrp.xml"/>
<file name="runtime.wstcgrp" url="groups/MyGroup/runtimeWstcgrp.xml"/>
<file name="properties.wstcgrp" url="groups/MyGroup/propertiesWstcgrp.xml"/>
<file name="WelcomeComponent.wstcgrp" url="groups/MyGroup/WelcomeComponentWstcgrp.xml"/>
<file name="projectTabLogical_tc.wstcgrp" url="groups/MyGroup/projectTabLogical_tcWstcgrp.xml"/>
<file name="projectTab_tc.wstcgrp" url="groups/MyGroup/projectTab_tcWstcgrp.xml"/>
<file name="navigatorTC.wstcgrp" url="groups/MyGroup/navigatorTCWstcgrp.xml"/>
<file name="favorites.wstcgrp" url="groups/MyGroup/favoritesWstcgrp.xml"/>

The only tricky part is finding out what a TopComponent's ID is. But even that's not very hard. Just open the window you want to include in a group, close down the IDE, go to the Windows2Local/Modes folder, open the TopComponent's wstcref file and look at the tc-id element. The only one that's a bit tricky is the Welcome screen, where the ID is "WelcomeComponent", which you can only find by digging in the NetBeans sources. And even then the Welcome screen doesn't behave very well in a group. But apart from that, all this is really very easy and can be very powerful in letting your module control the layout of the application in which it is installed.

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.