X-Git-Url: https://git.danieliu.xyz/?p=taskasaur.git;a=blobdiff_plain;f=menu.c;h=816b5ddcf6c3c8e4705674566952b739b8f742f7;hp=e9071d6d805dc10679b5cba4d5f58515ee03f382;hb=HEAD;hpb=b1a5da51ad170de714ed6b0b7a566f867cde6c16 diff --git a/menu.c b/menu.c index e9071d6..816b5dd 100644 --- a/menu.c +++ b/menu.c @@ -10,7 +10,7 @@ #include "headers/utils.h" #define MENU_PAD_TOP 2 -#define MENU_PAD_BOTTOM 1 +#define MENU_PAD_BOTTOM 2 #define MENU_PAD_LEFT 2 #define MENU_PAD_RIGHT 1 @@ -19,6 +19,7 @@ typedef struct MenuItem { char* title; char* description; + void* userdata; } MenuItem; typedef struct Menu { @@ -29,9 +30,11 @@ typedef struct Menu { int scroll_offset; bool focused; WINDOW* menu_win; - WINDOW* sub_win; int max_height; int max_width; + void* userdata; + void (*render_item)(Menu*, int, int); + int (*item_height)(MenuItem*); } Menu; int swap_item(Menu* menu, int src_index, int dest_index); @@ -42,16 +45,31 @@ int menu_insert_mode(Menu* menu, int insert_index); /* prob temp for now */ MenuItem* create_blank_menuitem(void); +/* rendering stuff */ +void default_render_item(Menu* menu, int item_index, int start_y); +int default_item_height(MenuItem* menuitem); +int items_visible(Menu* menu, int offset); +int items_visible_rev(Menu* menu, int offset); MenuItem* create_menuitem(char* title) { MenuItem* new_menuitem; + TodoItem* new_userdata; new_menuitem = malloc(sizeof(MenuItem)); new_menuitem->title = title; new_menuitem->description = strdup(""); //TEMP FOR NOW + new_userdata = malloc(sizeof(TodoItem)); + new_userdata->item_name = title; + new_userdata->description = strdup(""); + new_userdata->due = strdup(""); + new_userdata->subtask_list = malloc(0); + new_userdata->subtask_count = 0; + + new_menuitem->userdata = new_userdata; + return new_menuitem; } @@ -73,6 +91,9 @@ create_menu(char* menu_name, MenuItem** item_list) new_menu->selected_item = 0; new_menu->scroll_offset = 0; new_menu->focused = false; + new_menu->userdata = NULL; + new_menu->render_item = *default_render_item; + new_menu->item_height = *default_item_height; set_menu_win(new_menu, stdscr); return new_menu; @@ -85,12 +106,6 @@ get_menu_win(Menu* menu) return menu->menu_win; } -WINDOW* -get_menu_subwin(Menu* menu) -{ - return menu->sub_win; -} - MenuItem* get_menu_item(Menu* menu, int index) { @@ -99,12 +114,30 @@ get_menu_item(Menu* menu, int index) return menu->menu_items[index]; } +MenuItem** +get_menu_itemlist(Menu* menu) +{ + return menu->menu_items; +} + int get_selected_item(Menu* menu) { return menu->selected_item; } +MenuItem* +get_selected_menuitem(Menu* menu) +{ + return get_menu_item(menu, get_selected_item(menu)); +} + +bool +get_menu_focused(Menu* menu) +{ + return menu->focused; +} + int get_menu_length(Menu* menu) { @@ -117,6 +150,12 @@ get_menu_name(Menu* menu) return menu->menu_name; } +void* +get_menu_userdata(Menu* menu) +{ + return menu->userdata; +} + char* get_menuitem_title(MenuItem* menuitem) { @@ -129,6 +168,12 @@ get_menuitem_descrip(MenuItem* menuitem) return menuitem->description; } +void* +get_menuitem_userdata(MenuItem* menuitem) +{ + return menuitem->userdata; +} + /* setters */ int @@ -139,16 +184,8 @@ set_menu_win(Menu* menu, WINDOW* win) menu->menu_win = win; getmaxyx(menu->menu_win, height, width); - /* create a subwin (also prob free old subwin?) */ menu->max_height = height-MENU_PAD_TOP-MENU_PAD_BOTTOM; menu->max_width = width-MENU_PAD_LEFT-MENU_PAD_RIGHT; - menu->sub_win = derwin( - menu->menu_win, - menu->max_height, - menu->max_width, - MENU_PAD_TOP, - MENU_PAD_LEFT - ); return 0; } @@ -157,7 +194,6 @@ int set_selected_item(Menu* menu, int selected_item) { menu->selected_item = selected_item; - return 0; } @@ -165,7 +201,48 @@ int set_menu_focus(Menu* menu, bool focus) { menu->focused = focus; - + return 0; +} + +int +set_menu_userdata(Menu* menu, void* userdata) +{ + menu->userdata = userdata; + return 0; +} + +int +set_menu_renderitem(Menu* menu, void (*render_item)(Menu*, int, int)) +{ + menu->render_item = render_item; + return 0; +} + +int +set_menu_itemheight(Menu* menu, int (*item_height)(MenuItem*)) +{ + menu->item_height = item_height; + return 0; +} + +int +set_menuitem_title(MenuItem* menuitem, char* title) +{ + menuitem->title = title; + return 0; +} + +int +set_menuitem_descrip(MenuItem* menuitem, char* descrip) +{ + menuitem->description = descrip; + return 0; +} + +int +set_menuitem_userdata(MenuItem* menuitem, void* userdata) +{ + menuitem->userdata = userdata; return 0; } @@ -197,8 +274,6 @@ delete_item(Menu* menu, int index) menu->selected_item = menu->menu_length-1; } - wclear(menu->sub_win); - return 0; } @@ -228,17 +303,20 @@ menu_insert_mode(Menu* menu, int insert_index) { char temp[MAX_CONTENTS_LENGTH+1]; // remember null char* new_contents; - - /* this is bad */ - wclear(menu->sub_win); - render_menu(menu); + int insert_pos; curs_on(); + // account for multiline items + insert_pos = menu->scroll_offset; + for (int i = 0; i < insert_index; i++) { + insert_pos += menu->item_height(menu->menu_items[i]); + } + /* move cursor to right spot */ ungetstr(menu->menu_items[insert_index]->title); - mvwgetnstr(menu->sub_win, - insert_index, // account for wrap later too + mvwgetnstr(menu->menu_win, + insert_pos, 0, temp, MAX_CONTENTS_LENGTH @@ -296,16 +374,19 @@ menu_driver(Menu* menu, MenuAction action) case MENU_APPEND: insert_item(menu, create_blank_menuitem(), menu->menu_length); + render_menu(menu); // refresh after inserting menu_insert_mode(menu, menu->selected_item); break; case MENU_INSERT_ABOVE: insert_item(menu, create_blank_menuitem(), menu->selected_item); + render_menu(menu); menu_insert_mode(menu, menu->selected_item); break; case MENU_INSERT_BELOW: insert_item(menu, create_blank_menuitem(), menu->selected_item+1); + render_menu(menu); menu_insert_mode(menu, menu->selected_item); // inserted item is cur now break; @@ -323,48 +404,102 @@ menu_driver(Menu* menu, MenuAction action) int render_menu(Menu* menu) { - /* draw outer menu (prob dont need this every render) */ - int menu_header_color; + wclear(menu->menu_win); + + /* calculate scroll */ + int visible; + + visible = items_visible(menu, menu->scroll_offset); + + if (menu->selected_item >= menu->scroll_offset+visible) { + menu->scroll_offset = clamp( + menu->selected_item-items_visible_rev(menu, menu->selected_item)+1, + 0, + floorzero(menu->menu_length-1) + ); + + } else if (menu->selected_item < menu->scroll_offset) { + menu->scroll_offset = clamp( + menu->selected_item, + 0, + floorzero(menu->menu_length-1) + ); + } - /* menu_header_color = */ - wattron(menu->menu_win, COLOR_PAIR( - (menu->focused == true) ? - TS_MENU_SELECTED: TS_MENU_NONSELECTED - )); - mvwprintw(menu->menu_win, 0, MENU_PAD_LEFT, menu->menu_name); - wattroff(menu->menu_win, COLOR_PAIR(0)); + /* render menu items */ + int curline = 0; + for (int i = menu->scroll_offset; i < menu->menu_length; i++) { + menu->render_item(menu, i, curline); + curline += menu->item_height(menu->menu_items[i]); + } - /* draw inner menu */ - int cur_line = 0; - for (int i = 0; i < menu->menu_length-menu->scroll_offset; i++) { + wrefresh(menu->menu_win); - int wrapped_lines; - char* wrapped_text; - - /* wrap text by inserting newlines (maxwidth-1 for newline char)*/ - wrapped_text = wrap_text(menu->menu_items[i]->title, menu->max_width-1, &wrapped_lines); + return 0; +} - /* color selected item */ - wattron(menu->sub_win, COLOR_PAIR( - (i == menu->selected_item && menu->focused == true) ? - TS_SELECTED : TS_NONSELECTED - )); - mvwprintw(menu->sub_win, cur_line, 0, wrapped_text); - wattroff(menu->sub_win, COLOR_PAIR(0)); +void +default_render_item(Menu* menu, int item_index, int start_y) +{ + MenuItem* curitem; + int hlcolor; - cur_line += wrapped_lines; + curitem = menu->menu_items[item_index]; + + /* color selected item */ + hlcolor = COLOR_PAIR((item_index == menu->selected_item && menu->focused == true) ? TS_SELECTED : TS_NONSELECTED); + wattron(menu->menu_win, hlcolor); + mvwprintw(menu->menu_win, start_y, 0, curitem->title); + wattroff(menu->menu_win, hlcolor); +} - /* display number of items */ - /* if (menu->menu_items[i]->) */ - free(wrapped_text); +int +default_item_height(MenuItem* menuitem) +{ + return 1; // maybe account for line wrap by default +} + +int +items_visible(Menu* menu, int offset) +{ + int maxheight; + int maxwidth; // unused + + getmaxyx(menu->menu_win, maxheight, maxwidth); + + int vis = 0; + int lines = 0; + for (int i = offset ; i < menu->menu_length; i++) { + + lines += menu->item_height(menu->menu_items[i]); + if (lines > maxheight) break; + vis += 1; } - wrefresh(menu->sub_win); - wrefresh(menu->menu_win); + return vis; +} - return 0; +int +items_visible_rev(Menu* menu, int offset) +{ + int maxheight; + int maxwidth; // unused + + getmaxyx(menu->menu_win, maxheight, maxwidth); + + int vis = 0; + int lines = 0; + for (int i = offset; i > 0; i--) { + + lines += menu->item_height(menu->menu_items[i]); + if (lines > maxheight) break; + vis +=1; + + } + + return vis; } int