Lazy instantiation of MultiCDockables

The documentation of Common specifies that MultiCDockables are created lazily, when needed. But this is not necessarily true: If I have a stack of dockables, only the top of them is initially shown when I load a layout from disk. If the user does not switch to another dockable in the stack, then only the first top dockable needs to be created. The others do not need to be created until their tab is clicked (or some other action occurs which makes them show up).
In my application, most dockables are provided by plugins. Often, lots of dockables are stacked together in a shared area, and the behavior implemented by the docking framework that’s built into the application (which is very primitive compared to DockingFrames) is that none of the dockables are created until they are shown. As long as they are not visible, they do not actually exist. The plugins (jar files) to which the dockables belong are not loaded until they are actually needed (e.g. until the first of their dockables is made visible), thus saving a lot of memory.
Is there support for this in DockingFrames? How do I do this? There should be some way, when loading a layout, to find out whether a dockable will be shown on the screen in the loaded layout or not, and later to be notified when the dockable becomes visible.

In some frameworks there is a distinction between Dockable and code of the client. These frameworks can create Dockables without the need to invoke client code. In DF this is not the case, Dockables are supposed to be client code.

However, you can of course have your plugins provide the contents of the Dockables, but the Dockables itself created by your main-application. Then only the question remains when is a Dockable visible (and thus should show content), and when not.

This problem has to be solved on the level of Core: Every DockStation can tell for each child whether it is visible, the method DockStation#isVisible(Dockable) is responsible for that. If you add a DockStationListener to a DockStation you’ll be informed whenever the visibility state of a child changes (through the method “dockableVisibilitySet”). Finally a DockHierarchyListener, added to a Dockable will inform you when the parent of a Dockable is exchanged.

While a layout is loading the visibility information may change often, I would advise to just assume everything is invisible until the layout is completely loaded.

To map between CDockable and Dockable: every CDockable is associated with a CommonDockable. CDockable#intern returns the CommonDockable, and CommonDockable#getDockable returns the associated CDockable.

Thanks! Just what I needed.

I am using the Common project, not the Core. How do I find the DockStation of my CDockables?
Also, I noticed that it’s possible to register a state listener on the CDockable itself, to get notified when the dockable state changes or when its visibility changes. However, the visibility change method is not called in the listener when the dockable gets hidden because another dockable in the same stack (tabbed pane) was made the active one. Will this be different if I register the DockStationListener, or should I expect it to work the same way?

  1. CDockable#intern returns a Dockable. The parent of this Dockable is the DockStation on which the CDockable lies.
  2. Yes, they have different behavior. The state listener treats visible as “somehow accessible by the user”, the DockStationListener treats it as “visible to the user right now”.

I don’t know if this is the right place to post such things. I used a dock station listener to find when dockables become visible, and a dock hierarchy listener to know when the dock station listener needs to be added to the new station of the dockable.
I have a saved layout in which one of the dockables is minimized on the left. When I click on its “normalize” button, I get the following exception;
Exception in thread “AWT-EventQueue-0”
java.lang.NullPointerException
at bibliothek.gui.dock.dockable.DockHierarchyObserver.fireControllerChanged(Unknown Source)
at bibliothek.gui.dock.dockable.DockHierarchyObserver.controllerChanged(Unknown Source)
at bibliothek.gui.dock.dockable.AbstractDockable.setController(Unknown Source)
at bibliothek.gui.dock.control.DockRegister.unregister(Unknown Source)
at bibliothek.gui.dock.control.DockRegister$StationListener.removeDockable(Unknown Source)
at bibliothek.gui.dock.control.DockRegister$StationListener.fire(Unknown Source)
at bibliothek.gui.dock.control.DockRegister.setStalled(Unknown Source)
at bibliothek.gui.dock.facile.state.StateManager.transition(Unknown Source)
at bibliothek.gui.dock.support.action.ModeTransitionManager.goIn(Unknown Source)
at bibliothek.gui.dock.support.action.ModeTransitionManager$Mode$1.action(Unknown Source)
at bibliothek.gui.dock.themes.basic.action.BasicButtonHandler.triggered(Unknown Source)
at bibliothek.gui.dock.themes.basic.action.BasicButtonModel.trigger(Unknown Source)
at bibliothek.gui.dock.themes.basic.action.BasicButtonModel$Listener.mouseReleased(Unknown Source)
at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)

Any idea what the problem is?

Could it be, that you added a null-DockHierarchyListener?

Yes, thanks! Silly me…
Shlomy