FlexDock: Views Tutorial

Nov 22, 07:58 PM

I have been writing a little project using FlexDock and thought I’d do a write-up. R.J. Lorimer’s tutorial on FlexDock is a good starting place, if you haven’t read it, you may want to read it before trying this. Most of the examples you’ll find create all the dockables and place them on the screen in a very static way. FlexDock offers a way to persist layouts between sessions; which will be needed if you plan to take your application beyond the demo stage. FlexDock has a very nice user’s guide, but the advanced features (views, perspectives, persistance, and themes) aren’t documented yet.

FlexDock Demo screen shot. Click  for larger image.
Download Demo Source Code (Zip file).

Creating the Docked Components

To save a layout means we need to load a layout. To load a layout, we need to provide the library with a way to create our dockables. For that FlexDock provides the DockableFactory. The DockableFactory interface specifies two methods getDockableComponent and getDockable. These two methods are where you put all the code that builds the components you wish to dock. Both methods take a String id as a parameter. I like to build the components and then wrap the component in a Dockable, so I created a third method that creates the component based on the ID. So getDockableComponent and getDockable are small methods the read and write into a map.

Default Layout

To support layout persistence, we need to support “perspectives”. The concept of perspectives received a lot of attention recently when Microsoft decided to add this well-worn concept to MS Office. Basically, a perspective is a group of windows (or views or dockables) laid out according to a task. To find examples of applications with perspectives look at Eclipse, Blender, or almost any video editing software. FlexDock’s PerspectiveFactory is the interface required to support perspectives; it has one method, getPerspective, which takes a string id. In this method, you need to build a layout. In other tutorials you built the layouts with dockables and the DockingManager. In the getPerspective method, however, you’ll work with the string ids of dockables and the LayoutSequence class. Below is an example from an application that only uses one perspective.

    private static class MyPrespectiveFactory implements PerspectiveFactory{
	public Perspective getPerspective(String persistentId) {
	    Perspective perspective = null;
	    if(PERSPECTIVEID.equals(persistentId)){
		perspective = new Perspective(PERSPECTIVEID, “Standard”);
		LayoutSequence seq = perspective.getInitialSequence(true);

String vCtrl = DockIDs.IMAGE.toString(); String vRins = DockIDs.INSPECTOR.toString(); String vGrid = DockIDs.GRID.toString(); seq.add(vCtrl); seq.add(vRins, vCtrl, DockingConstants.EAST_REGION, .3f); seq.add(vGrid, vRins, DockingConstants.SOUTH_REGION, .7f); seq.add(DockIDs.BACKGROUND.toString(), vGrid, DockingConstants.SOUTH_REGION,.3f); }

return perspective; } }

Startup

Now, we need to tie all this together. In your app init code, you’ll need something like the following…
<pre> private static final String PERSISTANCEFILE = "demo.xml"; private static final String PERSPECTIVEID = "demo_std"; ... DockingPort port = new DefaultDockingPort(); // Note: This JFrame implements DockableFactory DockingManager.setDockableFactory(this); DockingManager.setMainDockingPort(this, DockIDs.IMAGE.toString()); PerspectiveManager.setFactory(new MyPrespectiveFactory()); PerspectiveManager.getInstance().setCurrentPerspective(PERSPECTIVEID, true); PersistenceHandler persister = FilePersistenceHandler.createDefault(PERSISTANCEFILE); PerspectiveManager.setPersistenceHandler(persister); try{ DockingManager.loadLayoutModel(); }catch(Exception e){ logger.fine("Docking layout not loaded."); } DockingManager.setAutoPersist(true); ... </pre>

The FilePersistenceHandler class saves the layout as xml in a subdirectory of the users home directory. DockingManager.loadLayoutModel(); loads a stored layout. DockingManager.setAutoPersist(true); enables auto saving the layout. I’ve experienced some problems during development when the app crashes during startup, the layout becomes trashed. So, it may be a good idea to only enable auto persist after the window is visible. One should note that FlexDock does not store the window size and only persists the split between dockables as a percentage. This means if you don’t save and restore window size and positions between sessions then your dockables may restore with odd sizes. The filed based persistence handler is currently the only one included with FlexDock, so if you deploy with WebStart you must sign your app or write a custom persistence handler.

Views

There is still the matter of providing a way for the user to change the layout. There are two ways to do this, writing your own actions for buttons and menu items and building the ui, or you can use FlexDock’s View class. Using View in your code is easy. Replace the DefaultDockingPort with ViewPort and create a View instead of a Dockable and add the default actions to the view.

<pre> Viewport port = new Viewport(); ... View view = new View(...); // The order of actions matter. Close should be leftmost. if(closable) view.addAction(View.CLOSE_ACTION); if(pinnable) view.addAction(View.PIN_ACTION); view.setContentPane(comp); </pre>

Themes

The header used with the view is rather disappointing at first. On my Mac, the header doesn’t use icons and sometimes the text is invisible and on Windows the theme reminds me of Windows 3.0. However, this is easily fixed because FlexDock supports themes via XML. The FlexDock source archive includes a file called “flexdock-themes-default.xml” which describes all the themes and maps Look and Feel classes to FlexDock themes. To customize the themes, we need to create a file called “flexdock-themes.xml” in our default package which the library loads automatically to augment the default set. The source archive includes an example I created called “flashlight” (See screen shot above) that uses the FlexDock “OfficeXP” theme with different colors and icons.

Summary

We have scratched the surface of FlexDock’s advanced features, but more remains. Such as providing menu access to show/hide/focus views, custom actions, custom persistence, resetting perspectives, and allowing the user to create custom perspectives. Some of these I have tried, most I have not.

Commenting is closed for this article.