[gnome-builder] libide/tweaks: use visitor pattern for item->model conversion
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] libide/tweaks: use visitor pattern for item->model conversion
- Date: Wed, 3 Aug 2022 01:19:24 +0000 (UTC)
commit b066bf118dcc1d0887bfcfedc668e5f7c65b573b
Author: Christian Hergert <chergert redhat com>
Date: Tue Aug 2 18:19:17 2022 -0700
libide/tweaks: use visitor pattern for item->model conversion
This makes it a bit easier to control if we need to recurse through an
intermediate node (such as a section) without being so type based. We still
keep special handling for factories though.
src/libide/tweaks/ide-tweaks-model-private.h | 18 +++-
src/libide/tweaks/ide-tweaks-model.c | 120 ++++++++++++++++-----------
src/libide/tweaks/ide-tweaks-panel-list.c | 30 ++++++-
3 files changed, 115 insertions(+), 53 deletions(-)
---
diff --git a/src/libide/tweaks/ide-tweaks-model-private.h b/src/libide/tweaks/ide-tweaks-model-private.h
index 5dd6bc032..6db7c9487 100644
--- a/src/libide/tweaks/ide-tweaks-model-private.h
+++ b/src/libide/tweaks/ide-tweaks-model-private.h
@@ -27,11 +27,23 @@ G_BEGIN_DECLS
#define IDE_TYPE_TWEAKS_MODEL (ide_tweaks_model_get_type())
+typedef enum
+{
+ IDE_TWEAKS_ITEM_VISIT_STOP = 0,
+ IDE_TWEAKS_ITEM_VISIT_SKIP,
+ IDE_TWEAKS_ITEM_VISIT_ACCEPT,
+ IDE_TWEAKS_ITEM_VISIT_RECURSE,
+} IdeTweaksItemVisitResult;
+
+typedef IdeTweaksItemVisitResult (*IdeTweaksItemVisitor) (IdeTweaksItem *item,
+ gpointer user_data);
+
G_DECLARE_FINAL_TYPE (IdeTweaksModel, ide_tweaks_model, IDE, TWEAKS_MODEL, GObject)
-IdeTweaksModel *ide_tweaks_model_new (IdeTweaksItem *item,
- const GType *allowed_types,
- guint n_allowed_types);
+IdeTweaksModel *ide_tweaks_model_new (IdeTweaksItem *item,
+ IdeTweaksItemVisitor visitor,
+ gpointer visitor_data,
+ GDestroyNotify visitor_data_destroy);
IdeTweaksItem *ide_tweaks_model_get_item (IdeTweaksModel *self);
G_END_DECLS
diff --git a/src/libide/tweaks/ide-tweaks-model.c b/src/libide/tweaks/ide-tweaks-model.c
index 2a4ca9f97..1e0a7bc15 100644
--- a/src/libide/tweaks/ide-tweaks-model.c
+++ b/src/libide/tweaks/ide-tweaks-model.c
@@ -28,11 +28,17 @@
struct _IdeTweaksModel
{
- GObject parent_instance;
- IdeTweaksItem *item;
- GPtrArray *items;
+ GObject parent_instance;
+ IdeTweaksItem *item;
+ GPtrArray *items;
+ IdeTweaksItemVisitor visitor;
+ gpointer visitor_data;
+ GDestroyNotify visitor_data_destroy;
};
+static gboolean ide_tweaks_model_populate (IdeTweaksModel *self,
+ IdeTweaksItem *item);
+
static GType
list_model_get_item_type (GListModel *model)
{
@@ -76,81 +82,92 @@ enum {
static GParamSpec *properties [N_PROPS];
-static inline gboolean
-descendant_is_allowed (IdeTweaksItem *item,
- const GType *allowed_types,
- guint n_allowed_types)
+static gboolean
+ide_tweaks_model_visit (IdeTweaksModel *self,
+ IdeTweaksItem *item)
{
- GType item_type = G_OBJECT_TYPE (item);
+ IdeTweaksItemVisitResult res;
+
+ g_assert (IDE_IS_TWEAKS_MODEL (self));
+ g_assert (IDE_IS_TWEAKS_ITEM (item));
- for (guint i = 0; i < n_allowed_types; i++)
+ res = self->visitor (item, self->visitor_data);
+
+ switch (res)
{
- if (g_type_is_a (item_type, allowed_types[i]))
- return TRUE;
+ case IDE_TWEAKS_ITEM_VISIT_STOP:
+ return TRUE;
+
+ case IDE_TWEAKS_ITEM_VISIT_SKIP:
+ return FALSE;
+
+ case IDE_TWEAKS_ITEM_VISIT_ACCEPT:
+ g_ptr_array_add (self->items, g_object_ref (item));
+ return FALSE;
+
+ case IDE_TWEAKS_ITEM_VISIT_RECURSE:
+ return ide_tweaks_model_populate (self, item);
+
+ default:
+ break;
}
- return FALSE;
+ g_assert_not_reached ();
}
-static void
+static gboolean
ide_tweaks_model_populate (IdeTweaksModel *self,
- const GType *allowed_types,
- guint n_allowed_types)
+ IdeTweaksItem *item)
{
g_assert (IDE_IS_TWEAKS_MODEL (self));
- g_assert (IDE_IS_TWEAKS_ITEM (self->item));
g_assert (self->items != NULL);
- g_assert (self->items->len == 0);
- g_assert (allowed_types != NULL);
- g_assert (n_allowed_types > 0);
+ g_assert (self->visitor != NULL);
- for (IdeTweaksItem *child = ide_tweaks_item_get_first_child (self->item);
- child != NULL;
- child = ide_tweaks_item_get_next_sibling (child))
+ if (IDE_IS_TWEAKS_FACTORY (item))
{
- if (descendant_is_allowed (child, allowed_types, n_allowed_types))
- {
- g_ptr_array_add (self->items, g_object_ref (child));
- continue;
- }
+ g_autoptr(GPtrArray) factory_items = _ide_tweaks_factory_inflate (IDE_TWEAKS_FACTORY (item));
- /* Now check if this is a factory, we might need to create
- * items based on the factory.
- */
- if (IDE_IS_TWEAKS_FACTORY (child) &&
- _ide_tweaks_factory_is_one_of (IDE_TWEAKS_FACTORY (child),
- allowed_types,
- n_allowed_types))
+ for (guint i = 0; i < factory_items->len; i++)
{
- g_autoptr(GPtrArray) factory_items = _ide_tweaks_factory_inflate (IDE_TWEAKS_FACTORY (child));
-
- for (guint i = 0; i < factory_items->len; i++)
- {
- IdeTweaksItem *factory_item = g_ptr_array_index (factory_items, i);
+ IdeTweaksItem *factory_item = g_ptr_array_index (factory_items, i);
- if (descendant_is_allowed (factory_item, allowed_types, n_allowed_types))
- g_ptr_array_add (self->items, g_object_ref (factory_item));
- }
+ if (ide_tweaks_model_visit (self, factory_item))
+ return TRUE;
+ }
+ }
+ else
+ {
+ for (IdeTweaksItem *child = ide_tweaks_item_get_first_child (item);
+ child != NULL;
+ child = ide_tweaks_item_get_next_sibling (child))
+ {
+ if (ide_tweaks_model_visit (self, child))
+ return TRUE;
}
}
+
+ return FALSE;
}
IdeTweaksModel *
-ide_tweaks_model_new (IdeTweaksItem *item,
- const GType *allowed_types,
- guint n_allowed_types)
+ide_tweaks_model_new (IdeTweaksItem *item,
+ IdeTweaksItemVisitor visitor,
+ gpointer visitor_data,
+ GDestroyNotify visitor_data_destroy)
{
IdeTweaksModel *self;
g_return_val_if_fail (IDE_IS_TWEAKS_ITEM (item), NULL);
- g_return_val_if_fail (allowed_types != NULL, NULL);
- g_return_val_if_fail (n_allowed_types > 0, NULL);
+ g_return_val_if_fail (visitor != NULL, NULL);
self = g_object_new (IDE_TYPE_TWEAKS_MODEL, NULL);
self->items = g_ptr_array_new_with_free_func (g_object_unref);
+ self->visitor = visitor;
+ self->visitor_data = visitor_data;
+ self->visitor_data_destroy = visitor_data_destroy;
if (g_set_object (&self->item, item))
- ide_tweaks_model_populate (self, allowed_types, n_allowed_types);
+ ide_tweaks_model_populate (self, item);
return self;
}
@@ -162,6 +179,13 @@ ide_tweaks_model_dispose (GObject *object)
g_clear_object (&self->item);
+ if (self->visitor_data_destroy)
+ {
+ GDestroyNotify notify = g_steal_pointer (&self->visitor_data_destroy);
+ self->visitor = NULL;
+ g_clear_pointer (&self->visitor_data, notify);
+ }
+
G_OBJECT_CLASS (ide_tweaks_model_parent_class)->dispose (object);
}
diff --git a/src/libide/tweaks/ide-tweaks-panel-list.c b/src/libide/tweaks/ide-tweaks-panel-list.c
index fa41e16ab..4a0b0a369 100644
--- a/src/libide/tweaks/ide-tweaks-panel-list.c
+++ b/src/libide/tweaks/ide-tweaks-panel-list.c
@@ -22,9 +22,11 @@
#include "config.h"
+#include "ide-tweaks-factory-private.h"
#include "ide-tweaks-model-private.h"
#include "ide-tweaks-page.h"
#include "ide-tweaks-panel-list-private.h"
+#include "ide-tweaks-section.h"
#include "ide-tweaks-subpage.h"
struct _IdeTweaksPanelList
@@ -148,6 +150,28 @@ ide_tweaks_panel_list_create_row_cb (gpointer item,
return g_object_new (GTK_TYPE_LABEL, "label", "TODO: ", NULL);
}
+static IdeTweaksItemVisitResult
+panel_list_visitor (IdeTweaksItem *item,
+ gpointer user_data)
+{
+ static GType page_type;
+
+ if (!page_type)
+ page_type = IDE_TYPE_TWEAKS_PAGE;
+
+ if (IDE_IS_TWEAKS_SECTION (item))
+ return IDE_TWEAKS_ITEM_VISIT_RECURSE;
+
+ if (IDE_IS_TWEAKS_PAGE (item))
+ return IDE_TWEAKS_ITEM_VISIT_ACCEPT;
+
+ if (IDE_IS_TWEAKS_FACTORY (item) &&
+ _ide_tweaks_factory_is_one_of (IDE_TWEAKS_FACTORY (item), &page_type, 1))
+ return IDE_TWEAKS_ITEM_VISIT_ACCEPT;
+
+ return IDE_TWEAKS_ITEM_VISIT_SKIP;
+}
+
void
ide_tweaks_panel_list_set_item (IdeTweaksPanelList *self,
IdeTweaksItem *item)
@@ -161,9 +185,11 @@ ide_tweaks_panel_list_set_item (IdeTweaksPanelList *self,
if (item != NULL)
{
- const GType allowed_types[] = { IDE_TYPE_TWEAKS_PAGE, IDE_TYPE_TWEAKS_SUBPAGE };
+ model = ide_tweaks_model_new (item, panel_list_visitor, NULL, NULL);
+
+ g_print ("Setting model: %p %d items\n",
+ model, g_list_model_get_n_items (G_LIST_MODEL (model)));
- model = ide_tweaks_model_new (item, allowed_types, G_N_ELEMENTS (allowed_types));
gtk_list_box_bind_model (self->list_box,
G_LIST_MODEL (model),
ide_tweaks_panel_list_create_row_cb,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]