menu: extend across width of screen #179

pull/315/head
nick black 5 years ago
parent ad77933058
commit 31a07dab33
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.14)
project(notcurses VERSION 1.1.4
project(notcurses VERSION 1.1.5
DESCRIPTION "UI for modern terminal emulators"
HOMEPAGE_URL "https://nick-black.com/dankwiki/index.php/notcurses"
LANGUAGES C CXX)

@ -2210,28 +2210,28 @@ API void ncselector_destroy(struct ncselector* n, char** item);
// a screen resize, menus will be automatically moved/resized. Elements can be
// dynamically enabled or disabled at all levels (menu, section, and item),
struct menu_section {
struct ncmenu_section {
char* name; // utf-8 c string
struct menu_item {
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 menu_options {
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 menu_section* sections; // array of 'sectioncount' menu_sections
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;
// Create a menu with the specified options. Menus are currently bound to an
// overall notcurses object (as opposed to a particular plane), and are
// implemented as ncplanes kept atop other ncplanes.
API struct ncmenu* ncmenu_create(struct notcurses* nc, const menu_options* opts);
API struct ncmenu* ncmenu_create(struct notcurses* nc, const ncmenu_options* opts);
// Unroll the specified menu section, making the menu visible if it was
// invisible, and rolling up any menu section that is already unrolled.

@ -125,9 +125,10 @@ typedef struct renderstate {
typedef struct ncmenu {
ncplane* ncp;
struct menu_section* sections;
struct ncmenu_section* sections;
int sectioncount; // must be positive
int unrolledsection; // currently unrolled section, -1 if none
int headerwidth; // minimum space necessary to display all sections
uint64_t headerchannels; // styling for header
uint64_t sectionchannels; // styling for sections
} ncmenu;

@ -1,7 +1,7 @@
#include "internal.h"
static void
free_menu_section(struct menu_section* ms){
free_menu_section(struct ncmenu_section* ms){
for(int i = 0 ; i < ms->itemcount ; ++i){
free(ms->items[i].desc);
}
@ -18,7 +18,7 @@ free_menu_sections(ncmenu* ncm){
}
static int
dup_menu_section(struct menu_section* dst, const struct menu_section* src){
dup_menu_section(struct ncmenu_section* dst, const struct ncmenu_section* src){
dst->items = NULL;
if(src->itemcount){
dst->items = malloc(sizeof(*dst->items) * src->itemcount);
@ -38,7 +38,7 @@ dup_menu_section(struct menu_section* dst, const struct menu_section* src){
// Duplicates all menu sections in opts, adding their length to '*totalwidth'.
static int
dup_menu_items(ncmenu* ncm, const menu_options* opts, int* totalwidth){
dup_menu_items(ncmenu* ncm, const ncmenu_options* opts, int* totalwidth){
ncm->sections = NULL;
if((ncm->sectioncount = opts->sectioncount) == 0){
++*totalwidth; // one character margin on right
@ -76,12 +76,12 @@ write_header(ncmenu* ncm){
if(ncplane_putstr_yx(ncm->ncp, 0, xoff, ncm->sections[i].name) < 0){
return -1;
}
xoff += mbswidth(ncm->sections[i].name) + 1;
xoff += mbswidth(ncm->sections[i].name) + 2;
}
return 0;
}
ncmenu* ncmenu_create(notcurses* nc, const menu_options* opts){
ncmenu* ncmenu_create(notcurses* nc, const ncmenu_options* opts){
if(opts->sectioncount < 0){
return NULL;
}else if(opts->sectioncount == 0 && opts->sections){
@ -91,14 +91,20 @@ ncmenu* ncmenu_create(notcurses* nc, const menu_options* opts){
}
int totalheight = 1;
int totalwidth = 1; // start with one character margin on the left
// FIXME calaculate maximum dimensions
// FIXME calculate maximum dimensions
ncmenu* ret = malloc(sizeof(*ret));
ret->sectioncount = opts->sectioncount;
ret->sections = NULL;
int dimy = ncplane_dim_y(notcurses_stdplane(nc));
int dimy, dimx;
ncplane_dim_yx(notcurses_stdplane(nc), &dimy, &dimx);
int ypos = opts->bottom ? dimy - 1 : 0;
if(ret){
// FIXME maximum width could be more than section headers, due to items!
if(dup_menu_items(ret, opts, &totalwidth) == 0){
ret->headerwidth = totalwidth;
if(totalwidth < dimx){
totalwidth = dimx;
}
ret->ncp = ncplane_new(nc, totalheight, totalwidth, ypos, 0, NULL);
if(ret->ncp){
ret->unrolledsection = -1;

@ -33,35 +33,35 @@ int main(void){
if(nc == NULL){
return EXIT_FAILURE;
}
struct menu_item demo_items[] = {
struct ncmenu_item demo_items[] = {
{ .desc = "Restart", },
};
struct menu_item file_items[] = {
struct ncmenu_item file_items[] = {
{ .desc = "New", },
{ .desc = "Open", },
{ .desc = "Close", },
{ .desc = NULL, },
{ .desc = "Quit", },
};
struct menu_section sections[] = {
struct ncmenu_section sections[] = {
{ .name = "Demo", .items = demo_items, },
{ .name = "File", .items = file_items, },
};
sections[0].itemcount = sizeof(demo_items) / sizeof(*demo_items);
sections[1].itemcount = sizeof(file_items) / sizeof(*file_items);
menu_options mopts;
ncmenu_options mopts;
memset(&mopts, 0, sizeof(mopts));
mopts.sections = sections;
mopts.sectioncount = sizeof(sections) / sizeof(*sections);
channels_set_fg(&mopts.headerchannels, 0x000000);
channels_set_bg(&mopts.headerchannels, 0xff0000);
channels_set_fg(&mopts.headerchannels, 0x00ff00);
channels_set_bg(&mopts.headerchannels, 0x880000);
struct ncmenu* top = ncmenu_create(nc, &mopts);
notcurses_render(nc);
int dimy, dimx;
struct ncplane* n = notcurses_stdplane(nc);
ncplane_dim_yx(n, &dimy, &dimx);
ncplane_styles_on(n, NCSTYLE_REVERSE);
ncplane_set_fg(n, 0x00dddd);
if(ncplane_putstr_aligned(n, dimy - 1, NCALIGN_RIGHT, " -=+ menu poc. press q to exit +=- ") < 0){
return EXIT_FAILURE;
}
@ -70,7 +70,6 @@ int main(void){
ncplane_erase(n);
mopts.bottom = true;
struct ncmenu* bottom = ncmenu_create(nc, &mopts);
ncplane_styles_on(n, NCSTYLE_REVERSE);
if(ncplane_putstr_aligned(n, 0, NCALIGN_RIGHT, " -=+ menu poc. press q to exit +=- ") < 0){
return EXIT_FAILURE;
}

@ -18,7 +18,7 @@ TEST_CASE("MenuTest") {
REQUIRE(0 == ncplane_cursor_move_yx(n_, 0, 0));
SUBCASE("EmptyMenuTop") {
struct menu_options opts{};
struct ncmenu_options opts{};
struct ncmenu* ncm = ncmenu_create(nc_, &opts);
REQUIRE(nullptr != ncm);
CHECK(0 == notcurses_render(nc_));
@ -26,7 +26,7 @@ TEST_CASE("MenuTest") {
}
SUBCASE("EmptyMenuBottom") {
struct menu_options opts{};
struct ncmenu_options opts{};
opts.bottom = true;
struct ncmenu* ncm = ncmenu_create(nc_, &opts);
REQUIRE(nullptr != ncm);

Loading…
Cancel
Save