Currently, I am working on music rendering in Flex. This is not a trivial task to say the least, considering how screwed up music notation can actually be. Plus, to make things difficult, there are various dependencies with chords and other music notation such as accidentals, beams, ties, slurs, etc. and if you aren’t careful, music rendering can be very inefficient and a maintenance nightmare!
Since I have started Flex, I have paid particular attention to Flex’s Custom Component Lifecycle. I have been impressed with how the core events of UIComponent are dispatched throughout various stages of it’s lifecycle. For example, after a component is added to the display list, the measure() functions are called starting from the bottom-most elements on the display list (most deeply nested — usually your custom components) up to the top of the display list (the stage). After this happens, the updateDisplayList() function is called starting at the top of the display list all the way to the bottom.
While it would be possible to lay components out without this lifecycle, it would be horribly inefficient! That’s the problem I ran into with music rendering. There are certain dependencies that music notation has. We can’t draw ties that connect notes if we don’t know where the notes are positioned. However, if I could guarantee order in my music rendering process by first laying out all the notes and then drawing the ties, things would be easier and much more efficient.
In order to guarantee that order and efficiency, it was necessary for us to create a custom lifecycle. Looking at this process will almost certainly remind you of the custom component lifecycle in Flex if you are familiar with it.
- Creation process
- Top-down approach. Start at the top-most container and work your way down to the most basic container (you can think of this as the component with the highest z-index)
- In the case of music notation, you might want to start at a page container level and work your way down to the note level.
- This can be analagous to the updateDisplayList() function in the Flex Component Lifecycle where updates happen at the top (the Stage) and work their way down to your bottom-most components (A TextField or Button).
- Purpose: The purpose of this step is to create the components and to establish hierarchy and flow.
- Layout Process
- Bottom-up approach. Start at the container with the highest z-index and work your way up to the root.
- In the case of music notation, you would probably want to start at the note level and then work your way up to the top
- This can be analagous to the measure() function in the Flex Component Lifecycle where updates happen at the bottom (A Text Field or Button) and work their way up to your top-most container(the Stage).
- Purpose: The purpose of this step is to position and draw the components.
Now that we have identified the structure, how would we ensure that creation and layout occur in the correct order we want them? The answer: events! The same thing Adobe uses to manage their Component Lifecycle. We can do this by establishing an Array of events and then step through the Array in the order we are looking for.
var steps:Array = new Array(CREATE_PAGE, CREATE_LINE, ..., CREATE_NOTE, LAYOUT_NOTE, ..., LAYOUT_LINE, LAYOUT_PAGE, CREATION_COMPLETE);
We can then add event listeners for these lifecycle events in the constructor for each of our components and then kick this lifecycle off. Once a lifecycle event has completed, we will fire the next one off until we have finished. Then in this case, we dispatch a CREATION_COMPLETE event to notify our application that the lifecycle has completed and the components are laid out.
Hopefully this sheds some light on some of the lesser used methods for event-driven programming. Using an event-driven lifecycle, we are able to ensure order with little manipulation and a high degree of efficiency.