#include "menu.h"
//Initalize Menu Struct
void initMenu(menu_t *menu, enum colors itemColor, enum colors textColor, int centerX, int centerY, int bWidth, int bHeight)
{
menu->center[0] = centerX;
menu->center[1] = centerY;
menu->bound[0] = bWidth;
menu->bound[1] = bHeight;
menu->itemColor = itemColor;
menu->textColor = textColor;
menu->itemCount = 0;
}
//Initialize Menu Item
void initMenuItem(menuItem_t *item, char *text, int (*f) ())
{
//Copies a static string into an array of characters, used to avoid malloc since infinite characters are not practical
snprintf(item->text, 20, "%s", text);
item->stringLen = strlen(item->text);
item->clickAction = f;
item->highlight = 0;
}
//Adds a menu item to a menu struct and returns 1 on success
int addMenuItem(menu_t *menu, menuItem_t *menuItem)
{
//Get number of items in menu
int indx = menu->itemCount;
//If already more than four items, return
if(indx == 4) return 0;
menu->menuItems[indx] = menuItem;
menu->itemCount++;
return 1;
}
char result[50];
//Handles Input associated with a given menu struct
int handleInput(menu_t *menu, int cursorX, int cursorY, int userClicked)
{
//Check if within bounding box, otherwise return (quick check)
int topLeftX = menu->center[0] - (menu->bound[0] / 2);
int topLeftY = menu->center[1] - (menu->bound[1] / 2);
int menuX = menu->center[0];
int menuY = menu->center[1];
int itemWidth = (int) menu->bound[0] * 0.7;
int itemHeight = (int) menu->bound[1] * .1;
int cursorWithinBoundingBox = (cursorX >= topLeftX && cursorX <= topLeftX + menu->bound[0]) && (cursorY >= topLeftY && cursorY <= topLeftY + menu->bound[0]);
//if(!cursorWithinBoundingBox) return 0;
//Loop through each item, useful since we can keep track of which item has the cursor within the bounding box
//One item is drawn a bit differently, so it must be handled differently
if(menu->itemCount == 1)
{
//First item x position is half the width of the item subtracted from the center position. Ensures item is centered in bounding box
int itemX = menuX - (itemWidth >> 1);
//Same premise for an item's y position
int itemY = menuY - (itemHeight >> 1);
//Checks if the given cursor position is within the items box
int cursorWithinItem = (cursorX >= itemX && cursorX <= itemX + itemWidth) && (cursorY >= itemY && cursorY <= itemY + itemHeight);
if(cursorWithinItem)
{
menu->menuItems[0]->highlight = 1;
//Initiate click action if user indeed clicked
if(userClicked) menu->menuItems[0]->clickAction;
return 1;
}
else
{
menu->menuItems[0]->highlight = 0;
}
}
if(menu->itemCount == 2)
{
int spacerY = itemHeight >> 1;
//First item x position is half the width of the item subtracted from the center position. Ensures item is centered in bounding box
int itemX = menuX - (itemWidth >> 1);
//Same premise for an item's y position
int itemY = menuY - itemHeight - spacerY;
for(int item = 0; item < menu->itemCount; item++)
{
//Checks if the given cursor position is within the items box
int cursorWithinItem = (cursorX >= itemX && cursorX <= itemX + itemWidth) && (cursorY >= itemY && cursorY <= itemY + itemHeight);
if(cursorWithinItem)
{
//highlight box
menu->menuItems[item]->highlight = 1;
//Initiate click action if user indeed clicked
if(userClicked) menu->menuItems[item]->clickAction;
return 1;
}
else
{
menu->menuItems[item]->highlight = 0;
}
itemY = itemY + itemHeight + spacerY;
}
}
if(menu->itemCount == 3)
{
int spacerY = itemHeight >> 1;
//First item x position is half the width of the item subtracted from the center position. Ensures item is centered in bounding box
int itemX = menuX - (itemWidth >> 1);
//Same premise for an item's y position
int itemY = menuY - (itemHeight >> 1) - (itemHeight) - spacerY;
for(int item = 0; item < menu->itemCount; item++)
{
//Check if cursor is within item's box
int cursorWithinItem = (cursorX >= itemX && cursorX <= itemX + itemWidth) && (cursorY >= itemY && cursorY <= itemY + itemHeight);
if(cursorWithinItem)
{
//highlight box
menu->menuItems[item]->highlight = 1;
//Initiate click action if user indeed clicked
if(userClicked) menu->menuItems[item]->clickAction;
return 1;
}
else
{
menu->menuItems[item]->highlight = 0;
}
itemY = itemY + itemHeight + spacerY;
}
}
if(menu->itemCount == 4)
{
int spacerY = itemHeight >> 1;
//First item x position is half the width of the item subtracted from the center position. Ensures item is centered in bounding box
int itemX = menuX - (itemWidth >> 1);
//Same premise for an item's y position
int itemY = menuY - (2*itemHeight) - 2*spacerY;
for(int item = 0; item < menu->itemCount; item++)
{
//Check if cursor is within item's box
int cursorWithinItem = (cursorX >= itemX && cursorX <= itemX + itemWidth) && (cursorY >= itemY && cursorY <= itemY + itemHeight);
if(cursorWithinItem)
{
//highlight box
menu->menuItems[item]->highlight = 1;
//Initiate click action if user indeed clicked
if(userClicked) menu->menuItems[item]->clickAction(userClicked, cursorX, cursorY);
}
else
{
menu->menuItems[item]->highlight = 0;
}
itemY = itemY + itemHeight + spacerY;
}
}
return 0;
//Check if within menu item box
//If in menu item box, highlight menu item
//If userClicked, perform menu item action
//Else return
}
//Draws a menu associated with a menu struct
void drawMenu(menu_t *menu)
{
//Calculate where to place boxes dependent on item count, center position, and bound box
// 1 item -> 5%-10% height of bound box, 70% width of bound box centered in height/width, centered width/height
// 2 - 4 items -> same dimensions as 1 item, 5-10% spacing centered width/height
int menuX = menu->center[0];
int menuY = menu->center[1];
int itemWidth = (int) menu->bound[0] * 0.7;
int itemHeight = (int) menu->bound[1] * .1;
int topLeftX = menu->center[0] - (menu->bound[0] / 2);
int topLeftY = menu->center[1] - (menu->bound[1] / 2);
//Amount of menu items affects how the menu is drawn, but general process is the same
if(menu->itemCount == 1)
{
//First item x position is half the width of the item subtracted from the center position. Ensures item is centered in bounding box
int itemX = menuX - (itemWidth >> 1);
//Same premise for an item's y position
int itemY = menuY - (itemHeight >> 1);
fillRect(itemX, itemY, itemWidth, itemHeight, menu->itemColor);
//Text scaling, used to attempt to center any text in a menu item
float scale = (-.02)*(menu->menuItems[0]->stringLen) + .46;
setCursor(itemX+(int)(scale * itemWidth), itemY+10);
setTextColor(menu->textColor);
setTextSize(2);
writeString(menu->menuItems[0]->text);
//Menu item requires highlighting
if(menu->menuItems[0]->highlight)
{
drawRect(itemX, itemY, itemWidth, itemHeight, YELLOW);
drawRect(itemX+1, itemY+1, itemWidth-2, itemHeight-2, YELLOW);
drawRect(itemX+2, itemY+2, itemWidth-4, itemHeight-4, YELLOW);
}
}
if(menu->itemCount == 2)
{
int spacerY = itemHeight >> 1;
//First item x position is half the width of the item subtracted from the center position. Ensures item is centered in bounding box
int itemX = menuX - (itemWidth >> 1);
//Same premise for an item's y position
int itemY = menuY - itemHeight - spacerY;
for(int item = 0; item < menu->itemCount; item++)
{
fillRect(itemX, itemY, itemWidth, itemHeight, menu->itemColor);
float scale = (-.02)*(menu->menuItems[item]->stringLen) + .46;
setCursor(itemX+(int)(scale * itemWidth), itemY+10);
setTextColor(menu->textColor);
setTextSize(2);
writeString(menu->menuItems[item]->text);
itemY = itemY + itemHeight + spacerY;
if(menu->menuItems[item]->highlight)
{
drawRect(itemX, itemY, itemWidth, itemHeight, YELLOW);
drawRect(itemX+1, itemY+1, itemWidth-2, itemHeight-2, YELLOW);
drawRect(itemX+2, itemY+2, itemWidth-4, itemHeight-4, YELLOW);
}
}
}
if(menu->itemCount == 3)
{
//spacer is half the height of a menu item
int spacerY = itemHeight >> 1;
int itemX = menuX - (itemWidth >> 1);
//items y position is two spacers up and an item menu item (since theres three items)
int itemY = menuY - (itemHeight >> 1) - itemHeight - spacerY;
for(int item = 0; item < menu->itemCount; item++)
{
fillRect(itemX, itemY, itemWidth, itemHeight, menu->itemColor);
float scale = (-.02)*(menu->menuItems[item]->stringLen) + .46;
setCursor(itemX+(int)(scale * itemWidth), itemY+10);
setTextColor(menu->textColor);
setTextSize(2);
writeString(menu->menuItems[item]->text);
itemY = itemY + itemHeight + spacerY;
if(menu->menuItems[item]->highlight)
{
drawRect(itemX, itemY, itemWidth, itemHeight, YELLOW);
drawRect(itemX+1, itemY+1, itemWidth-2, itemHeight-2, YELLOW);
drawRect(itemX+2, itemY+2, itemWidth-4, itemHeight-4, YELLOW);
}
}
}
if(menu->itemCount == 4)
{
int spacerY = itemHeight >> 1;
//First item x position is half the width of the item subtracted from the center position. Ensures item is centered in bounding box
int itemX = menuX - (itemWidth >> 1);
//Same premise for an item's y position, except two items up
int itemY = menuY - 2*itemHeight - 2*spacerY;
for(int item = 0; item < menu->itemCount; item++)
{
fillRect(itemX, itemY, itemWidth, itemHeight, menu->itemColor);
float scale = (-.02)*(menu->menuItems[item]->stringLen) + .46;
setCursor(itemX+(int)(scale * itemWidth), itemY+10);
setTextColor(menu->textColor);
setTextSize(2);
writeString(menu->menuItems[item]->text);
if(menu->menuItems[item]->highlight)
{
drawRect(itemX, itemY, itemWidth, itemHeight, YELLOW);
drawRect(itemX+1, itemY+1, itemWidth-2, itemHeight-2, YELLOW);
drawRect(itemX+2, itemY+2, itemWidth-4, itemHeight-4, YELLOW);
}
itemY = itemY + itemHeight + spacerY;
}
}
//Draw boxes and text for each menu item
}
//Clears menu by drawing a bg color box around the menu's bounding box
void clearMenu(menu_t *menu, enum colors bg)
{
int menuX = menu->center[0];
int menuY = menu->center[1];
int topLeftX = menuX - (menu->bound[0] >> 1);
int topLeftY = menuY - (menu->bound[1] >> 1);
fillRect(topLeftX, topLeftY, menu->bound[0], menu->bound[1], bg);
}