From: Benjamin Otte Date: Sun, 12 Mar 2023 04:05:48 +0000 (+0100) Subject: listitemwidget: split out GtkListItemBase X-Git-Tag: archive/raspbian/4.12.3+ds-1+rpi1~1^2^2^2~22^2~1^2~514^2~12 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=1f3a2734ebd9073f96d0170b4f30d863ced01518;p=gtk4.git listitemwidget: split out GtkListItemBase There's 2 reasons for this: 1. Adding a custom widget for columnview rows 2. Using this as base class for sections --- diff --git a/gtk/a11y/gtkatspiselection.c b/gtk/a11y/gtkatspiselection.c index db2c76c03e..7d67d5f062 100644 --- a/gtk/a11y/gtkatspiselection.c +++ b/gtk/a11y/gtkatspiselection.c @@ -256,7 +256,7 @@ listview_handle_method (GDBusConnection *connection, child; child = gtk_widget_get_next_sibling (child)) { - if (gtk_list_item_widget_get_selected (GTK_LIST_ITEM_WIDGET (child))) + if (gtk_list_item_base_get_selected (GTK_LIST_ITEM_BASE (child))) { if (idx == 0) break; @@ -303,7 +303,7 @@ listview_handle_method (GDBusConnection *connection, guint pos; gboolean ret; - pos = gtk_list_item_widget_get_position (GTK_LIST_ITEM_WIDGET (child)); + pos = gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (child)); ret = gtk_selection_model_select_item (model, pos, FALSE); g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", ret)); @@ -335,7 +335,7 @@ listview_handle_method (GDBusConnection *connection, guint pos; gboolean ret; - pos = gtk_list_item_widget_get_position (GTK_LIST_ITEM_WIDGET (child)); + pos = gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (child)); ret = gtk_selection_model_unselect_item (model, pos); g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", ret)); @@ -353,7 +353,7 @@ listview_handle_method (GDBusConnection *connection, child; child = gtk_widget_get_next_sibling (child)) { - if (gtk_list_item_widget_get_selected (GTK_LIST_ITEM_WIDGET (child))) + if (gtk_list_item_base_get_selected (GTK_LIST_ITEM_BASE (child))) { if (idx == 0) break; @@ -371,7 +371,7 @@ listview_handle_method (GDBusConnection *connection, guint pos; gboolean ret; - pos = gtk_list_item_widget_get_position (GTK_LIST_ITEM_WIDGET (child)); + pos = gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (child)); ret = gtk_selection_model_unselect_item (model, pos); g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", ret)); @@ -402,7 +402,7 @@ listview_handle_method (GDBusConnection *connection, { gboolean ret; - ret = gtk_list_item_widget_get_selected (GTK_LIST_ITEM_WIDGET (child)); + ret = gtk_list_item_base_get_selected (GTK_LIST_ITEM_BASE (child)); g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", ret)); } diff --git a/gtk/gtkcolumnlistitemfactory.c b/gtk/gtkcolumnlistitemfactory.c index 94a1695caa..e60057ab10 100644 --- a/gtk/gtkcolumnlistitemfactory.c +++ b/gtk/gtkcolumnlistitemfactory.c @@ -114,10 +114,10 @@ gtk_column_list_item_factory_update (GtkListItemFactory *factory, { GtkListItem *cell_item; - gtk_list_item_widget_update (GTK_LIST_ITEM_WIDGET (child), - gtk_list_item_get_position (list_item), - gtk_list_item_get_item (list_item), - gtk_list_item_get_selected (list_item)); + gtk_list_item_base_update (GTK_LIST_ITEM_BASE (child), + gtk_list_item_get_position (list_item), + gtk_list_item_get_item (list_item), + gtk_list_item_get_selected (list_item)); cell_item = gtk_list_item_widget_get_list_item (GTK_LIST_ITEM_WIDGET (child)); if (cell_item) @@ -169,12 +169,13 @@ gtk_column_list_item_factory_add_column (GtkColumnListItemFactory *factory, GtkColumnViewColumn *column, gboolean check_bind) { + GtkListItemBase *base = GTK_LIST_ITEM_BASE (list_item); GtkWidget *cell; cell = gtk_column_view_cell_new (column); gtk_list_item_widget_add_child (GTK_LIST_ITEM_WIDGET (list_item), GTK_WIDGET (cell)); - gtk_list_item_widget_update (GTK_LIST_ITEM_WIDGET (cell), - gtk_list_item_widget_get_position (list_item), - gtk_list_item_widget_get_item (list_item), - gtk_list_item_widget_get_selected (list_item)); + gtk_list_item_base_update (GTK_LIST_ITEM_BASE (cell), + gtk_list_item_base_get_position (base), + gtk_list_item_base_get_item (base), + gtk_list_item_base_get_selected (base)); } diff --git a/gtk/gtkcolumnviewcolumn.c b/gtk/gtkcolumnviewcolumn.c index c67fb50b0b..58432d7a33 100644 --- a/gtk/gtkcolumnviewcolumn.c +++ b/gtk/gtkcolumnviewcolumn.c @@ -529,18 +529,20 @@ gtk_column_view_column_create_cells (GtkColumnViewColumn *self) row = gtk_widget_get_next_sibling (row)) { GtkListItemWidget *list_item; + GtkListItemBase *base; GtkWidget *cell; if (!gtk_widget_get_root (row)) continue; list_item = GTK_LIST_ITEM_WIDGET (row); + base = GTK_LIST_ITEM_BASE (row); cell = gtk_column_view_cell_new (self); gtk_list_item_widget_add_child (list_item, cell); - gtk_list_item_widget_update (GTK_LIST_ITEM_WIDGET (cell), - gtk_list_item_widget_get_position (list_item), - gtk_list_item_widget_get_item (list_item), - gtk_list_item_widget_get_selected (list_item)); + gtk_list_item_base_update (GTK_LIST_ITEM_BASE (cell), + gtk_list_item_base_get_position (base), + gtk_list_item_base_get_item (base), + gtk_list_item_base_get_selected (base)); } } diff --git a/gtk/gtkdropdown.c b/gtk/gtkdropdown.c index 3fcfeb71f4..e0eea43d70 100644 --- a/gtk/gtkdropdown.c +++ b/gtk/gtkdropdown.c @@ -219,12 +219,12 @@ selection_changed (GtkSingleSelection *selection, gtk_stack_set_visible_child_name (GTK_STACK (self->button_stack), "item"); } - if (selected != gtk_list_item_widget_get_position (GTK_LIST_ITEM_WIDGET (self->button_item))) + if (selected != gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self->button_item))) { - gtk_list_item_widget_update (GTK_LIST_ITEM_WIDGET (self->button_item), - selected, - gtk_single_selection_get_selected_item (GTK_SINGLE_SELECTION (self->selection)), - FALSE); + gtk_list_item_base_update (GTK_LIST_ITEM_BASE (self->button_item), + selected, + gtk_single_selection_get_selected_item (GTK_SINGLE_SELECTION (self->selection)), + FALSE); } /* reset the filter so positions are 1-1 */ @@ -246,12 +246,12 @@ selection_item_changed (GtkSingleSelection *selection, item = gtk_single_selection_get_selected_item (GTK_SINGLE_SELECTION (self->selection)); - if (item != gtk_list_item_widget_get_item (GTK_LIST_ITEM_WIDGET (self->button_item))) + if (item != gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (self->button_item))) { - gtk_list_item_widget_update (GTK_LIST_ITEM_WIDGET (self->button_item), - gtk_single_selection_get_selected (GTK_SINGLE_SELECTION (self->selection)), - item, - FALSE); + gtk_list_item_base_update (GTK_LIST_ITEM_BASE (self->button_item), + gtk_single_selection_get_selected (GTK_SINGLE_SELECTION (self->selection)), + item, + FALSE); } g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED_ITEM]); diff --git a/gtk/gtklistbase.c b/gtk/gtklistbase.c index 1adecc87f3..a9d6700bf1 100644 --- a/gtk/gtklistbase.c +++ b/gtk/gtklistbase.c @@ -896,10 +896,10 @@ gtk_list_base_set_focus_child (GtkWidget *widget, GTK_WIDGET_CLASS (gtk_list_base_parent_class)->set_focus_child (widget, child); - if (!GTK_IS_LIST_ITEM_WIDGET (child)) + if (!GTK_IS_LIST_ITEM_BASE (child)) return; - pos = gtk_list_item_widget_get_position (GTK_LIST_ITEM_WIDGET (child)); + pos = gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (child)); if (pos != gtk_list_item_tracker_get_position (priv->item_manager, priv->focus)) { diff --git a/gtk/gtklistitem.c b/gtk/gtklistitem.c index 28614b62f8..837784bd47 100644 --- a/gtk/gtklistitem.c +++ b/gtk/gtklistitem.c @@ -94,12 +94,12 @@ gtk_list_item_get_property (GObject *object, case PROP_ITEM: if (self->owner) - g_value_set_object (value, gtk_list_item_widget_get_item (self->owner)); + g_value_set_object (value, gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (self->owner))); break; case PROP_POSITION: if (self->owner) - g_value_set_uint (value, gtk_list_item_widget_get_position (self->owner)); + g_value_set_uint (value, gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self->owner))); else g_value_set_uint (value, GTK_INVALID_LIST_POSITION); break; @@ -110,7 +110,7 @@ gtk_list_item_get_property (GObject *object, case PROP_SELECTED: if (self->owner) - g_value_set_boolean (value, gtk_list_item_widget_get_selected (self->owner)); + g_value_set_boolean (value, gtk_list_item_base_get_selected (GTK_LIST_ITEM_BASE (self->owner))); else g_value_set_boolean (value, FALSE); break; @@ -268,7 +268,7 @@ gtk_list_item_get_item (GtkListItem *self) if (self->owner == NULL) return NULL; - return gtk_list_item_widget_get_item (self->owner); + return gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (self->owner)); } /** @@ -344,7 +344,7 @@ gtk_list_item_get_position (GtkListItem *self) if (self->owner == NULL) return GTK_INVALID_LIST_POSITION; - return gtk_list_item_widget_get_position (self->owner); + return gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self->owner)); } /** @@ -366,7 +366,7 @@ gtk_list_item_get_selected (GtkListItem *self) if (self->owner == NULL) return FALSE; - return gtk_list_item_widget_get_selected (self->owner); + return gtk_list_item_base_get_selected (GTK_LIST_ITEM_BASE (self->owner)); } /** diff --git a/gtk/gtklistitembase.c b/gtk/gtklistitembase.c new file mode 100644 index 0000000000..67bbf95912 --- /dev/null +++ b/gtk/gtklistitembase.c @@ -0,0 +1,125 @@ +/* + * Copyright © 2023 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: Benjamin Otte + */ + +#include "config.h" + +#include "gtklistitembaseprivate.h" + +#include "gtkaccessible.h" + +typedef struct _GtkListItemBasePrivate GtkListItemBasePrivate; +struct _GtkListItemBasePrivate +{ + GObject *item; + guint position; + gboolean selected; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (GtkListItemBase, gtk_list_item_base, GTK_TYPE_WIDGET) + +static void +gtk_list_item_base_default_update (GtkListItemBase *self, + guint position, + gpointer item, + gboolean selected) +{ + GtkListItemBasePrivate *priv = gtk_list_item_base_get_instance_private (self); + + g_set_object (&priv->item, item); + priv->position = position; + priv->selected = selected; +} + +static void +gtk_list_item_base_dispose (GObject *object) +{ + GtkListItemBase *self = GTK_LIST_ITEM_BASE (object); + GtkListItemBasePrivate *priv = gtk_list_item_base_get_instance_private (self); + + g_clear_object (&priv->item); + + G_OBJECT_CLASS (gtk_list_item_base_parent_class)->dispose (object); +} + +static void +gtk_list_item_base_class_init (GtkListItemBaseClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + klass->update = gtk_list_item_base_default_update; + + gobject_class->dispose = gtk_list_item_base_dispose; +} + +static void +gtk_list_item_base_init (GtkListItemBase *self) +{ +} + +void +gtk_list_item_base_update (GtkListItemBase *self, + guint position, + gpointer item, + gboolean selected) +{ + GtkListItemBasePrivate *priv = gtk_list_item_base_get_instance_private (self); + gboolean was_selected; + + was_selected = priv->selected; + + GTK_LIST_ITEM_BASE_GET_CLASS (self)->update (self, position, item, selected); + + /* don't look at selected variable, it's not reentrancy safe */ + if (was_selected != priv->selected) + { + if (priv->selected) + gtk_widget_set_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_SELECTED, FALSE); + else + gtk_widget_unset_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_SELECTED); + + gtk_accessible_update_state (GTK_ACCESSIBLE (self), + GTK_ACCESSIBLE_STATE_SELECTED, priv->selected, + -1); + } +} + +guint +gtk_list_item_base_get_position (GtkListItemBase *self) +{ + GtkListItemBasePrivate *priv = gtk_list_item_base_get_instance_private (self); + + return priv->position; +} + +gpointer +gtk_list_item_base_get_item (GtkListItemBase *self) +{ + GtkListItemBasePrivate *priv = gtk_list_item_base_get_instance_private (self); + + return priv->item; +} + +gboolean +gtk_list_item_base_get_selected (GtkListItemBase *self) +{ + GtkListItemBasePrivate *priv = gtk_list_item_base_get_instance_private (self); + + return priv->selected; +} + diff --git a/gtk/gtklistitembaseprivate.h b/gtk/gtklistitembaseprivate.h new file mode 100644 index 0000000000..a5b48dd1ca --- /dev/null +++ b/gtk/gtklistitembaseprivate.h @@ -0,0 +1,65 @@ +/* + * Copyright © 2023 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: Benjamin Otte + */ + +#ifndef __GTK_LIST_ITEM_BASE_PRIVATE_H__ +#define __GTK_LIST_ITEM_BASE_PRIVATE_H__ + +#include "gtkwidget.h" + +G_BEGIN_DECLS + +#define GTK_TYPE_LIST_ITEM_BASE (gtk_list_item_base_get_type ()) +#define GTK_LIST_ITEM_BASE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_LIST_ITEM_BASE, GtkListItemBase)) +#define GTK_LIST_ITEM_BASE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_LIST_ITEM_BASE, GtkListItemBaseClass)) +#define GTK_IS_LIST_ITEM_BASE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_LIST_ITEM_BASE)) +#define GTK_IS_LIST_ITEM_BASE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_LIST_ITEM_BASE)) +#define GTK_LIST_ITEM_BASE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_LIST_ITEM_BASE, GtkListItemBaseClass)) + +typedef struct _GtkListItemBase GtkListItemBase; +typedef struct _GtkListItemBaseClass GtkListItemBaseClass; + +struct _GtkListItemBase +{ + GtkWidget parent_instance; +}; + +struct _GtkListItemBaseClass +{ + GtkWidgetClass parent_class; + + void (* update) (GtkListItemBase *self, + guint position, + gpointer item, + gboolean selected); +}; + +GType gtk_list_item_base_get_type (void) G_GNUC_CONST; + +void gtk_list_item_base_update (GtkListItemBase *self, + guint position, + gpointer item, + gboolean selected); + +guint gtk_list_item_base_get_position (GtkListItemBase *self); +gpointer gtk_list_item_base_get_item (GtkListItemBase *self); +gboolean gtk_list_item_base_get_selected (GtkListItemBase *self); + +G_END_DECLS + +#endif /* __GTK_LIST_ITEM_BASE_PRIVATE_H__ */ diff --git a/gtk/gtklistitemmanager.c b/gtk/gtklistitemmanager.c index b959406c79..9f671b6168 100644 --- a/gtk/gtklistitemmanager.c +++ b/gtk/gtklistitemmanager.c @@ -21,6 +21,7 @@ #include "gtklistitemmanagerprivate.h" +#include "gtklistitembaseprivate.h" #include "gtklistitemwidgetprivate.h" #include "gtkwidgetprivate.h" @@ -49,7 +50,7 @@ struct _GtkListItemManagerClass struct _GtkListItemTracker { guint position; - GtkListItemWidget *widget; + GtkListItemBase *widget; guint n_before; guint n_after; }; @@ -874,7 +875,7 @@ gtk_list_item_manager_model_items_changed_cb (GListModel *model, if (tracker->widget == NULL) continue; - if (g_hash_table_lookup (change, gtk_list_item_widget_get_item (tracker->widget))) + if (g_hash_table_lookup (change, gtk_list_item_base_get_item (tracker->widget))) break; } @@ -952,7 +953,7 @@ gtk_list_item_manager_model_items_changed_cb (GListModel *model, } else if (tracker->position >= position) { - if (g_hash_table_lookup (change, gtk_list_item_widget_get_item (tracker->widget))) + if (g_hash_table_lookup (change, gtk_list_item_base_get_item (tracker->widget))) { /* The item is gone. Guess a good new position */ tracker->position = position + (tracker->position - position) * added / removed; @@ -970,7 +971,7 @@ gtk_list_item_manager_model_items_changed_cb (GListModel *model, /* item was put in its right place in the expensive loop above, * and we updated its position while at it. So grab it from there. */ - tracker->position = gtk_list_item_widget_get_position (tracker->widget); + tracker->position = gtk_list_item_base_get_position (tracker->widget); } } else @@ -997,7 +998,7 @@ gtk_list_item_manager_model_items_changed_cb (GListModel *model, tile = gtk_list_item_manager_get_nth (self, tracker->position, NULL); g_assert (tile != NULL); g_assert (tile->widget); - tracker->widget = GTK_LIST_ITEM_WIDGET (tile->widget); + tracker->widget = GTK_LIST_ITEM_BASE (tile->widget); } g_hash_table_unref (change); @@ -1118,7 +1119,7 @@ gtk_list_item_manager_set_factory (GtkListItemManager *self, tile = gtk_list_item_manager_get_nth (self, tracker->position, NULL); g_assert (tile); - tracker->widget = GTK_LIST_ITEM_WIDGET (tile->widget); + tracker->widget = GTK_LIST_ITEM_BASE (tile->widget); } } @@ -1205,7 +1206,7 @@ gtk_list_item_manager_acquire_list_item (GtkListItemManager *self, item = g_list_model_get_item (G_LIST_MODEL (self->model), position); selected = gtk_selection_model_is_selected (self->model, position); - gtk_list_item_widget_update (GTK_LIST_ITEM_WIDGET (result), position, item, selected); + gtk_list_item_base_update (GTK_LIST_ITEM_BASE (result), position, item, selected); g_object_unref (item); gtk_widget_insert_after (result, self->widget, prev_sibling); @@ -1243,11 +1244,11 @@ gtk_list_item_manager_try_reacquire_list_item (GtkListItemManager *self, item = g_list_model_get_item (G_LIST_MODEL (self->model), position); if (g_hash_table_steal_extended (change, item, NULL, (gpointer *) &result)) { - GtkListItemWidget *list_item = GTK_LIST_ITEM_WIDGET (result); - gtk_list_item_widget_update (list_item, - position, - gtk_list_item_widget_get_item (list_item), - gtk_selection_model_is_selected (self->model, position)); + GtkListItemBase *list_item = GTK_LIST_ITEM_BASE (result); + gtk_list_item_base_update (list_item, + position, + gtk_list_item_base_get_item (list_item), + gtk_selection_model_is_selected (self->model, position)); gtk_widget_insert_after (result, self->widget, prev_sibling); /* XXX: Should we let the listview do this? */ gtk_widget_queue_resize (result); @@ -1285,10 +1286,10 @@ gtk_list_item_manager_move_list_item (GtkListItemManager *self, item = g_list_model_get_item (G_LIST_MODEL (self->model), position); selected = gtk_selection_model_is_selected (self->model, position); - gtk_list_item_widget_update (GTK_LIST_ITEM_WIDGET (list_item), - position, - item, - selected); + gtk_list_item_base_update (GTK_LIST_ITEM_BASE (list_item), + position, + item, + selected); gtk_widget_insert_after (list_item, _gtk_widget_get_parent (list_item), prev_sibling); g_object_unref (item); } @@ -1307,17 +1308,17 @@ gtk_list_item_manager_update_list_item (GtkListItemManager *self, GtkWidget *item, guint position) { - GtkListItemWidget *list_item = GTK_LIST_ITEM_WIDGET (item); + GtkListItemBase *list_item = GTK_LIST_ITEM_BASE (item); gboolean selected; g_return_if_fail (GTK_IS_LIST_ITEM_MANAGER (self)); - g_return_if_fail (GTK_IS_LIST_ITEM_WIDGET (item)); + g_return_if_fail (GTK_IS_LIST_ITEM_BASE (item)); selected = gtk_selection_model_is_selected (self->model, position); - gtk_list_item_widget_update (list_item, - position, - gtk_list_item_widget_get_item (list_item), - selected); + gtk_list_item_base_update (list_item, + position, + gtk_list_item_base_get_item (list_item), + selected); } /* @@ -1337,11 +1338,11 @@ gtk_list_item_manager_release_list_item (GtkListItemManager *self, GtkWidget *item) { g_return_if_fail (GTK_IS_LIST_ITEM_MANAGER (self)); - g_return_if_fail (GTK_IS_LIST_ITEM_WIDGET (item)); + g_return_if_fail (GTK_IS_LIST_ITEM_BASE (item)); if (change != NULL) { - if (!g_hash_table_replace (change, gtk_list_item_widget_get_item (GTK_LIST_ITEM_WIDGET (item)), item)) + if (!g_hash_table_replace (change, gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (item)), item)) { g_warning ("Duplicate item detected in list. Picking one randomly."); } @@ -1437,7 +1438,7 @@ gtk_list_item_tracker_set_position (GtkListItemManager *self, tile = gtk_list_item_manager_get_nth (self, position, NULL); if (tile) - tracker->widget = GTK_LIST_ITEM_WIDGET (tile->widget); + tracker->widget = GTK_LIST_ITEM_BASE (tile->widget); gtk_widget_queue_resize (self->widget); } diff --git a/gtk/gtklistitemwidget.c b/gtk/gtklistitemwidget.c index 0d66566dcb..5b770bf030 100644 --- a/gtk/gtklistitemwidget.c +++ b/gtk/gtklistitemwidget.c @@ -38,9 +38,6 @@ struct _GtkListItemWidgetPrivate GtkListItemFactory *factory; GtkListItem *list_item; - GObject *item; - guint position; - gboolean selected; gboolean single_click_activate; }; @@ -58,7 +55,7 @@ enum LAST_SIGNAL }; -G_DEFINE_TYPE_WITH_PRIVATE (GtkListItemWidget, gtk_list_item_widget, GTK_TYPE_WIDGET) +G_DEFINE_TYPE_WITH_PRIVATE (GtkListItemWidget, gtk_list_item_widget, GTK_TYPE_LIST_ITEM_BASE) static GParamSpec *properties[N_PROPS] = { NULL, }; static guint signals[LAST_SIGNAL] = { 0 }; @@ -74,7 +71,7 @@ gtk_list_item_widget_activate_signal (GtkListItemWidget *self) gtk_widget_activate_action (GTK_WIDGET (self), "list.activate-item", "u", - priv->position); + gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self))); } static gboolean @@ -155,9 +152,9 @@ gtk_list_item_widget_setup_func (gpointer object, gtk_list_item_widget_set_activatable (self, list_item->activatable); gtk_list_item_do_notify (list_item, - priv->item != NULL, - priv->position != GTK_INVALID_LIST_POSITION, - priv->selected); + gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (self)) != NULL, + gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self)) != GTK_INVALID_LIST_POSITION, + gtk_list_item_base_get_selected (GTK_LIST_ITEM_BASE (self))); } static void @@ -170,7 +167,7 @@ gtk_list_item_widget_setup_factory (GtkListItemWidget *self) gtk_list_item_factory_setup (priv->factory, G_OBJECT (list_item), - priv->item != NULL, + gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (self)) != NULL, gtk_list_item_widget_setup_func, self); @@ -196,9 +193,9 @@ gtk_list_item_widget_teardown_func (gpointer object, gtk_list_item_widget_set_activatable (self, FALSE); gtk_list_item_do_notify (list_item, - priv->item != NULL, - priv->position != GTK_INVALID_LIST_POSITION, - priv->selected); + gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (self)) != NULL, + gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self)) != GTK_INVALID_LIST_POSITION, + gtk_list_item_base_get_selected (GTK_LIST_ITEM_BASE (self))); gtk_list_item_set_child (list_item, NULL); } @@ -211,7 +208,7 @@ gtk_list_item_widget_teardown_factory (GtkListItemWidget *self) gtk_list_item_factory_teardown (priv->factory, G_OBJECT (list_item), - priv->item != NULL, + gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (self)) != NULL, gtk_list_item_widget_teardown_func, self); @@ -219,6 +216,62 @@ gtk_list_item_widget_teardown_factory (GtkListItemWidget *self) g_object_unref (list_item); } +typedef struct { + GtkListItemWidget *widget; + guint position; + gpointer item; + gboolean selected; +} GtkListItemWidgetUpdate; + +static void +gtk_list_item_widget_update_func (gpointer object, + gpointer data) +{ + GtkListItemWidgetUpdate *update = data; + GtkListItem *list_item = object; + /* Track notify manually instead of freeze/thaw_notify for performance reasons. */ + gboolean notify_item = FALSE, notify_position = FALSE, notify_selected = FALSE; + GtkListItemWidget *self = update->widget; + GtkListItemBase *base = GTK_LIST_ITEM_BASE (self); + + /* FIXME: It's kinda evil to notify external objects from here... */ + notify_item = gtk_list_item_base_get_item (base) != update->item; + notify_position = gtk_list_item_base_get_position (base) != update->position; + notify_selected = gtk_list_item_base_get_selected (base) != update->selected; + + GTK_LIST_ITEM_BASE_CLASS (gtk_list_item_widget_parent_class)->update (base, + update->position, + update->item, + update->selected); + if (list_item) + gtk_list_item_do_notify (list_item, notify_item, notify_position, notify_selected); +} + +static void +gtk_list_item_widget_update (GtkListItemBase *base, + guint position, + gpointer item, + gboolean selected) +{ + GtkListItemWidget *self = GTK_LIST_ITEM_WIDGET (base); + GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self); + GtkListItemWidgetUpdate update = { self, position, item, selected }; + + if (priv->list_item) + { + gtk_list_item_factory_update (priv->factory, + G_OBJECT (priv->list_item), + gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (self)) != NULL, + item != NULL, + gtk_list_item_widget_update_func, + &update); + } + else + { + gtk_list_item_widget_update_func (NULL, &update); + } +} + static void gtk_list_item_widget_root (GtkWidget *widget) { @@ -275,7 +328,6 @@ gtk_list_item_widget_dispose (GObject *object) g_assert (priv->list_item == NULL); - g_clear_object (&priv->item); g_clear_object (&priv->factory); G_OBJECT_CLASS (gtk_list_item_widget_parent_class)->dispose (object); @@ -298,7 +350,7 @@ gtk_list_item_widget_select_action (GtkWidget *widget, gtk_widget_activate_action (GTK_WIDGET (self), "list.select-item", "(ubb)", - priv->position, modify, extend); + gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self)), modify, extend); } static void @@ -306,23 +358,23 @@ gtk_list_item_widget_scroll_to_action (GtkWidget *widget, const char *action_name, GVariant *parameter) { - GtkListItemWidget *self = GTK_LIST_ITEM_WIDGET (widget); - GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self); - - gtk_widget_activate_action (GTK_WIDGET (self), + gtk_widget_activate_action (widget, "list.scroll-to-item", "u", - priv->position); + gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (widget))); } static void gtk_list_item_widget_class_init (GtkListItemWidgetClass *klass) { + GtkListItemBaseClass *base_class = GTK_LIST_ITEM_BASE_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass); klass->activate_signal = gtk_list_item_widget_activate_signal; + base_class->update = gtk_list_item_widget_update; + widget_class->focus = gtk_list_item_widget_focus; widget_class->grab_focus = gtk_list_item_widget_grab_focus; widget_class->root = gtk_list_item_widget_root; @@ -438,7 +490,7 @@ gtk_list_item_widget_click_gesture_pressed (GtkGestureClick *gesture, gtk_widget_activate_action (GTK_WIDGET (self), "list.activate-item", "u", - priv->position); + gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self))); } } @@ -463,7 +515,7 @@ gtk_list_item_widget_click_gesture_released (GtkGestureClick *gesture, gtk_widget_activate_action (GTK_WIDGET (self), "list.activate-item", "u", - priv->position); + gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self))); return; } } @@ -484,7 +536,7 @@ gtk_list_item_widget_click_gesture_released (GtkGestureClick *gesture, gtk_widget_activate_action (GTK_WIDGET (self), "list.select-item", "(ubb)", - priv->position, modify, extend); + gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self)), modify, extend); } } @@ -504,7 +556,7 @@ gtk_list_item_widget_hover_cb (GtkEventControllerMotion *controller, gtk_widget_activate_action (GTK_WIDGET (self), "list.select-item", "(ubb)", - priv->position, FALSE, FALSE); + gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self)), FALSE, FALSE); } } @@ -548,85 +600,6 @@ gtk_list_item_widget_new (GtkListItemFactory *factory, NULL); } -typedef struct { - GtkListItemWidget *widget; - guint position; - gpointer item; - gboolean selected; -} GtkListItemWidgetUpdate; - -static void -gtk_list_item_widget_update_func (gpointer object, - gpointer data) -{ - GtkListItemWidgetUpdate *update = data; - GtkListItem *list_item = object; - /* Track notify manually instead of freeze/thaw_notify for performance reasons. */ - gboolean notify_item = FALSE, notify_position = FALSE, notify_selected = FALSE; - GtkListItemWidget *self = update->widget; - GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self); - - /* FIXME: It's kinda evil to notify external objects from here... */ - - if (g_set_object (&priv->item, update->item)) - notify_item = TRUE; - - if (priv->position != update->position) - { - priv->position = update->position; - notify_position = TRUE; - } - - if (priv->selected != update->selected) - { - priv->selected = update->selected; - notify_selected = TRUE; - } - - if (list_item) - gtk_list_item_do_notify (list_item, notify_item, notify_position, notify_selected); -} - -void -gtk_list_item_widget_update (GtkListItemWidget *self, - guint position, - gpointer item, - gboolean selected) -{ - GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self); - GtkListItemWidgetUpdate update = { self, position, item, selected }; - gboolean was_selected; - - was_selected = priv->selected; - - if (priv->list_item) - { - gtk_list_item_factory_update (priv->factory, - G_OBJECT (priv->list_item), - priv->item != NULL, - item != NULL, - gtk_list_item_widget_update_func, - &update); - } - else - { - gtk_list_item_widget_update_func (NULL, &update); - } - - /* don't look at selected variable, it's not reentrancy safe */ - if (was_selected != priv->selected) - { - if (priv->selected) - gtk_widget_set_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_SELECTED, FALSE); - else - gtk_widget_unset_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_SELECTED); - - gtk_accessible_update_state (GTK_ACCESSIBLE (self), - GTK_ACCESSIBLE_STATE_SELECTED, priv->selected, - -1); - } -} - void gtk_list_item_widget_set_factory (GtkListItemWidget *self, GtkListItemFactory *factory) @@ -729,27 +702,3 @@ gtk_list_item_widget_get_list_item (GtkListItemWidget *self) return priv->list_item; } -guint -gtk_list_item_widget_get_position (GtkListItemWidget *self) -{ - GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self); - - return priv->position; -} - -gpointer -gtk_list_item_widget_get_item (GtkListItemWidget *self) -{ - GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self); - - return priv->item; -} - -gboolean -gtk_list_item_widget_get_selected (GtkListItemWidget *self) -{ - GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self); - - return priv->selected; -} - diff --git a/gtk/gtklistitemwidgetprivate.h b/gtk/gtklistitemwidgetprivate.h index 7ac53df413..5345419a19 100644 --- a/gtk/gtklistitemwidgetprivate.h +++ b/gtk/gtklistitemwidgetprivate.h @@ -20,8 +20,9 @@ #ifndef __GTK_LIST_ITEM_WIDGET_PRIVATE_H__ #define __GTK_LIST_ITEM_WIDGET_PRIVATE_H__ +#include "gtklistitembaseprivate.h" + #include "gtklistitemfactory.h" -#include "gtkwidget.h" G_BEGIN_DECLS @@ -37,12 +38,12 @@ typedef struct _GtkListItemWidgetClass GtkListItemWidgetClass; struct _GtkListItemWidget { - GtkWidget parent_instance; + GtkListItemBase parent_instance; }; struct _GtkListItemWidgetClass { - GtkWidgetClass parent_class; + GtkListItemBaseClass parent_class; void (* activate_signal) (GtkListItemWidget *self); }; @@ -53,10 +54,6 @@ GtkWidget * gtk_list_item_widget_new (GtkListItemFact const char *css_name, GtkAccessibleRole role); -void gtk_list_item_widget_update (GtkListItemWidget *self, - guint position, - gpointer item, - gboolean selected); GtkListItem * gtk_list_item_widget_get_list_item (GtkListItemWidget *self); void gtk_list_item_widget_set_factory (GtkListItemWidget *self, @@ -74,10 +71,6 @@ void gtk_list_item_widget_reorder_child (GtkListItemWidg void gtk_list_item_widget_remove_child (GtkListItemWidget *self, GtkWidget *child); -guint gtk_list_item_widget_get_position (GtkListItemWidget *self); -gpointer gtk_list_item_widget_get_item (GtkListItemWidget *self); -gboolean gtk_list_item_widget_get_selected (GtkListItemWidget *self); - G_END_DECLS #endif /* __GTK_LIST_ITEM_WIDGET_PRIVATE_H__ */ diff --git a/gtk/meson.build b/gtk/meson.build index a8e108846d..bcb92fe443 100644 --- a/gtk/meson.build +++ b/gtk/meson.build @@ -270,6 +270,7 @@ gtk_public_sources = files([ 'gtklinkbutton.c', 'gtklistbox.c', 'gtklistitem.c', + 'gtklistitembase.c', 'gtklistitemfactory.c', 'gtklistitemmanager.c', 'gtklistitemwidget.c',