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.
This commit is contained in:
Benjamin Otte
2018-10-05 23:24:18 +02:00
parent 46fa122c98
commit be4fe26fef
6 changed files with 130 additions and 18 deletions

View File

@@ -22,7 +22,9 @@
#include "gtklistitemprivate.h"
#include "gtkcssnodeprivate.h"
#include "gtkgesturemultipress.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,22 +205,101 @@ gtk_list_item_class_init (GtkListItemClass *klass)
gtk_widget_class_set_css_name (widget_class, I_("row"));
}
static void
gtk_list_item_multipress_gesture_pressed (GtkGestureMultiPress *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_multipress_gesture_released (GtkGestureMultiPress *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_multipress_gesture_canceled (GtkGestureMultiPress *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;
gtk_widget_set_has_surface (GTK_WIDGET (self), FALSE);
self->selectable = TRUE;
gtk_widget_set_can_focus (GTK_WIDGET (self), TRUE);
gesture = gtk_gesture_multi_press_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_multipress_gesture_pressed), self);
g_signal_connect (gesture, "released",
G_CALLBACK (gtk_list_item_multipress_gesture_released), self);
g_signal_connect (gesture, "cancel",
G_CALLBACK (gtk_list_item_multipress_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;
}
/**
@@ -370,5 +453,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]);
}

View File

@@ -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

View File

@@ -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,

View File

@@ -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);

View File

@@ -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,

View File

@@ -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);