I recently built a splitter-based UI for a project. The layout part ended up being pretty interesting, so I spun off a basic, standalone win32 implementation to share here:

An example splitter window layout

The way I approached the layout was to build a hierarchy of “panels”, starting with the full window region. A panel is either a leaf node– which represents a visible “window” region– or a splitter that divides the parent region (vertically or horizontally) into two child regions (a bit like a kd-tree.)

In this implementation, I separated the layout processing from the actual windows so that it could be used in different contexts (ie, win32 windows, rendering manually to a framebuffer, OpenGL, etc.)

The layout hierarchy is defined using a simple configuration string, such as the following:

H{W{1}:W{2}}

V or H indicates the direction of the split for any panel with children. The W’s are leaves (actual window regions), with an identifying number. Each non-leaf panel (ie, splitter)’s two children are separated by a colon. Additional information could conveniently be stored here, such as splitter positions or configuration details for the actual windows.

The example above defines a single horizontal split with two resulting window regions, like this:

An example splitter window layout

And a layout with four panes could be defined like this:

V{H{W{1}:W{2}}:H{W{3}:W{4}}}

The expanded hierarchy would look like this:

An example splitter window layout

An example splitter window layout

For the brave, the funky example in the image at the very top has the following definition:

V{H{V{W{1}:W{2}}:H{W{3}:V{W{4}:W{5}}}}:V{W{6}:H{W{7}:W{8}}}}

Using the Window Layout

During layout processing, pointers to the leaves are stored in a flat map to provide easy access to the “window” regions without needing to walk the tree. Likewise, the rectangles that represent the splitters are cached for easier interaction. When the splitters are manipulated, the tree is walked again to update the layout. In a real application it could be worth doing partial updates.

Once the layout is built, mouse clicks and movements are checked to manipulate the splitters, and then a bit of simple collision detection is performed against splitters of equal type. That is, a vertical splitter bar can not move to the “left” or “right” of another vertical bar that’s (visually) blocking it. Same for the horizontal bars– against those “above” or “below” them. Different applications might require different behaviors though– for example, the regions could auto-resize rather than block.

The hierarchical set up makes it pretty simple to add functionality to further split or collapse panels in a setting where a more dynamic UI is required.

If you’re interested in additional details about how the layout works, or need something similar for your own applications, feel free to check out the source code below.

Source Code and Implementation Notes

My C++ implementation is available here. As per my usual warning, this is essentially hobby code. An executable demo of the project for Windows can be downloaded here (zip, 780k.)