SophiaFramework UNIVERSE 5.3 |
Menu(SFYMenu) is the responder to select an item from the menu list.
If the operation key or the ESCAPE key is pressed, default handler, which has already been registered into SFYMenu, will send the result event.
SFYMenu has function to close itself automatically after the specified time elapses.
There are three kinds of concrete menu classes: text menu[SFZTextMenu], grid menu[SFZGridMenu], and flex list menu[SFZFlexListMenu].
In this section, text menu(SFZTextMenu) will be described.
Let's make the text menu[SFZTextMenu] in the helloworld application class as the figure below.
The following is the code to define function and structure which are useful to set the color scheme of text menu together at once.
Example 3.44. Define the helloworld application class and the custom color structure
// define the helloworld class SFMTYPEDEFCLASS(helloworld) // macro to generate the useful types class helloworld : public SFYApplication { SFMSEALCOPY(helloworld) // macro to prohibit the developer from copying this instance private: MyWindowSmp _myWindow; // *** added and updated code segments are in bold // SFZTextMenu's smart pointer SFZTextMenuSmp _textMenu; public: static SFCInvokerPtr Factory(Void); private: explicit helloworld(Void) static_throws; virtual ~helloworld(Void); // make MyWindow SFCError MakeMy(Void); // change name from Make into MakeMy // make SFZTextMenu SFCError MakeMenu(Void); // declare the function to set the text menu's color scheme together Void SetMenuColors(UserColorConstRef color); XANDLER_DECLARE_VOIDRENDER(OnRenderRequest) // declare the drawing handler XANDLER_DECLARE_BOOLEVENT(OnKey) // declare the key handler // declare the result handler of text menu XANDLER_DECLARE_VOIDRESULT(OnMenuResult) }; // custom color structure(for setting menu's color scheme) SFMTYPEDEFSTRUCT(UserColor) struct UserColor { SFMTYPEDEFSTRUCT(AtomRec) struct AtomRec { // macro to declare the implicit type conversion from UserColor::AtomRec to UserColor SFMUTILITYATOMDECLARE(UserColor) SFXRGBColor::AtomRec light; SFXRGBColor::AtomRec base; SFXRGBColor::AtomRec dark; SFXRGBColor::AtomRec titleFore; SFXRGBColor::AtomRec titleBack; SFXRGBColor::AtomRec itemFore; SFXRGBColor::AtomRec itemBack; SFXRGBColor::AtomRec selFore; SFXRGBColor::AtomRec selBack; }; SFXRGBColor light; SFXRGBColor base; SFXRGBColor dark; SFXRGBColor titleFore; SFXRGBColor titleBack; SFXRGBColor itemFore; SFXRGBColor itemBack; SFXRGBColor selFore; SFXRGBColor selBack; }; // guarantee that sizes of two classes are same SFMCONCEPTGLOBALTWO(concept_size_eq_type, UserColor, UserColor::AtomRec) // this macro implements implicit type conversion from UserColor::AtomRec to UserColor SFMUTILITYATOMIMPLEMENT(UserColor, AtomRec)
AtomRec struct | |
---|---|
AtomRec struct is POD(Plain Old Data) struct in C language which has the same memory layout with the corresponding class or structure. For more details, see Optimize ARM RealView Compilation Tool for BREW(at Sophia Cradle web site). If you define the AtomRec struct for the class or structure, you can optimize class or structure initialization with regard to size and speed. In this case, you must not use virtual function, multiple inheritance, and virtual inheritance for the class where the AtomRec struct is defined. The AtomRec struct is used in the SFXEvent, SFXEventRange, and shape and color classes and so on. In these classes, the atomic_cast operator is available for type conversion between SFXxxxxx and SFXxxxxx::AtomRec. The atomic_cast operator is declared and implemented with the SFMUTILITYATOMICCASTDECLARE macro and the SFMUTILITYATOMICCASTIMPLEMENT macro. The implicit type conversion operator from the AtomRec struct into class or structure is declared and implemented with the SFMUTILITYATOMDECLARE macro and the SFMUTILITYATOMIMPLEMENT macro. |
The following is the code to make the text menu and implement its result handler, which will perform color scheme processing.
Example 3.46.
// make the text menu SFCError helloworld::MakeMenu(Void) { SFCError error(SFERR_NO_ERROR); // create the text menu if ((_textMenu = SFZTextMenu::NewInstance(&error)) != null) { // set the text menu's parent responder to the application class(root) error = _textMenu->SetParent(GetThis()); if (error == SFERR_NO_ERROR) { // register the result handler into the text menu error = _textMenu->RegisterHandler( SFXEventRange(SFEVT_RESPONDER_RESULT, SFEVT_RESPONDER_RESULT, SFP16_BEGIN, SFP16_END), XANDLER_INTERNAL(OnMenuResult) ); if (error == SFERR_NO_ERROR) { // set title of the text menu error = _textMenu->SetTitle("TextMenu"); if (error == SFERR_NO_ERROR) { // intialize strings SFXWideString item[] = { "Elegant", "Carnival", "Dynamic", "Black", "***", "Scrollable Style", "Page Style", "***", "Sample9", "Sample10", "Sample11", "Sample12", "Sample13", "Sample14", "Sample15", "Sample16" }; // intialize the access key // access keys are set at index from 0 to 8, and 15 AVKType key[lengthof(item)] = { AVK_1, AVK_2, AVK_3, AVK_4, AVK_5, AVK_6, AVK_7, AVK_8, AVK_9, 0, 0, 0, 0, 0, 0, AVK_0 }; // intialize key icon WChar icon[lengthof(item)] = { '1', '2', '3', '4', '5', '6', '7', '8', '9', ' ', ' ', ' ', ' ', ' ', ' ', '0' }; for (SInt16 i = 0; i < lengthof(item); ++i) { // add all items on the text menu together if ((error = _textMenu->InsertLast(item[i], key[i], icon[i])) != SFERR_NO_ERROR) { break; } } // set the 5th item's enable flag to "false" _textMenu->SetItemEnable(4, false); // set the 8th otem's enable flag to "false" _textMenu->SetItemEnable(7, false); if (error == SFERR_NO_ERROR) { // the LEFT key of the text menu is not used (key for sub menu) _textMenu->SetSelectLeftKey(null); // the RIGHT key of the text menu is not used (key for sub menu) _textMenu->SetSelectRightKey(null); // set the text menu's real region to device screen region _textMenu->SetRealBound(GetLocalBound()); // set the text menu's state to "visible" + "active" + "enable" + "focus" together _textMenu->SetState(true, true, true, true); // move text menu formost _textMenu->ToFront(); } } } } } return error; } // define colors #define ATOM_MENU_ELEGANT_LIGHT {0x00, 0xCB, 0xBD, 0xDC} #define ATOM_MENU_ELEGANT_BASE {0x00, 0xAB, 0xA7, 0xC4} #define ATOM_MENU_ELEGANT_DARK {0x00, 0x00, 0x00, 0x00} #define ATOM_MENU_ELEGANT_TITLE_BACK {0x00, 0xBF, 0xE6, 0xCF} #define ATOM_MENU_ELEGANT_TITLE_FORE {0x00, 0xFF, 0xFF, 0xFF} #define ATOM_MENU_ELEGANT_ITEM_FORE {0x00, 0x00, 0x00, 0x00} #define ATOM_MENU_ELEGANT_ITEM_BACK {0x00, 0xAB, 0xA7, 0xC4} #define ATOM_MENU_ELEGANT_SELBACK {0x00, 0xFC, 0xCD, 0xE5} #define ATOM_MENU_ELEGANT_SELFORE {0x00, 0xFF, 0x00, 0x00} #define ATOM_MENU_CARNIVAL_LIGHT {0x00, 0xFF, 0xCC, 0x00} #define ATOM_MENU_CARNIVAL_BASE {0x00, 0xFF, 0x7F, 0x00} #define ATOM_MENU_CARNIVAL_DARK {0x00, 0x0A, 0x50, 0xA1} #define ATOM_MENU_CARNIVAL_TITLE_BACK {0x00, 0x7D, 0x01, 0x77} #define ATOM_MENU_CARNIVAL_TITLE_FORE {0x00, 0xFF, 0xFF, 0xFF} #define ATOM_MENU_CARNIVAL_ITEM_FORE {0x00, 0xFF, 0xFF, 0xFF} #define ATOM_MENU_CARNIVAL_ITEM_BACK {0x00, 0xFF, 0x7F, 0x00} #define ATOM_MENU_CARNIVAL_SELBACK {0x00, 0xFF, 0xFF, 0x00} #define ATOM_MENU_CARNIVAL_SELFORE {0x00, 0x09, 0x30, 0x73} #define ATOM_MENU_DYNAMIC_LIGHT {0x00, 0xFF, 0xCC, 0x00} #define ATOM_MENU_DYNAMIC_BASE {0x00, 0x80, 0x9C, 0xC9} #define ATOM_MENU_DYNAMIC_DARK {0x00, 0x0A, 0x50, 0xA1} #define ATOM_MENU_DYNAMIC_TITLE_BACK {0x00, 0xFF, 0xFF, 0x00} #define ATOM_MENU_DYNAMIC_TITLE_FORE {0x00, 0x00, 0x00, 0x00} #define ATOM_MENU_DYNAMIC_ITEM_FORE {0x00, 0x00, 0x00, 0x00} #define ATOM_MENU_DYNAMIC_ITEM_BACK {0x00, 0x80, 0x9C, 0xC9} #define ATOM_MENU_DYNAMIC_SELBACK {0x00, 0xFF, 0x00, 0x00} #define ATOM_MENU_DYNAMIC_SELFORE {0x00, 0xFF, 0xFF, 0xFF} #define ATOM_MENU_MONO_LIGHT {0x00, 0xFF, 0xFF, 0xFF} #define ATOM_MENU_MONO_BASE {0x00, 0x00, 0x00, 0x00} #define ATOM_MENU_MONO_DARK {0x00, 0x00, 0x00, 0x00} #define ATOM_MENU_MONO_TITLE_BACK {0x00, 0x7F, 0x7F, 0x7F} #define ATOM_MENU_MONO_TITLE_FORE {0x00, 0x00, 0x00, 0x00} #define ATOM_MENU_MONO_ITEM_FORE {0x00, 0xFF, 0xFF, 0xFF} #define ATOM_MENU_MONO_ITEM_BACK {0x00, 0x00, 0x00, 0x00} #define ATOM_MENU_MONO_SELBACK {0x00, 0x7F, 0x7F, 0x7F} #define ATOM_MENU_MONO_SELFORE {0x00, 0xFF, 0xFF, 0xFF} // implement the result handler of the text menu // this handler will be booted up when item is selected XANDLER_IMPLEMENT_VOIDRESULT(helloworld, OnMenuResult, invoker, reason, result) { // set the text menu's color scheme static UserColor::AtomRecConst color[] = { { ATOM_MENU_ELEGANT_LIGHT, ATOM_MENU_ELEGANT_BASE, ATOM_MENU_ELEGANT_DARK, ATOM_MENU_ELEGANT_TITLE_FORE, ATOM_MENU_ELEGANT_TITLE_BACK, ATOM_MENU_ELEGANT_ITEM_FORE, ATOM_MENU_ELEGANT_ITEM_BACK, ATOM_MENU_ELEGANT_SELFORE, ATOM_MENU_ELEGANT_SELBACK }, { ATOM_MENU_CARNIVAL_LIGHT, ATOM_MENU_CARNIVAL_BASE, ATOM_MENU_CARNIVAL_DARK, ATOM_MENU_CARNIVAL_TITLE_FORE, ATOM_MENU_CARNIVAL_TITLE_BACK, ATOM_MENU_CARNIVAL_ITEM_FORE, ATOM_MENU_CARNIVAL_ITEM_BACK, ATOM_MENU_CARNIVAL_SELFORE, ATOM_MENU_CARNIVAL_SELBACK }, { ATOM_MENU_DYNAMIC_LIGHT, ATOM_MENU_DYNAMIC_BASE, ATOM_MENU_DYNAMIC_DARK, ATOM_MENU_DYNAMIC_TITLE_FORE, ATOM_MENU_DYNAMIC_TITLE_BACK, ATOM_MENU_DYNAMIC_ITEM_FORE, ATOM_MENU_DYNAMIC_ITEM_BACK, ATOM_MENU_DYNAMIC_SELFORE, ATOM_MENU_DYNAMIC_SELBACK }, { ATOM_MENU_MONO_LIGHT, ATOM_MENU_MONO_BASE, ATOM_MENU_MONO_DARK, ATOM_MENU_MONO_TITLE_FORE, ATOM_MENU_MONO_TITLE_BACK, ATOM_MENU_MONO_ITEM_FORE, ATOM_MENU_MONO_ITEM_BACK, ATOM_MENU_MONO_SELFORE, ATOM_MENU_MONO_SELBACK } }; switch (reason) { case SFP16_RESULT_OK: // when item is selected // display the selected item's string on BREW Output Window TRACE("'%S' is selected", _textMenu->GetItemText(static_cast<SInt16>(result)).GetCString()); switch (result) { case 0: case 1: case 2: case 3: // change the color scheme of the text menu according to the item number SetMenuColors(color[result]); break; case 5: // change the menu style to the scroll style _textMenu->SetMenuStyle(SFZTextMenu::SCROLLABLE_STYLE); break; case 6: // change the menu style to the page style _textMenu->SetMenuStyle(SFZTextMenu::PAGE_STYLE); break; } break; case SFP16_RESULT_ESCAPE: // when the ESCAPE key(by default, the CLEAR key) is pressed // close the text menu invoker->Terminate(); break; } return; } // set the text menu's color together Void helloworld::SetMenuColors(UserColorConstRef color) { if (_textMenu != null) { // set menu title's foreground color _textMenu->SetTitleForeColor(color.titleFore); // set menu title's background color _textMenu->SetTitleBackColor(color.titleBack); // set selected item's background color _textMenu->SetSelBackColor(color.selBack); // set selected item's foreground color _textMenu->SetSelForeColor(color.selFore); // set menu's bevel color _textMenu->SetBevelColor(SFXBevelColor(color.light, color.base, color.dark)); // set foreground color and background color for all items for (SInt16 i = 0; i < _textMenu->GetItemCount(); ++i) { _textMenu->SetItemForeColor(i, color.itemFore); _textMenu->SetItemBackColor(i, color.itemBack); } } return; }
Parent responder of the menu | |
---|---|
In general, the parent responder of the menu is set to the application class [i.e., root(SFZRoot) which the helloworld application class(SFYApplication) contains by default]. The root can be obtained by calling SFYApplication::GetRoot(). |
Register the result handler into the menu | |
---|---|
The menu will receive the result event when the item is selected. You can register the result handler for the result event into the text menu with the SFYResponder::RegisterHandler function. Reference: Result Event[SFEVT_RESPONDER_RESULT] | Handler for the Result Event[XANDLER_DECLARE_VOIDRESULT] |
Access key | |
---|---|
The function of access key is that user can select a particular item directly by pressing the corresponding key once, which is associated with that item. |
Let's update the code to display the text menu when the "2" key is pressed in the initial screen.
Example 3.47. Update drawing processing and key handling in the initial screen
// drawing handler XANDLER_IMPLEMENT_VOIDRENDER(helloworld, OnRenderRequest, invoker, reason, graphics) { unused(invoker); // by default, background will be filled in white color // *** updated code segments are in bold graphics->DrawSingleText("Key 1- Controls", SFXGrid(20, 20), GetLocalBound(), COLOR_BLACK); graphics->DrawSingleText("Key 2- TextMenu", SFXGrid(20, 40), GetLocalBound(), COLOR_BLACK); return; } // key handler XANDLER_IMPLEMENT_BOOLEVENT(helloworld, OnKey, invoker, event) { unused(invoker); // *** added code segments are in bold // handle the key event only when the application class has no visible child responder if (this->GetChildFront(true, false, false, false) == null) { switch (event.GetP16()) { case AVK_SELECT: Terminate(); return true; case AVK_1: TRACE("key 1"); if (MakeMy() != SFERR_NO_ERROR) { return false; } return true; case AVK_2: // when the "2" key is pressed TRACE("key 2"); // make the text menu if (MakeMenu() != SFERR_NO_ERROR) { return false; } // return "true" since the key event handled return true; } } // return "false" when key event is not handled return false; }
As a result of added code segments in bold,
...
// handle the key event only when the application class has no visible child responder
if (this->GetChildFront(true, false, false, false) == null) {
...
the helloworld application class(i.e., root[SFZRoot]) will not handle the key events when it has the child responder whose visible state is "ON"(i.e., when MyWindow or _textMenu is displayed).
With the added code segments in bold above, key events which are not handled by MyWindow nor _textMenu will be handled by the helloworld application class(i.e., root[SFZRoot]).
The following is execution result on BREW simulator.
Selection key of the text menu | |
---|---|
The focus can be moved among items with the selection key of the text menu. In default settings, the focus will be moved the previous or the next item if the UP or DOWN key is pressed respectively. Setting of the selection key can be changed with the SFYMenu::SetSelectUpKey and SFYMenu::SetSelectDownKey functions. |
Operation key of the text menu | |
---|---|
An item can be selected with the operation key of menu. In default settings, the focused item will be selected if the SELECT key is pressed. Setting of the operation key can be changed with the SFYMenu::SetOperateKey function. |
Reference: Menu(Basic) | SFYResponder::GetChildFront
Copyright(c) 2002 - 2024 Sophia Cradle Incorporated All Rights Reserved. |