forked from RepoMirrors/bemenu
Make scrollbar autohideable
This commit is contained in:
parent
f2eaf599f6
commit
c2eabf2be1
@ -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':
|
||||
|
@ -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[]);
|
||||
|
29
lib/bemenu.h
29
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.
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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, "▒");
|
||||
|
Loading…
Reference in New Issue
Block a user