SophiaFramework UNIVERSE 5.3 |
In the responder system, the procedure to draw the responders is divided into the 6 parts as follows:
Booting up the renderer | |
---|---|
There are the following three cases in booting up the renderer: In case of "1." and "2.", the SFYResponder::Render function is called automatically. But, in case of "3.", it is necessary to call the SFYResponder::Render function explicitly. |
Drawing the "invisible" responder | |
---|---|
Even if the contents of the responder such as the text or the color are changed during an event loop, the drawing handler of the responder, which is in the "invisible" state or hidden by other responders, will not be booted up. |
Rendering the responder is divided into registering the redrawing area and actual redrawing with the drawing handler.
For instance, if the text of the label control is changed with the USRResponder::SetText function in the code below, this label control must be redrawn since its content is updated. Here, only register the redrawing area into the renderer with the SFYResponder::Invalidate function. Redrawing the label itself is described in the drawing handler.
Example 9.26. Registering the redrawing area
// register the drawing handler USRResponder::USRResponder(Void) static_throws { if (static_try()) { ... static_throw(RegisterHandler( SFXEventRange(SFEVT_RESPONDER_RENDER, SFEVT_RESPONDER_RENDER, SFP16_RENDER_REQUEST, SFP16_RENDER_REQUEST), XANDLER_INTERNAL(OnRenderRequest) )); ... } } Void USRResponder::SetText(SFXAnsiStringConstRef param) { SFCError error(SFERR_NO_ERROR); if (!param.equals(_text)) { if ((error = _text.Set(param)) == SFERR_NO_ERROR) { Invalidate(); // here not draw the label but register the redrawing area only } } return error; } // implement the drawing handler(actual redrawing is described in the drawing handler) XANDLER_IMPLEMENT_VOIDRENDER(USRResponder, OnRenderRequest, invoker, reason, graphics) { SFXRectangle local; // redrawing the label is described in the drawing handler local.Set(GetLocalBound()); graphics->FillRectangle(local, SFXRGBColor(0xFF, 0xFF, 0xFF, 0x00)); graphics->DrawSingleText(_text, local, SFXRGBColor(0x00, 0x00, 0x00, 0x00)); return; }
IMPORTANT | |
---|---|
In the USRResponder::SetText function where redrawing is needed, only registering the redrawing area is described. Actual drawing is described in the OnRenderRequest drawing handler, which will be booted up after the SFYResponder::Render function is called. |
Hint on performance improvement | |
---|---|
The SFYResponder::Invalidate function has the overload function with the rectangle argument. If the subset rectangular region of the responder is specified as the redrawing area, since there is more possibility that it will be included in the union of responders placed foreground, the drawing performance may improve. |
Registering the redrawing area and calling the Render function | |
---|---|
Registering the redrawing area is valid only when rendering is performed by calling the SFYResponder::Render function without no argument specified(i.e., "false" is specified in the argument). At this time, only the responders whose redrawing areas are registered receive the drawing event. |
Redrawing the standard responders of SophiaFramework UNIVERSE | |
---|---|
In case of the standard responder of SophiaFramework UNIVERSE, even if the visual element such as state, attribute, region, parent-child or sibling relationship, ID, type, reference, text, font, color and so on is changed by executing its function(mainly, the prefix is "Set"), the related responders will be automatically redrawn. Therefore, there is no need to register the redrawing area when the standard responder of SophiaFramework UNIVERSE is used. |
The default drawing handler registered into SFYWidget is booted up first. This drawing handler will call the SFYWidget::HandleRenderRequest function after filling the background in the color set with the SFYWidget::SetBackgroundColor function if the transparency attribute is "false".
After this, the developer's own drawing handlers, if any, will be booted up in the registered order.
Example 9.27. Registering the drawing handler
// register drawing handler
USRResponder::USRResponder(Void) static_throws
{
if (static_try()) {
...
static_throw(RegisterHandler(
SFXEventRange(SFEVT_RESPONDER_RENDER, SFEVT_RESPONDER_RENDER, SFP16_RENDER_REQUEST, SFP16_RENDER_REQUEST),
XANDLER_INTERNAL(OnRenderRequest)
));
...
}
}
Tip | |
---|---|
The drawing handler is registered with the SFYResponder::RegisterHandler function. However, drawing the responder can be also described by overriding the SFYWidget::HandleRenderRequest function. This method is more useful since there is no need to register the handler. |
Example 9.28. Implementing the drawing handler
// implement drawing handler XANDLER_IMPLEMENT_VOIDRENDER(USRResponder, OnRenderRequest, invoker, reason, graphics) { // draw "Hello World" in black at the center graphics->DrawSingleText("Hello World", GetLocalBound(), SFXRGBColor(0x00, 0x00, 0x00, 0x00)); return; }
Tip | |
---|---|
The drawing handler gets the SFXGraphics instance as the argument and draws the corresponding responder using the local region coordinate. |
When the applet receives the event from the BREW environment, the SFYApplication::HandleEvent function below will be called automatically. The SFYApplication::HandleEvent function starts the event loop, and if the event is assumed to be handled at the end of the event loop, it will call the SFYResponder::Render function to boot up the renderer.
The renderer will send the drawing event only to the responders to be actually redrawn by calculating the state and the positional relation among the responders.
In each event loop, only the necessary drawing handlers are called. As a result, performance will not deteriorate even if it is the complex rendering.
Example 9.29. Implementation of the SFYApplication::HandleEvent function
// virtual function that will be called when the event dispatched from the BREW environment needs to be handled /*protected virtual */Bool SFYApplication::HandleEvent(SFXEventConstRef event) { // here describe the handling of the event dispatched from the BREW environment SFCError error; Bool result(false); // boot up the distributer to distribute the event using the tracer // first of all, the SFYDistributer instance bound with the root will receive the event // then, the event will be distributed to the responders in the responder tree according to the dispatching rules of the tracer // * _root is the root(SFZRoot) if ((error = _root->Distribute(event, &result)) == SFERR_NO_ERROR) { if (event.GetType() != SFEVT_APP_STOP && event.GetType() != SFEVT_APP_SUSPEND)) { // if redrawing is necessary if (IsRenderable()) { // if the screen can be redrawn (i.e., if no highest priority event handler is registered) // boot up the renderer to redraw the responder tree below the root error = _root->Render(); } } } if (error != SFERR_NO_ERROR) { // call HandleError() in case the fatal error such as insufficient memory during the initialization of the distributer or the renderer occurs if (HandleError(event, error)) { result = true; } } if ((event.GetType() == SFEVT_APP_SUSPEND) && IsRendererIntermissive()) { // if the back-up bitmap inside the renderer is released when an application suspends // terminate the renderer _renderer.Terminate(); } return result; // return "true" if the event has been handled, otherwise return "false" }// SFYApplication::HandleEvent //
Reference: SFCApplication::HandleEvent | SFCApplication::IsRenderable | SFCApplication::HandleError | SFYApplication::IsRendererIntermissive | SFYResponder::Distribute | SFYResponder::Render | SFYRenderer::Initialize | SFYRenderer::Terminate | SFZRoot | Root | Tracer | Distributer | Renderer Drawing Event | Drawing Handler | Event Loop
Highest Priority Event Handler | |
---|---|
For more details, see the description of the SFCApplication::RegisterBypass function. |
When all handlers return "false" during the event loop, the SFEVT_APP_STOP / SFEVT_APP_SUSPEND event is received, the highest priority event handler is registered, or there is no region to be redrawn, the renderer will not be booted up. As a result, no responder will be redrawn.
Different from redrawing in the event loop, the renderer will not be automatically booted up in the callback outside the event loop such as the network or the timer processing.
To redraw the responder on the device screen in the callback, call the SFYResponder::Render function explicitly after registering the redrawing areas to booted up the renderer.
Example 9.30. Redrawing in the callback
SFCError USRResponder::OpenConnection(Void) { SFCError error(SFERR_NO_ERROR); _label->SetText("); ... error = _http.Connect(XALLBACK_INTERNAL(OnConnect)); ... return error; } // implement callback for completing the http connection XALLBACK_IMPLEMENT_SFXHTTPCONNECTION(USRResponder, OnConnect, error) { if (error == SFERR_NO_ERROR) { ... } _label->SetText("OnConnect was called."); // the Invalidate() function is called inside the SetText() function Render(); // redraw by calling the Render() function explicitly return; }
High performance redrawing | |
---|---|
To get the highest performance, you had better boot up the renderer only once per callback. At the end of the callback, you should call the SFYResponder::Render function of as low as possible responder in the responder tree, which includes all possible responders to be redrawn as the child responder. |
When an applet starts / resumes or a highest priority event handler ends, the SFYApplication::HandleRender function will be called automatically.
The SFYApplication::HandleRender function redraws the full screen, i.e., the device screen and the responder tree below the root.
Highest Priority Event Handler | |
---|---|
For more details, see the description of the SFCApplication::RegisterBypass function. |
In the SFYApplication::HandleRender function, the SFYResponder::Render function will be called to boot up the renderer as in the code below.
If the saved bitmap to restore the device screen is available, the argument of the SFYResponder::Render function will become "true". Otherwise, "false".
Note | |
---|---|
If "true" is specified in the argument of the SFYResponder::Render function, all visible responders in the device screen will be redrawn regardless of registering the redrawing area. |
Example 9.31. Implementation of the SFYApplication::HandleRender function
// virtual function that will be called when the full screen needs to be redrawn /*protected virtual */Bool SFYApplication::HandleRender(SFXEventConstRef event) { // here describe full screen redrawing SFCError error; Bool result(false); if (SFCApplication::HandleRender(event)) { // redraw the device screen // redraw the responder tree below the root // *1. if possible, redraw using the bitmap to restore the device screen // *2. start up the renderer by calling "Render(true)" if the bitmap to restore the device screen is not available in a timing such as receiving the SFEVT_APP_START event // *3. in case of "Render(true)", all visible responders' drawing handlers will be called error = _root->Render((event.GetType() == SFEVT_APP_START) || (_root->Recover() != SFERR_NO_ERROR)); if (error == SFERR_NO_ERROR) { result = true; } else { // call HandleError() when fatal error such as insufficient memory during initialization of renderer HandleError(event, error); } } return result; }// SFYApplication::HandleRender //
Reference: SFCApplication::HandleRender | SFCApplication::HandleError | SFCApplication::RenderDeviceScreen | SFYResponder::Render | SFYResponder::Recover | SFZRoot | Root | Renderer
About "_root->Render()" in the implementation of the SFYApplication::HandleRender function | |
---|---|
If "true" is specified in the argument of the SFYResponder::Render function, the responder will be redrawn whether or not the redrawing area is registered. In the implementation code of the SFYApplication::HandleRender function, error = _root->Render((event.GetType() == SFEVT_APP_START) || (_root->Recover() != SFERR_NO_ERROR)); the above statement will redraw all visible responders in the device screen by force when an applet starts or no saved bitmap to restore the device screen is available. If "false" is specified, the drawing handler of the responder which is not registered into the redrawing area will be not booted up. When there is intersection region between parent or younger sister responder and this one, the visible region of this responder will be recovered by copying from the saved bitmap to restore the device screen. |
Copyright(c) 2002 - 2024 Sophia Cradle Incorporated All Rights Reserved. |