From c2eabf2be13de14e0e57ad6374cceb049b8d03da Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Sun, 18 Jan 2015 02:07:30 +0200 Subject: [PATCH] Make scrollbar autohideable --- client/common/common.c | 6 +++--- client/common/common.h | 2 +- lib/bemenu.h | 29 +++++++++++++++++++++++------ lib/internal.h | 10 +++++----- lib/menu.c | 6 +++--- lib/renderers/cairo.h | 15 ++++++++------- lib/renderers/curses/curses.c | 7 ++++--- 7 files changed, 47 insertions(+), 28 deletions(-) diff --git a/client/common/common.c b/client/common/common.c index 982f89a..14837cb 100644 --- a/client/common/common.c +++ b/client/common/common.c @@ -68,7 +68,7 @@ usage(FILE *out, const char *name) " -p, --prompt defines the prompt text to be displayed.\n" " -P, --prefix text to shown before highlighted item.\n" " -I, --index select item at index automatically.\n" - " --scrollbar display scrollbar.\n\n" + " --scrollbar display scrollbar. (always, autohide)\n\n" "Use BEMENU_BACKEND env variable to force backend:\n" " curses ncurses based terminal backend\n" @@ -117,7 +117,7 @@ parse_args(struct client *client, int *argc, char **argv[]) { "prompt", required_argument, 0, 'p' }, { "index", required_argument, 0, 'I' }, { "prefix", required_argument, 0, 'P' }, - { "scrollbar", no_argument, 0, 0x113 }, + { "scrollbar", required_argument, 0, 0x113 }, { "bottom", no_argument, 0, 'b' }, { "grab", no_argument, 0, 'f' }, @@ -177,7 +177,7 @@ parse_args(struct client *client, int *argc, char **argv[]) client->selected = strtol(optarg, NULL, 10); break; case 0x113: - client->scrollbar = true; + client->scrollbar = (!strcmp(optarg, "always") ? BM_SCROLLBAR_ALWAYS : (!strcmp(optarg, "autohide") ? BM_SCROLLBAR_AUTOHIDE : BM_SCROLLBAR_NONE)); break; case 'b': diff --git a/client/common/common.h b/client/common/common.h index 914ddf0..eafbb3a 100644 --- a/client/common/common.h +++ b/client/common/common.h @@ -5,6 +5,7 @@ struct client { enum bm_filter_mode filter_mode; + enum bm_scrollbar_mode scrollbar; const char *colors[BM_COLOR_LAST]; const char *title; const char *prefix; @@ -15,7 +16,6 @@ struct client { bool bottom; bool grab; bool wrap; - bool scrollbar; }; void parse_args(struct client *client, int *argc, char **argv[]); diff --git a/lib/bemenu.h b/lib/bemenu.h index b5598d0..4010683 100644 --- a/lib/bemenu.h +++ b/lib/bemenu.h @@ -134,6 +134,23 @@ enum bm_filter_mode { BM_FILTER_MODE_LAST }; +/** + * Scrollbar display mode constants for bm_menu instance scrollbar. + * + * - @link ::bm_run_result BM_SCROLLBAR_ALWAYS @endlink means that scrollbar is not displayed. + * - @link ::bm_run_result BM_SCROLLBAR_ALWAYS @endlink means that scrollbar is displayed always. + * - @link ::bm_run_result BM_SCROLLBAR_AUTOHIDE @endlink means that scrollbar is only displayed when there are more items than lines. + * + * @link ::bm_scrollbar_mode BM_SCROLLBAR_LAST @endlink is provided for enumerating scrollbar modes. + * Using it as scrollbar mode however provides exactly same functionality as BM_SCROLLBAR_NONE. + */ +enum bm_scrollbar_mode { + BM_SCROLLBAR_NONE, + BM_SCROLLBAR_ALWAYS, + BM_SCROLLBAR_AUTOHIDE, + BM_SCROLLBAR_LAST, +}; + /** * Result constants from bm_menu_run_with_key function. * @@ -389,20 +406,20 @@ bool bm_menu_set_color(struct bm_menu *menu, enum bm_color color, const char *he const char* bm_menu_get_color(const struct bm_menu *menu, enum bm_color color); /** - * Display scrollbar at left side of the menu. + * Set scrollbar display mode. * * @param menu bm_menu instance to set scrollbar for. - * @param scrollbar true for scrollbar, false for no scrollbar. + * @param mode bm_scrollbar_mode constant. */ -void bm_menu_set_scrollbar(struct bm_menu *menu, bool scrollbar); +void bm_menu_set_scrollbar(struct bm_menu *menu, enum bm_scrollbar_mode mode); /** - * Is scrollbar being displayed on the menu? + * Return current scrollbar display mode. * * @param menu bm_menu instance where to get scrollbar display state from. - * @return true if scrollbar displayed, false otherwise. + * @return bm_scrollbar_mode constant. */ -bool bm_menu_get_scrollbar(struct bm_menu *menu); +enum bm_scrollbar_mode bm_menu_get_scrollbar(struct bm_menu *menu); /** * Display menu at bottom of the screen. diff --git a/lib/internal.h b/lib/internal.h index 5291b56..52d4125 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -273,6 +273,11 @@ struct bm_menu { */ enum bm_filter_mode filter_mode; + /** + * Current Scrollbar display mode. + */ + enum bm_scrollbar_mode scrollbar; + /** * Should selection be wrapped? */ @@ -287,11 +292,6 @@ struct bm_menu { * Is menu grabbed? */ bool grabbed; - - /** - * Scrollbar enabled? - */ - bool scrollbar; }; /* library.c */ diff --git a/lib/menu.c b/lib/menu.c index b816b28..2eea897 100644 --- a/lib/menu.c +++ b/lib/menu.c @@ -298,12 +298,12 @@ char* bm_menu_get_color(const struct bm_menu *menu, enum bm_color color) } void -bm_menu_set_scrollbar(struct bm_menu *menu, bool scrollbar) +bm_menu_set_scrollbar(struct bm_menu *menu, enum bm_scrollbar_mode mode) { - menu->scrollbar = scrollbar; + menu->scrollbar = (mode == BM_SCROLLBAR_LAST ? BM_SCROLLBAR_NONE : mode); } -bool +enum bm_scrollbar_mode bm_menu_get_scrollbar(struct bm_menu *menu) { return menu->scrollbar; diff --git a/lib/renderers/cairo.h b/lib/renderers/cairo.h index 1a4f7c2..59f61d3 100644 --- a/lib/renderers/cairo.h +++ b/lib/renderers/cairo.h @@ -197,17 +197,18 @@ bm_cairo_paint(struct cairo *cairo, uint32_t width, uint32_t height, uint32_t ma paint.pos = (struct pos){ (menu->title ? 2 : 0) + result.x_advance, 2 }; paint.box = (struct box){ (menu->title ? 2 : 4), 0, 2, 2, width - paint.pos.x, 0 }; bm_cairo_draw_line(cairo, &paint, &result, "%s", (menu->filter ? menu->filter : "")); + const uint32_t titleh = result.height; + out_result->height = titleh; uint32_t count; struct bm_item **items = bm_menu_get_filtered_items(menu, &count); uint32_t lines = (menu->lines > 0 ? menu->lines : 1); - uint32_t titleh = result.height; - out_result->height = titleh; if (lines > 1) { /* vertical mode */ - uint32_t spacing_x = (menu->scrollbar ? 4 : 0); + const bool scrollbar = (menu->scrollbar > BM_SCROLLBAR_NONE && (menu->scrollbar != BM_SCROLLBAR_AUTOHIDE || count > lines) ? true : false); + const uint32_t spacing_x = (scrollbar ? 4 : 0); uint32_t spacing_y = 0; // 0 == variable width spacing if (lines > max_height / titleh) { /* there is more lines than screen can fit, enter fixed spacing mode */ @@ -251,17 +252,17 @@ bm_cairo_paint(struct cairo *cairo, uint32_t width, uint32_t height, uint32_t ma out_result->displayed++; } - if (menu->scrollbar && count > 0) { + if (scrollbar && count > 0) { bm_cairo_color_from_menu_color(menu, BM_COLOR_SCROLLBAR_BG, &paint.bg); bm_cairo_color_from_menu_color(menu, BM_COLOR_SCROLLBAR_FG, &paint.fg); - uint32_t sheight = out_result->height - titleh; + const uint32_t sheight = out_result->height - titleh; cairo_set_source_rgba(cairo->cr, paint.bg.r, paint.bg.b, paint.bg.g, paint.bg.a); cairo_rectangle(cairo->cr, 0, titleh, 2, sheight); cairo_fill(cairo->cr); - uint32_t size = sheight / lines; - uint32_t percent = (menu->index / (float)(count - 1)) * (sheight - size); + const uint32_t size = sheight / lines; + const uint32_t percent = (menu->index / (float)(count - 1)) * (sheight - size); cairo_set_source_rgba(cairo->cr, paint.fg.r, paint.fg.b, paint.fg.g, paint.fg.a); cairo_rectangle(cairo->cr, 0, titleh + percent, 2, size); cairo_fill(cairo->cr); diff --git a/lib/renderers/curses/curses.c b/lib/renderers/curses/curses.c index 852eb88..1f81775 100644 --- a/lib/renderers/curses/curses.c +++ b/lib/renderers/curses/curses.c @@ -186,11 +186,12 @@ render(const struct bm_menu *menu) uint32_t count, cl = 1; const uint32_t lines = getmaxy(curses.stdscr); - const int32_t prefix_x = (menu->prefix ? bm_utf8_string_screen_width(menu->prefix) : 0); - const int32_t offset_x = (menu->scrollbar ? 2 : 0); if (lines > 1) { uint32_t displayed = 0; struct bm_item **items = bm_menu_get_filtered_items(menu, &count); + const bool scrollbar = (menu->scrollbar > BM_SCROLLBAR_NONE && (menu->scrollbar != BM_SCROLLBAR_AUTOHIDE || count > lines) ? true : false); + const int32_t offset_x = (scrollbar ? 2 : 0); + const int32_t prefix_x = (menu->prefix ? bm_utf8_string_screen_width(menu->prefix) : 0); for (uint32_t i = (menu->index / (lines - 1)) * (lines - 1); i < count && cl < lines; ++i) { bool highlighted = (items[i] == bm_menu_get_highlighted_item(menu)); int32_t color = (highlighted ? 2 : (bm_menu_item_is_selected(menu, items[i]) ? 1 : 0)); @@ -204,7 +205,7 @@ render(const struct bm_menu *menu) ++displayed; } - if (menu->scrollbar) { + if (scrollbar) { attron(COLOR_PAIR(1)); uint32_t percent = (menu->index / (float)(count - 1)) * (displayed - 1); mvprintw(1 + percent, 0, "▒");