It is only if the button can be pressed, not dimmed, that we will redraw it and restore its state. The button callback will be called in both cases, however; lGood will be false when the button is dimmed.
The last part of handling the user input goes into specific case where the user clicks or taps down on a button, but never releases the mouse button or its finger (when there is no mouse or pen). How could that be? Imagine you are driving a four wheel SUV on a bumpy road (.... okay, trail :) ... Now, you reach for the console in order to stop the playback, but just as you touch the on-screen button, the car rocks and your finger moves off the button. The problem is that the console widget may register the pressed down action on the button, but because you released your finger outside of the widget, the pressed up event will not be processed by the widget.
A simple solution is to use the method OutBound() that is called every time the mouse or finger leaves the widget while still pressed down. When this occurs, we will revert its state and redraw it:
When a button is active, we want to display a pulsating effect on the active button. To render this, we need to redraw the button at a given interval in time. We have used the flag kFlgBeatNeeded in the cDConsoleView base class initialization. Now let's have a look at the implementation of the method Beat(), which will be called at the rate set by the parent window:
Because this method will still be called even when there is no button active, we will only draw the animation effect if there is an active button.
The pulsating effect is rendered by incrementing the state of the button from kStateActive to kStateActive2 and then reversing back to kStateActive.
We use the data member iActiveDir to store the direction we are going. The only thing left to do, is to redraw the button. We simply call the method Render() which use the button state to render it:
Later, we will see how to setup the window to beat.
All that is left to be done, is SetState(). This method will be used from outside the class in order to change the state of the console. For example, when the user presses the Play button and playback successfully starts, the state should be changed to ePlaying.
Here's the method implementation:
Since we do not know who will be calling this method and when, we need to insure that the looper (the window) is locked. The macro TheLooperMustBeLocked() will check this for us. If it is not locked, an exception will be raised and the application will likely be terminated. This helps us to easily detect situations where we are executing code that should only be executed when the window is locked. Don't forget that the Zinzala SDK, is multithreaded, and that only one thread should be changing the button's state or widget internals at any given time.