listview: Add list.scroll_to_item action
The action scrolls the given item into view. Listitems activate this action when they gain focus.
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
#include "gtklistitemprivate.h"
|
||||
|
||||
#include "gtkcssnodeprivate.h"
|
||||
#include "gtkeventcontrollerkey.h"
|
||||
#include "gtkgestureclick.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtkmain.h"
|
||||
@@ -242,6 +243,22 @@ gtk_list_item_click_gesture_pressed (GtkGestureClick *gesture,
|
||||
gtk_widget_grab_focus (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_list_item_focus_changed_cb (GtkEventControllerKey *controller,
|
||||
GParamSpec *psepc,
|
||||
GtkListItem *self)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (self);
|
||||
|
||||
if (gtk_event_controller_key_contains_focus (controller))
|
||||
{
|
||||
gtk_widget_activate_action (widget,
|
||||
"list.scroll-to-item",
|
||||
"u",
|
||||
self->position);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_list_item_click_gesture_released (GtkGestureClick *gesture,
|
||||
int n_press,
|
||||
@@ -263,6 +280,7 @@ gtk_list_item_click_gesture_canceled (GtkGestureClick *gesture,
|
||||
static void
|
||||
gtk_list_item_init (GtkListItem *self)
|
||||
{
|
||||
GtkEventController *controller;
|
||||
GtkGesture *gesture;
|
||||
|
||||
self->selectable = TRUE;
|
||||
@@ -282,6 +300,10 @@ gtk_list_item_init (GtkListItem *self)
|
||||
g_signal_connect (gesture, "cancel",
|
||||
G_CALLBACK (gtk_list_item_click_gesture_canceled), self);
|
||||
gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (gesture));
|
||||
|
||||
controller = gtk_event_controller_key_new ();
|
||||
g_signal_connect (controller, "notify::contains-focus", G_CALLBACK (gtk_list_item_focus_changed_cb), self);
|
||||
gtk_widget_add_controller (GTK_WIDGET (self), controller);
|
||||
}
|
||||
|
||||
GtkListItem *
|
||||
|
@@ -731,6 +731,48 @@ gtk_list_view_select_item (GtkWidget *widget,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_list_view_scroll_to_item (GtkWidget *widget,
|
||||
const char *action_name,
|
||||
GVariant *parameter)
|
||||
{
|
||||
GtkListView *self = GTK_LIST_VIEW (widget);
|
||||
ListRow *row;
|
||||
guint pos;
|
||||
|
||||
if (!g_variant_check_format_string (parameter, "u", FALSE))
|
||||
return;
|
||||
|
||||
g_variant_get (parameter, "u", &pos);
|
||||
row = gtk_list_item_manager_get_nth (self->item_manager, pos, NULL);
|
||||
if (row == NULL)
|
||||
return;
|
||||
|
||||
if (row->parent.widget)
|
||||
{
|
||||
int y = list_row_get_y (self, row);
|
||||
int start = gtk_adjustment_get_value (self->adjustment[GTK_ORIENTATION_VERTICAL]);
|
||||
int height = gtk_widget_get_height (GTK_WIDGET (self));
|
||||
double align;
|
||||
|
||||
if (y < start)
|
||||
align = 0.0;
|
||||
else if (y + row->height > start + height)
|
||||
align = 1.0;
|
||||
else
|
||||
align = (double) (y - start) / (height - row->height);
|
||||
|
||||
gtk_list_view_set_anchor (self, pos, align);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pos < gtk_list_item_tracker_get_position (self->item_manager, self->anchor))
|
||||
gtk_list_view_set_anchor (self, pos, 0.0);
|
||||
else
|
||||
gtk_list_view_set_anchor (self, pos, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_list_view_class_init (GtkListViewClass *klass)
|
||||
{
|
||||
@@ -810,6 +852,18 @@ gtk_list_view_class_init (GtkListViewClass *klass)
|
||||
"(ubb)",
|
||||
gtk_list_view_select_item);
|
||||
|
||||
/**
|
||||
* GtkListView|list.scroll-to-item:
|
||||
* @position: position of item to scroll to
|
||||
*
|
||||
* Scrolls to the item given in @position with the minimum amount
|
||||
* of scrolling required. If the item is already visible, nothing happens.
|
||||
*/
|
||||
gtk_widget_class_install_action (widget_class,
|
||||
"list.scroll-to-item",
|
||||
"u",
|
||||
gtk_list_view_scroll_to_item);
|
||||
|
||||
gtk_widget_class_set_css_name (widget_class, I_("list"));
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user