commit
99154516c3
109
menu.c
109
menu.c
@ -1,5 +1,6 @@
|
||||
#include "pch.h"
|
||||
#include "framework.h"
|
||||
|
||||
#include "menu.h"
|
||||
|
||||
const struct MenuBorder DEFAULT = {
|
||||
@ -18,6 +19,66 @@ const struct MenuBorder SOLID = {
|
||||
186, 205, 201, 187, 200, 188, '[', ']'
|
||||
};
|
||||
|
||||
void show_menu(const int itemc, const struct MenuItem itemv[], const char title[], const struct MenuBorder* border);
|
||||
|
||||
void page(const struct MenuPage* pages, const size_t page_count, const bool infinite_loop)
|
||||
{
|
||||
unsigned int page_index = 0;
|
||||
bool action_performed, loop, page_changed = true;
|
||||
char page_key, itemKey;
|
||||
int i;
|
||||
|
||||
do {
|
||||
do {
|
||||
show_menu(pages[page_index].item_count, pages[page_index].items, pages[page_index].title, pages[page_index].border);
|
||||
|
||||
// Wait for user selection
|
||||
putchar('>');
|
||||
putchar(' ');
|
||||
|
||||
loop = pages[page_index].loopback;
|
||||
page_key = _getch();
|
||||
|
||||
// Forward paging
|
||||
if (page_key == 'm' && page_index < page_count - 1)
|
||||
++page_index;
|
||||
// Backward paging
|
||||
else if (page_key == 'n' && page_index > 0)
|
||||
--page_index;
|
||||
else
|
||||
{
|
||||
page_changed = false;
|
||||
itemKey = page_key;
|
||||
do {
|
||||
action_performed = false;
|
||||
|
||||
itemKey != page_key ? itemKey = _getch() : page_key;
|
||||
page_key = 0;
|
||||
for (i = 0; i < pages[page_index].item_count; ++i)
|
||||
{
|
||||
if (pages[page_index].items[i].key == itemKey)
|
||||
{
|
||||
// Perform action
|
||||
system("cls");
|
||||
pages[page_index].items[i].action();
|
||||
action_performed = true;
|
||||
|
||||
// Pause if requested
|
||||
if (pages[page_index].pause)
|
||||
{
|
||||
putchar('\n');
|
||||
system("pause");
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (!action_performed);
|
||||
}
|
||||
} while (loop || page_changed);
|
||||
|
||||
page_index = 0;
|
||||
} while (infinite_loop);
|
||||
}
|
||||
|
||||
// Checks if a line index should display a menu item
|
||||
bool is_item_line(const int line, const int itemc, int* item_index)
|
||||
{
|
||||
@ -40,18 +101,17 @@ void get_console_dimensions(int* width, int* height)
|
||||
*height = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
|
||||
}
|
||||
|
||||
void show_menu(const int itemc, const struct MenuItem itemv[], const char title[], const bool loopback, const bool pause, const struct MenuBorder *border)
|
||||
// Draws a menu to the console
|
||||
void show_menu(const int itemc, const struct MenuItem itemv[], const char title[], const struct MenuBorder* border)
|
||||
{
|
||||
unsigned width, height, item_index;
|
||||
char key;
|
||||
bool action_performed;
|
||||
|
||||
// Clear the console window
|
||||
system("cls");
|
||||
|
||||
// Get the width and height of the console window
|
||||
get_console_dimensions(&width, &height);
|
||||
|
||||
|
||||
// Print frame with title
|
||||
for (unsigned i = 0; i < height - 1; ++i)
|
||||
{
|
||||
@ -63,13 +123,13 @@ void show_menu(const int itemc, const struct MenuItem itemv[], const char title[
|
||||
|
||||
for (unsigned j = 1; j < width - strlen(title) - 2; ++j)
|
||||
{
|
||||
if (j == ((width - strlen(title)) - 2)/ 2)
|
||||
if (j == ((width - strlen(title)) - 2) / 2)
|
||||
{
|
||||
putchar(border->title_left);
|
||||
fputs(title, stdout);
|
||||
putchar(border->title_right);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
putchar(border->line_horizontal);
|
||||
}
|
||||
@ -84,7 +144,7 @@ void show_menu(const int itemc, const struct MenuItem itemv[], const char title[
|
||||
// Print item text
|
||||
putchar(border->line_vertical);
|
||||
|
||||
if (strcmp(itemv[item_index].text, "BLANK") == 0) {
|
||||
if (strcmp(itemv[item_index].text, "BLANK") == 0) {
|
||||
putchar('\t');
|
||||
|
||||
// BLANK equals 5 characters
|
||||
@ -98,13 +158,13 @@ void show_menu(const int itemc, const struct MenuItem itemv[], const char title[
|
||||
{
|
||||
printf("\t%c) %s", itemv[item_index].key, itemv[item_index].text);
|
||||
}
|
||||
|
||||
|
||||
// Print right side of frame
|
||||
for (unsigned j = 0; j < width - strlen(itemv[item_index].text) - 12; ++j)
|
||||
{
|
||||
putchar(' ');
|
||||
}
|
||||
|
||||
|
||||
putchar(border->line_vertical);
|
||||
}
|
||||
// Line above bottom line
|
||||
@ -132,35 +192,4 @@ void show_menu(const int itemc, const struct MenuItem itemv[], const char title[
|
||||
i != height - 2 ? putchar(border->line_vertical) : putchar(' ');
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for user selection
|
||||
putchar('>');
|
||||
putchar(' ');
|
||||
action_performed = false;
|
||||
do {
|
||||
key = _getch();
|
||||
for (int i = 0; i < itemc; ++i)
|
||||
{
|
||||
if (itemv[i].key == key)
|
||||
{
|
||||
// Perform action
|
||||
system("cls");
|
||||
itemv[i].action();
|
||||
action_performed = true;
|
||||
|
||||
// Pause if requested
|
||||
if (pause)
|
||||
{
|
||||
putchar('\n');
|
||||
system("pause");
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (!action_performed);
|
||||
|
||||
// Show menu again if requested
|
||||
if (loopback)
|
||||
{
|
||||
show_menu(itemc, itemv, title, loopback, pause, border);
|
||||
}
|
||||
}
|
23
menu.h
23
menu.h
@ -21,13 +21,20 @@ struct MenuBorder {
|
||||
char title_right;
|
||||
};
|
||||
|
||||
// Default borders initialized in menu.c
|
||||
const extern struct MenuBorder DEFAULT, MODERN, NO_BORDER, SOLID;
|
||||
|
||||
/// <summary>Displaces a CUI menu to the user and lets them choose an option, then calls the corresponding function.</summary>
|
||||
/// <param name="itemc">The length of the array <c>itemv</c> of menu items.</param>
|
||||
/// <param name="itemv">An array of all menu items to display in the menu.</param>
|
||||
/// <param name="title">The title of the menu.</param>
|
||||
/// <param name="loopback">If this parameter is set to <c>true</c>, the menu will be displayed again after an action is executed.</param>
|
||||
/// <param name="pause">If this parameter is set to <c>true</c>, a <c>pause</c>command will be run after an action is executed.</param>
|
||||
/// <param name="border">Specifies the border in which the menu is displayed.</param>
|
||||
void show_menu(const int itemc, const struct MenuItem itemv[], const char title[], const bool loopback, const bool pause, const struct MenuBorder *border);
|
||||
/// <summary>Represents a page containing menu items inside a menu.</summary>
|
||||
struct MenuPage {
|
||||
const struct MenuItem* items;
|
||||
const size_t item_count;
|
||||
char* title;
|
||||
bool loopback, pause;
|
||||
const struct MenuBorder* border;
|
||||
};
|
||||
|
||||
/// <summary>Constructs a CUI menu with a specific amount of pages.</summary>
|
||||
/// <param name="pages">An array of all pages to display.</param>
|
||||
/// <param name="page_count">The length of the array <c>pages</c>.</param>
|
||||
/// <param name="infinite_loop">Always display the first page after a loopback=false item finished executing.</param>
|
||||
void page(const struct MenuPage* pages, const size_t page_count, const bool infinite_loop);
|
Reference in New Issue
Block a user