Merge branch '3554_listbox_wrap'

* 3554_listbox_wrap:
  Listbox: don't wraparound on mouse scroll.
  Ticket #3554: Listbox: don't wraparound on mouse scroll.
This commit is contained in:
Andrew Borodin 2015-12-31 10:43:29 +03:00
commit 1cf18abd62

View File

@ -52,6 +52,9 @@ const global_keymap_t *listbox_map = NULL;
/*** file scope macro definitions ****************************************************************/ /*** file scope macro definitions ****************************************************************/
/* Gives the position of the last item. */
#define LISTBOX_LAST(l) (g_queue_is_empty ((l)->list) ? 0 : (int) g_queue_get_length ((l)->list) - 1)
/*** file scope type declarations ****************************************************************/ /*** file scope type declarations ****************************************************************/
/*** file scope variables ************************************************************************/ /*** file scope variables ************************************************************************/
@ -215,42 +218,49 @@ listbox_check_hotkey (WListbox * l, int key)
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
/* Selects from base the pos element */ /* Calculates the item displayed at screen row 'y' (y==0 being the widget's 1st row). */
static int static int
listbox_select_pos (WListbox * l, int base, int pos) listbox_y_pos (WListbox * l, int y)
{ {
int last = 0; return min (l->top + y, LISTBOX_LAST (l));
base += pos;
if (!listbox_is_empty (l))
last = g_queue_get_length (l->list) - 1;
base = min (base, last);
return base;
} }
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
static void static void
listbox_fwd (WListbox * l) listbox_fwd (WListbox * l, gboolean wrap)
{ {
if ((guint) l->pos + 1 >= g_queue_get_length (l->list)) if ((guint) l->pos + 1 < g_queue_get_length (l->list))
listbox_select_first (l);
else
listbox_select_entry (l, l->pos + 1); listbox_select_entry (l, l->pos + 1);
else if (wrap)
listbox_select_first (l);
} }
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
static void static void
listbox_back (WListbox * l) listbox_fwd_n (WListbox * l, int n)
{ {
if (l->pos <= 0) listbox_select_entry (l, min (l->pos + n, LISTBOX_LAST (l)));
listbox_select_last (l); }
else
/* --------------------------------------------------------------------------------------------- */
static void
listbox_back (WListbox * l, gboolean wrap)
{
if (l->pos > 0)
listbox_select_entry (l, l->pos - 1); listbox_select_entry (l, l->pos - 1);
else if (wrap)
listbox_select_last (l);
}
/* --------------------------------------------------------------------------------------------- */
static void
listbox_back_n (WListbox * l, int n)
{
listbox_select_entry (l, max (l->pos - n, 0));
} }
/* --------------------------------------------------------------------------------------------- */ /* --------------------------------------------------------------------------------------------- */
@ -259,9 +269,7 @@ static cb_ret_t
listbox_execute_cmd (WListbox * l, unsigned long command) listbox_execute_cmd (WListbox * l, unsigned long command)
{ {
cb_ret_t ret = MSG_HANDLED; cb_ret_t ret = MSG_HANDLED;
int i;
Widget *w = WIDGET (l); Widget *w = WIDGET (l);
int length;
if (l->list == NULL || g_queue_is_empty (l->list)) if (l->list == NULL || g_queue_is_empty (l->list))
return MSG_NOT_HANDLED; return MSG_NOT_HANDLED;
@ -269,10 +277,10 @@ listbox_execute_cmd (WListbox * l, unsigned long command)
switch (command) switch (command)
{ {
case CK_Up: case CK_Up:
listbox_back (l); listbox_back (l, TRUE);
break; break;
case CK_Down: case CK_Down:
listbox_fwd (l); listbox_fwd (l, TRUE);
break; break;
case CK_Top: case CK_Top:
listbox_select_first (l); listbox_select_first (l);
@ -281,18 +289,16 @@ listbox_execute_cmd (WListbox * l, unsigned long command)
listbox_select_last (l); listbox_select_last (l);
break; break;
case CK_PageUp: case CK_PageUp:
for (i = 0; (i < w->lines - 1) && (l->pos > 0); i++) listbox_back_n (l, w->lines - 1);
listbox_back (l);
break; break;
case CK_PageDown: case CK_PageDown:
length = g_queue_get_length (l->list); listbox_fwd_n (l, w->lines - 1);
for (i = 0; i < w->lines - 1 && l->pos < length - 1; i++)
listbox_fwd (l);
break; break;
case CK_Delete: case CK_Delete:
if (l->deletable) if (l->deletable)
{ {
gboolean is_last, is_more; gboolean is_last, is_more;
int length;
length = g_queue_get_length (l->list); length = g_queue_get_length (l->list);
@ -488,27 +494,24 @@ listbox_event (Gpm_Event * event, void *data)
{ {
int ret = MOU_REPEAT; int ret = MOU_REPEAT;
Gpm_Event local; Gpm_Event local;
int i;
local = mouse_get_local (event, w); local = mouse_get_local (event, w);
if (local.y < 1) if (local.y < 1)
for (i = -local.y; i >= 0; i--) listbox_back_n (l, -local.y + 1);
listbox_back (l);
else if (local.y > w->lines) else if (local.y > w->lines)
for (i = local.y - w->lines; i > 0; i--) listbox_fwd_n (l, local.y - w->lines);
listbox_fwd (l);
else if ((local.buttons & GPM_B_UP) != 0) else if ((local.buttons & GPM_B_UP) != 0)
{ {
listbox_back (l); listbox_back (l, FALSE);
ret = MOU_NORMAL; ret = MOU_NORMAL;
} }
else if ((local.buttons & GPM_B_DOWN) != 0) else if ((local.buttons & GPM_B_DOWN) != 0)
{ {
listbox_fwd (l); listbox_fwd (l, FALSE);
ret = MOU_NORMAL; ret = MOU_NORMAL;
} }
else else
listbox_select_entry (l, listbox_select_pos (l, l->top, local.y - 1)); listbox_select_entry (l, listbox_y_pos (l, local.y - 1));
/* We need to refresh ourselves since the dialog manager doesn't */ /* We need to refresh ourselves since the dialog manager doesn't */
/* know about this event */ /* know about this event */
@ -524,7 +527,7 @@ listbox_event (Gpm_Event * event, void *data)
local = mouse_get_local (event, w); local = mouse_get_local (event, w);
dlg_select_widget (l); dlg_select_widget (l);
listbox_select_entry (l, listbox_select_pos (l, l->top, local.y - 1)); listbox_select_entry (l, listbox_y_pos (l, local.y - 1));
if (l->callback != NULL) if (l->callback != NULL)
action = l->callback (l); action = l->callback (l);