Case Study: Customizing the NetBeans Window System

The NetBeans window system can be used "as is" in, I guess, 90% of cases. However, it's that final 10% that's always the problem! That's when the NetBeans window system becomes, potentially, a little bit painful. Less so, though, when you become aware of the MANY different ways in which you can tweak it. I want to illustrate this point by means of a concrete example.

You're working on a welcome screen with the following requirements:

  1. It should be undocked when the application starts.
  2. It should be modal so that when the user clicks on the application behind it, the welcome screen shouldn't disappear behind it.
  3. It should have a certain default size.
  4. It should have no buttons or right-click menu items or anything else in its titlebar, except for 'Close'.
  5. When 'Close' is clicked, it should dock into the right sliding side.
  6. When it is 'slided in', i.e., when the mouse hovers over the button in the right sliding side, the full welcome screen should be shown, instead of the default slided in size, which is much smaller.
  7. The application must run on NetBeans Platform 6.1, which means that the previous requirement cannot be solved in the new 6.5 way of doing so (via a client property in the TopComponent constructor).
  8. When the 'Pin' event is invoked, i.e., when the user clicks the 'Pin' button while the welcome screen is slided in from its position in the right sliding side, it should be docked back into its original undocked mode.

Now, in case you don't realize it, the above puts a lot of strain on the NetBeans window system. In terms of the concepts made available by the NetBeans window system, the above requirements are extremely obtuse. Below I will describe one solution to this case study. I think if you read what follows closely enough, anyone wrestling with the NetBeans window system should gain a lot from it. Just to give a clear impression of the intended end result, below the screenshots show a mock up of the solution. In the first screenshot, you see the welcome screen (empty of content, but that's not the point), exactly as it should appear when the user starts the application:

When the user clicks behind the welcome screen, the welcome screen does not disappear behind the application, i.e., the welcome screen is modal. Next, here's a screenshot that shows the welcome screen when it is closed, i.e., it is never actually closed; it 'closes' into the right sliding side:

When it is opened from its closed state, it should be exactly as shown in the first screenshot.

And the reason for all of the above? The users of the application are either not finding the welcome screen or find that it gets in their way. They can't find the 'undock' functionality very easily and so, whenever the 'editor' mode is occupied by documents (or whatever else is docked there) the welcome screen (which is in the 'editor' mode by default) is hidden and thereby unusable. By making the welcome screen more prominent (as described in the list of requirements above), the user is more likely to find it and also to find it useful. The easy switching between undocked and slided out also aids in this.

A summary of everything that you'd need to do to obtain the above result:

  • Create a new mode for the undocked welcome screen. When the application starts, the welcome screen should be modal and undocked. So you need a new mode (i.e., a new position) in the window system, because none of the default modes provide these features. Modes are defined in XML. Here's the new mode for the above:
    <?xml version="1.0" encoding="UTF-8"?>
    <mode version="2.3">
        <name unique="welcomeScreen" />
        <kind type="view" />
        <state type="separated" />
        <constraints>
            <path orientation="vertical" number="0" weight="0.5"/>
            <path orientation="horizontal" number="1" weight="0.5"/>
        </constraints>
        <bounds x="312" y="237" width="679" height="378" />
        <frame state="0"/>
        <active-tc  id="DemoTopComponent" />
        <empty-behavior permanent="true"/>
    </mode>

    Brief explanation of each element: 'name' is used in the layer to hook the welcome screen to this mode; 'kind' specifies that the mode will cause its TopComponents to be modal (instead of 'editor' and 'slidingSide'); 'state' specifies that the mode supports undocked TopComponents; 'constraints' and 'bounds' set position and size; 'frame' sets whether the frame is normal or iconified (or a few others, see the JFrame documentation); 'active-tc' sets which of the TopComponents within the mode will be active by default; 'empty-behavior' sets whether the mode will be destroyed if it is empty (normally, best to always set it to be 'permanent=true').

  • Connect the mode to the TopComponent. In the layer, you need this, taking careful note of the section in bold:
    <folder name="Windows2">
        <folder name="Components">
            <file name="DemoTopComponent.settings" url="DemoTopComponentSettings.xml"/>
        </folder>
        <folder name="Modes">
            <file name="welcomeScreen.wsmode" url="welcomeScreenWsmode.xml"/>
            <folder name="welcomeScreen">
                <file name="DemoTopComponent.wstcref" url="DemoTopComponentWstcref.xml"/>
            </folder>
        </folder>
    </folder>

  • Use the installer to force the TopComponent into the mode. Despite all of the above, I found that the TopComponent was still not modal. It appeared in the right place, but it wasn't modal. So I forced it via the installer:
    public class Installer extends ModuleInstall {
    
        @Override
        public void restored() {
            WindowManager.getDefault().invokeWhenUIReady(new Runnable() {
    
                public void run() {
                    DemoTopComponent demoTC = DemoTopComponent.findInstance();
                    Mode mode = WindowManager.getDefault().findMode("welcomeScreen");
                    if (mode != null) {
                        mode.dockInto(demoTC);
                        demoTC.open();
                    }
                }
            });
    
        }
    }

  • Override TopComponent.componentClose. Instead of the standard Close behavior, you want the welcome screen to be docked into the right sliding side. The right sliding side is provided by one of the default modes, called 'rightSlidingSide'. You can reuse it as follows:
    @Override
    public void componentClosed() {
        Mode mode = WindowManager.getDefault().findMode("rightSlidingSide");
        if (mode != null) {
            mode.dockInto(this);
            this.open();
        }
    }

    So, whenever Close is clicked, the welcome screen will dock into the right sliding side.

  • Handle the Pin event problem. When the user hovers with the mouse over the slided out welcome screen (i.e., when it is docked into the right sliding side), the welcome screen forms a pop up (called 'slided in' in NetBeans terminology). This slided in mode has some problems for our scenario. Firstly, the default size cannot be controlled by our module. In 6.5 this is changed, i.e., in 6.5 each TopComponent can set its slided in size (client property in constructor specifies that TopComponent preferred size should be used when sliding in). However, if we want the whole welcome screen to be shown in 6.1, we'd need to create a new mode. And that's where the TopComponent should be slided out to, instead of the right sliding side. Secondly, when slided in, the TopComponent has a button which, when you hover over it, says 'Pin'. When clicked 'Pin' behaves oddly, in my opinion. It should return our TopComponent to its original undocked modal state, but instead it puts the welcome screen in the 'explorer' view, where it doesn't make any sense.

    To get around both these problems, override TopComponent.requestVisible, which is called when the welcome screen is slided in. So, whenever the TopComponent slides in, you will force it into your own custom mode, which is the undocked and modal mode with which we started:

    @Override
    public void requestVisible() {
        Mode mode = WindowManager.getDefault().findMode("welcomeScreen");
        if (mode != null) {
            mode.dockInto(this);
            this.open();
        }
    }

    In this way, the user is never confronted with the 'Pin' event. The user also doesn't ever see the 'slided in' mode, so that the size of the popup is irrelevant.

  • Force the menu item in the menu bar to dock the TopComponent into the custom mode. To make sure the custom mode is used when the user chooses the menu item that opens the welcome screen, do something similar to the code shown above, such as the below:
    @Override
    public void actionPerformed(ActionEvent evt) {
        DemoTopComponent demoTC = DemoTopComponent.findInstance();
        Mode mode = WindowManager.getDefault().findMode("welcomeScreen");
        if (mode != null) {
            mode.dockInto(demoTC);
            demoTC.open();
        }
    }

  • Remove the actions from the welcome screen titlebar. When the user right-clicks in the titlebar, there's an undock menu item, among others. These are dangerous because you want to control this particular TopComponent as much as possible. So remove them:
    @Override
    public Action[] getActions() {
        ArrayList actions = new ArrayList();
        Action[] retVal = new Action[actions.size()];
        actions.toArray(retVal);
        return retVal;
    }

And that's "all". Now you have absolute control of your welcome screen and it does exactly what you want it to do. As you can see, modifying the NetBeans window system can be done in various ways—through overriding methods on the TopComponent as well as some carefully thought out XML entries. The trick with the XML is to start up the application, put all the windows where you want them to be at start up, close down the application, and then move the generated XML from the application's user directory into your module's XML files. That, at least, gives a strong starting point, after which your tweaking can begin.

Comments:

I am a newbie to RCP using the netbeans platform. I couldn't quite understand the flow in your example. I presume the first xml(using the mode DTD) is the one referred to in the second (layer.xml?) as DemoTopComponent.settings. Are the files referred to as welcomeScreen.wsmode and DemoTopComponent.wstcref generated by netbeans?

Posted by Sid Kurias on September 29, 2008 at 07:51 PM PDT #

Doesn't matter the wiki helped me figure it out

http://wiki.netbeans.org/DevFaqWindowsWstcrefAndFriends

Posted by Sid Kurias on September 29, 2008 at 09:24 PM PDT #

Hi,

"It should be modal so that when the user clicks on the application behind it, the welcome screen shouldn't disappear behind it."

How to make the top component modal and that which does not allow user-clicks on the application behind it?

Thanks
Karthik

Posted by Karthik Vivek on October 07, 2010 at 05:35 PM PDT #

Hi

Could you teach me how to make window maximized by default when opened?

Thanks!

Posted by guest on January 23, 2012 at 02:36 AM PST #

1. Use the "Installer/Activator" wizard (in the Module Development category of the New File dialog) to create a new Module Installer.

2. Then, once you have done the above, define the installer like this:

public class Installer extends ModuleInstall {

@Override
public void restored() {
WindowManager.getDefault().invokeWhenUIReady(new Runnable() {
@Override
public void run() {
FileUtil.getConfigObject("Actions/Window/org-netbeans-core-windows-actions-ToggleFullScreenAction.instance", Action.class).actionPerformed(null);
}
});
}

}

Posted by Geertjan on January 23, 2012 at 02:51 AM PST #

I want my top component be opened as new window which I am able to do with <kind type="editor" />
<state type="separated" />
but I want to use progress bar which should be visible when used at the bottom right corner of the opened TopComponent instead of the main window. How can I achieve that.

Posted by guest on February 03, 2014 at 04:37 AM PST #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
12
13
14
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today