I love NetBeans and the NetBeans Platform for creating Rich Client Applications. I first started using NetBeans while searching for a new application framework to port an existing Swing application.
I needed more sophisticated window management. The NetBeans Platform provided a lot of the functionality I was looking for: an easy way to create modular extensible applications with dock-able windows and application life-cycle management.
As with any framework I eventually found I wanted behavior that was not provided. Fortunately NetBeans is Open Source and that makes it extendable.
I was originally drawn to NB because it provided an API for drag & drop window partitioning that would allow my users to customize their content in a way that would help improve their productivity.
The NetBeans Window Manager works great for applications built around a single main-window but it’s support for multiple windows is limited.
A customized Main Window Layout
Floating windows are restricted to a single tabbed-pane. I can have multiple documents in a floating window but I can’t arrange them like I can in the main-window.
A floating window
The NetBeans WindowManager was created before large or multiple monitors were common and was designed around the concept of a single main-window with a main editing area and peripheral utility views.
The platform was originally created as a framework for developing the NetBeans IDE and was later modified to allow more generic application development.
The Window Manager contains some fairly complex code. Converting the existing internal models and interfaces to provide multiple window support wasn’t an easy task. While testing my changes I started to discover a number of existing bugs or inconsistent behaviors in the original Window Manager that I wanted to address.
Z-Order
Swing doesn’t track the z-order of window components. In the netbeans DND package There is a ZOrderManager class that is used to keep track of window order. There’s a comment at the top of the class that states:
* Note, manager is NetBeans specific, not general. It automatically attaches
* main window and expects that all registered zOrder are always above this main
* window.
However dragging an editor top component out of the main window creates a Frame based window. A frame can go behind the main window and this breaks the z-order this class was designed to track (windows are ALWAYS above the main window).
NetBeans shows an incorrect drop location when a floating window is behind the main window as seen here:
In the screen shot below multiple drop location indicators are visible at the same time!
When NetBeans is restarted it restores the previous state. Modes and Floating windows that were open when the application closed are reopened. However NetBeans does not persist the Z-Order information. The windows to open are returned in an un-ordered set. If you had overlapping windows they may overlap differently after a restart.
Views & Editors
NetBeans has the concept of views and editors – although this concept is not at the TopComponent level as you might expect. NetBeans has the concept of View and Editor modes (dockable regions).
Originally a TopComponent in an editor mode could only be moved into another editor mode and a TopComponent in a view mode could only be moved into another view mode. The two modes have slightly different look & feels.
The editor mode shows icons on the tabs and has a maximize button and tab navigation buttons.
The view mode does not show icons on the tabs and has a minimize button. The view tabs do not scroll they compact in size to keep all tabs visible on a single row.
The NetBeans Window Manager was updated to allow Top Components to be moved anywhere allowing the user more control over their screen real-estate. Unfortunately in NetBeans it’s not the TopComponent that determines if it is a view or an editor – it’s the mode that determines the type.
I find this leads to some really confusing and inconsistent behavior.
If I drag a text-editor out of an editor mode it creates a floating window based on a Frame. The frame can be above or below the main window and the text editor shows a status-bar where I can see my insert location.
If I move my text-editor into a view mode and then drag my text-editor out of the view mode it creates a floating window based on a Dialog. The dialog always floats above the main-window. It will minimize/hide when I minimize the main-window. It cannot be maximied. It does not have a status-bar where I can see my cursor position!
The Frame shows a title and the Dialog does not.
StatusLine Fix
In the Editor module there is a StatusLineFactories class that determines when this additional status line should be shown.
It performs the following test:
1 2 |
boolean underMainWindow = (SwingUtilities.isDescendingFrom(component, WindowManager.getDefault().getMainWindow())); |
This works for floating frames however a dialog has a parent and the parent of a floating dialog is the main-window!
I changed that test to the following:
1 2 |
Container ancestor = SwingUtilities.getAncestorOfClass(Window.class, component); boolean underMainWindow = ancestor != null && "NbMainWindow".equals(ancestor.getName()); |
This finds the window the component is within and determines if the window is the main-window or not.
Now my dialogs show a status line when I’m displaying a TopComponent that is an editor:
I would like my editor TopComponents to always have an icon – no mater where I place them.
Here I can easily identify my editor TopComponents because they both have icons: