I am trying to wrap my mind around the best way to implement nested state transitions in a single threaded programming language (Actionscript). Say I have a structure like this
I'll try to simplify the problem before suggesting a possible approach. The transitions seem related to the views, and not the model. If I were to skip the transitions and go straight to some other leaf node, the application still works but there is not visual clue for the users. So I'd suggest you use a view-controller specifically to hold the current branch and the transitions of various views.
It's probably a better approach to split the two types of transitions into a sort of stack where a pop transition is to go back to a previous node, while a push transition goes forward in the hierarchy. Apple uses a similar technique to manage navigational applications using a navigation view controller. It basically maintains a stack of view controllers that the user followed to get to a particular node. When a user goes back, the top item is popped off the stack, and the user sees the previous item. If the user goes deeper in the hierarchy, a new view controller is pushed onto the stack.
You would still need a global way to represent the hierarchies in a flyweight manner, while the navigation stack only stores the currently visible branch down to the leaf node.
If a user went from one leaf node to another, the current stack will be popped out upto the common parent. Then the global tree structure will be asked to get the path from that parent upto the new leaf node. This path of nodes is pushed into the current navigation stack, and as each item is pushed, the transition is shown.
In a simple algorithm, there'd be these two data structures and a way to get the entire branch that contains leaf node:
initially:
stack = []
tree = create-tree()
algorithm:
// empty current branch upto the common ancestor, root node if nothing else
until stack.peek() is in leaf-node.ancestors() {
stack.pop() // animates the transition-out
}
parent = stack.peek();
// get a path from the parent to leaf-node
path = tree.get-path(parent, leaf-node)
for each node in path {
stack.push(node) // animates the transition-in
}
Update:
The entire application could have a single navigation controller, or multiple such controllers. A navigation controller only needs to know that there is a tree which exposes certain operations. So you could create an interface with those operations and let concrete subclasses implement that.
I can only think of two operations that would need to be exposed (pseudo-Java syntax):
interface Tree {
List getAncestors(node);
List findPath(ancestorNode, descendantNode);
}
That should provide sufficient abstraction to keep the navigation controller poking inside the global tree structure. To take it to the next level, use dependency injection so the tree object is injected into the navigation controller, improving testability and breaking the tree connection completely.