all repos — mgba @ c14da05d8dca225010677643c32fea5c0ac8517a

mGBA Game Boy Advance Emulator

src/util/gui/menu.c (view raw)

  1/* Copyright (c) 2013-2015 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#include "menu.h"
  7
  8#include "util/gui.h"
  9#include "util/gui/font.h"
 10
 11DEFINE_VECTOR(GUIMenuItemList, struct GUIMenuItem);
 12
 13enum GUIMenuExitReason GUIShowMenu(struct GUIParams* params, struct GUIMenu* menu, struct GUIMenuItem* item) {
 14	size_t start = 0;
 15	size_t pageSize = params->height / GUIFontHeight(params->font);
 16	if (pageSize > 4) {
 17		pageSize -= 4;
 18	} else {
 19		pageSize = 1;
 20	}
 21
 22	GUIInvalidateKeys(params);
 23	while (true) {
 24		uint32_t newInput = 0;
 25		GUIPollInput(params, &newInput, 0);
 26
 27		if (newInput & (1 << GUI_INPUT_UP) && menu->index > 0) {
 28			--menu->index;
 29		}
 30		if (newInput & (1 << GUI_INPUT_DOWN) && menu->index < GUIMenuItemListSize(&menu->items) - 1) {
 31			++menu->index;
 32		}
 33		if (newInput & (1 << GUI_INPUT_LEFT)) {
 34			if (menu->index >= pageSize) {
 35				menu->index -= pageSize;
 36			} else {
 37				menu->index = 0;
 38			}
 39		}
 40		if (newInput & (1 << GUI_INPUT_RIGHT)) {
 41			if (menu->index + pageSize < GUIMenuItemListSize(&menu->items)) {
 42				menu->index += pageSize;
 43			} else {
 44				menu->index = GUIMenuItemListSize(&menu->items) - 1;
 45			}
 46		}
 47
 48		if (menu->index < start) {
 49			start = menu->index;
 50		}
 51		while ((menu->index - start + 4) * GUIFontHeight(params->font) > params->height) {
 52			++start;
 53		}
 54		if (newInput & (1 << GUI_INPUT_CANCEL)) {
 55			break;
 56		}
 57		if (newInput & (1 << GUI_INPUT_SELECT)) {
 58			*item = *GUIMenuItemListGetPointer(&menu->items, menu->index);
 59			if (item->submenu) {
 60				enum GUIMenuExitReason reason = GUIShowMenu(params, item->submenu, item);
 61				if (reason != GUI_MENU_EXIT_BACK) {
 62					return reason;
 63				}
 64			} else {
 65				return GUI_MENU_EXIT_ACCEPT;
 66			}
 67		}
 68		if (newInput & (1 << GUI_INPUT_BACK)) {
 69			return GUI_MENU_EXIT_BACK;
 70		}
 71
 72		params->drawStart();
 73		if (menu->background) {
 74			menu->background->draw(menu->background, GUIMenuItemListGetPointer(&menu->items, menu->index)->data);
 75		}
 76		if (params->guiPrepare) {
 77			params->guiPrepare();
 78		}
 79		unsigned y = GUIFontHeight(params->font);
 80		GUIFontPrint(params->font, 0, y, GUI_TEXT_LEFT, 0xFFFFFFFF, menu->title);
 81		y += 2 * GUIFontHeight(params->font);
 82		size_t i;
 83		for (i = start; i < GUIMenuItemListSize(&menu->items); ++i) {
 84			int color = 0xE0A0A0A0;
 85			char bullet = ' ';
 86			if (i == menu->index) {
 87				color = 0xFFFFFFFF;
 88				bullet = '>';
 89			}
 90			GUIFontPrintf(params->font, 0, y, GUI_TEXT_LEFT, color, "%c %s", bullet, GUIMenuItemListGetPointer(&menu->items, i)->title);
 91			y += GUIFontHeight(params->font);
 92			if (y + GUIFontHeight(params->font) > params->height) {
 93				break;
 94			}
 95		}
 96		if (params->guiFinish) {
 97			params->guiFinish();
 98		}
 99		y += GUIFontHeight(params->font) * 2;
100
101		params->drawEnd();
102	}
103	return GUI_MENU_EXIT_CANCEL;
104}