mirror of https://github.com/mgba-emu/mgba.git
mGUI: Refactor menu code into separate functions
This commit is contained in:
parent
c9e1b78426
commit
603de394d8
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
CXX_GUARD_START
|
CXX_GUARD_START
|
||||||
|
|
||||||
|
#include <mgba-util/gui.h>
|
||||||
#include <mgba-util/vector.h>
|
#include <mgba-util/vector.h>
|
||||||
|
|
||||||
#define GUI_V_V (struct GUIVariant) { .type = GUI_VARIANT_VOID }
|
#define GUI_V_V (struct GUIVariant) { .type = GUI_VARIANT_VOID }
|
||||||
|
@ -73,10 +74,29 @@ struct GUIMenu {
|
||||||
struct GUIBackground* background;
|
struct GUIBackground* background;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GUIMenuSavedState {
|
||||||
|
struct GUIMenu* menu;
|
||||||
|
size_t start;
|
||||||
|
};
|
||||||
|
|
||||||
|
DECLARE_VECTOR(GUIMenuSavedList, struct GUIMenuSavedState);
|
||||||
|
|
||||||
|
struct GUIMenuState {
|
||||||
|
size_t start;
|
||||||
|
int cursorOverItem;
|
||||||
|
enum GUICursorState cursor;
|
||||||
|
unsigned cx, cy;
|
||||||
|
struct GUIMenuSavedList stack;
|
||||||
|
|
||||||
|
struct GUIMenuItem* resultItem;
|
||||||
|
};
|
||||||
|
|
||||||
enum GUIMenuExitReason {
|
enum GUIMenuExitReason {
|
||||||
|
GUI_MENU_CONTINUE = 0,
|
||||||
GUI_MENU_EXIT_ACCEPT,
|
GUI_MENU_EXIT_ACCEPT,
|
||||||
GUI_MENU_EXIT_BACK,
|
GUI_MENU_EXIT_BACK,
|
||||||
GUI_MENU_EXIT_CANCEL,
|
GUI_MENU_EXIT_CANCEL,
|
||||||
|
GUI_MENU_ENTER,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum GUIMessageBoxButtons {
|
enum GUIMessageBoxButtons {
|
||||||
|
@ -85,7 +105,11 @@ enum GUIMessageBoxButtons {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GUIParams;
|
struct GUIParams;
|
||||||
|
void GUIMenuStateInit(struct GUIMenuState*);
|
||||||
|
void GUIMenuStateDeinit(struct GUIMenuState*);
|
||||||
|
|
||||||
enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* menu, struct GUIMenuItem** item);
|
enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* menu, struct GUIMenuItem** item);
|
||||||
|
enum GUIMenuExitReason GUIMenuRun(struct GUIParams* params, struct GUIMenu* menu, struct GUIMenuState* state);
|
||||||
|
|
||||||
ATTRIBUTE_FORMAT(printf, 4, 5)
|
ATTRIBUTE_FORMAT(printf, 4, 5)
|
||||||
enum GUIMenuExitReason GUIShowMessageBox(struct GUIParams* params, int buttons, int frames, const char* format, ...);
|
enum GUIMenuExitReason GUIShowMessageBox(struct GUIParams* params, int buttons, int frames, const char* format, ...);
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DEFINE_VECTOR(GUIMenuItemList, struct GUIMenuItem);
|
DEFINE_VECTOR(GUIMenuItemList, struct GUIMenuItem);
|
||||||
|
DEFINE_VECTOR(GUIMenuSavedList, struct GUIMenuSavedState);
|
||||||
|
|
||||||
void _itemNext(struct GUIMenuItem* item, bool wrap) {
|
void _itemNext(struct GUIMenuItem* item, bool wrap) {
|
||||||
if (item->state < item->nStates - 1) {
|
if (item->state < item->nStates - 1) {
|
||||||
|
@ -44,17 +45,21 @@ void _itemPrev(struct GUIMenuItem* item, bool wrap) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* menu, struct GUIMenuItem** item) {
|
void GUIMenuStateInit(struct GUIMenuState* state) {
|
||||||
size_t start = 0;
|
state->start = 0;
|
||||||
size_t lineHeight = GUIFontHeight(params->font);
|
state->cursorOverItem = 0;
|
||||||
size_t pageSize = params->height / lineHeight;
|
state->cursor = GUI_CURSOR_NOT_PRESENT;
|
||||||
if (pageSize > 4) {
|
state->resultItem = NULL;
|
||||||
pageSize -= 4;
|
GUIMenuSavedListInit(&state->stack, 0);
|
||||||
} else {
|
}
|
||||||
pageSize = 1;
|
|
||||||
}
|
|
||||||
int cursorOverItem = 0;
|
|
||||||
|
|
||||||
|
void GUIMenuStateDeinit(struct GUIMenuState* state) {
|
||||||
|
GUIMenuSavedListDeinit(&state->stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* menu, struct GUIMenuItem** item) {
|
||||||
|
struct GUIMenuState state;
|
||||||
|
GUIMenuStateInit(&state);
|
||||||
GUIInvalidateKeys(params);
|
GUIInvalidateKeys(params);
|
||||||
while (true) {
|
while (true) {
|
||||||
#ifdef _3DS
|
#ifdef _3DS
|
||||||
|
@ -66,151 +71,213 @@ enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* men
|
||||||
return GUI_MENU_EXIT_CANCEL;
|
return GUI_MENU_EXIT_CANCEL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
uint32_t newInput = 0;
|
enum GUIMenuExitReason reason = GUIMenuRun(params, menu, &state);
|
||||||
GUIPollInput(params, &newInput, 0);
|
switch (reason) {
|
||||||
unsigned cx, cy;
|
case GUI_MENU_EXIT_BACK:
|
||||||
enum GUICursorState cursor = GUIPollCursor(params, &cx, &cy);
|
if (GUIMenuSavedListSize(&state.stack) > 0) {
|
||||||
|
struct GUIMenuSavedState* last = GUIMenuSavedListGetPointer(&state.stack, GUIMenuSavedListSize(&state.stack) - 1);
|
||||||
if (newInput & (1 << GUI_INPUT_UP) && menu->index > 0) {
|
state.start = last->start;
|
||||||
--menu->index;
|
menu = last->menu;
|
||||||
}
|
GUIMenuSavedListResize(&state.stack, -1);
|
||||||
if (newInput & (1 << GUI_INPUT_DOWN) && menu->index < GUIMenuItemListSize(&menu->items) - 1) {
|
|
||||||
++menu->index;
|
|
||||||
}
|
|
||||||
if (newInput & (1 << GUI_INPUT_LEFT)) {
|
|
||||||
struct GUIMenuItem* item = GUIMenuItemListGetPointer(&menu->items, menu->index);
|
|
||||||
if (item->validStates) {
|
|
||||||
_itemPrev(item, false);
|
|
||||||
} else if (menu->index >= pageSize) {
|
|
||||||
menu->index -= pageSize;
|
|
||||||
} else {
|
|
||||||
menu->index = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (newInput & (1 << GUI_INPUT_RIGHT)) {
|
|
||||||
struct GUIMenuItem* item = GUIMenuItemListGetPointer(&menu->items, menu->index);
|
|
||||||
if (item->validStates) {
|
|
||||||
_itemNext(item, false);
|
|
||||||
} else if (menu->index + pageSize < GUIMenuItemListSize(&menu->items)) {
|
|
||||||
menu->index += pageSize;
|
|
||||||
} else {
|
|
||||||
menu->index = GUIMenuItemListSize(&menu->items) - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cursor != GUI_CURSOR_NOT_PRESENT) {
|
|
||||||
if (cx < params->width - 16) {
|
|
||||||
int index = (cy / lineHeight) - 2;
|
|
||||||
if (index >= 0 && index + start < GUIMenuItemListSize(&menu->items)) {
|
|
||||||
if (menu->index != index + start || !cursorOverItem) {
|
|
||||||
cursorOverItem = 1;
|
|
||||||
}
|
|
||||||
menu->index = index + start;
|
|
||||||
} else {
|
|
||||||
cursorOverItem = 0;
|
|
||||||
}
|
|
||||||
} else if (cursor == GUI_CURSOR_DOWN || cursor == GUI_CURSOR_DRAGGING) {
|
|
||||||
if (cy <= 2 * lineHeight && cy > lineHeight && menu->index > 0) {
|
|
||||||
--menu->index;
|
|
||||||
} else if (cy <= params->height && cy > params->height - lineHeight && menu->index < GUIMenuItemListSize(&menu->items) - 1) {
|
|
||||||
++menu->index;
|
|
||||||
} else if (cy <= params->height - lineHeight && cy > 2 * lineHeight) {
|
|
||||||
size_t location = cy - 2 * lineHeight;
|
|
||||||
location *= GUIMenuItemListSize(&menu->items) - 1;
|
|
||||||
menu->index = location / (params->height - 3 * lineHeight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (menu->index < start) {
|
|
||||||
start = menu->index;
|
|
||||||
}
|
|
||||||
while ((menu->index - start + 4) * lineHeight > params->height) {
|
|
||||||
++start;
|
|
||||||
}
|
|
||||||
if (newInput & (1 << GUI_INPUT_CANCEL)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (newInput & (1 << GUI_INPUT_SELECT) || (cursorOverItem == 2 && cursor == GUI_CURSOR_CLICKED)) {
|
|
||||||
*item = GUIMenuItemListGetPointer(&menu->items, menu->index);
|
|
||||||
if ((*item)->submenu) {
|
|
||||||
enum GUIMenuExitReason reason = GUIShowMenu(params, (*item)->submenu, item);
|
|
||||||
if (reason != GUI_MENU_EXIT_BACK) {
|
|
||||||
return reason;
|
|
||||||
}
|
|
||||||
} else if ((*item)->validStates && GUIVariantIsString((*item)->data)) {
|
|
||||||
_itemNext(*item, true);
|
|
||||||
} else {
|
|
||||||
return GUI_MENU_EXIT_ACCEPT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cursorOverItem == 1 && (cursor == GUI_CURSOR_UP || cursor == GUI_CURSOR_NOT_PRESENT)) {
|
|
||||||
cursorOverItem = 2;
|
|
||||||
}
|
|
||||||
if (newInput & (1 << GUI_INPUT_BACK)) {
|
|
||||||
return GUI_MENU_EXIT_BACK;
|
|
||||||
}
|
|
||||||
|
|
||||||
params->drawStart();
|
|
||||||
if (menu->background) {
|
|
||||||
menu->background->draw(menu->background, GUIMenuItemListGetPointer(&menu->items, menu->index)->data.v.p);
|
|
||||||
}
|
|
||||||
if (params->guiPrepare) {
|
|
||||||
params->guiPrepare();
|
|
||||||
}
|
|
||||||
unsigned y = lineHeight;
|
|
||||||
GUIFontPrint(params->font, 0, y, GUI_ALIGN_LEFT, 0xFFFFFFFF, menu->title);
|
|
||||||
if (menu->subtitle) {
|
|
||||||
GUIFontPrint(params->font, 0, y * 2, GUI_ALIGN_LEFT, 0xFFFFFFFF, menu->subtitle);
|
|
||||||
}
|
|
||||||
y += 2 * lineHeight;
|
|
||||||
unsigned right;
|
|
||||||
GUIFontIconMetrics(params->font, GUI_ICON_SCROLLBAR_BUTTON, &right, 0);
|
|
||||||
size_t itemsPerScreen = (params->height - y) / lineHeight;
|
|
||||||
size_t i;
|
|
||||||
for (i = start; i < GUIMenuItemListSize(&menu->items); ++i) {
|
|
||||||
int color = 0xE0A0A0A0;
|
|
||||||
if (i == menu->index) {
|
|
||||||
color = 0xFFFFFFFF;
|
|
||||||
GUIFontDrawIcon(params->font, lineHeight * 0.8f, y, GUI_ALIGN_BOTTOM | GUI_ALIGN_RIGHT, GUI_ORIENT_0, 0xFFFFFFFF, GUI_ICON_POINTER);
|
|
||||||
}
|
|
||||||
struct GUIMenuItem* item = GUIMenuItemListGetPointer(&menu->items, i);
|
|
||||||
GUIFontPrint(params->font, lineHeight, y, GUI_ALIGN_LEFT, color, item->title);
|
|
||||||
if (item->validStates && item->validStates[item->state]) {
|
|
||||||
GUIFontPrintf(params->font, params->width - right - 8, y, GUI_ALIGN_RIGHT, color, "%s ", item->validStates[item->state]);
|
|
||||||
}
|
|
||||||
y += lineHeight;
|
|
||||||
if (y + lineHeight > params->height) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// Fall through
|
||||||
|
case GUI_MENU_EXIT_CANCEL:
|
||||||
|
case GUI_MENU_EXIT_ACCEPT:
|
||||||
|
*item = state.resultItem;
|
||||||
|
GUIMenuStateDeinit(&state);
|
||||||
|
return reason;
|
||||||
|
case GUI_MENU_ENTER:
|
||||||
|
*GUIMenuSavedListAppend(&state.stack) = (struct GUIMenuSavedState) {
|
||||||
|
.start = state.start,
|
||||||
|
.menu = menu
|
||||||
|
};
|
||||||
|
menu = state.resultItem->submenu;
|
||||||
|
state.start = 0;
|
||||||
|
break;
|
||||||
|
case GUI_MENU_CONTINUE:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemsPerScreen < GUIMenuItemListSize(&menu->items)) {
|
|
||||||
size_t top = 2 * lineHeight;
|
|
||||||
size_t bottom = params->height - 8;
|
|
||||||
unsigned w;
|
|
||||||
GUIFontIconMetrics(params->font, GUI_ICON_SCROLLBAR_TRACK, &w, 0);
|
|
||||||
right = (right - w) / 2;
|
|
||||||
GUIFontDrawIconSize(params->font, params->width - right - 8, top, 0, bottom - top, 0xA0FFFFFF, GUI_ICON_SCROLLBAR_TRACK);
|
|
||||||
GUIFontDrawIcon(params->font, params->width - 8, top, GUI_ALIGN_HCENTER | GUI_ALIGN_BOTTOM, GUI_ORIENT_VMIRROR, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_BUTTON);
|
|
||||||
GUIFontDrawIcon(params->font, params->width - 8, bottom, GUI_ALIGN_HCENTER | GUI_ALIGN_TOP, GUI_ORIENT_0, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_BUTTON);
|
|
||||||
|
|
||||||
y = menu->index * (bottom - top - 16) / GUIMenuItemListSize(&menu->items);
|
|
||||||
GUIFontDrawIcon(params->font, params->width - 8, top + y, GUI_ALIGN_HCENTER | GUI_ALIGN_TOP, GUI_ORIENT_0, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_THUMB);
|
|
||||||
}
|
|
||||||
|
|
||||||
GUIDrawBattery(params);
|
|
||||||
GUIDrawClock(params);
|
|
||||||
|
|
||||||
if (cursor != GUI_CURSOR_NOT_PRESENT) {
|
|
||||||
GUIFontDrawIcon(params->font, cx, cy, GUI_ALIGN_HCENTER | GUI_ALIGN_TOP, GUI_ORIENT_0, 0xFFFFFFFF, GUI_ICON_CURSOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params->guiFinish) {
|
|
||||||
params->guiFinish();
|
|
||||||
}
|
|
||||||
params->drawEnd();
|
|
||||||
}
|
}
|
||||||
return GUI_MENU_EXIT_CANCEL;
|
}
|
||||||
|
|
||||||
|
static enum GUIMenuExitReason GUIMenuPollInput(struct GUIParams* params, struct GUIMenu* menu, struct GUIMenuState* state) {
|
||||||
|
size_t lineHeight = GUIFontHeight(params->font);
|
||||||
|
size_t pageSize = params->height / lineHeight;
|
||||||
|
if (pageSize > 4) {
|
||||||
|
pageSize -= 4;
|
||||||
|
} else {
|
||||||
|
pageSize = 1;
|
||||||
|
}
|
||||||
|
uint32_t newInput = 0;
|
||||||
|
GUIPollInput(params, &newInput, NULL);
|
||||||
|
state->cursor = GUIPollCursor(params, &state->cx, &state->cy);
|
||||||
|
|
||||||
|
// Check for new direction presses
|
||||||
|
if (newInput & (1 << GUI_INPUT_UP) && menu->index > 0) {
|
||||||
|
--menu->index;
|
||||||
|
}
|
||||||
|
if (newInput & (1 << GUI_INPUT_DOWN) && menu->index < GUIMenuItemListSize(&menu->items) - 1) {
|
||||||
|
++menu->index;
|
||||||
|
}
|
||||||
|
if (newInput & (1 << GUI_INPUT_LEFT)) {
|
||||||
|
struct GUIMenuItem* item = GUIMenuItemListGetPointer(&menu->items, menu->index);
|
||||||
|
if (item->validStates) {
|
||||||
|
_itemPrev(item, false);
|
||||||
|
} else if (menu->index >= pageSize) {
|
||||||
|
menu->index -= pageSize;
|
||||||
|
} else {
|
||||||
|
menu->index = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (newInput & (1 << GUI_INPUT_RIGHT)) {
|
||||||
|
struct GUIMenuItem* item = GUIMenuItemListGetPointer(&menu->items, menu->index);
|
||||||
|
if (item->validStates) {
|
||||||
|
_itemNext(item, false);
|
||||||
|
} else if (menu->index + pageSize < GUIMenuItemListSize(&menu->items)) {
|
||||||
|
menu->index += pageSize;
|
||||||
|
} else {
|
||||||
|
menu->index = GUIMenuItemListSize(&menu->items) - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle cursor movement
|
||||||
|
if (state->cursor != GUI_CURSOR_NOT_PRESENT) {
|
||||||
|
unsigned cx = state->cx;
|
||||||
|
unsigned cy = state->cy;
|
||||||
|
if (cx < params->width - 16) {
|
||||||
|
int index = (cy / lineHeight) - 2;
|
||||||
|
if (index >= 0 && index + state->start < GUIMenuItemListSize(&menu->items)) {
|
||||||
|
if (menu->index != index + state->start || !state->cursorOverItem) {
|
||||||
|
state->cursorOverItem = 1;
|
||||||
|
}
|
||||||
|
menu->index = index + state->start;
|
||||||
|
} else {
|
||||||
|
state->cursorOverItem = 0;
|
||||||
|
}
|
||||||
|
} else if (state->cursor == GUI_CURSOR_DOWN || state->cursor == GUI_CURSOR_DRAGGING) {
|
||||||
|
if (cy <= 2 * lineHeight && cy > lineHeight && menu->index > 0) {
|
||||||
|
--menu->index;
|
||||||
|
} else if (cy <= params->height && cy > params->height - lineHeight && menu->index < GUIMenuItemListSize(&menu->items) - 1) {
|
||||||
|
++menu->index;
|
||||||
|
} else if (cy <= params->height - lineHeight && cy > 2 * lineHeight) {
|
||||||
|
size_t location = cy - 2 * lineHeight;
|
||||||
|
location *= GUIMenuItemListSize(&menu->items) - 1;
|
||||||
|
menu->index = location / (params->height - 3 * lineHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move view up if the active item is before the top of the view
|
||||||
|
if (menu->index < state->start) {
|
||||||
|
state->start = menu->index;
|
||||||
|
}
|
||||||
|
// Move the view down if the active item is after the bottom of the view
|
||||||
|
while ((menu->index - state->start + 4) * lineHeight > params->height) {
|
||||||
|
// TODO: Should this loop be replaced with division?
|
||||||
|
++state->start;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle action inputs
|
||||||
|
if (newInput & (1 << GUI_INPUT_CANCEL)) {
|
||||||
|
return GUI_MENU_EXIT_CANCEL;
|
||||||
|
}
|
||||||
|
if (newInput & (1 << GUI_INPUT_SELECT) || (state->cursorOverItem == 2 && state->cursor == GUI_CURSOR_CLICKED)) {
|
||||||
|
struct GUIMenuItem* item = GUIMenuItemListGetPointer(&menu->items, menu->index);
|
||||||
|
if (item->submenu) {
|
||||||
|
// Selected menus get shown inline
|
||||||
|
state->resultItem = item;
|
||||||
|
return GUI_MENU_ENTER;
|
||||||
|
} else if (item->validStates && GUIVariantIsString(item->data)) {
|
||||||
|
// Selected items with multiple (named) states get scrolled through
|
||||||
|
_itemNext(item, true);
|
||||||
|
} else {
|
||||||
|
// Otherwise tell caller item was accepted
|
||||||
|
state->resultItem = item;
|
||||||
|
return GUI_MENU_EXIT_ACCEPT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (state->cursorOverItem == 1 && (state->cursor == GUI_CURSOR_UP || state->cursor == GUI_CURSOR_NOT_PRESENT)) {
|
||||||
|
state->cursorOverItem = 2;
|
||||||
|
}
|
||||||
|
if (newInput & (1 << GUI_INPUT_BACK)) {
|
||||||
|
return GUI_MENU_EXIT_BACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No action taken
|
||||||
|
return GUI_MENU_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GUIMenuDraw(struct GUIParams* params, const struct GUIMenu* menu, const struct GUIMenuState* state) {
|
||||||
|
size_t lineHeight = GUIFontHeight(params->font);
|
||||||
|
params->drawStart();
|
||||||
|
if (menu->background) {
|
||||||
|
menu->background->draw(menu->background, GUIMenuItemListGetConstPointer(&menu->items, menu->index)->data.v.p);
|
||||||
|
}
|
||||||
|
if (params->guiPrepare) {
|
||||||
|
params->guiPrepare();
|
||||||
|
}
|
||||||
|
unsigned y = lineHeight;
|
||||||
|
GUIFontPrint(params->font, 0, y, GUI_ALIGN_LEFT, 0xFFFFFFFF, menu->title);
|
||||||
|
if (menu->subtitle) {
|
||||||
|
GUIFontPrint(params->font, 0, y * 2, GUI_ALIGN_LEFT, 0xFFFFFFFF, menu->subtitle);
|
||||||
|
}
|
||||||
|
y += 2 * lineHeight;
|
||||||
|
unsigned right;
|
||||||
|
GUIFontIconMetrics(params->font, GUI_ICON_SCROLLBAR_BUTTON, &right, 0);
|
||||||
|
size_t itemsPerScreen = (params->height - y) / lineHeight;
|
||||||
|
size_t i;
|
||||||
|
for (i = state->start; i < GUIMenuItemListSize(&menu->items); ++i) {
|
||||||
|
int color = 0xE0A0A0A0;
|
||||||
|
if (i == menu->index) {
|
||||||
|
color = 0xFFFFFFFF;
|
||||||
|
GUIFontDrawIcon(params->font, lineHeight * 0.8f, y, GUI_ALIGN_BOTTOM | GUI_ALIGN_RIGHT, GUI_ORIENT_0, 0xFFFFFFFF, GUI_ICON_POINTER);
|
||||||
|
}
|
||||||
|
const struct GUIMenuItem* item = GUIMenuItemListGetConstPointer(&menu->items, i);
|
||||||
|
GUIFontPrint(params->font, lineHeight, y, GUI_ALIGN_LEFT, color, item->title);
|
||||||
|
if (item->validStates && item->validStates[item->state]) {
|
||||||
|
GUIFontPrintf(params->font, params->width - right - 8, y, GUI_ALIGN_RIGHT, color, "%s ", item->validStates[item->state]);
|
||||||
|
}
|
||||||
|
y += lineHeight;
|
||||||
|
if (y + lineHeight > params->height) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemsPerScreen < GUIMenuItemListSize(&menu->items)) {
|
||||||
|
size_t top = 2 * lineHeight;
|
||||||
|
size_t bottom = params->height - 8;
|
||||||
|
unsigned w;
|
||||||
|
GUIFontIconMetrics(params->font, GUI_ICON_SCROLLBAR_TRACK, &w, 0);
|
||||||
|
right = (right - w) / 2;
|
||||||
|
GUIFontDrawIconSize(params->font, params->width - right - 8, top, 0, bottom - top, 0xA0FFFFFF, GUI_ICON_SCROLLBAR_TRACK);
|
||||||
|
GUIFontDrawIcon(params->font, params->width - 8, top, GUI_ALIGN_HCENTER | GUI_ALIGN_BOTTOM, GUI_ORIENT_VMIRROR, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_BUTTON);
|
||||||
|
GUIFontDrawIcon(params->font, params->width - 8, bottom, GUI_ALIGN_HCENTER | GUI_ALIGN_TOP, GUI_ORIENT_0, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_BUTTON);
|
||||||
|
|
||||||
|
y = menu->index * (bottom - top - 16) / GUIMenuItemListSize(&menu->items);
|
||||||
|
GUIFontDrawIcon(params->font, params->width - 8, top + y, GUI_ALIGN_HCENTER | GUI_ALIGN_TOP, GUI_ORIENT_0, 0xFFFFFFFF, GUI_ICON_SCROLLBAR_THUMB);
|
||||||
|
}
|
||||||
|
|
||||||
|
GUIDrawBattery(params);
|
||||||
|
GUIDrawClock(params);
|
||||||
|
|
||||||
|
if (state->cursor != GUI_CURSOR_NOT_PRESENT) {
|
||||||
|
GUIFontDrawIcon(params->font, state->cx, state->cy, GUI_ALIGN_HCENTER | GUI_ALIGN_TOP, GUI_ORIENT_0, 0xFFFFFFFF, GUI_ICON_CURSOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params->guiFinish) {
|
||||||
|
params->guiFinish();
|
||||||
|
}
|
||||||
|
params->drawEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
enum GUIMenuExitReason GUIMenuRun(struct GUIParams* params, struct GUIMenu* menu, struct GUIMenuState* state) {
|
||||||
|
enum GUIMenuExitReason reason = GUIMenuPollInput(params, menu, state);
|
||||||
|
if (reason != GUI_MENU_CONTINUE) {
|
||||||
|
return reason;
|
||||||
|
}
|
||||||
|
GUIMenuDraw(params, menu, state);
|
||||||
|
return GUI_MENU_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum GUIMenuExitReason GUIShowMessageBox(struct GUIParams* params, int buttons, int frames, const char* format, ...) {
|
enum GUIMenuExitReason GUIShowMessageBox(struct GUIParams* params, int buttons, int frames, const char* format, ...) {
|
||||||
|
|
Loading…
Reference in New Issue