[gtk/wip/otte/listview: 111/119] listitem: Add a press gesture to select the item
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/listview: 111/119] listitem: Add a press gesture to select the item
- Date: Mon, 3 Jun 2019 18:53:25 +0000 (UTC)
commit b475ea664c11c0e5cdab71525854d692b3f01d0a
Author: Benjamin Otte <otte redhat com>
Date: Fri Oct 5 23:24:18 2018 +0200
listitem: Add a press gesture to select the item
This requires a bunch of refactoring because so far the ListItem had no
knowledge of the manager, but it needs the manager so it can access the
selection to trigger the select/unselect operation.
gtk/gtklistitem.c | 95 ++++++++++++++++++++++++++++++++++++++---
gtk/gtklistitemfactory.c | 15 +++----
gtk/gtklistitemfactoryprivate.h | 3 +-
gtk/gtklistitemmanager.c | 25 ++++++++++-
gtk/gtklistitemmanagerprivate.h | 5 +++
gtk/gtklistitemprivate.h | 5 ++-
6 files changed, 130 insertions(+), 18 deletions(-)
---
diff --git a/gtk/gtklistitem.c b/gtk/gtklistitem.c
index 822e4e8944..2844cf853f 100644
--- a/gtk/gtklistitem.c
+++ b/gtk/gtklistitem.c
@@ -22,7 +22,9 @@
#include "gtklistitemprivate.h"
#include "gtkcssnodeprivate.h"
+#include "gtkgestureclick.h"
#include "gtkintl.h"
+#include "gtkmain.h"
#include "gtkwidgetprivate.h"
/**
@@ -53,6 +55,8 @@ struct _GtkListItem
{
GtkBin parent_instance;
+ GtkListItemManager *manager; /* no ref, the manager refs us */
+
GObject *item;
guint position;
@@ -201,20 +205,99 @@ gtk_list_item_class_init (GtkListItemClass *klass)
gtk_widget_class_set_css_name (widget_class, I_("row"));
}
+static void
+gtk_list_item_click_gesture_pressed (GtkGestureClick *gesture,
+ int n_press,
+ double x,
+ double y,
+ GtkListItem *self)
+{
+ GtkWidget *widget = GTK_WIDGET (self);
+ GdkModifierType state;
+ GdkModifierType mask;
+ gboolean extend = FALSE, modify = FALSE;
+
+ if (!self->selectable)
+ {
+ gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
+ return;
+ }
+
+ if (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_item_manager_select (self->manager, self, modify, extend);
+
+ gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_ACTIVE, FALSE);
+
+ if (gtk_widget_get_focus_on_click (widget))
+ gtk_widget_grab_focus (widget);
+}
+
+static void
+gtk_list_item_click_gesture_released (GtkGestureClick *gesture,
+ int n_press,
+ double x,
+ double y,
+ GtkListItem *self)
+{
+ gtk_widget_unset_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_ACTIVE);
+}
+
+static void
+gtk_list_item_click_gesture_canceled (GtkGestureClick *gesture,
+ GdkEventSequence *sequence,
+ GtkListItem *self)
+{
+ gtk_widget_unset_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_ACTIVE);
+}
+
static void
gtk_list_item_init (GtkListItem *self)
{
+ GtkGesture *gesture;
+
self->selectable = TRUE;
+ gtk_widget_set_can_focus (GTK_WIDGET (self), TRUE);
+
+ gesture = gtk_gesture_click_new ();
+ gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (gesture),
+ GTK_PHASE_BUBBLE);
+ gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (gesture),
+ FALSE);
+ gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture),
+ GDK_BUTTON_PRIMARY);
+ g_signal_connect (gesture, "pressed",
+ G_CALLBACK (gtk_list_item_click_gesture_pressed), self);
+ g_signal_connect (gesture, "released",
+ G_CALLBACK (gtk_list_item_click_gesture_released), 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));
}
-GtkWidget *
-gtk_list_item_new (const char *css_name)
+GtkListItem *
+gtk_list_item_new (GtkListItemManager *manager,
+ const char *css_name)
{
+ GtkListItem *result;
+
g_return_val_if_fail (css_name != NULL, NULL);
- return g_object_new (GTK_TYPE_LIST_ITEM,
- "css-name", css_name,
- NULL);
+ result = g_object_new (GTK_TYPE_LIST_ITEM,
+ "css-name", css_name,
+ NULL);
+
+ result->manager = manager;
+
+ return result;
}
/**
@@ -368,5 +451,7 @@ gtk_list_item_set_selectable (GtkListItem *self,
self->selectable = selectable;
+ gtk_widget_set_can_focus (GTK_WIDGET (self), self->selectable);
+
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTABLE]);
}
diff --git a/gtk/gtklistitemfactory.c b/gtk/gtklistitemfactory.c
index 454344ae9b..d701918ea1 100644
--- a/gtk/gtklistitemfactory.c
+++ b/gtk/gtklistitemfactory.c
@@ -85,19 +85,14 @@ gtk_list_item_factory_new (GtkListItemSetupFunc setup_func,
return self;
}
-GtkListItem *
-gtk_list_item_factory_create (GtkListItemFactory *self)
+void
+gtk_list_item_factory_setup (GtkListItemFactory *self,
+ GtkListItem *list_item)
{
- GtkWidget *result;
-
- g_return_val_if_fail (GTK_IS_LIST_ITEM_FACTORY (self), NULL);
-
- result = gtk_list_item_new ("row");
+ g_return_if_fail (GTK_IS_LIST_ITEM_FACTORY (self));
if (self->setup_func)
- self->setup_func (GTK_LIST_ITEM (result), self->user_data);
-
- return GTK_LIST_ITEM (result);
+ self->setup_func (list_item, self->user_data);
}
void
diff --git a/gtk/gtklistitemfactoryprivate.h b/gtk/gtklistitemfactoryprivate.h
index 3e815fa131..dc538f09fa 100644
--- a/gtk/gtklistitemfactoryprivate.h
+++ b/gtk/gtklistitemfactoryprivate.h
@@ -43,7 +43,8 @@ GtkListItemFactory * gtk_list_item_factory_new (GtkListItemSetu
gpointer user_data,
GDestroyNotify user_destroy);
-GtkListItem * gtk_list_item_factory_create (GtkListItemFactory *self);
+void gtk_list_item_factory_setup (GtkListItemFactory *self,
+ GtkListItem *list_item);
void gtk_list_item_factory_bind (GtkListItemFactory *self,
GtkListItem *list_item,
diff --git a/gtk/gtklistitemmanager.c b/gtk/gtklistitemmanager.c
index e7c11f483f..9d8fbbc85a 100644
--- a/gtk/gtklistitemmanager.c
+++ b/gtk/gtklistitemmanager.c
@@ -21,6 +21,7 @@
#include "gtklistitemmanagerprivate.h"
+#include "gtklistitemprivate.h"
#include "gtkwidgetprivate.h"
struct _GtkListItemManager
@@ -129,6 +130,27 @@ gtk_list_item_manager_get_model (GtkListItemManager *self)
return self->model;
}
+void
+gtk_list_item_manager_select (GtkListItemManager *self,
+ GtkListItem *item,
+ gboolean modify,
+ gboolean extend)
+{
+ guint pos = gtk_list_item_get_position (item);
+
+ if (modify)
+ {
+ if (gtk_list_item_get_selected (item))
+ gtk_selection_model_unselect_item (self->model, pos);
+ else
+ gtk_selection_model_select_item (self->model, pos, FALSE);
+ }
+ else
+ {
+ gtk_selection_model_select_item (self->model, pos, TRUE);
+ }
+}
+
#if 0
/*
* gtk_list_item_manager_get_size:
@@ -260,7 +282,8 @@ gtk_list_item_manager_acquire_list_item (GtkListItemManager *self,
g_return_val_if_fail (GTK_IS_LIST_ITEM_MANAGER (self), NULL);
g_return_val_if_fail (prev_sibling == NULL || GTK_IS_WIDGET (prev_sibling), NULL);
- result = gtk_list_item_factory_create (self->factory);
+ result = gtk_list_item_new (self, "row");
+ gtk_list_item_factory_setup (self->factory, result);
item = g_list_model_get_item (G_LIST_MODEL (self->model), position);
selected = gtk_selection_model_is_selected (self->model, position);
diff --git a/gtk/gtklistitemmanagerprivate.h b/gtk/gtklistitemmanagerprivate.h
index 47a4434d7d..bd189539d6 100644
--- a/gtk/gtklistitemmanagerprivate.h
+++ b/gtk/gtklistitemmanagerprivate.h
@@ -52,6 +52,11 @@ GtkSelectionModel * gtk_list_item_manager_get_model (GtkListItemMana
guint gtk_list_item_manager_get_size (GtkListItemManager *self);
+void gtk_list_item_manager_select (GtkListItemManager *self,
+ GtkListItem *item,
+ gboolean modify,
+ gboolean extend);
+
GtkListItemManagerChange *
gtk_list_item_manager_begin_change (GtkListItemManager *self);
void gtk_list_item_manager_end_change (GtkListItemManager *self,
diff --git a/gtk/gtklistitemprivate.h b/gtk/gtklistitemprivate.h
index 08ed82f162..141471ecd7 100644
--- a/gtk/gtklistitemprivate.h
+++ b/gtk/gtklistitemprivate.h
@@ -22,9 +22,12 @@
#include "gtklistitem.h"
+#include "gtklistitemmanagerprivate.h"
+
G_BEGIN_DECLS
-GtkWidget * gtk_list_item_new (const char *css_name);
+GtkListItem * gtk_list_item_new (GtkListItemManager *manager,
+ const char *css_name);
void gtk_list_item_set_item (GtkListItem *self,
gpointer item);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]