Menu system wip.

This commit is contained in:
Niels Sonnich Poulsen 2023-01-24 22:29:26 +01:00
parent 4c3c30b6cb
commit 327a7e577d
3 changed files with 201 additions and 4 deletions

View file

@ -25,4 +25,4 @@ install(TARGETS csol DESTINATION bin COMPONENT binaries)
install(FILES "${CMAKE_BINARY_DIR}/csolrc" DESTINATION /etc/xdg/csol COMPONENT config) install(FILES "${CMAKE_BINARY_DIR}/csolrc" DESTINATION /etc/xdg/csol COMPONENT config)
install(DIRECTORY "${CMAKE_BINARY_DIR}/themes" DESTINATION /etc/xdg/csol COMPONENT config) install(DIRECTORY "${CMAKE_BINARY_DIR}/themes" DESTINATION /etc/xdg/csol COMPONENT config)
install(DIRECTORY "${CMAKE_BINARY_DIR}/games" DESTINATION /etc/xdg/csol COMPONENT config) install(DIRECTORY "${CMAKE_BINARY_DIR}/games" DESTINATION /etc/xdg/csol COMPONENT config)
install(FILES "${CMAKE_BINARY_DIR}/doc/csol.6" DESTINATION ${CMAKE_INSTALL_PREFIX}/man/man6) install(FILES "${PROJECT_SOURCE_DIR}/doc/csol.6" DESTINATION ${CMAKE_INSTALL_PREFIX}/share/man/man6)

View file

@ -31,6 +31,9 @@ struct color {
short red; short red;
short green; short green;
short blue; short blue;
short old_red;
short old_green;
short old_blue;
}; };
struct color_pair { struct color_pair {

200
src/ui.c
View file

@ -99,6 +99,58 @@ struct color_name default_colors[] = {
{NULL, -1} {NULL, -1}
}; };
typedef struct Menu Menu;
struct Menu {
char *label;
char *key;
Menu *submenu;
};
Menu file_menu[] = {
{"Select &game", NULL, NULL},
{"Select &theme", NULL, NULL},
{"&Quit", "q", NULL},
{NULL, NULL, NULL}
};
Menu game_menu[] = {
{"&Undo", "u", NULL},
{"&Redo", "U", NULL},
{"&Auto", "a", NULL},
{"From &Stock", "s", NULL},
{"From &Waste", "w", NULL},
{"R&estart", "r", NULL},
{NULL, NULL, NULL}
};
Menu settings_menu[] = {
{"Smart &cursor", "^S", NULL},
{"&Vertical stabilization", "^V", NULL},
{"Show &score", "", NULL},
{"Show &menubar", "", NULL},
{NULL, NULL, NULL}
};
Menu help_menu[] = {
{"&How to play", "?", NULL},
{"&About csol", "", NULL},
{NULL, NULL, NULL}
};
Menu main_menu[] = {
{"&File", NULL, file_menu},
{"&Game", NULL, game_menu},
{"&Settings", NULL, settings_menu},
{"&Help", NULL, help_menu},
{NULL, NULL, NULL}
};
Menu *menu_selection[] = {
NULL,
NULL
};
static void print_card_name_l(int y, int x, Card *card, Theme *theme) { static void print_card_name_l(int y, int x, Card *card, Theme *theme) {
if (y < 0 || y >= win_h) { if (y < 0 || y >= win_h) {
return; return;
@ -519,7 +571,78 @@ static int ui_victory(Pile *piles, Theme *theme, int32_t score, int32_t time, St
} }
} }
static void print_menu_label(const char *label) {
while (*label) {
if (*label == '&') {
label++;
attron(A_BOLD);
if (*label) {
printw("%c", *label);
label++;
}
attroff(A_BOLD);
} else {
printw("%c", *label);
label++;
}
}
}
static void ui_menu(int y, int x, Menu *menu, Menu **selection) {
Menu *item;
int max_length = 0;
int height = 0;
for (item = menu; item->label; item++) {
int length = strlen(item->label);
if (item->key) {
length += 2 + strlen(item->key);
}
if (length > max_length) {
max_length = length;
}
height++;
}
ui_box(y++, x, height + 2, max_length + 4, 1);
for (item = menu; item->label; item++) {
if (item == *selection) {
attron(A_REVERSE);
}
mvprintw(y, x + 1, " %*s ", max_length, item->key ? item-> key : "");
move(y, x + 2);
print_menu_label(item->label);
if (item == *selection) {
attroff(A_REVERSE);
}
y++;
}
}
static void ui_menubar() {
Menu *item;
move(0, 0);
for (item = main_menu; item->label; item++) {
if (item == menu_selection[0]) {
int x1 = getcurx(stdscr), x2;
attron(A_REVERSE);
printw(" ");
print_menu_label(item->label);
printw(" ");
attroff(A_REVERSE);
x2 = getcurx(stdscr);
if (item->submenu) {
ui_menu(1, x1, item->submenu, &menu_selection[1]);
}
move(0, x2);
} else {
printw(" ");
print_menu_label(item->label);
printw(" ");
}
}
}
static int ui_loop(Game *game, Theme *theme, Pile *piles) { static int ui_loop(Game *game, Theme *theme, Pile *piles) {
Menu *menu_item;
MEVENT mouse; MEVENT mouse;
int new_game = 1; int new_game = 1;
int move_made = 0; int move_made = 0;
@ -563,6 +686,7 @@ static int ui_loop(Game *game, Theme *theme, Pile *piles) {
print_pile(pile, theme); print_pile(pile, theme);
} }
attron(COLOR_PAIR(COLOR_PAIR_BACKGROUND)); attron(COLOR_PAIR(COLOR_PAIR_BACKGROUND));
ui_menubar();
if (show_score) { if (show_score) {
mvprintw(win_h - 1, 0, "Score: %d", game_score); mvprintw(win_h - 1, 0, "Score: %d", game_score);
} }
@ -642,6 +766,51 @@ static int ui_loop(Game *game, Theme *theme, Pile *piles) {
} else { } else {
ch = getch(); ch = getch();
} }
if (menu_selection[0]) {
switch (ch) {
case KEY_LEFT:
if (menu_selection[0] > main_menu) {
menu_selection[0]--;
} else {
for (menu_item = main_menu; menu_item->label; menu_item++) {
menu_selection[0] = menu_item;
}
}
menu_selection[1] = NULL;
break;
case KEY_RIGHT:
menu_selection[0]++;
if (!menu_selection[0]->label) {
menu_selection[0] = main_menu;
}
menu_selection[1] = NULL;
break;
case KEY_UP:
if (menu_selection[1] && menu_selection[1] > menu_selection[0]->submenu) {
menu_selection[1]--;
} else if (menu_selection[0]->submenu) {
for (menu_item = menu_selection[0]->submenu; menu_item->label; menu_item++) {
menu_selection[1] = menu_item;
}
}
break;
case KEY_DOWN:
if (menu_selection[1]) {
menu_selection[1]++;
if (!menu_selection[1]->label) {
menu_selection[1] = menu_selection[0]->submenu;
}
} else {
menu_selection[1] = menu_selection[0]->submenu;
}
break;
case 27:
menu_selection[0] = NULL;
menu_selection[1] = NULL;
break;
}
continue;
}
switch (ch) { switch (ch) {
case 'h': case 'h':
case KEY_LEFT: case KEY_LEFT:
@ -960,10 +1129,29 @@ static int ui_loop(Game *game, Theme *theme, Pile *piles) {
redo_move(); redo_move();
clear(); clear();
break; break;
case KEY_F(10):
menu_selection[0] = main_menu;
break;
case 27: case 27:
clear();
selection = NULL; selection = NULL;
selection_pile = NULL; selection_pile = NULL;
ch = getch();
for (menu_item = main_menu; menu_item->label; menu_item++) {
char *l = menu_item->label;
while (*l) {
if (*l == '&') {
if (tolower(l[1]) == ch) {
menu_selection[0] = menu_item;
}
break;
}
l++;
}
if (menu_selection[0]) {
break;
}
}
clear();
break; break;
case 19: /* ^s */ case 19: /* ^s */
smart_cursor = !smart_cursor; smart_cursor = !smart_cursor;
@ -1218,6 +1406,7 @@ static void convert_theme(Theme *theme) {
#endif #endif
void ui_main(Game *game, Theme *theme, int enable_color, unsigned int seed) { void ui_main(Game *game, Theme *theme, int enable_color, unsigned int seed) {
Color *color;
#ifdef USE_PDCURSES #ifdef USE_PDCURSES
if (theme->utf8) { if (theme->utf8) {
printf("Converting UTF8 theme\n"); printf("Converting UTF8 theme\n");
@ -1228,10 +1417,10 @@ void ui_main(Game *game, Theme *theme, int enable_color, unsigned int seed) {
initscr(); initscr();
if (enable_color) { if (enable_color) {
short index = 15; short index = 15;
Color *color;
start_color(); start_color();
for (color = theme->colors; color; color = color->next) { for (color = theme->colors; color; color = color->next) {
short color_index = color->name ? ++index : color->index; short color_index = color->name ? ++index : color->index;
color_content(color_index, &color->old_red, &color->old_green, &color->old_blue);
if (init_color(color_index, color->red, color->green, color->blue) == 0) { if (init_color(color_index, color->red, color->green, color->blue) == 0) {
color->index = color_index; color->index = color_index;
} else { } else {
@ -1274,7 +1463,12 @@ void ui_main(Game *game, Theme *theme, int enable_color, unsigned int seed) {
break; break;
} }
} }
/* Restore palette colors to their previous values */
for (color = theme->colors; color; color = color->next) {
if (color->index) {
init_color(color->index, color->old_red, color->old_green, color->old_blue);
}
}
endwin(); endwin();
} }