My company wants to introduce Google Chrome-like tabs into our application using a pre-existing docking framework. I would rather write my own tiny little system specifically adapted for that, but they think it would take too long. Hooray for Agile timeboxing. In fact it is taking me longer to figure out how to wrangle a docking framework into plain old Google Chrome tabs.
So,
I want to create a window containing a single docking area that shows the dockables in tabs and doesn’t allow the user to create splits, complex layouts, etc…just one dockable showing at a time. StackDockStation seems like what I need, but it’s not a Component like SplitDockStation so how do I use it by itself?
Also, whenever the user drags a tab away from a stack my code needs to find out and create a new window for the Dockable, instead of letting Docking Frames take care of it. Any quick pointers on how to do this?
I agree with you, that writing a new system may take less time then learning how to do the same thing with DockingFrames… At least I can tell you that the framework could be modified to support a chome like application.
While StackDockStation is not a Component itself, it internally uses a Component. And you can get that Component by calling “StackDockStation.getComponent”. For the prototype I suggest below, you won’t need to touch the StackDockStation at all.
The “ScreenDockStation” is used to show floating dockables. In theory modifying ScreenDockStation not to use an undecorated JDialog but a more complex JFrame should get you pretty close to the behavior your need.
Another solution would be to write an entire new DockStation with the behavior of “creating new windows when dropping a Dockable”. While writing a DockStation is possible, it takes some time.
For a small prototype I would
probably create a subclass of “ScreenDockFrame”, you could add some menus if you wanted.
probably write a “ScreenDockWindowFactory”, this factory should create your new frames
probably Install the factory using “DockController.getProperties().set( ScreenDockStation.WINDOW_FACTORY, new CustomFrameFactory() );”
create an application without any main-JFrame. Just one main-method. Create one ScreenDockStation without owner and add it as root station to a DockController. Call “setShowing(true)” on the ScreenDockStation.
add some Dockables to the station (using the “drop” method). Drag the dockables around, the behavior should already be very chrome-like.
The look of the tabs: I would apply the EclipseTheme, and just implement a new tab. Basically copy “ArchGradientPainter” or “RectGradientPainter” and just replace the painting code.
Animations: the tabs that slide around during drag and drop are not supported by DockingFrames. Nor will it be supported in the near future. It would just be too time consuming to implement that feature.
The “new tab button” could probably be an empty tab (with an icon) leading to a special “create new dockable” dockable. I’ll have to search a bit, but I faintly remember that once an interface existed that allowed clients to force some order on the tabs. If not, it would certainly be possible to add such a thing.
[Edit: If you are interested I can write a little test app showing how I would implement the whole thing.]
I started with DefaultScreenDockWindowFactory and will of course need to make my own but the basic behavior is fine. I also got ScreenDockStation working, that was easy to copy from one of the examples. I noticed that to drop a Dockable onto a stack containing only one dockable in one of those windows, I have to drag over the title bar for that Dockable – I can’t drag over the content of the Dockable. But I assume it’s just a matter of making a ScreenDockWindowFactory that installs a StackDockStation in each window it creates?
The animation is not important, no worries there.
Also, can I force a tab to show even when there is only one Dockable in the station?
About the tab: If you use the EclipseTheme (DockController.setTheme…) there will a tab for any Dockable, and titles will disappear.
You can also implement the interface “SingleTabDecider”, always return “true” in its “showSingleTab” method. To install the new class use “DockController.getProperties().set( SingleTabDecider.SINGLE_TAB_DECIDER, new MyCustomImplementation())”.
About the drop behavior: creating StackDockStations will not help, the framework will mark them as unnecessary and automatically remove them. Whether a dragged Dockable is combined/merged with an existing one is decided by the ScreenDockWindow itself. Overriding/implementing the method ScreenDockWindow.inCombineArea(x,y)", and just returing the result of “contains(x,y)” should do the trick.