diff --git a/include/notcurses/notcurses.h b/include/notcurses/notcurses.h index 30db3c115..3de1814b3 100644 --- a/include/notcurses/notcurses.h +++ b/include/notcurses/notcurses.h @@ -2276,6 +2276,12 @@ API bool ncselector_offer_input(struct ncselector* n, const struct ncinput* nc); // be strdup()ed and assigned to '*item' (and must be free()d by the caller). API void ncselector_destroy(struct ncselector* n, char** item); +struct mselector_item { + char* option; + char* desc; + bool selected; +}; + // multiselection widget -- a selector supporting multiple selections. // // ╭────────────────────────────────────────────────────────────────╮ @@ -2301,7 +2307,7 @@ typedef struct multiselector_options { char* title; // title may be NULL, inhibiting riser, saving two rows. char* secondary; // secondary may be NULL char* footer; // footer may be NULL - struct selector_item* items; // initial items and descriptions + struct mselector_item* items; // initial items, descriptions, and statuses unsigned itemcount; // number of items and descriptions, can't be 0 // maximum number of options to display at once, 0 to use all available space unsigned maxdisplay; diff --git a/src/lib/internal.h b/src/lib/internal.h index d4990d9f1..076b5ff02 100644 --- a/src/lib/internal.h +++ b/src/lib/internal.h @@ -188,7 +188,7 @@ typedef struct ncmultiselector { unsigned startdisp; // index of first option displayed unsigned maxdisplay; // max number of items to display, 0 -> no limit int longitem; // columns occupied by longest item - struct selector_item* items; // list of items and descriptions, heap-copied + struct mselector_item* items;// items, descriptions, and statuses, heap-copied unsigned itemcount; // number of pairs in 'items' char* title; // can be NULL, in which case there's no riser int titlecols; // columns occupied by title diff --git a/src/lib/selector.c b/src/lib/selector.c index 607bf1e66..b764d0511 100644 --- a/src/lib/selector.c +++ b/src/lib/selector.c @@ -491,7 +491,7 @@ ncmultiselector_draw(ncmultiselector* n){ if(printidx == n->current){ n->ncp->channels = (uint64_t)channels_bchannel(n->descchannels) << 32u | channels_fchannel(n->descchannels); } - ncplane_putegc_yx(n->ncp, yoff, bodyoffset, "☐", NULL); + ncplane_putegc_yx(n->ncp, yoff, bodyoffset, n->items[printidx].selected ? "☒" : "☐", NULL); n->ncp->channels = n->opchannels; if(printidx == n->current){ n->ncp->channels = (uint64_t)channels_bchannel(n->opchannels) << 32u | channels_fchannel(n->opchannels); @@ -563,8 +563,11 @@ const char* ncmultiselector_nextitem(ncmultiselector* n){ } bool ncmultiselector_offer_input(ncmultiselector* n, const ncinput* nc){ - // FIXME handle space to toggle selection - if(nc->id == NCKEY_UP){ + if(nc->id == ' '){ + n->items[n->current].selected = !n->items[n->current].selected; + ncmultiselector_draw(n); + return true; + }else if(nc->id == NCKEY_UP){ ncmultiselector_previtem(n); return true; }else if(nc->id == NCKEY_DOWN){ @@ -671,19 +674,18 @@ ncmultiselector* ncmultiselector_create(ncplane* n, int y, int x, const multisel ns->items = NULL; } for(ns->itemcount = 0 ; ns->itemcount < opts->itemcount ; ++ns->itemcount){ - const struct selector_item* src = &opts->items[ns->itemcount]; + const struct mselector_item* src = &opts->items[ns->itemcount]; int cols = mbswidth(src->option); - ns->items[ns->itemcount].opcolumns = cols; if(cols > ns->longitem){ ns->longitem = cols; } int cols2 = mbswidth(src->desc); - ns->items[ns->itemcount].desccolumns = cols2; if(cols + cols2 > ns->longitem){ ns->longitem = cols + cols2; } ns->items[ns->itemcount].option = strdup(src->option); ns->items[ns->itemcount].desc = strdup(src->desc); + ns->items[ns->itemcount].selected = src->selected; if(!(ns->items[ns->itemcount].desc && ns->items[ns->itemcount].option)){ free(ns->items[ns->itemcount].option); free(ns->items[ns->itemcount].desc); diff --git a/src/poc/multiselect.c b/src/poc/multiselect.c index 61be0b7a4..ecf4be8d9 100644 --- a/src/poc/multiselect.c +++ b/src/poc/multiselect.c @@ -5,18 +5,18 @@ #include // http://theboomerbible.com/tbb112.html -static struct selector_item items[] = { - { "1", "Across the Atlantic Ocean, there was a place called North America", }, - { "2", "Discovered by an Italian in the employ of the queen of Spain", }, - { "3", "Colonized extensively by the Spanish and the French", }, - { "4", "Developed into a rich nation by Dutch-supplied African slaves", }, - { "5", "And thus became the largest English-speaking nation on earth", }, - { "6", "Namely, the United States of America", }, - { "7", "The inhabitants of the United States called themselves Yankees", }, - { "8", "For some reason", }, - { "9", "And, eventually noticing the rest of the world was there,", }, - { "10", "Decided to rule it.", }, - { "11", "This is their story.", }, +static struct mselector_item items[] = { + { "1", "Across the Atlantic Ocean, there was a place called North America", .selected = false, }, + { "2", "Discovered by an Italian in the employ of the queen of Spain", .selected = false, }, + { "3", "Colonized extensively by the Spanish and the French", .selected = false, }, + { "4", "Developed into a rich nation by Dutch-supplied African slaves", .selected = false, }, + { "5", "And thus became the largest English-speaking nation on earth", .selected = false, }, + { "6", "Namely, the United States of America", .selected = false, }, + { "7", "The inhabitants of the United States called themselves Yankees", .selected = false, }, + { "8", "For some reason", .selected = false, }, + { "9", "And, eventually noticing the rest of the world was there,", .selected = false, }, + { "10", "Decided to rule it.", .selected = false, }, + { "11", "This is their story.", .selected = false, }, }; static void