Drop Down Menu
Drop down menus are versatile GUI elements that allow users to select from a list of options. The GUIDropDownMenu
class, along with the GUIDropDownMenuItem
class, provides a robust implementation of this functionality. Below is the detailed documentation for these classes.
GUIDropDownMenu
Constructor
GUIDropDownMenu(
uint16_t leftX, uint16_t topY, uint16_t rightX, uint16_t bottomY,
uint16_t eventID
)
Creates a drop down menu with the specified bounding box and event ID.
leftX
,topY
,rightX
,bottomY
: Coordinates defining the bounding box of the drop down menu.eventID
: The event ID for the drop down menu.
Methods
SetScrollBarVisibility
void SetScrollBarVisibility(ScrollBarVisibility visibility)
Sets the visibility of the scroll bar.
visibility
: One of theScrollBarVisibility
enum values:ScrollBarHidden
: Always hide the scroll bar.ScrollBarAlwaysVisible
: Always show the scroll bar.ScrollBarVisibleWhenRequired
: Show the scroll bar only when required.
AddMenuItem
void AddMenuItem(GUIDropDownMenuItem &dropDownMenuItem)
Adds a menu item to the drop down menu.
dropDownMenuItem
: The menu item to add.
GUIDropDownMenuItem
Constructor
GUIDropDownMenuItem(const char *s, int idx, int flags)
Creates a drop down menu item with the specified text, index, and flags.
s
: The text displayed for the menu item.idx
: The index of the menu item.flags
: A bitfield of flags specified by bitwise-ORing members of theFlag
enum (e.g.,FlagTextAlignRight
,FlagTextAlignLeft
,FlagEnabled
).
Flags
FlagTextAlignRight
FlagTextAlignRight = 1 << 5
Aligns the text of the item within the drop down to the right.
FlagTextAlignLeft
FlagTextAlignLeft = 1 << 6
Aligns the text of the item within the drop down to the left.
FlagEnabled
FlagEnabled = 1 << 15
Allows the item to be selected.
Usage
Here’s an example that demonstrates the creation and usage of a drop down menu with multiple items:
// parent is the dialog or parent container
const uint16_t APP_NAMES_EVENT_ID = 1;
GUIDropDownMenu m_appNames(
parent.GetLeftX() + 10,
parent.GetTopY() + 10,
parent.GetRightX() - 10,
parent.GetBottomY() - 10,
APP_NAMES_EVENT_ID
);
// Adding items to the drop down menu
m_appNames.AddMenuItem(*(
new GUIDropDownMenuItem(
"Option 1", 1,
GUIDropDownMenuItem::FlagEnabled | GUIDropDownMenuItem::FlagTextAlignLeft
)
));
m_appNames.AddMenuItem(*(
new GUIDropDownMenuItem(
"Option 2", 2,
GUIDropDownMenuItem::FlagEnabled | GUIDropDownMenuItem::FlagTextAlignLeft
)
));
m_appNames.SetScrollBarVisibility(
GUIDropDownMenu::ScrollBarVisibleWhenRequired
);
parent.AddElement(m_appNames);
Example Dialog Implementation
A real world usage example dialog class that uses the GUIDropDownMenu
and GUIDropDownMenuItem
is the actual
Hollyhock 2 Launcher
Fruits Picker dialog
It’s important to note a few things there:
- MenuItem index starts at 1, not 0
- You can’t size the dropdown button, only the dropdown popup dialog
#include <appdef.hpp>
#include <sdk/os/debug.hpp>
#include <sdk/os/gui.hpp>
#include <sdk/os/lcd.hpp>
#include <sdk/os/mem.hpp>
#include <sdk/os/string.hpp>
/*
* Fill this section in with some information about your app.
* All fields are optional - so if you don't need one, take it out.
*/
APP_NAME("DropDown dialog app")
APP_DESCRIPTION("Testing a DropDown with a button")
APP_AUTHOR("Demo")
APP_VERSION("1.0.0")
class FruitSelector : public GUIDialog {
public:
int m_selectedFruitIndex;
FruitSelector()
: GUIDialog(GUIDialog::Height95, GUIDialog::AlignTop,
"What's the best fruit?", GUIDialog::KeyboardStateNone),
m_fruitDropDown(GetLeftX() + 10, GetTopY() + 10, GetRightX() - 10,
// You can't size the dropdown picker element, only the
// dropdown menu size
GetBottomY() - 10, FRUIT_DROPDOWN_EVENT_ID),
m_selectedFruitTextBox(GetLeftX() + 10, GetTopY() + 60,
GetRightX() - 10, GetTopY() + 100,
"The best fruit is: None selected"),
m_selectButton(GetLeftX() + 10, GetTopY() + 110, GetRightX() - 10,
GetTopY() + 145, "Select", SELECT_BUTTON_EVENT_ID) {
const char *fruits[] = {"Apple", "Banana", "Orange", "Grape", "Mango"};
const int numFruits = sizeof(fruits) / sizeof(fruits[0]);
for (int i = 0; i < numFruits; ++i) {
m_fruitDropDown.AddMenuItem(*(new GUIDropDownMenuItem(
fruits[i], i + 1, // off-by-one, indexes begin at 1 for the DropDown
GUIDropDownMenuItem::FlagEnabled |
GUIDropDownMenuItem::FlagTextAlignLeft)));
}
m_fruitDropDown.SetScrollBarVisibility(
GUIDropDownMenu::ScrollBarVisibleWhenRequired);
AddElement(m_fruitDropDown);
AddElement(m_selectedFruitTextBox);
AddElement(m_selectButton);
}
virtual int OnEvent(GUIDialog_Wrapped *dialog,
GUIDialog_OnEvent_Data *event) {
if (event->GetEventID() == SELECT_BUTTON_EVENT_ID) {
UpdateSelectedFruit();
return 0;
}
if (event->GetEventID() == FRUIT_DROPDOWN_EVENT_ID &&
(event->type & 0xF) == 0xD) {
m_selectedFruitIndex = event->data - 1; // -1 to fox the off-by-one
return 0;
}
return GUIDialog::OnEvent(dialog, event);
}
void UpdateSelectedFruit() {
const char *fruits[] = {"Apple", "Banana", "Orange", "Grape", "Mango"};
const int numFruits = sizeof(fruits) / sizeof(fruits[0]);
if (m_selectedFruitIndex >= 0 && m_selectedFruitIndex < numFruits) {
m_selectedFruitTextBox.SetText(fruits[m_selectedFruitIndex]);
Refresh();
}
}
private:
const uint16_t FRUIT_DROPDOWN_EVENT_ID = 1;
const uint16_t SELECT_BUTTON_EVENT_ID = 2;
GUIDropDownMenu m_fruitDropDown;
GUITextBox m_selectedFruitTextBox;
GUIButton m_selectButton;
};
int main() {
FruitSelector fruitSelector;
fruitSelector.ShowDialog();
return 0;
}
This example creates a dialog with a drop down menu containing a list of fruits (“Apple”, “Banana”, “Orange”, “Grape”, “Mango”). There is a label initially displaying “The best fruit is: None selected” and a button labeled “Select”. When the button is pressed, the label is updated to show the selected fruit.