listbase: Move focus moving keybindings here
The focus tracker is not yet moved because that depends on scroll_to() support and we don't have that yet. Whoops. So we use a hack.
This commit is contained in:
@@ -400,60 +400,46 @@ gtk_grid_view_set_anchor (GtkGridView *self,
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_grid_view_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
static guint
|
||||
gtk_grid_view_move_focus_along (GtkListBase *base,
|
||||
guint pos,
|
||||
int steps)
|
||||
{
|
||||
GtkGridView *self = GTK_GRID_VIEW (widget);
|
||||
GtkWidget *old_focus_child, *new_focus_child;
|
||||
GtkGridView *self = GTK_GRID_VIEW (base);
|
||||
|
||||
old_focus_child = gtk_widget_get_focus_child (widget);
|
||||
steps *= self->n_columns;
|
||||
|
||||
if (old_focus_child == NULL &&
|
||||
(direction == GTK_DIR_TAB_FORWARD || direction == GTK_DIR_TAB_BACKWARD))
|
||||
if (steps < 0)
|
||||
{
|
||||
Cell *cell;
|
||||
guint pos;
|
||||
|
||||
/* When tabbing into the listview, don't focus the first/last item,
|
||||
* but keep the previously focused item
|
||||
*/
|
||||
pos = gtk_list_item_tracker_get_position (self->item_manager, self->focus);
|
||||
cell = gtk_list_item_manager_get_nth (self->item_manager, pos, NULL);
|
||||
if (cell && gtk_widget_grab_focus (cell->parent.widget))
|
||||
goto moved_focus;
|
||||
if (pos >= self->n_columns)
|
||||
pos -= MIN (pos, -steps);
|
||||
}
|
||||
else
|
||||
{
|
||||
guint n_items = self->model ? g_list_model_get_n_items (self->model) : 0;
|
||||
if (n_items / self->n_columns > pos / self->n_columns)
|
||||
pos += MIN (n_items - pos - 1, steps);
|
||||
}
|
||||
|
||||
if (!GTK_WIDGET_CLASS (gtk_grid_view_parent_class)->focus (widget, direction))
|
||||
return FALSE;
|
||||
return pos;
|
||||
}
|
||||
|
||||
moved_focus:
|
||||
new_focus_child = gtk_widget_get_focus_child (widget);
|
||||
static guint
|
||||
gtk_grid_view_move_focus_across (GtkListBase *base,
|
||||
guint pos,
|
||||
int steps)
|
||||
{
|
||||
GtkGridView *self = GTK_GRID_VIEW (base);
|
||||
|
||||
if (old_focus_child != new_focus_child &&
|
||||
GTK_IS_LIST_ITEM (new_focus_child))
|
||||
if (steps < 0)
|
||||
return pos - MIN (pos, -steps);
|
||||
else
|
||||
{
|
||||
GdkModifierType state;
|
||||
GdkModifierType mask;
|
||||
gboolean extend = FALSE, modify = FALSE;
|
||||
|
||||
if (old_focus_child && gtk_get_current_event_state (&state))
|
||||
{
|
||||
mask = gtk_widget_get_modifier_mask (widget, GDK_MODIFIER_INTENT_MODIFY_SELECTION);
|
||||
if ((state & mask) == mask)
|
||||
modify = TRUE;
|
||||
mask = gtk_widget_get_modifier_mask (widget, GDK_MODIFIER_INTENT_EXTEND_SELECTION);
|
||||
if ((state & mask) == mask)
|
||||
extend = TRUE;
|
||||
}
|
||||
|
||||
gtk_list_base_select_item (GTK_LIST_BASE (self),
|
||||
gtk_list_item_get_position (GTK_LIST_ITEM (new_focus_child)),
|
||||
modify,
|
||||
extend);
|
||||
guint n_items = self->model ? g_list_model_get_n_items (self->model) : 0;
|
||||
pos += MIN (n_items - pos - 1, steps);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return pos;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1253,81 +1239,6 @@ gtk_grid_view_activate_item (GtkWidget *widget,
|
||||
g_signal_emit (widget, signals[ACTIVATE], 0, pos);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_grid_view_move_cursor (GtkWidget *widget,
|
||||
GVariant *args,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkGridView *self = GTK_GRID_VIEW (widget);
|
||||
int amount;
|
||||
guint orientation;
|
||||
guint pos, n_items;
|
||||
gboolean select, modify, extend;
|
||||
|
||||
g_variant_get (args, "(ubbbi)", &orientation, &select, &modify, &extend, &amount);
|
||||
|
||||
if (gtk_list_base_get_orientation (GTK_LIST_BASE (self)) == orientation)
|
||||
amount *= self->n_columns;
|
||||
|
||||
if (orientation == GTK_ORIENTATION_HORIZONTAL &&
|
||||
gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
|
||||
amount = -amount;
|
||||
|
||||
pos = gtk_list_item_tracker_get_position (self->item_manager, self->focus);
|
||||
n_items = self->model ? g_list_model_get_n_items (self->model) : 0;
|
||||
if (pos >= n_items || /* no focused item */
|
||||
(amount < 0 && pos < -amount))
|
||||
return;
|
||||
if (amount > 0 && amount > n_items - pos)
|
||||
{
|
||||
/* pressing down with no item below the current item is more complicated
|
||||
* because we want to move to the last row if we're not there yet */
|
||||
if (pos / self->n_columns < (n_items - 1) / self->n_columns)
|
||||
amount = n_items - pos - 1;
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), pos + amount, select, modify, extend);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_grid_view_move_cursor_to_start (GtkWidget *widget,
|
||||
GVariant *args,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkGridView *self = GTK_GRID_VIEW (widget);
|
||||
gboolean select, modify, extend;
|
||||
|
||||
if (self->model == NULL || g_list_model_get_n_items (self->model) == 0)
|
||||
return;
|
||||
|
||||
g_variant_get (args, "(bbb)", &select, &modify, &extend);
|
||||
|
||||
gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), 0, select, modify, extend);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_grid_view_move_cursor_to_end (GtkWidget *widget,
|
||||
GVariant *args,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkGridView *self = GTK_GRID_VIEW (widget);
|
||||
gboolean select, modify, extend;
|
||||
guint n_items;
|
||||
|
||||
if (self->model == NULL)
|
||||
return;
|
||||
|
||||
n_items = g_list_model_get_n_items (self->model);
|
||||
if (n_items == 0)
|
||||
return;
|
||||
|
||||
g_variant_get (args, "(bbb)", &select, &modify, &extend);
|
||||
|
||||
gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), n_items - 1, select, modify, extend);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_grid_view_move_cursor_page_up (GtkWidget *widget,
|
||||
GVariant *args,
|
||||
@@ -1446,32 +1357,6 @@ gtk_grid_view_add_custom_move_binding (GtkBindingSet *binding_set,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_grid_view_add_move_binding (GtkBindingSet *binding_set,
|
||||
guint keyval,
|
||||
GtkOrientation orientation,
|
||||
int amount)
|
||||
{
|
||||
gtk_binding_entry_add_callback (binding_set,
|
||||
keyval,
|
||||
GDK_CONTROL_MASK,
|
||||
gtk_grid_view_move_cursor,
|
||||
g_variant_new ("(ubbbi)", orientation, FALSE, FALSE, FALSE, amount),
|
||||
NULL, NULL);
|
||||
gtk_binding_entry_add_callback (binding_set,
|
||||
keyval,
|
||||
GDK_SHIFT_MASK,
|
||||
gtk_grid_view_move_cursor,
|
||||
g_variant_new ("(ubbbi)", orientation, TRUE, FALSE, TRUE, amount),
|
||||
NULL, NULL);
|
||||
gtk_binding_entry_add_callback (binding_set,
|
||||
keyval,
|
||||
GDK_CONTROL_MASK | GDK_SHIFT_MASK,
|
||||
gtk_grid_view_move_cursor,
|
||||
g_variant_new ("(ubbbi)", orientation, TRUE, TRUE, TRUE, amount),
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_grid_view_class_init (GtkGridViewClass *klass)
|
||||
{
|
||||
@@ -1485,8 +1370,9 @@ gtk_grid_view_class_init (GtkGridViewClass *klass)
|
||||
list_base_class->list_item_augment_size = sizeof (CellAugment);
|
||||
list_base_class->list_item_augment_func = cell_augment;
|
||||
list_base_class->adjustment_value_changed = gtk_grid_view_adjustment_value_changed;
|
||||
list_base_class->move_focus_along = gtk_grid_view_move_focus_along;
|
||||
list_base_class->move_focus_across = gtk_grid_view_move_focus_across;
|
||||
|
||||
widget_class->focus = gtk_grid_view_focus;
|
||||
widget_class->measure = gtk_grid_view_measure;
|
||||
widget_class->size_allocate = gtk_grid_view_size_allocate;
|
||||
|
||||
@@ -1598,32 +1484,12 @@ gtk_grid_view_class_init (GtkGridViewClass *klass)
|
||||
|
||||
binding_set = gtk_binding_set_by_class (klass);
|
||||
|
||||
gtk_grid_view_add_move_binding (binding_set, GDK_KEY_Up, GTK_ORIENTATION_VERTICAL, -1);
|
||||
gtk_grid_view_add_move_binding (binding_set, GDK_KEY_KP_Up, GTK_ORIENTATION_VERTICAL, -1);
|
||||
gtk_grid_view_add_move_binding (binding_set, GDK_KEY_Down, GTK_ORIENTATION_VERTICAL, 1);
|
||||
gtk_grid_view_add_move_binding (binding_set, GDK_KEY_KP_Down, GTK_ORIENTATION_VERTICAL, 1);
|
||||
gtk_grid_view_add_move_binding (binding_set, GDK_KEY_Left, GTK_ORIENTATION_HORIZONTAL, -1);
|
||||
gtk_grid_view_add_move_binding (binding_set, GDK_KEY_KP_Left, GTK_ORIENTATION_HORIZONTAL, -1);
|
||||
gtk_grid_view_add_move_binding (binding_set, GDK_KEY_Right, GTK_ORIENTATION_HORIZONTAL, 1);
|
||||
gtk_grid_view_add_move_binding (binding_set, GDK_KEY_KP_Right, GTK_ORIENTATION_HORIZONTAL, 1);
|
||||
|
||||
gtk_grid_view_add_custom_move_binding (binding_set, GDK_KEY_Home, gtk_grid_view_move_cursor_to_start);
|
||||
gtk_grid_view_add_custom_move_binding (binding_set, GDK_KEY_KP_Home, gtk_grid_view_move_cursor_to_start);
|
||||
gtk_grid_view_add_custom_move_binding (binding_set, GDK_KEY_End, gtk_grid_view_move_cursor_to_end);
|
||||
gtk_grid_view_add_custom_move_binding (binding_set, GDK_KEY_KP_End, gtk_grid_view_move_cursor_to_end);
|
||||
gtk_grid_view_add_custom_move_binding (binding_set, GDK_KEY_Page_Up, gtk_grid_view_move_cursor_page_up);
|
||||
gtk_grid_view_add_custom_move_binding (binding_set, GDK_KEY_KP_Page_Up, gtk_grid_view_move_cursor_page_up);
|
||||
gtk_grid_view_add_custom_move_binding (binding_set, GDK_KEY_Page_Down, gtk_grid_view_move_cursor_page_down);
|
||||
gtk_grid_view_add_custom_move_binding (binding_set, GDK_KEY_KP_Page_Down, gtk_grid_view_move_cursor_page_down);
|
||||
|
||||
gtk_binding_entry_add_action (binding_set, GDK_KEY_a, GDK_CONTROL_MASK, "list.select-all", NULL);
|
||||
gtk_binding_entry_add_action (binding_set, GDK_KEY_slash, GDK_CONTROL_MASK, "list.select-all", NULL);
|
||||
|
||||
gtk_binding_entry_add_action (binding_set, GDK_KEY_A, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "list.unselect-all", NULL);
|
||||
gtk_binding_entry_add_action (binding_set, GDK_KEY_backslash, GDK_CONTROL_MASK, "list.unselect-all", NULL);
|
||||
|
||||
gtk_widget_class_set_css_name (widget_class, I_("flowbox"));
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "gtklistbaseprivate.h"
|
||||
|
||||
#include "gtkadjustment.h"
|
||||
#include "gtkbindings.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtkorientableprivate.h"
|
||||
#include "gtkscrollable.h"
|
||||
@@ -93,6 +94,68 @@ gtk_list_base_clear_adjustment (GtkListBase *self,
|
||||
g_clear_object (&priv->adjustment[orientation]);
|
||||
}
|
||||
|
||||
/*
|
||||
* gtk_list_base_move_focus_along:
|
||||
* @self: a #GtkListBase
|
||||
* @pos: position from which to move focus
|
||||
* @steps: steps to move focus - negative numbers
|
||||
* move focus backwards
|
||||
*
|
||||
* Moves focus @steps in the direction of the list.
|
||||
* If focus cannot be moved, @pos is returned.
|
||||
* If focus should be moved out of the widget, %GTK_INVALID_LIST_POSITION
|
||||
* is returned.
|
||||
*
|
||||
* Returns: new focus position
|
||||
**/
|
||||
static guint
|
||||
gtk_list_base_move_focus_along (GtkListBase *self,
|
||||
guint pos,
|
||||
int steps)
|
||||
{
|
||||
return GTK_LIST_BASE_GET_CLASS (self)->move_focus_along (self, pos, steps);
|
||||
}
|
||||
|
||||
/*
|
||||
* gtk_list_base_move_focus_across:
|
||||
* @self: a #GtkListBase
|
||||
* @pos: position from which to move focus
|
||||
* @steps: steps to move focus - negative numbers
|
||||
* move focus backwards
|
||||
*
|
||||
* Moves focus @steps in the direction across the list.
|
||||
* If focus cannot be moved, @pos is returned.
|
||||
* If focus should be moved out of the widget, %GTK_INVALID_LIST_POSITION
|
||||
* is returned.
|
||||
*
|
||||
* Returns: new focus position
|
||||
**/
|
||||
static guint
|
||||
gtk_list_base_move_focus_across (GtkListBase *self,
|
||||
guint pos,
|
||||
int steps)
|
||||
{
|
||||
return GTK_LIST_BASE_GET_CLASS (self)->move_focus_across (self, pos, steps);
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_list_base_move_focus (GtkListBase *self,
|
||||
guint pos,
|
||||
GtkOrientation orientation,
|
||||
int steps)
|
||||
{
|
||||
GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self);
|
||||
|
||||
if (orientation == GTK_ORIENTATION_HORIZONTAL &&
|
||||
gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL)
|
||||
steps = -steps;
|
||||
|
||||
if (orientation == priv->orientation)
|
||||
return gtk_list_base_move_focus_along (self, pos, steps);
|
||||
else
|
||||
return gtk_list_base_move_focus_across (self, pos, steps);
|
||||
}
|
||||
|
||||
/*
|
||||
* gtk_list_base_select_item:
|
||||
* @self: a %GtkListBase
|
||||
@@ -185,6 +248,108 @@ gtk_list_base_select_item (GtkListBase *self,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_list_base_get_n_items (GtkListBase *self)
|
||||
{
|
||||
GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self);
|
||||
GtkSelectionModel *model;
|
||||
|
||||
model = gtk_list_item_manager_get_model (priv->item_manager);
|
||||
if (model == NULL)
|
||||
return 0;
|
||||
|
||||
return g_list_model_get_n_items (G_LIST_MODEL (model));
|
||||
}
|
||||
|
||||
guint
|
||||
gtk_list_base_get_focus_position (GtkListBase *self)
|
||||
{
|
||||
#if 0
|
||||
GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self);
|
||||
|
||||
return gtk_list_item_tracker_get_position (priv->item_manager, priv->focus);
|
||||
#else
|
||||
GtkWidget *focus_child = gtk_widget_get_focus_child (GTK_WIDGET (self));
|
||||
if (focus_child)
|
||||
return gtk_list_item_get_position (GTK_LIST_ITEM (focus_child));
|
||||
else
|
||||
return GTK_INVALID_LIST_POSITION;
|
||||
#endif
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_list_base_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
GtkListBase *self = GTK_LIST_BASE (widget);
|
||||
guint old, pos, n_items;
|
||||
|
||||
pos = gtk_list_base_get_focus_position (self);
|
||||
n_items = gtk_list_base_get_n_items (self);
|
||||
old = pos;
|
||||
|
||||
if (pos >= n_items)
|
||||
{
|
||||
if (n_items == 0)
|
||||
return FALSE;
|
||||
|
||||
pos = 0;
|
||||
}
|
||||
else if (gtk_widget_get_focus_child (widget) == NULL)
|
||||
{
|
||||
/* Focus was outside the list, just grab the old focus item
|
||||
* while keeping the selection intact.
|
||||
*/
|
||||
return gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), pos, FALSE, FALSE, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (direction)
|
||||
{
|
||||
case GTK_DIR_TAB_FORWARD:
|
||||
pos++;
|
||||
if (pos >= n_items)
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
case GTK_DIR_TAB_BACKWARD:
|
||||
if (pos == 0)
|
||||
return FALSE;
|
||||
pos--;
|
||||
break;
|
||||
|
||||
case GTK_DIR_UP:
|
||||
pos = gtk_list_base_move_focus (self, pos, GTK_ORIENTATION_VERTICAL, -1);
|
||||
break;
|
||||
|
||||
case GTK_DIR_DOWN:
|
||||
pos = gtk_list_base_move_focus (self, pos, GTK_ORIENTATION_VERTICAL, 1);
|
||||
break;
|
||||
|
||||
case GTK_DIR_LEFT:
|
||||
pos = gtk_list_base_move_focus (self, pos, GTK_ORIENTATION_HORIZONTAL, -1);
|
||||
break;
|
||||
|
||||
case GTK_DIR_RIGHT:
|
||||
pos = gtk_list_base_move_focus (self, pos, GTK_ORIENTATION_HORIZONTAL, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (old != pos)
|
||||
{
|
||||
return gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), pos, TRUE, FALSE, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_list_base_dispose (GObject *object)
|
||||
{
|
||||
@@ -378,13 +543,126 @@ gtk_list_base_unselect_all (GtkWidget *widget,
|
||||
gtk_selection_model_unselect_all (selection_model);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_list_base_move_cursor_to_start (GtkWidget *widget,
|
||||
GVariant *args,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkListBase *self = GTK_LIST_BASE (widget);
|
||||
gboolean select, modify, extend;
|
||||
|
||||
if (gtk_list_base_get_n_items (self) == 0)
|
||||
return;
|
||||
|
||||
g_variant_get (args, "(bbb)", &select, &modify, &extend);
|
||||
|
||||
gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), 0, select, modify, extend);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_list_base_move_cursor_to_end (GtkWidget *widget,
|
||||
GVariant *args,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkListBase *self = GTK_LIST_BASE (widget);
|
||||
gboolean select, modify, extend;
|
||||
guint n_items;
|
||||
|
||||
n_items = gtk_list_base_get_n_items (self);
|
||||
if (n_items == 0)
|
||||
return;
|
||||
|
||||
g_variant_get (args, "(bbb)", &select, &modify, &extend);
|
||||
|
||||
gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), n_items - 1, select, modify, extend);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_list_base_move_cursor (GtkWidget *widget,
|
||||
GVariant *args,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkListBase *self = GTK_LIST_BASE (widget);
|
||||
int amount;
|
||||
guint orientation;
|
||||
guint pos;
|
||||
gboolean select, modify, extend;
|
||||
|
||||
g_variant_get (args, "(ubbbi)", &orientation, &select, &modify, &extend, &amount);
|
||||
|
||||
pos = gtk_list_base_get_focus_position (self);
|
||||
pos = gtk_list_base_move_focus (self, pos, orientation, amount);
|
||||
|
||||
gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), pos, select, modify, extend);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_list_base_add_move_binding (GtkBindingSet *binding_set,
|
||||
guint keyval,
|
||||
GtkOrientation orientation,
|
||||
int amount)
|
||||
{
|
||||
gtk_binding_entry_add_callback (binding_set,
|
||||
keyval,
|
||||
GDK_CONTROL_MASK,
|
||||
gtk_list_base_move_cursor,
|
||||
g_variant_new ("(ubbbi)", orientation, FALSE, FALSE, FALSE, amount),
|
||||
NULL, NULL);
|
||||
gtk_binding_entry_add_callback (binding_set,
|
||||
keyval,
|
||||
GDK_SHIFT_MASK,
|
||||
gtk_list_base_move_cursor,
|
||||
g_variant_new ("(ubbbi)", orientation, TRUE, FALSE, TRUE, amount),
|
||||
NULL, NULL);
|
||||
gtk_binding_entry_add_callback (binding_set,
|
||||
keyval,
|
||||
GDK_CONTROL_MASK | GDK_SHIFT_MASK,
|
||||
gtk_list_base_move_cursor,
|
||||
g_variant_new ("(ubbbi)", orientation, TRUE, TRUE, TRUE, amount),
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_list_base_add_custom_move_binding (GtkBindingSet *binding_set,
|
||||
guint keyval,
|
||||
GtkBindingCallback callback)
|
||||
{
|
||||
gtk_binding_entry_add_callback (binding_set,
|
||||
keyval,
|
||||
0,
|
||||
callback,
|
||||
g_variant_new ("(bbb)", TRUE, FALSE, FALSE),
|
||||
NULL, NULL);
|
||||
gtk_binding_entry_add_callback (binding_set,
|
||||
keyval,
|
||||
GDK_CONTROL_MASK,
|
||||
callback,
|
||||
g_variant_new ("(bbb)", FALSE, FALSE, FALSE),
|
||||
NULL, NULL);
|
||||
gtk_binding_entry_add_callback (binding_set,
|
||||
keyval,
|
||||
GDK_SHIFT_MASK,
|
||||
callback,
|
||||
g_variant_new ("(bbb)", TRUE, FALSE, TRUE),
|
||||
NULL, NULL);
|
||||
gtk_binding_entry_add_callback (binding_set,
|
||||
keyval,
|
||||
GDK_CONTROL_MASK | GDK_SHIFT_MASK,
|
||||
callback,
|
||||
g_variant_new ("(bbb)", TRUE, TRUE, TRUE),
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_list_base_class_init (GtkListBaseClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GtkBindingSet *binding_set;
|
||||
gpointer iface;
|
||||
|
||||
widget_class->focus = gtk_list_base_focus;
|
||||
|
||||
gobject_class->dispose = gtk_list_base_dispose;
|
||||
gobject_class->get_property = gtk_list_base_get_property;
|
||||
gobject_class->set_property = gtk_list_base_set_property;
|
||||
@@ -465,6 +743,26 @@ gtk_list_base_class_init (GtkListBaseClass *klass)
|
||||
NULL,
|
||||
gtk_list_base_unselect_all);
|
||||
|
||||
binding_set = gtk_binding_set_by_class (klass);
|
||||
|
||||
gtk_list_base_add_move_binding (binding_set, GDK_KEY_Up, GTK_ORIENTATION_VERTICAL, -1);
|
||||
gtk_list_base_add_move_binding (binding_set, GDK_KEY_KP_Up, GTK_ORIENTATION_VERTICAL, -1);
|
||||
gtk_list_base_add_move_binding (binding_set, GDK_KEY_Down, GTK_ORIENTATION_VERTICAL, 1);
|
||||
gtk_list_base_add_move_binding (binding_set, GDK_KEY_KP_Down, GTK_ORIENTATION_VERTICAL, 1);
|
||||
gtk_list_base_add_move_binding (binding_set, GDK_KEY_Left, GTK_ORIENTATION_HORIZONTAL, -1);
|
||||
gtk_list_base_add_move_binding (binding_set, GDK_KEY_KP_Left, GTK_ORIENTATION_HORIZONTAL, -1);
|
||||
gtk_list_base_add_move_binding (binding_set, GDK_KEY_Right, GTK_ORIENTATION_HORIZONTAL, 1);
|
||||
gtk_list_base_add_move_binding (binding_set, GDK_KEY_KP_Right, GTK_ORIENTATION_HORIZONTAL, 1);
|
||||
|
||||
gtk_list_base_add_custom_move_binding (binding_set, GDK_KEY_Home, gtk_list_base_move_cursor_to_start);
|
||||
gtk_list_base_add_custom_move_binding (binding_set, GDK_KEY_KP_Home, gtk_list_base_move_cursor_to_start);
|
||||
gtk_list_base_add_custom_move_binding (binding_set, GDK_KEY_End, gtk_list_base_move_cursor_to_end);
|
||||
gtk_list_base_add_custom_move_binding (binding_set, GDK_KEY_KP_End, gtk_list_base_move_cursor_to_end);
|
||||
|
||||
gtk_binding_entry_add_action (binding_set, GDK_KEY_a, GDK_CONTROL_MASK, "list.select-all", NULL);
|
||||
gtk_binding_entry_add_action (binding_set, GDK_KEY_slash, GDK_CONTROL_MASK, "list.select-all", NULL);
|
||||
gtk_binding_entry_add_action (binding_set, GDK_KEY_A, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "list.unselect-all", NULL);
|
||||
gtk_binding_entry_add_action (binding_set, GDK_KEY_backslash, GDK_CONTROL_MASK, "list.unselect-all", NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -41,10 +41,17 @@ struct _GtkListBaseClass
|
||||
|
||||
void (* adjustment_value_changed) (GtkListBase *self,
|
||||
GtkOrientation orientation);
|
||||
guint (* move_focus_along) (GtkListBase *self,
|
||||
guint pos,
|
||||
int steps);
|
||||
guint (* move_focus_across) (GtkListBase *self,
|
||||
guint pos,
|
||||
int steps);
|
||||
};
|
||||
|
||||
GtkOrientation gtk_list_base_get_orientation (GtkListBase *self);
|
||||
#define gtk_list_base_get_opposite_orientation(self) OPPOSITE_ORIENTATION(gtk_list_base_get_orientation(self))
|
||||
guint gtk_list_base_get_focus_position (GtkListBase *self);
|
||||
GtkListItemManager * gtk_list_base_get_manager (GtkListBase *self);
|
||||
GtkScrollablePolicy gtk_list_base_get_scroll_policy (GtkListBase *self,
|
||||
GtkOrientation orientation);
|
||||
|
||||
@@ -393,6 +393,32 @@ gtk_list_view_adjustment_value_changed (GtkListBase *base,
|
||||
gtk_widget_queue_allocate (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_list_view_move_focus_along (GtkListBase *base,
|
||||
guint pos,
|
||||
int steps)
|
||||
{
|
||||
GtkListView *self = GTK_LIST_VIEW (base);
|
||||
|
||||
if (steps < 0)
|
||||
return pos - MIN (pos, -steps);
|
||||
else
|
||||
{
|
||||
guint n_items = self->model ? g_list_model_get_n_items (self->model) : 0;
|
||||
pos += MIN (n_items - pos - 1, steps);
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_list_view_move_focus_across (GtkListBase *base,
|
||||
guint pos,
|
||||
int steps)
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
|
||||
static int
|
||||
gtk_list_view_update_adjustments (GtkListView *self,
|
||||
GtkOrientation orientation)
|
||||
@@ -689,62 +715,6 @@ gtk_list_view_size_allocate (GtkWidget *widget,
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_list_view_focus (GtkWidget *widget,
|
||||
GtkDirectionType direction)
|
||||
{
|
||||
GtkListView *self = GTK_LIST_VIEW (widget);
|
||||
GtkWidget *old_focus_child, *new_focus_child;
|
||||
|
||||
old_focus_child = gtk_widget_get_focus_child (widget);
|
||||
|
||||
if (old_focus_child == NULL &&
|
||||
(direction == GTK_DIR_TAB_FORWARD || direction == GTK_DIR_TAB_BACKWARD))
|
||||
{
|
||||
ListRow *row;
|
||||
guint pos;
|
||||
|
||||
/* When tabbing into the listview, don't focus the first/last item,
|
||||
* but keep the previously focused item
|
||||
*/
|
||||
pos = gtk_list_item_tracker_get_position (self->item_manager, self->focus);
|
||||
row = gtk_list_item_manager_get_nth (self->item_manager, pos, NULL);
|
||||
if (row && gtk_widget_grab_focus (row->parent.widget))
|
||||
goto moved_focus;
|
||||
}
|
||||
|
||||
if (!GTK_WIDGET_CLASS (gtk_list_view_parent_class)->focus (widget, direction))
|
||||
return FALSE;
|
||||
|
||||
moved_focus:
|
||||
new_focus_child = gtk_widget_get_focus_child (widget);
|
||||
|
||||
if (old_focus_child != new_focus_child &&
|
||||
GTK_IS_LIST_ITEM (new_focus_child))
|
||||
{
|
||||
GdkModifierType state;
|
||||
GdkModifierType mask;
|
||||
gboolean extend = FALSE, modify = FALSE;
|
||||
|
||||
if (old_focus_child && gtk_get_current_event_state (&state))
|
||||
{
|
||||
mask = gtk_widget_get_modifier_mask (widget, GDK_MODIFIER_INTENT_MODIFY_SELECTION);
|
||||
if ((state & mask) == mask)
|
||||
modify = TRUE;
|
||||
mask = gtk_widget_get_modifier_mask (widget, GDK_MODIFIER_INTENT_EXTEND_SELECTION);
|
||||
if ((state & mask) == mask)
|
||||
extend = TRUE;
|
||||
}
|
||||
|
||||
gtk_list_base_select_item (GTK_LIST_BASE (self),
|
||||
gtk_list_item_get_position (GTK_LIST_ITEM (new_focus_child)),
|
||||
modify,
|
||||
extend);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_list_view_dispose (GObject *object)
|
||||
{
|
||||
@@ -962,76 +932,6 @@ gtk_list_view_activate_item (GtkWidget *widget,
|
||||
g_signal_emit (widget, signals[ACTIVATE], 0, pos);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_list_view_move_cursor (GtkWidget *widget,
|
||||
GVariant *args,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkListView *self = GTK_LIST_VIEW (widget);
|
||||
int amount;
|
||||
guint orientation;
|
||||
guint pos, new_pos, n_items;
|
||||
gboolean select, modify, extend;
|
||||
|
||||
g_variant_get (args, "(ubbbi)", &orientation, &select, &modify, &extend, &amount);
|
||||
|
||||
if (gtk_list_base_get_orientation (GTK_LIST_BASE (self)) != orientation)
|
||||
return;
|
||||
|
||||
if (orientation == GTK_ORIENTATION_HORIZONTAL &&
|
||||
gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
|
||||
amount = -amount;
|
||||
|
||||
pos = gtk_list_item_tracker_get_position (self->item_manager, self->focus);
|
||||
n_items = self->model ? g_list_model_get_n_items (self->model) : 0;
|
||||
if (pos >= n_items)
|
||||
return;
|
||||
|
||||
new_pos = pos + amount;
|
||||
/* This overflow check only works reliably for amount == 1 */
|
||||
if (new_pos >= n_items)
|
||||
return;
|
||||
|
||||
gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), new_pos, select, modify, extend);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_list_view_move_cursor_to_start (GtkWidget *widget,
|
||||
GVariant *args,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkListView *self = GTK_LIST_VIEW (widget);
|
||||
gboolean select, modify, extend;
|
||||
|
||||
if (self->model == NULL || g_list_model_get_n_items (self->model) == 0)
|
||||
return;
|
||||
|
||||
g_variant_get (args, "(bbb)", &select, &modify, &extend);
|
||||
|
||||
gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), 0, select, modify, extend);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_list_view_move_cursor_to_end (GtkWidget *widget,
|
||||
GVariant *args,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkListView *self = GTK_LIST_VIEW (widget);
|
||||
gboolean select, modify, extend;
|
||||
guint n_items;
|
||||
|
||||
if (self->model == NULL)
|
||||
return;
|
||||
|
||||
n_items = g_list_model_get_n_items (self->model);
|
||||
if (n_items == 0)
|
||||
return;
|
||||
|
||||
g_variant_get (args, "(bbb)", &select, &modify, &extend);
|
||||
|
||||
gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), n_items - 1, select, modify, extend);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_list_view_move_cursor_page_up (GtkWidget *widget,
|
||||
GVariant *args,
|
||||
@@ -1144,32 +1044,6 @@ gtk_list_view_add_custom_move_binding (GtkBindingSet *binding_set,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_list_view_add_move_binding (GtkBindingSet *binding_set,
|
||||
guint keyval,
|
||||
GtkOrientation orientation,
|
||||
int amount)
|
||||
{
|
||||
gtk_binding_entry_add_callback (binding_set,
|
||||
keyval,
|
||||
GDK_CONTROL_MASK,
|
||||
gtk_list_view_move_cursor,
|
||||
g_variant_new ("(ubbbi)", orientation, FALSE, FALSE, FALSE, amount),
|
||||
NULL, NULL);
|
||||
gtk_binding_entry_add_callback (binding_set,
|
||||
keyval,
|
||||
GDK_SHIFT_MASK,
|
||||
gtk_list_view_move_cursor,
|
||||
g_variant_new ("(ubbbi)", orientation, TRUE, FALSE, TRUE, amount),
|
||||
NULL, NULL);
|
||||
gtk_binding_entry_add_callback (binding_set,
|
||||
keyval,
|
||||
GDK_CONTROL_MASK | GDK_SHIFT_MASK,
|
||||
gtk_list_view_move_cursor,
|
||||
g_variant_new ("(ubbbi)", orientation, TRUE, TRUE, TRUE, amount),
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_list_view_class_init (GtkListViewClass *klass)
|
||||
{
|
||||
@@ -1183,10 +1057,11 @@ gtk_list_view_class_init (GtkListViewClass *klass)
|
||||
list_base_class->list_item_augment_size = sizeof (ListRowAugment);
|
||||
list_base_class->list_item_augment_func = list_row_augment;
|
||||
list_base_class->adjustment_value_changed = gtk_list_view_adjustment_value_changed;
|
||||
list_base_class->move_focus_along = gtk_list_view_move_focus_along;
|
||||
list_base_class->move_focus_across = gtk_list_view_move_focus_across;
|
||||
|
||||
widget_class->measure = gtk_list_view_measure;
|
||||
widget_class->size_allocate = gtk_list_view_size_allocate;
|
||||
widget_class->focus = gtk_list_view_focus;
|
||||
|
||||
gobject_class->dispose = gtk_list_view_dispose;
|
||||
gobject_class->get_property = gtk_list_view_get_property;
|
||||
@@ -1280,30 +1155,11 @@ gtk_list_view_class_init (GtkListViewClass *klass)
|
||||
|
||||
binding_set = gtk_binding_set_by_class (klass);
|
||||
|
||||
gtk_list_view_add_move_binding (binding_set, GDK_KEY_Up, GTK_ORIENTATION_VERTICAL, -1);
|
||||
gtk_list_view_add_move_binding (binding_set, GDK_KEY_KP_Up, GTK_ORIENTATION_VERTICAL, -1);
|
||||
gtk_list_view_add_move_binding (binding_set, GDK_KEY_Down, GTK_ORIENTATION_VERTICAL, 1);
|
||||
gtk_list_view_add_move_binding (binding_set, GDK_KEY_KP_Down, GTK_ORIENTATION_VERTICAL, 1);
|
||||
gtk_list_view_add_move_binding (binding_set, GDK_KEY_Left, GTK_ORIENTATION_HORIZONTAL, -1);
|
||||
gtk_list_view_add_move_binding (binding_set, GDK_KEY_KP_Left, GTK_ORIENTATION_HORIZONTAL, -1);
|
||||
gtk_list_view_add_move_binding (binding_set, GDK_KEY_Right, GTK_ORIENTATION_HORIZONTAL, 1);
|
||||
gtk_list_view_add_move_binding (binding_set, GDK_KEY_KP_Right, GTK_ORIENTATION_HORIZONTAL, 1);
|
||||
|
||||
gtk_list_view_add_custom_move_binding (binding_set, GDK_KEY_Home, gtk_list_view_move_cursor_to_start);
|
||||
gtk_list_view_add_custom_move_binding (binding_set, GDK_KEY_KP_Home, gtk_list_view_move_cursor_to_start);
|
||||
gtk_list_view_add_custom_move_binding (binding_set, GDK_KEY_End, gtk_list_view_move_cursor_to_end);
|
||||
gtk_list_view_add_custom_move_binding (binding_set, GDK_KEY_KP_End, gtk_list_view_move_cursor_to_end);
|
||||
gtk_list_view_add_custom_move_binding (binding_set, GDK_KEY_Page_Up, gtk_list_view_move_cursor_page_up);
|
||||
gtk_list_view_add_custom_move_binding (binding_set, GDK_KEY_KP_Page_Up, gtk_list_view_move_cursor_page_up);
|
||||
gtk_list_view_add_custom_move_binding (binding_set, GDK_KEY_Page_Down, gtk_list_view_move_cursor_page_down);
|
||||
gtk_list_view_add_custom_move_binding (binding_set, GDK_KEY_KP_Page_Down, gtk_list_view_move_cursor_page_down);
|
||||
|
||||
gtk_binding_entry_add_action (binding_set, GDK_KEY_a, GDK_CONTROL_MASK, "list.select-all", NULL);
|
||||
gtk_binding_entry_add_action (binding_set, GDK_KEY_slash, GDK_CONTROL_MASK, "list.select-all", NULL);
|
||||
|
||||
gtk_binding_entry_add_action (binding_set, GDK_KEY_A, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "list.unselect-all", NULL);
|
||||
gtk_binding_entry_add_action (binding_set, GDK_KEY_backslash, GDK_CONTROL_MASK, "list.unselect-all", NULL);
|
||||
|
||||
gtk_widget_class_set_css_name (widget_class, I_("list"));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user