ncmenu: calculate height based off sections #179

pull/319/head
nick black 5 years ago committed by Nick Black
parent aea6cdab08
commit db53b36d94

@ -13,21 +13,23 @@ notcurses_menu - operations on menus
```c ```c
struct ncmenu; struct ncmenu;
typedef struct menu_options { struct ncmenu_section {
bool bottom; // on the bottom row, as opposed to top row char* name; // utf-8 c string
bool hiding; // hide the menu when not being used struct ncmenu_item {
struct { char* desc; // utf-8 menu item, NULL for horizontal separator
char* name; // utf-8 c string ncinput shortcut; // shortcut, all should be distinct
struct { }* items;
char* desc; // utf-8 menu item, NULL for separator int itemcount;
ncinput shortcut; // shortcut, all should be distinct };
}* items;
int itemcount; typedef struct ncmenu_options {
}* sections; // array of menu sections bool bottom; // on the bottom row, as opposed to top row
int sectioncount; // must be positive bool hiding; // hide the menu when not being used
struct ncmenu_section* sections; // array of 'sectioncount' menu_sections
int sectioncount; // must be positive
uint64_t headerchannels; // styling for header uint64_t headerchannels; // styling for header
uint64_t sectionchannels; // styling for sections uint64_t sectionchannels; // styling for sections
} menu_options; } ncmenu_options;
``` ```
**struct ncmenu* ncmenu_create(struct notcurses* nc, const menu_options* opts);** **struct ncmenu* ncmenu_create(struct notcurses* nc, const menu_options* opts);**

@ -126,6 +126,7 @@ typedef struct renderstate {
typedef struct ncmenu { typedef struct ncmenu {
ncplane* ncp; ncplane* ncp;
struct ncmenu_section* sections; struct ncmenu_section* sections;
bool bottom; // are we on the bottom (vs top)?
int sectioncount; // must be positive int sectioncount; // must be positive
int unrolledsection; // currently unrolled section, -1 if none int unrolledsection; // currently unrolled section, -1 if none
int headerwidth; // minimum space necessary to display all sections int headerwidth; // minimum space necessary to display all sections

@ -38,7 +38,7 @@ dup_menu_section(struct ncmenu_section* dst, const struct ncmenu_section* src){
// Duplicates all menu sections in opts, adding their length to '*totalwidth'. // Duplicates all menu sections in opts, adding their length to '*totalwidth'.
static int static int
dup_menu_items(ncmenu* ncm, const ncmenu_options* opts, int* totalwidth){ dup_menu_items(ncmenu* ncm, const ncmenu_options* opts, int* totalwidth, int* totalheight){
ncm->sections = NULL; ncm->sections = NULL;
if((ncm->sectioncount = opts->sectioncount) == 0){ if((ncm->sectioncount = opts->sectioncount) == 0){
++*totalwidth; // one character margin on right ++*totalwidth; // one character margin on right
@ -48,6 +48,7 @@ dup_menu_items(ncmenu* ncm, const ncmenu_options* opts, int* totalwidth){
if(ncm->sections == NULL){ if(ncm->sections == NULL){
return -1; return -1;
} }
int maxheight = 0;
for(int i = 0 ; i < opts->sectioncount ; ++i){ for(int i = 0 ; i < opts->sectioncount ; ++i){
int cols = mbswidth(opts->sections[i].name); int cols = mbswidth(opts->sections[i].name);
if(cols < 0 || (ncm->sections[i].name = strdup(opts->sections[i].name)) == NULL){ if(cols < 0 || (ncm->sections[i].name = strdup(opts->sections[i].name)) == NULL){
@ -63,7 +64,11 @@ dup_menu_items(ncmenu* ncm, const ncmenu_options* opts, int* totalwidth){
} }
return -1; return -1;
} }
if(ncm->sections[i].itemcount > maxheight){
maxheight = ncm->sections[i].itemcount;
}
} }
*totalheight += maxheight + 2; // two rows of border
return 0; return 0;
} }
@ -71,9 +76,11 @@ static int
write_header(ncmenu* ncm){ write_header(ncmenu* ncm){
ncm->ncp->channels = ncm->headerchannels; ncm->ncp->channels = ncm->headerchannels;
ncplane_set_base(ncm->ncp, ncm->headerchannels, 0, " "); ncplane_set_base(ncm->ncp, ncm->headerchannels, 0, " ");
int dimy = ncplane_dim_y(ncm->ncp);
int xoff = 1; // 1 character margin on left int xoff = 1; // 1 character margin on left
int ypos = ncm->bottom ? dimy - 1 : 0;
for(int i = 0 ; i < ncm->sectioncount ; ++i){ for(int i = 0 ; i < ncm->sectioncount ; ++i){
if(ncplane_putstr_yx(ncm->ncp, 0, xoff, ncm->sections[i].name) < 0){ if(ncplane_putstr_yx(ncm->ncp, ypos, xoff, ncm->sections[i].name) < 0){
return -1; return -1;
} }
xoff += mbswidth(ncm->sections[i].name) + 2; xoff += mbswidth(ncm->sections[i].name) + 2;
@ -97,14 +104,15 @@ ncmenu* ncmenu_create(notcurses* nc, const ncmenu_options* opts){
ret->sections = NULL; ret->sections = NULL;
int dimy, dimx; int dimy, dimx;
ncplane_dim_yx(notcurses_stdplane(nc), &dimy, &dimx); ncplane_dim_yx(notcurses_stdplane(nc), &dimy, &dimx);
int ypos = opts->bottom ? dimy - 1 : 0;
if(ret){ if(ret){
ret->bottom = opts->bottom;
// FIXME maximum width could be more than section headers, due to items! // FIXME maximum width could be more than section headers, due to items!
if(dup_menu_items(ret, opts, &totalwidth) == 0){ if(dup_menu_items(ret, opts, &totalwidth, &totalheight) == 0){
ret->headerwidth = totalwidth; ret->headerwidth = totalwidth;
if(totalwidth < dimx){ if(totalwidth < dimx){
totalwidth = dimx; totalwidth = dimx;
} }
int ypos = opts->bottom ? dimy - totalheight : 0;
ret->ncp = ncplane_new(nc, totalheight, totalwidth, ypos, 0, NULL); ret->ncp = ncplane_new(nc, totalheight, totalwidth, ypos, 0, NULL);
if(ret->ncp){ if(ret->ncp){
ret->unrolledsection = -1; ret->unrolledsection = -1;
@ -124,9 +132,10 @@ int ncmenu_unroll(ncmenu* n, int sectionidx){
if(sectionidx < 0 || sectionidx >= n->sectioncount){ if(sectionidx < 0 || sectionidx >= n->sectioncount){
return -1; return -1;
} }
if(ncmenu_rollup(n)){ // roll up any unroled section if(ncmenu_rollup(n)){ // roll up any unrolled section
return -1; return -1;
} }
n->unrolledsection = sectionidx;
// FIXME // FIXME
return 0; return 0;
} }

@ -10,8 +10,15 @@ run_menu(struct notcurses* nc, struct ncmenu* ncm){
ncinput ni; ncinput ni;
notcurses_render(nc); notcurses_render(nc);
while((keypress = notcurses_getc_blocking(nc, &ni)) != (char32_t)-1){ while((keypress = notcurses_getc_blocking(nc, &ni)) != (char32_t)-1){
switch(keypress){ if(ni.alt){
// FIXME switch(keypress){
case 'd': case 'D':
ncmenu_unroll(ncm, 0);
break;
case 'f': case 'F':
ncmenu_unroll(ncm, 1);
break;
}
} }
if(keypress == 'q'){ if(keypress == 'q'){
ncmenu_destroy(ncm); ncmenu_destroy(ncm);
@ -54,7 +61,7 @@ int main(void){
mopts.sections = sections; mopts.sections = sections;
mopts.sectioncount = sizeof(sections) / sizeof(*sections); mopts.sectioncount = sizeof(sections) / sizeof(*sections);
channels_set_fg(&mopts.headerchannels, 0x00ff00); channels_set_fg(&mopts.headerchannels, 0x00ff00);
channels_set_bg(&mopts.headerchannels, 0x880000); channels_set_bg(&mopts.headerchannels, 0x440000);
struct ncmenu* top = ncmenu_create(nc, &mopts); struct ncmenu* top = ncmenu_create(nc, &mopts);
notcurses_render(nc); notcurses_render(nc);

Loading…
Cancel
Save