Hello! I’ve finally tidied up the code of my new favourite UI class, and it’s time to share it
Introduction
This is conceptually very simple, but in practical terms it is incredibly useful. While it may not be a common trope for a proper computer-based application UI, it’s perfectly suited to mobile platforms (it’s one of the main approaches used in iOS app UI navigation, for example). I’ve taken to using it as the foundation for all my little tools lately, as it massively simplifies the job of deciding what to put where; If it makes sense for the user to consider their data in a way that reflects how the document is structured (and for small tools that’s often the case), you can just stuff things onto separate pages, and it almost designs itself.
What it is…
Basically it’s a type of container for multiple components, much like a TabbedComponent. Unlike a TabbedComponent, however, it operates using a stack. This allows you to push components on, and pop them off. You can shift the focus to any component in the stack, but typically you would want the user to interact with the one at the top; when pushing/popping, there is an ‘autoFocus’ parameter which, if true, will automatically shift the focus to the head of the stack.
It is also highly customisable. While the TabbedComponent has a built in UI for choosing which tab to show, the StackComponent leaves such duties to a separate StackComponent::Controller base class. This allows you to create all kinds of UI controls to cooperate with the stack (and even have multiple simultaneous controllers). Also, the StackComponent has been designed specifically to minimise the restrictions placed on how its contents should be arranged and animated; by subclassing it you can have the components appear in any configuration, and animate in whatever manner you like. The comments explain this is more detail.
If you’ve used an iPhone, you’ll be familiar with the way such a system can work. I’ve provided a bunch of example classes to illustrate the sort of things you can do, along with a demo app and introjucer project.
DOWNOAD
The source for these classes (and a demo project) is here: StackComponent_v1.zip
There is also a prebuilt windows binary of the demo here: StackComponent_v1DemoWin.zip
The main classes
The base StackComponent can be used as is, but it has no animations. The focused content component is stretched to fill the container’s bounds, and all others are invisible.
SlidingStackComponent is an example of a subclass with animation. This uses a ComponentAnimator to slide the old/new content components off/on screen when the focus is changed.
The StackHeaderComponent is a type of controller, designed to sit above a StackComponent. This displays a ‘Back’ button when the current focus is not at the bottom of the stack, which will pop the focused component (with autoFocus shifting focus to the new head). It also displays a title for the focused content component; the static function StackHeaderComponent::setStackContentTitle(content,title) allows you to specify what this should say when you create your content component and push it onto the stack.
There’s also a StackNavigationList. This is another example of a controller, which provides a vertical ‘breadcrumb trail’, showing your current position in (and overall contents of) the stack. Like the StackHeaderComponent, there’s a static function allowing you to attach a property to your content so it can be identified in the list.
Of course, these aren’t the only kinds of controller you could make, but they should hopefully demonstrate the sort of thing you can do. They each link to a target StackComponent, and they all update automatically to reflect the current state of their target.
The demo
I’ve made a little example program to show these things in action. It’s basically a crude ValueTree browser. It just consists of a single hypothetical content component type (ValueTreeStackPanel), which shows the contents of a ValueTree node (properties and children) in a PropertyPanel (with the child nodes presented in a listbox). If you double click a child node, it will push a new ValueTreeStackPanel onto the stack for the selected child node. It’s very basic - just about the quickest thing I could think of to illustrate it without having to design anything that required multiple pages! Also, as I couldn’t be bothered making any data, i’ve just embedded the demo project’s jucer file for it to use. Not very glamorous content, but it does the job!
There are a few other classes in the project that are largely unrelated - either used by the example controllers or just helpers for the demo. The MarginedContainerComponent is kinda handy - that’s what the StackHeaderComponent uses. It also supports easily sticking other controls on the right hand side, though I haven’t got round to exposing any of that on the actual header component yet. The HeaderLabel is used to ensure the title is centred properly whilst still being constrained to the correct bounds (I.e. Not going behind the Back button); if it just used a normal Label the centring would be off when the button is showing. I’m sure you don’t need to care much about these, anyway. The only absolutely fundamental code file pair in the demo project is StackComponent.h/cpp (though SlidingStackComponent is a little more glitzy).
Hope you find this useful!