ncmenu: calculate height based off sections #179

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

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

@ -126,6 +126,7 @@ typedef struct renderstate {
typedef struct ncmenu {
ncplane* ncp;
struct ncmenu_section* sections;
bool bottom; // are we on the bottom (vs top)?
int sectioncount; // must be positive
int unrolledsection; // currently unrolled section, -1 if none
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'.
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;
if((ncm->sectioncount = opts->sectioncount) == 0){
++*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){
return -1;
}
int maxheight = 0;
for(int i = 0 ; i < opts->sectioncount ; ++i){
int cols = mbswidth(opts->sections[i].name);
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;
}
if(ncm->sections[i].itemcount > maxheight){
maxheight = ncm->sections[i].itemcount;
}
}
*totalheight += maxheight + 2; // two rows of border
return 0;
}
@ -71,9 +76,11 @@ static int
write_header(ncmenu* ncm){
ncm->ncp->channels = ncm->headerchannels;
ncplane_set_base(ncm->ncp, ncm->headerchannels, 0, " ");
int dimy = ncplane_dim_y(ncm->ncp);
int xoff = 1; // 1 character margin on left
int ypos = ncm->bottom ? dimy - 1 : 0;
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;
}
xoff += mbswidth(ncm->sections[i].name) + 2;
@ -97,14 +104,15 @@ ncmenu* ncmenu_create(notcurses* nc, const ncmenu_options* opts){
ret->sections = NULL;
int dimy, dimx;
ncplane_dim_yx(notcurses_stdplane(nc), &dimy, &dimx);
int ypos = opts->bottom ? dimy - 1 : 0;
if(ret){
ret->bottom = opts->bottom;
// 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;
if(totalwidth < dimx){
totalwidth = dimx;
}
int ypos = opts->bottom ? dimy - totalheight : 0;
ret->ncp = ncplane_new(nc, totalheight, totalwidth, ypos, 0, NULL);
if(ret->ncp){
ret->unrolledsection = -1;
@ -124,9 +132,10 @@ int ncmenu_unroll(ncmenu* n, int sectionidx){
if(sectionidx < 0 || sectionidx >= n->sectioncount){
return -1;
}
if(ncmenu_rollup(n)){ // roll up any unroled section
if(ncmenu_rollup(n)){ // roll up any unrolled section
return -1;
}
n->unrolledsection = sectionidx;
// FIXME
return 0;
}

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

Loading…
Cancel
Save