Rectify listview behaviour

This commit is contained in:
Přemysl Eric Janouch 2016-10-03 04:00:56 +02:00
parent 563c278771
commit f0c7092521
Signed by: p
GPG Key ID: B715679E3A361BE6
1 changed files with 105 additions and 71 deletions

182
nncmpp.c
View File

@ -947,66 +947,76 @@ app_redraw (void)
// --- Actions ----------------------------------------------------------------- // --- Actions -----------------------------------------------------------------
/// Scroll up @a n items. Doesn't redraw. static int
app_visible_items (void)
{
// This may eventually include a header bar and/or a status bar
return MAX (0, LINES - g_ctx.top_height);
}
/// Checks what items that are visible and returns if fixes were needed
static bool static bool
app_scroll_up (int n) app_fix_view_range (void)
{ {
struct tab *tab = g_ctx.active_tab; struct tab *tab = g_ctx.active_tab;
if (tab->item_top < n) if (tab->item_top < 0)
{ {
tab->item_top = 0; tab->item_top = 0;
return false; return false;
} }
tab->item_top -= n;
return true;
}
/// Scroll down @a n items. Doesn't redraw. // If the contents are at least as long as the screen, always fill it
static bool int max_item_top = (int) tab->item_count - app_visible_items ();
app_scroll_down (int n) // But don't let that suggest a negative offset
max_item_top = MAX (max_item_top, 0);
if (tab->item_top > max_item_top)
{ {
struct tab *tab = g_ctx.active_tab; tab->item_top = max_item_top;
// TODO: if (n_items >= lines), don't allow to scroll off past the end
if ((tab->item_top += n) >= (int) tab->item_count)
{
if (tab->item_count)
tab->item_top = tab->item_count - 1;
else
tab->item_top = 0;
return false; return false;
} }
return true; return true;
} }
/// Moves the selection one item up. /// Scroll down (positive) or up (negative) @a n items. Doesn't redraw.
static bool static bool
app_one_item_up (void) app_scroll (int n)
{
g_ctx.active_tab->item_top += n;
return app_fix_view_range ();
}
static void
app_ensure_selection_visible (void)
{ {
struct tab *tab = g_ctx.active_tab; struct tab *tab = g_ctx.active_tab;
if (tab->item_selected < 1) if (tab->item_selected < 0)
return false; return;
if (--tab->item_selected < tab->item_top) int too_high = tab->item_top - tab->item_selected;
app_scroll_up (tab->item_top - tab->item_selected); if (too_high > 0)
app_scroll (-too_high);
int too_low = tab->item_selected
- (tab->item_top + app_visible_items () - 1);
if (too_low > 0)
app_scroll (too_low);
}
static bool
app_move_selection (int diff)
{
struct tab *tab = g_ctx.active_tab;
int fixed = tab->item_selected += diff;
fixed = MAX (fixed, 0);
fixed = MIN (fixed, (int) tab->item_count - 1);
bool result = tab->item_selected != fixed;
tab->item_selected = fixed;
app_ensure_selection_visible ();
app_redraw_view (); app_redraw_view ();
return true; return result;
}
/// Moves the selection one item down.
static bool
app_one_item_down (void)
{
struct tab *tab = g_ctx.active_tab;
if (tab->item_selected + 1 >= (int) tab->item_count)
return false;
int n_visible = LINES - g_ctx.top_height;
if (++tab->item_selected >= tab->item_top + n_visible)
app_scroll_down (1);
app_redraw_view ();
return true;
} }
static bool static bool
@ -1023,25 +1033,6 @@ app_goto_tab (int tab_index)
return false; return false;
} }
static void
app_process_resize (void)
{
struct tab *tab = g_ctx.active_tab;
if (tab->item_selected < 0)
return;
int n_visible = LINES - g_ctx.top_height;
if (n_visible < 0)
return;
// Scroll up as needed to keep the selection visible
int selected_offset = tab->item_selected - tab->item_top;
if (selected_offset >= n_visible)
app_scroll_up (selected_offset - n_visible + 1);
app_redraw ();
}
// --- User input handling ----------------------------------------------------- // --- User input handling -----------------------------------------------------
enum user_action enum user_action
@ -1058,6 +1049,11 @@ enum user_action
USER_ACTION_MPD_VOLUME_UP, USER_ACTION_MPD_VOLUME_UP,
USER_ACTION_MPD_VOLUME_DOWN, USER_ACTION_MPD_VOLUME_DOWN,
USER_ACTION_SCROLL_UP,
USER_ACTION_SCROLL_DOWN,
USER_ACTION_GOTO_TOP,
USER_ACTION_GOTO_BOTTOM,
USER_ACTION_GOTO_ITEM_PREVIOUS, USER_ACTION_GOTO_ITEM_PREVIOUS,
USER_ACTION_GOTO_ITEM_NEXT, USER_ACTION_GOTO_ITEM_NEXT,
USER_ACTION_GOTO_PAGE_PREVIOUS, USER_ACTION_GOTO_PAGE_PREVIOUS,
@ -1081,6 +1077,7 @@ static bool
app_process_user_action (enum user_action action) app_process_user_action (enum user_action action)
{ {
struct mpd_client *c = &g_ctx.client; struct mpd_client *c = &g_ctx.client;
struct tab *tab = g_ctx.active_tab;
switch (action) switch (action)
{ {
case USER_ACTION_QUIT: case USER_ACTION_QUIT:
@ -1131,20 +1128,48 @@ app_process_user_action (enum user_action action)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// XXX: these should rather be parametrized
case USER_ACTION_SCROLL_UP:
app_scroll (-3);
app_redraw_view ();
return true;
case USER_ACTION_SCROLL_DOWN:
app_scroll (3);
app_redraw_view ();
return true;
case USER_ACTION_GOTO_TOP:
if (tab->item_count)
{
g_ctx.active_tab->item_selected = 0;
app_ensure_selection_visible ();
app_redraw_view ();
}
return true;
case USER_ACTION_GOTO_BOTTOM:
if (tab->item_count)
{
g_ctx.active_tab->item_selected =
(int) g_ctx.active_tab->item_count - 1;
app_ensure_selection_visible ();
app_redraw_view ();
}
return true;
case USER_ACTION_GOTO_ITEM_PREVIOUS: case USER_ACTION_GOTO_ITEM_PREVIOUS:
app_one_item_up (); app_move_selection (-1);
return true; return true;
case USER_ACTION_GOTO_ITEM_NEXT: case USER_ACTION_GOTO_ITEM_NEXT:
app_one_item_down (); app_move_selection (1);
return true; return true;
case USER_ACTION_GOTO_PAGE_PREVIOUS: case USER_ACTION_GOTO_PAGE_PREVIOUS:
app_scroll_up (LINES - (int) g_ctx.top_height); app_scroll ((int) g_ctx.top_height - LINES);
app_redraw_view (); app_move_selection ((int) g_ctx.top_height - LINES);
return true; return true;
case USER_ACTION_GOTO_PAGE_NEXT: case USER_ACTION_GOTO_PAGE_NEXT:
app_scroll_down (LINES - (int) g_ctx.top_height); app_scroll (LINES - (int) g_ctx.top_height);
app_redraw_view (); app_move_selection (LINES - (int) g_ctx.top_height);
return true; return true;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -1240,9 +1265,9 @@ app_process_mouse (termo_key_t *event)
if (button == 1) if (button == 1)
app_process_left_mouse_click (line, column); app_process_left_mouse_click (line, column);
else if (button == 4) else if (button == 4)
app_process_user_action (USER_ACTION_GOTO_ITEM_PREVIOUS); app_process_user_action (USER_ACTION_SCROLL_UP);
else if (button == 5) else if (button == 5)
app_process_user_action (USER_ACTION_GOTO_ITEM_NEXT); app_process_user_action (USER_ACTION_SCROLL_DOWN);
return true; return true;
} }
@ -1259,8 +1284,12 @@ g_default_bindings[] =
{ "Escape", USER_ACTION_QUIT }, { "Escape", USER_ACTION_QUIT },
{ "C-l", USER_ACTION_REDRAW }, { "C-l", USER_ACTION_REDRAW },
{ "Home", USER_ACTION_GOTO_TOP },
{ "End", USER_ACTION_GOTO_BOTTOM },
{ "Up", USER_ACTION_GOTO_ITEM_PREVIOUS }, { "Up", USER_ACTION_GOTO_ITEM_PREVIOUS },
{ "Down", USER_ACTION_GOTO_ITEM_NEXT }, { "Down", USER_ACTION_GOTO_ITEM_NEXT },
{ "k", USER_ACTION_GOTO_ITEM_PREVIOUS },
{ "j", USER_ACTION_GOTO_ITEM_NEXT },
{ "PageUp", USER_ACTION_GOTO_PAGE_PREVIOUS }, { "PageUp", USER_ACTION_GOTO_PAGE_PREVIOUS },
{ "PageDown", USER_ACTION_GOTO_PAGE_NEXT }, { "PageDown", USER_ACTION_GOTO_PAGE_NEXT },
{ "C-p", USER_ACTION_GOTO_ITEM_PREVIOUS }, { "C-p", USER_ACTION_GOTO_ITEM_PREVIOUS },
@ -1270,9 +1299,11 @@ g_default_bindings[] =
// Not sure how to set these up, they're pretty arbitrary so far // Not sure how to set these up, they're pretty arbitrary so far
{ "Left", USER_ACTION_MPD_PREVIOUS }, { "Left", USER_ACTION_MPD_PREVIOUS },
{ "Right", USER_ACTION_MPD_NEXT },
{ "h", USER_ACTION_MPD_PREVIOUS },
{ "l", USER_ACTION_MPD_NEXT },
{ "Space", USER_ACTION_MPD_TOGGLE }, { "Space", USER_ACTION_MPD_TOGGLE },
{ "C-Space", USER_ACTION_MPD_STOP }, { "C-Space", USER_ACTION_MPD_STOP },
{ "Right", USER_ACTION_MPD_NEXT },
{ "M-PageUp", USER_ACTION_MPD_VOLUME_UP }, { "M-PageUp", USER_ACTION_MPD_VOLUME_UP },
{ "M-PageDown", USER_ACTION_MPD_VOLUME_DOWN }, { "M-PageDown", USER_ACTION_MPD_VOLUME_DOWN },
{ NULL, USER_ACTION_NONE }, { NULL, USER_ACTION_NONE },
@ -1305,11 +1336,6 @@ app_process_termo_event (termo_key_t *event)
beep (); beep ();
return true; return true;
} }
if (!event->modifiers)
{
// TODO: normal unmodified keys will have functions as well
ucs4_t c = event->code.codepoint;
}
return true; return true;
} }
@ -1740,7 +1766,15 @@ app_on_signal_pipe_readable (const struct pollfd *fd, void *user_data)
if (g_winch_received) if (g_winch_received)
{ {
update_curses_terminal_size (); update_curses_terminal_size ();
app_process_resize (); app_redraw_top ();
app_fix_view_range ();
#if SELECTION_SHOULD_BE_VISIBLE_AFTER_RESIZE
// First we had to make the assumptions of this valid
app_ensure_selection_visible ();
#endif
app_redraw_view ();
g_winch_received = false; g_winch_received = false;
} }
} }