Skip to content

Commit

Permalink
Add dynamic paging to statusbar
Browse files Browse the repository at this point in the history
Significantly improve navigation by
making statusbar follow current page and display pages/tabs near it.
  • Loading branch information
H3rnand3zzz committed Nov 8, 2023
1 parent 9741f19 commit 5b6481d
Showing 1 changed file with 125 additions and 42 deletions.
167 changes: 125 additions & 42 deletions src/ui/statusbar.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,18 @@ static GTimeZone* tz;
static StatusBar* statusbar;
static WINDOW* statusbar_win;

void _get_range_bounds(int* start, int* end);
static int _status_bar_draw_time(int pos);
static int _status_bar_draw_maintext(int pos);
static int _status_bar_draw_bracket(gboolean current, int pos, const char* ch);
static int _status_bar_draw_extended_tabs(int pos);
static int _status_bar_draw_extended_tabs(int pos, gboolean prefix, int start, int end);
static int _status_bar_draw_tab(StatusBarTab* tab, int pos, int num);
static int _status_bar_draw_tabs(int pos);
static void _destroy_tab(StatusBarTab* tab);
static int _tabs_width(void);
static unsigned int _count_digits(int number);
static unsigned int _count_digits_in_range(int start, int end);
static char* _display_name(StatusBarTab* tab);
static gboolean _extended_new(void);
static gboolean _tabmode_is_actlist(void);

void
Expand Down Expand Up @@ -282,26 +285,39 @@ status_bar_draw(void)
werase(statusbar_win);
wbkgd(statusbar_win, theme_attrs(THEME_STATUS_TEXT));

gint max_tabs = prefs_get_statusbartabs();
int pos = 1;

pos = _status_bar_draw_time(pos);

pos = _status_bar_draw_maintext(pos);
if (max_tabs != 0)
pos = _status_bar_draw_tabs(pos);

wnoutrefresh(statusbar_win);
inp_put_back();
}

static int
_status_bar_draw_tabs(int pos)
{
if (!_tabmode_is_actlist()) {
pos = getmaxx(stdscr) - _tabs_width();
if (pos < 0) {
pos = 0;
}
gint max_tabs = prefs_get_statusbartabs();
for (int i = 1; i <= max_tabs; i++) {
int start, end;
_get_range_bounds(&start, &end);

pos = _status_bar_draw_extended_tabs(pos, TRUE, start, end);

for (int i = start; i <= end; i++) {
StatusBarTab* tab = g_hash_table_lookup(statusbar->tabs, GINT_TO_POINTER(i));
if (tab) {
pos = _status_bar_draw_tab(tab, pos, i);
}
}

_status_bar_draw_extended_tabs(pos);
pos = _status_bar_draw_extended_tabs(pos, FALSE, start, end);
} else {
pos++;
guint print_act = 0;
Expand Down Expand Up @@ -339,21 +355,23 @@ status_bar_draw(void)
pos = _status_bar_draw_bracket(FALSE, pos, "]");
}
}

wnoutrefresh(statusbar_win);
inp_put_back();
return pos;
}

// Checks if there are messages to the side of the current displayed tabs range
static gboolean
_extended_new(void)
_extended_new(gboolean left_side, int display_tabs_start, int display_tabs_end)
{
gint max_tabs = prefs_get_statusbartabs();
int tabs_count = g_hash_table_size(statusbar->tabs);
if (tabs_count <= max_tabs) {
return FALSE;
}

for (int i = max_tabs + 1; i <= tabs_count; i++) {
int start = left_side ? 1 : display_tabs_end + 1;
int end = left_side ? display_tabs_start - 1 : tabs_count;

for (int i = start; i <= end; i++) {
StatusBarTab* tab = g_hash_table_lookup(statusbar->tabs, GINT_TO_POINTER(i));
if (tab && tab->highlight) {
return TRUE;
Expand All @@ -364,44 +382,49 @@ _extended_new(void)
}

static int
_status_bar_draw_extended_tabs(int pos)
_status_bar_draw_extended_tabs(int pos, gboolean prefix, int start, int end)
{
gint max_tabs = prefs_get_statusbartabs();
if (max_tabs == 0) {
return pos;
}

if (g_hash_table_size(statusbar->tabs) > max_tabs) {
gboolean is_current = statusbar->current_tab > max_tabs;
guint opened_tabs = g_hash_table_size(statusbar->tabs);
if (g_hash_table_size(statusbar->tabs) <= max_tabs) {
return pos;
}

if (prefix && start < 2) {
return pos;
}
if (!prefix && end > opened_tabs - 1) {
return pos;
}
gboolean is_current = FALSE;

pos = _status_bar_draw_bracket(is_current, pos, "[");
pos = _status_bar_draw_bracket(is_current, pos, "[");

int status_attrs;
if (is_current) {
// currently selected
status_attrs = theme_attrs(THEME_STATUS_CURRENT);
} else if (_extended_new()) {
// new one
status_attrs = theme_attrs(THEME_STATUS_NEW);
} else {
// all other
status_attrs = theme_attrs(THEME_STATUS_ACTIVE);
}
wattron(statusbar_win, status_attrs);
mvwprintw(statusbar_win, 0, pos, ">");
wattroff(statusbar_win, status_attrs);
pos++;
int status_attrs;

pos = _status_bar_draw_bracket(is_current, pos, "]");
if (_extended_new(prefix, start, end)) {
// new message
status_attrs = theme_attrs(THEME_STATUS_NEW);
} else {
status_attrs = theme_attrs(THEME_STATUS_ACTIVE);
}
wattron(statusbar_win, status_attrs);
mvwprintw(statusbar_win, 0, pos, prefix ? "<" : ">");
wattroff(statusbar_win, status_attrs);
pos++;

pos = _status_bar_draw_bracket(is_current, pos, "]");

return pos;
}

static int
_status_bar_draw_tab(StatusBarTab* tab, int pos, int num)
{
int display_num = num == 10 ? 0 : num;
gboolean is_current = num == statusbar->current_tab;

gboolean show_number = prefs_get_boolean(PREF_STATUSBAR_SHOW_NUMBER);
Expand All @@ -424,8 +447,9 @@ _status_bar_draw_tab(StatusBarTab* tab, int pos, int num)
}
wattron(statusbar_win, status_attrs);
if (show_number) {
mvwprintw(statusbar_win, 0, pos, "%d", display_num);
pos++;
mvwprintw(statusbar_win, 0, pos, "%d", num);
// calculate number of digits
pos += _count_digits(num);
}
if (show_number && show_name) {
mvwprintw(statusbar_win, 0, pos, ":");
Expand Down Expand Up @@ -591,10 +615,15 @@ _tabs_width(void)
gboolean show_name = prefs_get_boolean(PREF_STATUSBAR_SHOW_NAME);
gboolean show_read = prefs_get_boolean(PREF_STATUSBAR_SHOW_READ);
gint max_tabs = prefs_get_statusbartabs();
guint opened_tabs = g_hash_table_size(statusbar->tabs);
int start, end;
_get_range_bounds(&start, &end);

int width = start < 2 ? 1 : 4;
width += end > opened_tabs - 1 ? 0 : 3;

if (show_name && show_number) {
int width = g_hash_table_size(statusbar->tabs) > max_tabs ? 4 : 1;
for (int i = 1; i <= max_tabs; i++) {
for (int i = start; i <= end; i++) {
StatusBarTab* tab = g_hash_table_lookup(statusbar->tabs, GINT_TO_POINTER(i));
if (tab) {
gboolean is_current = i == statusbar->current_tab;
Expand All @@ -604,15 +633,14 @@ _tabs_width(void)

auto_char char* display_name = _display_name(tab);
width += utf8_display_len(display_name);
width += 4;
width += 3 + _count_digits(i);
}
}
return width;
}

if (show_name && !show_number) {
int width = g_hash_table_size(statusbar->tabs) > max_tabs ? 4 : 1;
for (int i = 1; i <= max_tabs; i++) {
for (int i = start; i <= end; i++) {
StatusBarTab* tab = g_hash_table_lookup(statusbar->tabs, GINT_TO_POINTER(i));
if (tab) {
gboolean is_current = i == statusbar->current_tab;
Expand All @@ -628,10 +656,12 @@ _tabs_width(void)
return width;
}

if (g_hash_table_size(statusbar->tabs) > max_tabs) {
return max_tabs * 3 + (g_hash_table_size(statusbar->tabs) > max_tabs ? 4 : 1);
if (opened_tabs > max_tabs) {
width += _count_digits_in_range(start, end);
width += start > end ? 0 : (end - start) * 3;
return width;
}
return g_hash_table_size(statusbar->tabs) * 3 + (g_hash_table_size(statusbar->tabs) > max_tabs ? 4 : 1);
return opened_tabs * 3 + 1;
}

static char*
Expand Down Expand Up @@ -679,3 +709,56 @@ _display_name(StatusBarTab* tab)

return trimmedname;
}

void
_get_range_bounds(int* start, int* end)
{
int current_tab = statusbar->current_tab;
gint display_range = prefs_get_statusbartabs();
int total_tabs = g_hash_table_size(statusbar->tabs);
int side_range = display_range / 2;

if (total_tabs <= display_range) {
*start = 1;
*end = total_tabs;
} else if (current_tab - side_range <= 1) {
*start = 1;
*end = display_range;
} else if (current_tab + side_range >= total_tabs) {
*start = total_tabs - display_range + 1;
*end = total_tabs;
} else {
*start = current_tab - side_range;
*end = current_tab + side_range;
}
}

// Counts amount of digits in a number
static unsigned int
_count_digits(int number)
{
unsigned int digits_count = 0;
if (number < 0)
number = -number;

do {
number /= 10;
digits_count++;
} while (number != 0);

return digits_count;
}

// Counts the total number of digits in a range of numbers, inclusive.
// Example: _count_digits_in_range(2, 3) returns 2, _count_digits_in_range(2, 922) returns 2657
static unsigned int
_count_digits_in_range(int start, int end)
{
int total_digits = 0;

for (int i = start; i <= end; i++) {
total_digits += _count_digits(i);
}

return total_digits;
}

0 comments on commit 5b6481d

Please sign in to comment.