New Window System API Changes

Version: 0.6, January 8, 2004
Author: Peter Zavadsky, Sun Microsystems/NetBeans
               
Marek Slama, Sun Microsystems/NetBeans
Abstract:
Following document describes changes in API which emerged both from UI spec and problems with adjusting to the older API. It shows also recommends how the client code should be adjusted to the new window system.
Document History:
[10/01/2003] : version 0.1 : {First preliminary version of the document}

[10/08/2003] : version 0.2 : {Merged groups and workspaces documents into this one to have the changes together}
[10/10/2003] : version 0.3 : {Changed API according to internal API review, added explanation of createMode method behavior}
[10/20/2003] : version 0.4 : {Added also persistence descriptions (XML layers)}
[11/25/2003] : version 0.5 : {Added method findTopComponent}
[01/08/2004] : version 0.6 : {Added method TopComponent.getPersistenceType}

Contents:


1 Overview

This document describes all changes which come with the new window system implementation. There are a lot of them, abandoning workspaces, introducing window groups, new version of XML declarations, various API enhancements and API deprecations.
There is necessary to say, that the new window system is compatible with the older API, thus all older client code should work somehow even unchanged. On the other hand due to a significant changes it is recommended that those deprecated code is revised and adjusted to the new state accordingly, the special is about XML layer, which is almost necessary to redefine, in order to get the proper layout, since the change in layout is significant comparing to the older one.


2 New Concepts

The window spec UI spec introduced a couple of new concepts the implementation has to deal with. Those are changed layout from the border like one to generic split layout, division windows to documents and views, introduction of window groups, and abandoning workspaces.

2.1 Generic Split Layout

The original 'border-like' layout, which allowed center, north, south, west and east positioning of windows inside mode and also inside desktop was changed to generic split layout of desktop while mode isn't divided itself anymore. This has especially impact on changes of XML layer declaration, while the API is still kept kind of asymmetric like it was before, i.e. it is not possible to achieve the same layout  from client code. Currently the layout is matter of layers only. Client programmer is not allowed to manipulate it, just user. Manipulation of layout means adding, removing, repositioning of modes, which represent kind of cell in the generic split layout. Using API is allowed just move the windows (TopComponents) via those existing modes.

2.2 Document and View Windows

The windows (TopComponents) are divided to documents and views. From UI point of view document is window which is supposed for the main work. The most of working time is spent in it. Those are editors, GUI editor, image viewer etc. Views are windows which are just helper windows to the documents ones. Those are typically explorers, debugger windows, form palette and inspector, properties etc. The impact on user is, these windows can't be mixed together, i.e. they may not be contained in the same mode, e.g. editor (java source) can't be at the same place with explorer and vice versa.

Documents Area:
Therefore are also modes divided to document and view kinds. There is also defined (from UI point of view) editor are, which is always present on screen. This divides for user the views and documents. Every window (mode) which resides inside the document area are document windows (i.e. modes are documents kind) and all windows (modes) around that area are view windows (i.e. modes are of view kind). User can differentiate these two types by different UI of the tabbed components, (and also that she is not allowed to mix those windows together, e.g. when trying DnD).

Internal Implementation:
Currently it is implemented quite hard way. Modes are declared whether they are view or document (editor) kind (That way it defines whether its constraints are relative to the document area or not).
// PENDING Problem how to define undefined windows  Problematic is current implementation of TopComponent (window) type. It is defined by client property. Then this property is checked whether the TopComponent can or can't be added to particular mode. If the TopComponent is not defined (doesn't contain that client property) it is defined the way, depending to which mode is adding first time, it is set the appropriate type. But problem appears if some mode doesn't exist (e.g. mode was not loaded, because it was in old layer defined), then it is put into default editor mode.
After talk with Yarda, it seems there could be better solution than the current one, i.e. don't define the kind of TopComponent internally. For client programmer allow to add (dock) the TopComponent anywhere. For user prohibit the mixing (to achieve the UI goal) that way, take the type of TopComponent from mode it currently reside.


2.3 Window Groups


   Window groups offer client programmer easily to follow the concept of user managed opening/closing of 'helper' windows. There are tasks (like GUI editing, debugging) which typically uses certain helper windows needed to accomplish that task (like Component Palette/Inspector, debugger windows etc.). Those windows are typically needed to be present just during the time of that task, no sooner, no later. To get this goal, it could seems is enough just to open and close those windows, upon the task start or finish. But groups offer something more. They allow user to manage opening state of those helping windows. before, during and after that task. Window system group implementation allows this concept easily to follow for client programmers, it offers very simple API (the only more "complicate" part is the group definition in XML layer). All the runtime difficulties are done behind the scenes in window system implementation.

    Note about older name Window Sets: Please start to use term "window group" instead often older one "window set". Window set is a name coming from UI spec, but is a bit misleading, since in java is Set an unordered collection of objects. The group name fits much better, because it tells that those windows belong somehow together while they don't represent any collection at the same time.

    Groups are considered to be a replacement of workspaces concept. But those are not the same. In short there is a at least one significant difference, i.e. groups don't change the layout of windows, they manage just opening and closing of them. More detailed explanation should give UI document (UI spec).

    About the concept of groups: At first sight you can see the group is nothing more than just sheer opening or closing more windows. You would say it is nothing special, you can achieve the same goal with the API not using groups at all. Why are there those groups?
    The reason is there is some value group implementation adds there. I.e. groups can manage the opening/closing of its windows "accordingly to the user".  Look at the scenarios.

List of scenarios:
  1. Opening group when none of the member TopComponents are opened
    In that case, when group is opening (call group.open() method) all the member TopComponents with opening flag set to true are opened. In NB (new WS build) when you select the Form Designer window all the windows (Component Palette, Component Inspector, Properties) gets opened.
  2. Closing group when none of the member TopComponents were opened before the group was opened
    In that case, when group is closing (call group.close() method) all the member TopComponents with closing flag set to true are closed. In our case when you 'unselect' last Form Designer window (that way no FormDesigner window is selected on screen) all the windows (Component Palette, Component Inspector, Properties) gets closed.,
  3. Closing group when some of the member TopComponents were opened before the group was opened
    In that case are closed just those member TopComponents which closing flag is set to true and were not opened before the group was opened. In our case when you had opened e.g. Component Palette before the group was opened, then when closing the group Component Palette window remains opened (unless you closed it explicitly while the group was opened).
  4. Opening group when some of the member TopComponents were closed while the group was previously opened
    In that case was the opening flag of those member TopComponents set to false, thus upon next group opening are opened just those member TopComponents which have the opening flag set to true. In our case when you have opened form group (selected Form Designer window) and closed e.g. Component Palette during the time the group was previously opened, then closed the group ('unselect' Form Designer window). When opening the group next time the Component Palette is not opened. (User can get back the old behavior when opens the Component Palette while the group is opened see the next point.)
  5. Opening group when come of the member TopComponents were opened while the group was previously opened
    In this case was the opening flag of those member TopComponents set to true, thus upon next group opening are opened together with other member TopComponents which have the opening flag set to true. In our case (continue from the previous step), if you have opened the form group while the Component Palette wasn't, you can open the Component Palette 'manually' from the menu (before the group was closed), the close the group and when open the group again, you get also opened Component Palette.

These scenarios is a bit complicated to explain. Much more understandable is when you try it out, and imagine that for client programmer it is just simple group.open() and group.close() method calls.

See also Window Groups API.


2.4 Abandoning Workspaces

Since the new window system doesn't support concept of workspaces (see the UI spec) anymore, the older API dealing with workspaces (Workspace interface, and couple of methods in other class in org.openide.windows package) becomes useless. However the older client code dealing with the workspaces should work somehow. See more in deprecated API. This document also shows what are the replacements of the older Workspace API.

Replacements of the Workspace API should be understandable and self explaining. It could happen that some of the solutions may not fit, e.g. when finding of Workspace according some name the current solution returns the singleton implementation which has (in almost all cases)
different name. If you feel it is wrong, please demand the change of that solution. I preferred the most straightforward one in order to keep the older code working as much as possible.


    Compatibility Issues:
    In order the older API is working in some way, the new window system pretends it works with one internal workspace (which can be assumed as singleton workspace implementation). It means that all older client code referring to workspaces will remain working somehow. I.e. it always gets the singleton instance of workspace, e.g. when creating the new workspace, there is returned the singleton instance, when asking for workspaces, it is again returned set which contains only the one singleton instance. Other older API  methods which uses workspace as an argument, just ignore the argument and are considering they are working in the singleton workspace instance context.

See also deprecated API working with Workspaces.

2.5 Note about Focus Management

Old window system supported, probably from the wrong reasons, managing of itself by requesting focus of Component (please don't mix with old API TopComponent.requestFocus() call). I.e. when was passed focus to e.g. JButton which was contained
in not active TopComponent, that TopComponent got activated.
This is no more supported, (I believe) this was an undocumented feature and is highly problematic... for managing of window system, i.e. activating TopComponents is necessary used purely the API from org.openide.windows package.


3 Summary of API Changes

Describes API changes both in code and XML layer declarations.

3.1 API Enhancements

There are a couple of API enhancements.


3.1.1 Window Groups API


The API for window groups is extremely simple. It consists currently of a method in WindowManager class and one TopComponentGroup interface.

The WindowManager methods are:

public TopComponentGroup findTopComponentGroup(String name) {  ...  }

The method is used to find the TopComponentGroup according its specified name.

There is an interface which represents the group

public interface TopComponentGroup {
    public void open();
    public void close();
}

The interface is used to open or close the group respectively.


    Usage:

    The TopComponentGroup interface helps client programmer (module owner) to use the concept of groups in a very simple way. There is necessary to specify the group in XML layer, define member TopComponents (see below), find it via WindowManager.findTopComponentGroup(String name) method and then open or close it when needed. All the other staff adds window system group implementation, i.e. the managing opening and closing according to the above scenarios. Let have a look at the real example:

Code snippet from form/src/.... FormGroupActivator.java:

            TopComponentGroup group = WindowManager.getDefault().findTopComponentGroup("form"); // NOI18N
            if(group != null) {
               if(isFormDesignerSelected()) {
                    group.open();
                } else {
                    group.close();
                }
            }

The client code is very simple. It just finds the group named "form" (form group defined in XML layer) and opens or closes it respectively according to its needs (i.e. when there is selected FormDesigner component or not respectively). The group has to be properly defined in the XML layer (i.e. define its members and opening and closing flags, in our case it includes Component Palette, Component Inspector and Properties windows all with opening and closing flags set to true ).

Hint for modules:
Usage of group is restricted to view kind of TopComponents... i.e. to the helper singleton windows. Programmatically isn't allowed anything but opening and closing of the group.  This is a warning before overusing of this feature. First have a look at the already using form, output and execution groups.


3.1.2 Other API Enhancements

TopComponent.activate() method replaces usage of TopComponent.requestFocus() method. The requestFocus() method was misused in the past API for activation of TopComponent, which could cause problems if that method is used for requesting focus only (e.g. by focus management framework when the TopComponent is used as an ordinary Component). Instead of this method client code should use TopComponent.activate() method.

Older API
New API
Explanation
method public void requestFocus () in TopComponent class [Note: this is talked about using this method for TopComponent activation]
method public void requestActive() in TopComponent class

method public void setName(String name) in TopComponent class
methods public void setDisplayName(String displayName) in TopComponent class
Field name is supposed to be programmatic name of component
method public String getName() in TopComponent class
methods public String getDisplayName() in TopComponent class
Field name is supposed to be programmatic name of component
No API
method public int getPersistenceType() in TopComponent class
This method should be overriden in subclass to return proper constant defining component persistence type. Possible values are TopComponent.PERSISTENCE_ALWAYS, TopComponent.PERSISTENCE_ONLY_OPENED, TopComponent.PERSISTENCE_NEVER. It replaces TopComponent client property PersistenceType.
No API
method public String findTopComponentID(TopComponent) in WindowManager class and method protected String preferredID() in TopComponent class Provides unique ID for each TopComponent instance, preferredID method allows subclasses influence the resulting ID, it is used as a base when creating the ID.
No API
method public TopComponent findTopComponent(String) in WindowManager class Retrieves TopComponent instance by TopComponent unique ID. It is used mainly to access persistent singleton TopComponent instance. Complementary method with method findTopComponentID.
No API
method public TopComponent getSelectedTopComponent() in Mode interface
No API
There is also introduced new API, i.e. TopComponentGroup interface, which allows client programmer to use concept of window groups. Have a look at TopComponentGroup API description
 
 

3.2 API Deprecations


3.2.1 API Replacing Deprecated Workspace



Table shows what are the replacements instead of the deprecated Workspace API.

Deprecated Workspace API
API replacing the deprecated Workspace API
field public static final String PROP_MODES Use field public static final String PROP_MODES in WindowManager class
field public static final String PROP_NAME Do not use anymore, it is redundant
field public static final String PROP_DISPLAY_NAME
Do not use anymore, it is redundant
method public String getName ();
Do not use anymore, it is redundant
method public String getDisplayName ();
Do not use anymore, it is redundant
method public Set getModes ();
Use method public Set getModes() in WindowManager class
method public Rectangle getBounds ();
Do not use anymore, it is redundant
method public void activate ();
Do not use anymore, it is redundant
method public Mode createMode (String name, String displayName, URL icon);
see explanation 
method public Mode findMode (String name);
Use method public Mode findMode(String name) in WindowManager class
method public Mode findMode (TopComponent tc);
Use method public Mode findMode(TopComponent tc) in WindowManager class
method public void remove ();
Do not use anymore, it is redundant
method public void addPropertyChangeListener (PropertyChangeListener list);
Use method public abstract void addPropertyChangeListener (PropertyChangeListener l); in WindowManager class
method public void removePropertyChangeListener (PropertyChangeListener list);
Use method public abstract void removePropertyChangeListener (PropertyChangeListener l); in WindowManager class


Problem with createMode method

Since the current layout differs from the previous one, and restrictions defined by UI to the current behavior differs dramatically. It was needed to change behavior of createMode method. That method currently doesn't create new mode instance but always returns the default editor mode (the one in documents area). Thus currently there is no way to create mode programmaticaly. It is possible via declaration in XML layer only. This restriction was made from the reason, that no floating modes (nor the internal ones) are allowed, just those ones residing in the generic split layout. Since the usecase for the createMode method was to create floating mode, it was bypassed the above described way. This solution is fully reasonable for current implementation which is 'MDI like'. That is the mainly supported state and only focused by HIE. However there is also support for 'SDI like' state. For that case the creation of the floating modes has sense. Thus it is necessary to specify how the createMode method should behave, whether is could differ depending on which state is currently on.

3.2.2 Deprecated API Working with Workspaces in WindowManager Class

In the class WindowManager are deprecated following:

Deprecated API dealing with Workspaces in WindowManager class
API replacing the deprecated one
field public static final String PROP_WORKSPACES Do not use anymore, it is redundant
method public final Workspace createWorkspace (String name) Do not use anymore, it is redundant. It always returns the singleton Workspace implementation
method public abstract Workspace createWorkspace (String name, String displayName); Do not use anymore, it is redundant. It always returns the singleton Workspace implementation
method public abstract Workspace findWorkspace (String name); Do not use anymore, it is redundant. It always returns the singleton Workspace implementation
method public abstract Workspace[] getWorkspaces (); Do not use anymore, it is redundant. It always retuns an array containing the singleton Workspace implementation only
method public abstract void setWorkspaces (Workspace[] workspaces); Do not use anymore. Does nothing
method public abstract Workspace getCurrentWorkspace (); Do not use anymore, it is redundant. It always returns the singleton Workspace implementation


3.2.3 Deprecated API Working with Workspaces in Mode Interface


In the interface Mode is deprecated following:
Deprecated API dealing with Workspaces in Mode Interface
API replacing the deprecated one
method public Workspace getWorkspace ()
Do not use anymore, it is redundant. It always returns the singleton Workspace implementation


3.2.4 Deprecated API Working with Workspaces in TopComponent Class


In the class TopComponent are deprecated following:
Deprecated API dealing with Workspaces in TopComponent class
API replacing the deprecated one
field public static final int CLOSE_EACH
Do not use anymore, it is redundant
field public static final int CLOSE_LAST
Do not use anymore, it is redundant
method public void open (Workspace workspace)
Use method public void open () in TopComponent class instead
method public final boolean isOpened(Workspace workspace)
Use method public final boolean isOpened () in TopComponent class instead
method public final boolean close (Workspace workspace)
Use method public final boolean close () in TopComponent class instead
method public boolean canClose (Workspace workspace, boolean last)
Use method public boolean canClose() in TopComponent class instead



 

3.3 Internal API changes

No change is required from modules! These changes are relevant only to implementors of window system!

This is purely internal change unless you are creating its own window system implementation.
There is added a bunch of  protected methods in WindowManager class which replace the interface Component in WindowManager class. Those methods better describe the needs of management of TopComponents. It is also saved not just one class in window system implementation but all instances of that class created per one TopComponent instance.


Older API
New API
method public void open () in WindowManager.Component interface method protected void topComponentOpen(TopComponent tc) in WindowManager class
method public void open (Workspace workspace) in WindowManager.Component interface No new API, Workspaces are not supported, use the above method.
method public void close (Workspace workspace) in WindowManager.Component interface method protected void topComponentClose(TopComponent tc) in WindowManager class
method public void requestFocus () in WindowManager.Component interface method protected void topComponentRequestActive(TopComponent tc) in WindowManager class
method public void requestVisible () in WindowManager.Component interface method protected void topComponentRequestVisible(TopComponent tc) in WindowManager class
method public Node[] getActivatedNodes () in WindowManager.Component interface No new API, the TopComponent itself manages activated nodes.
method public void setActivatedNodes (Node[] nodes) in WindowManager.Component interface method protected void topComponentActivatedNodesChanged(TopComponent tc, Node[] activatedNodes) in WindowManager class
method public void nameChanged () in WIndowManager.Component interface method protected void topComponentDisplayNameChanged(TopComponent tc, String displayName) in WindowManager class
method public void setIcon (Image icon) in WindowManager.Component interface method protected void topComponentIconChanged(TopComponent tc, Image icon) in WindowManager class
method public Image getIcon () in WindowManager.Component interface No new API, the TopComponent itself manages icon.
method public Set whereOpened () in WindowManager.Component interface method protected boolean topComponentIsOpened(TopComponent tc) in WindowManager class
No API
method protected void topComponentDisplayNameAnnotationChanged(TopComponent tc, String displayNameAnnotation) in WindowManager class
No API
method protected void topComponentToolTipChanged(TopComponent tc, String toolTip) in WindowManager class

method protected String topComponentID(TopComponent tc, String preferredID) in WindowManager class

method protected Action[] topComponentDefaultActions(TopComponent tc, String preferredID) in WindowManager class



3.4 Changes in XML layer declarations

Due to a new layout specified by UI specification, the XML declaration has overcome the major redesign.  There are created new declarations for the new XML format. The older XML format is also read and converted to the new one by window system
internally (it is scheduled to to yet), but the position of the TopComponent in old layout should not fit as desired in the new one.

Highly recommended  changes in modules:

All modules declaring window system components in XML layer should upgrade those definitions.



3.4.1 Overview of Changes in XML layer declarations

State of window system must be persistent among sessions. It means that when IDE is restarted it must restore state of window system when IDE was exited. XML format is used to serialize state of window system. Window system has hierarchical structure. On top there is Window Manager. Window Manager contains global data like bounds of main window. Below Window Manager there are modes and groups. Mode is container for UI presentation of TopComponents. Group is logical group of TopComponents to control simultaneous opening/closing TopComponents. Mode and group contain reference to TopComponent. Unique TopComponent ID is used as key. TopComponents itself are stored separately.

3.4.2 Structure of configuration data

XML configuration files are placed in folders. Folders are different from previous version of window system. Module data and user data are saved in separate folders. Module folder contains configuration data defined in modules. Module folder is read only. Local folder contains customized data. Local folder data are created when window system is saved. Local folder is read/write.

Module folder structure:
Windows2
|--> WindowManager.wswmgr
|--> Groups
     |--> Group_1.wsgrp
     |--> Group_1
          |--> TC_1.wstcgrp
|--> Modes
     |--> Mode_1.wsmode
     |--> Mode_1
          |--> TC_1.wstcref
          |--> TC_2.wstcref
|--> Components
     |--> TC_1.settings
     |--> TC_2.settings
Local folder structure:
Windows2Local
|--> WindowManager.wswmgr
|--> Groups
     |--> Group_1.wsgrp
     |--> Group_1
          |--> TC_1.wstcgrp
|--> Modes
     |--> Mode_1.wsmode
     |--> Mode_1
          |--> TC_1.wstcref
          |--> TC_2.wstcref
|--> Components
     |--> TC_1.settings
     |--> TC_2.settings
Handling of configuration data in module and local folders:
When IDE is started for the first time all configuration data are present only in module folder Windows2. When window system configuration is saved it is saved to local folder Windows2Local. By this way it is possible to handle changes in module and local folder separately. Changes in module folder are caused by enabling/disabling modules. Such changes make possible to update window system configuration when module is disabled/enabled. (For example if module defines some opened TopComponent this TopComponent is removed from window system ie. closed in GUI when module is disabled and this TopComponent is added ie. opened in GUI when module is enabled. At the same time corresponding configuration data present in local folder ie. wstcref file are deleted when module is disabled.) Changes in local folder are ignored.
Any configuration file is first read from local folder. If file is present in local folder presence of the same file (file with the same name ie. content can be different because it can be modified) in module folder is ignored. It becomes little bit more complicated in case of wstcref files because TopComponent can change its Mode eg. using Drag&Drop. In such case presence of wstcref file in local folder hides presence of file with the same name in ANY Mode folder in module folder. By this way precedence of local folder over module folder is achieved.

3.4.3 Split desktop

Desktop (main window content pane) can be recursively split. It can be completely and uniquely described using N-split tree model. Model can be serialized. We provide a few simple examples here how desktop is mapped to XML and vice versa. Elements "constraints" and "path" are used to give exact position of editor area and mode in model and define desktop layout. Editor area is actually subtree of model in this context. Editor area can contain one mode (no split inside editor area) or more modes (editor area is recursively split). Mode inside editor area uses editor area as root of their path ie. complete path = editor area path + mode path. Modes inside editor area are of type "editor". Modes outside of editor area are of type "view". (Attribute "type" of element "kind" in mode configuration XML.)
Simplest possible desktop is no split ie. one mode on desktop
----------------------
| |
| |
| M1 |
| |
| |
| |
----------------------
"constraints" element of mode M1 will be empty in such case:
<constraints>
</constraints>

Next we can split desktop horizontally (we use JSplitPane convention) to 2 equal cells.
---------------------
| | |
| | |
| M1 | M2 |
| | |
| | |
| | |
---------------------
"constraints" element of mode M1 will be as follows:
<constraints>
<path orientation="horizontal" number="0" weight="0.5" />
</constraints>
Mode M2:
<constraints>
<path orientation="horizontal" number="1" weight="0.5" />
</constraints>
It is possible to add third cell at the same level by adding mode M3 with attribute number="2". If weight="0.5" is used all cells have the same width. If one cell is hidden remaining cells stay equal ie. size of visible cells is proportional to their weights.
Last example contains 4 modes, desktop is first split vertically, then top cell is split horizontally, then right cell is split vertically.
---------------------
| | |
| | M2 |
| M1 | |
| |---------|
| | |
| | M3 |
| | |
---------------------
| |
| M4 |
| |
---------------------
Tree would be as follows (S1, S2, S3 are nodes of tree):
               M1
|
S2---|
| | M2
| S3---|
DESKTOP---S1 M3
|
|
M4
Mode M1:
<constraints>
<path orientation="vertical" number="0" weight="0.7" />
<path orientation="horizontal" number="0" weight="0.5" />
</constraints>
Mode M2:
<constraints>
<path orientation="vertical" number="0" weight="0.7" />
<path orientation="horizontal" number="1" weight="0.5" />
<path orientation="vertical" number="0" weight="0.5" />
</constraints>
Mode M3:
<constraints>
<path orientation="vertical" number="0" weight="0.7" />
<path orientation="horizontal" number="1" weight="0.5" />
<path orientation="vertical" number="1" weight="0.5" />
</constraints>
Mode M4:
<constraints>
<path orientation="vertical" number="1" weight="0.3" />
</constraints>

3.4.4 Difference between new and old version of window system persistence

  • Because of new desktop layout is different from old desktop layout configuration data are completely separated. Different folders are used to save winsys configuration data. Major version of XML configuration data is increased to 2.0. Format of XML configuration data is changed. Only format of TopComponent settings files stays unchanged. To keep backward compatibility with old XML configuration data import (ability to read and convert old layout) from install layer ie. data defined by modules not customized user data is supported.
  • Window system is not part of project. It means that configuration data are stored in session layer not in project layer. Window system is not changed when projects are switched.
  • Window system persistence is not based on datasystems any more (with exception of TopComponents, their persistence is still handled by InstanceDataObject). Main reason of this and previous change is to improve stability and robustness of window system persistence.

3.4.5 Simple examples

Window Manager

Name of window manager configuration file is WindowManager.wswmgr.
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE windowmanager PUBLIC
          "-//NetBeans//DTD Window Manager Properties 2.0//EN"
          "http://www.netbeans.org/dtds/windowmanager-properties2_0.dtd">

<windowmanager version="2.0">
    <main-window>
        <joined-properties x="0" y="0" width="1200" height="900"
                           centered-horizontally="true" centered-vertically="true" />
    </main-window>
    <editor-area state="joined">
        <constraints>
            <path orientation="vertical" number="0" weight="0.7" />
            <path orientation="horizontal" number="1" weight="0.55" />
        </constraints>
    </editor-area>
    <active-mode name="explorer" />
    <toolbar configuration="Standard" />
</windowmanager>
Example of WindowManager.wswmgr file is given above. As desktop can be in two different states joined or separated properties of both states can be present. (Joined state means one main window and everything is inside main window. Separated state means that main window and all modes have their own native frame.) These state are independent. Current state of desktop is given by state of editor area (element "editor-area" attribute "state"). As properties of both states can be saved in the same file some properties are relevant for separated state only, some for joined state only and some does not depend on desktop state. "joined-properties" of "main-window" in example sets initial size and position of main window used in layer. As winsys is saved only absolute bounds are stored. Attributes like "centered-horizontally" are suitable to set initial size and position of main window after first start independently on actual screen resolution. As state of editor area is "joined" it means that example contains only properties of joined desktop state. Element "constraints" describes where is editor area located in N-split tree which describes whole desktop. Desktop area can be split vertically or horizontally. Resulting area can be split again. So it is recursive splitting. Position (size of area) and orientation of splitter can be described completely and uniquely by N-split tree. In example first split is "vertical" (areas from top and bottom) and editor area is placed at first (top) cell. Second split is "horizontal" (areas from left to right) and editor area is in second cell (right cell when there are 2 cells, middle cell when there are 3 cells). Detail description of all elements/attributes is in DTD.

Mode

Mode configuration file name consists of unique mode name and suffix wsmode. Folder with the same name contains wstcref files - configuration files of TopComponent's references in Mode.
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE mode PUBLIC
          "-//NetBeans//DTD Mode Properties 2.0//EN"
          "http://www.netbeans.org/dtds/mode-properties2_0.dtd">

<mode version="2.0">
    <module name="org.netbeans.core.ui/1" spec="1.2" />
    <name unique="explorer" />
    <kind type="view" />
    <state type="joined" />
    <constraints>
        <path orientation="vertical" number="0" weight="0.7" />
        <path orientation="horizontal" number="0" weight="0.25" />
    </constraints>
    <active-tc id="filesystems" />
    <empty-behavior permanent="true" />
</mode>
As example of mode configuration we use "explorer" mode. It resides on top left cell of split desktop as it is obvious from its constraints. Current state of mode is "joined". As in Window Manager example both properties for split or joined state can be present. Current state controls what properties are effective. All configuration files below window manager ie. wsmode, wsgrp, wstcref, wstcgrp can contain module info. It allows window system to handle correctly enabling/disabling of modules. When module is disabled window system element defined in module layer ie. provided by module are removed when they contain module info. Detail description of all elements/attributes is in DTD.

TopComponent in Mode Reference

TopComponent in Mode Reference configuration file name consists of unique TopComponent ID and suffix wstcref. File is located in corresponding mode folder. TopComponent instances are serialized separately in folder Components as settings files.
<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE tc-ref PUBLIC
          "-//NetBeans//DTD Top Component in Mode Properties 2.0//EN"
          "http://www.netbeans.org/dtds/tc-ref2_0.dtd">

<tc-ref version="2.0">
    <module name="org.netbeans.core.ui/1" spec="1.2" />
    <tc-id id="filesystems" />
    <state opened="true" />
</tc-ref>
Configuration file contains just unique TopComponent ID and state of TopComponent in Mode. TopComponent state can be "opened" or "closed". Detail description of all elements/attributes is in DTD.

Group

Group configuration file name consists of unique group name and suffix wsgrp. Folder with the same name contains references to TopComponents in group.
<?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.netbeans.modules.form/2" spec="1.7" />
    <name unique="form" />
    <state opened="false" />
</group>
Group configuration contains only unique group name and state of group. Group state can be opened or closed. State is stored as boolean flag. Detail description of all elements/attributes is in DTD.

TopComponent in Group Reference

TopComponent in Group Reference configuration file name consists of unique TopComponent ID and suffix wstcgrp. File is located in corresponding group folder. TopComponent instances are serialized separately in folder Components as settings files.
<?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.form/2" spec="1.7" />
    <tc-id id="ComponentInspector" />
    <open-close-behavior open="true" close="true" />
</tc-group>
Configuration file contains unique TopComponent ID and flags to describe if component should be opened when group is being opened and if component should be closed when group is being closed. Detail description of all elements/attributes is in DTD.

TopComponent

TopComponent is serialized by InstanceDataObject as settings file. Settings file has 2 forms. First uses default constructor or method (method is used by singletons) to create instance of TopComponent. This form is preferred for definition of TopComponent in module layer. Second uses serialized data as text in settings file. When window system is saved TopComponents are serialized using second form.
First form:
<?xml version="1.0"?>
<!DOCTYPE settings PUBLIC "-//NetBeans//DTD Session settings 1.0//EN"
"http://www.netbeans.org/dtds/sessionsettings-1_0.dtd">
<settings version="1.0">
<module name="org.netbeans.modules.form/2" spec="1.7"/>
<instanceof class="org.netbeans.modules.form.ComponentInspector"/>
<instanceof class="java.awt.MenuContainer"/>
<instanceof class="java.lang.Object"/>
<instanceof class="java.awt.image.ImageObserver"/>
<instanceof class="org.openide.windows.TopComponent"/>
<instanceof class="java.awt.Container"/>
<instanceof class="org.openide.explorer.ExplorerManager$Provider"/>
<instanceof class="org.openide.explorer.ExplorerPanel"/>
<instanceof class="java.io.Serializable"/>
<instanceof class="javax.swing.JComponent"/>
<instanceof class="java.awt.Component"/>
<instanceof class="java.io.Externalizable"/>
<instance class="org.netbeans.modules.form.ComponentInspector"
method="getInstance"/>
</settings>
Second form:
<?xml version="1.0"?>
<!DOCTYPE settings PUBLIC "-//NetBeans//DTD Session settings 1.0//EN"
"http://www.netbeans.org/dtds/sessionsettings-1_0.dtd">
<settings version="1.0">
<module name="org.netbeans.modules.form/2" spec="1.7"/>
<instanceof class="org.netbeans.modules.form.ComponentInspector"/>
<instanceof class="java.awt.MenuContainer"/>
<instanceof class="java.lang.Object"/>
<instanceof class="java.awt.image.ImageObserver"/>
<instanceof class="org.openide.windows.TopComponent"/>
<instanceof class="java.awt.Container"/>
<instanceof class="org.openide.explorer.ExplorerManager$Provider"/>
<instanceof class="org.openide.explorer.ExplorerPanel"/>
<instanceof class="java.io.Serializable"/>
<instanceof class="javax.swing.JComponent"/>
<instanceof class="java.awt.Component"/>
<instanceof class="java.io.Externalizable"/>
<serialdata class="org.netbeans.modules.form.ComponentInspector">
ACED00057372003D6F72672E6E65746265616E732E6D6F64756C65732E666F72
6D2E436F6D706F6E656E74496E7370656374
6F72245265736F6C7661626C6548656C7065726709A43777F1AF080200007870
</serialdata>
</settings>

3.4.6 Import of old configuration data

Structure of configuration data folders:
Windows
|--> WindowManager.wswmgr
|--> WindowManager
     |--> Workspace_1.wswksp
     |--> Workspace_1
          |--> Mode_1.wsmode
          |--> Mode_1
               |--> TC_1.wstcref
               |--> TC_2.wstcref
|--> Components
     |--> TC_1.settings
     |--> TC_2.settings
When old configuration data (workspace, mode and/or top component reference) is detected at install layer (module jars) these are imported to new desktop layout by following way:
  1. From the old user dir read workspaces one by one (start with the Editing workspace). If you find a mode which is not defined in the new layout, do the following transformation:
  • a) If the unknown mode is internal and defines top components (not already known in the new layout) in:
  • the top area of the mode then create a special mode named "top_mode" (if not already created) in the new layout and put all unknown top components from the old mode there. Dock the "top_mode" to the top of the document area
  • the left area of the mode then put all unknown top components into the Explorer mode
  • the bottom area of the mode then put all unknown top components into the Output mode
  • the right area of the mode then put all unknown top components into the Properties mode
  • the center area of the mode then put all unknown top components into the Explorer
  • b) If the unknown mode is attached to:
    • the top then dock the mode to the top of the document area and move the unknown top components also (doesn't matter in which area of mode the TCs were)
    • the left then dock the mode to the left of the document area and move the unknown top components also (doesn't matter in which area of mode the TCs were)
    • the bottom then dock the mode to the bottom of the document area and move the unknown top components also (doesn't matter in which area of mode the TCs were)
    • the right then dock the mode to the right of the document area and move the unknown top components also (doesn't matter in which area of mode the TCs were)
  • c) If the unknown mode is a separate window then use the same rules as for the internal mode.
  • d) If a mode is already present in the new layout, we should still look for unknown TCs inside it.
  • If a module with old winsys config gets installed, then follow the same rules as for the old user dir.
  • 4 Use Cases

    This part compares old and new use cases, this way shows how the new API should be used comparing to the old one
    Use Case Description Old Use Case New Use Case Explanation
    Adding TopComponent into window system layout, opening and activating it.
    mode.dockInto(tc);
    tc.open();
    tc.requestFocus(); // NOW IMPROPER USAGE for activation
    mode.dockInto(tc);
    tc.open();
    tc.requestActive(); // NOW PROPER USAGE for activation
    The method requestFocus was wrongly overridden for the purpose of activation. Such API is misleading and wrong. The new activate method is starting to repair that state
    Setting localized display name of TopComponent. E.g. MyClass for java source editor window or Properties for the helper window. tc.setName (localizedDisplayName);
    tc.setDisplayName (localizedDisplayName)
    The method setName was misued for localized display name, which is wrong, name should be just programmatic name of component, not localized one. Therefore is introduced new setDisplayName method.
    Getting display name of TopComponent.
    String displayName = tc.getName();
    String displayName = tc.getDisplayName();
    if(displayName == null) {
        displayName = tc.getName();
    }
    Correspondent to the above case.

    Note the fallback to the getName() method.
    Retrieving selected TopComponent in mode.
    No API
    TopComponent selected = mode.getSelectedTopComponent();

    Finding and opening TopComponentGroup
    No API
    group = wm.findTopComponentGroup("myGroup");
    if(group != null) {
        group.open();
    }
    The TopComponent group named "myGroup": has to be defined in XML layer in order the code will return non-null instance.
    Finding and closing of TopComponentGroup
    No API
    group = wm.findTopComponentGroup("myGroup");
    if(group != null) {
        group.close();
    }
    The TopComponent group named "myGroup": has to be defined in XML layer in order the code will return non-null instance.
    Creating floating mode, docking and opening TopComponent in it mode = wm.getCurrentWorkspace().createMode("myMode", null, null);
    mode.dockInto(tc);
    mode.open();
    Floating modes are not supported now. This case will in new window system open the TopComponent in default editor mode.
    Note: This is true for the default "Compact" mode of window system(former MDI), but in "Separate" mode (former SDI) the case should work as before.
    In default "Compact" mode, the deprecated method createMode returns always the same instance of default editor mode (the one in documents area).

    Creating mode
    Used either former case for floating mode or there was possible to declare internal or docked modes in XML layer
    It is not possible to create modes programmatically (unless you are in the "Separate"  mode of window system). You have to declare the modes in XML layer.
    In default "Compact" mode is not possible to create new mode. It was fine when the floating modes were supported, but in case of generic split layout creating too much of new modes would make the split structure clumsy, therefore was taken this solution according to existing API.
    Note: It is not true for "Selected" mode.
    Finding mode and docking TopComponent into it, opening it and activating it.
    mode = wm.getCurrentWorkspace().findMode("myMode");
    if(mode == null) {
        mode = wm.getCurrentWorkspace().createMode("myMode", null, null);
    }
    mode.dockInto(tc);
    tc.open();
    tc.requestFocus();
    mode =wm.findMode("myMode");
    if(mode != null) {
        mode.dockInto(tc);
    }
    tc.open();
    tc.requestActive();
    Note: Mode named "myMode"  is supposed to be defined in XML layer.

    Both codes result to the same action in new window system (In "Compact" mode). It is due to the fact, that createMode method returns the default editor mode, and also that when opening undocked TopComponent it is docked into that default editor mode.
    Explanations used in use cases: tc ... instance of org.openide.windows.TopComponent,
                                                               mode ... instance of org.openide.windows.Mode,
                                                               group...instance of org.openide.windows.TopComponentGroup
                                                               wm.... instance of org.openide.windows.WindowManager.




    5 Summary


    The new window system is implementation of window system specified by UI spec document.

    Issue:

    http://netbeans.org/bugzilla/show_bug.cgi?id=29836


    Please put questions or comments directly into that issue or at [nbdev] netbeans developers mailing list.



    Project Features

    About this Project

    core was started in November 2009, is owned by Antonin Nebuzelsky, and has 83 members.
    By use of this website, you agree to the NetBeans Policies and Terms of Use (revision 20160708.bf2ac18). © 2014, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo
     
     
    Close
    loading
    Please Confirm
    Close