From e37540c76e009a598b6444bb78435eba48e33b75 Mon Sep 17 00:00:00 2001 From: nick black Date: Sun, 13 Dec 2020 07:22:43 -0500 Subject: [PATCH] ncprogbar: implement core draw loop #1202 --- include/notcurses/notcurses.h | 3 ++- src/lib/fill.c | 3 +-- src/lib/internal.h | 11 +++++++++++ src/lib/progbar.c | 25 ++++++++++++++++++++----- src/poc/progbar.c | 2 +- 5 files changed, 35 insertions(+), 9 deletions(-) diff --git a/include/notcurses/notcurses.h b/include/notcurses/notcurses.h index 1ca6af080..5cf42be0c 100644 --- a/include/notcurses/notcurses.h +++ b/include/notcurses/notcurses.h @@ -3039,7 +3039,8 @@ API int ncmenu_destroy(struct ncmenu* n); typedef struct ncprogbar_options { // channels for the maximum and minimum points. linear interpolation will be - // applied across the domain between these two. + // applied across the domain between these two. for both channels, both min + // and max must either be RGB, or both default, and alphas must match. uint64_t maxchannels; uint64_t minchannels; // provide NULL for default (geometric) glyphs. otherwise, provide one or diff --git a/src/lib/fill.c b/src/lib/fill.c index afe899db9..554ae02f4 100644 --- a/src/lib/fill.c +++ b/src/lib/fill.c @@ -115,8 +115,7 @@ check_gradient_channel_args(uint32_t ul, uint32_t ur, uint32_t bl, uint32_t br){ // - all foregrounds must have the same alpha // - all backgrounds must have the same alpha // - palette-indexed color must not be used -static bool -check_gradient_args(uint64_t ul, uint64_t ur, uint64_t bl, uint64_t br){ +bool check_gradient_args(uint64_t ul, uint64_t ur, uint64_t bl, uint64_t br){ if(check_gradient_channel_args(channels_fchannel(ul), channels_fchannel(ur), channels_fchannel(bl), channels_fchannel(br))){ return true; diff --git a/src/lib/internal.h b/src/lib/internal.h index 29c3c9394..c986eae60 100644 --- a/src/lib/internal.h +++ b/src/lib/internal.h @@ -1074,6 +1074,17 @@ int ncinputlayer_init(ncinputlayer* nilayer, FILE* infp); // FIXME absorb into ncinputlayer_init() int cbreak_mode(int ttyfd, const struct termios* tpreserved); +// Given the four channels arguments, verify that: +// +// - if any is default foreground, all are default foreground +// - if any is default background, all are default background +// - all foregrounds must have the same alpha +// - all backgrounds must have the same alpha +// - palette-indexed color must not be used +// +// If you only want to check n < 4 channels, just duplicate one. +bool check_gradient_args(uint64_t ul, uint64_t ur, uint64_t bl, uint64_t br); + #ifdef __cplusplus } #endif diff --git a/src/lib/progbar.c b/src/lib/progbar.c index 3cd929908..1c89c3eed 100644 --- a/src/lib/progbar.c +++ b/src/lib/progbar.c @@ -9,6 +9,10 @@ ncprogbar* ncprogbar_create(ncplane* n, const ncprogbar_options* opts){ default_opts.maxchannels = CHANNELS_RGB_INITIALIZER(0xe0, 0xee, 0xe0, 0, 0, 0); opts = &default_opts; } + if(check_gradient_args(opts->minchannels, opts->maxchannels, opts->minchannels, opts->maxchannels)){ + logerror(ncplane_notcurses(n), "Illegal progbar colors\n"); + return NULL; + } if(opts->flags > (NCPROGBAR_OPTION_FORCE_VERTICAL << 1u)){ logwarn(ncplane_notcurses(n), "Invalid flags %016lx\n", opts->flags); } @@ -55,13 +59,24 @@ progbar_redraw(ncprogbar* n){ }else{ // PROGRESS_HORIZ direction = n->retrograde ? DIR_LEFT : DIR_RIGHT; } - int range; - if(direction == DIR_UP || direction == DIR_DOWN){ - range = dimy; - }else{ + const bool horizontal = (direction == DIR_LEFT || direction == DIR_RIGHT); + int delt, range; + if(horizontal){ range = dimx; + delt = n->retrograde ? 1 : -1; + }else{ + range = dimy; + delt = n->retrograde ? -1 : 1; + } + double progress = n->progress * range; + if(n->retrograde){ + progress = range - progress; + } + while(progress > 0 && progress < range){ + // FIXME lerp min->max + ncplane_putchar_yx(ncprogbar_plane(n), 0, progress, 'X'); + progress += delt; } - // FIXME return 0; } diff --git a/src/poc/progbar.c b/src/poc/progbar.c index 84ac43cfe..5282a3491 100644 --- a/src/poc/progbar.c +++ b/src/poc/progbar.c @@ -16,7 +16,7 @@ pbar_fill(struct notcurses* nc, struct ncprogbar* pbar){ const uint64_t deadline = startns + delay; do{ uint64_t curns = ts_to_ns(&cur); - if(ncprogbar_set_progress(pbar, (curns - startns) / delay)){ + if(ncprogbar_set_progress(pbar, (curns - startns) / (double)delay)){ return -1; } notcurses_render(nc);