[gtk/wip/otte/whatever: 2/3] Add GtkArrayStore
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/whatever: 2/3] Add GtkArrayStore
- Date: Thu, 2 Jul 2020 18:42:49 +0000 (UTC)
commit 4d4d4374c85f7bfd08dd2704af7d2823ed6d1a18
Author: Benjamin Otte <otte redhat com>
Date: Thu Jul 2 17:46:06 2020 +0200
Add GtkArrayStore
This has roughly the same API as GListStore, it's just an array.
gtk/gtk.h | 1 +
gtk/gtkarraystore.c | 287 ++++++++++++++++++++++++++++++++++++++++++++++++++++
gtk/gtkarraystore.h | 54 ++++++++++
gtk/meson.build | 2 +
4 files changed, 344 insertions(+)
---
diff --git a/gtk/gtk.h b/gtk/gtk.h
index f4c105e6e5..fd503e1e4e 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -44,6 +44,7 @@
#include <gtk/gtkappchooserbutton.h>
#include <gtk/gtkapplication.h>
#include <gtk/gtkapplicationwindow.h>
+#include <gtk/gtkarraystore.h>
#include <gtk/gtkaspectframe.h>
#include <gtk/gtkassistant.h>
#include <gtk/gtkbinlayout.h>
diff --git a/gtk/gtkarraystore.c b/gtk/gtkarraystore.c
new file mode 100644
index 0000000000..78bd0520db
--- /dev/null
+++ b/gtk/gtkarraystore.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright © 2020 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte gnome org>
+ */
+
+#include "config.h"
+
+#include "gtkarraystore.h"
+
+#define GTK_VECTOR_ELEMENT_TYPE GObject *
+#define GTK_VECTOR_FREE_FUNC g_object_unref
+#include "gtkvectorimpl.c"
+
+/**
+ * SECTION:gtkarraystore
+ * @title: GtkArrayStore
+ * @short_description: A simple array implementation of #GListModel
+ *
+ * #GtkArrayStore is a simple implementation of #GListModel that stores all
+ * items in memory.
+ *
+ * It provides appending, deletions, and lookups in O(1) time and insertions
+ * in O(N) time. it is implemented using an array.
+ */
+
+/**
+ * GtkArrayStore:
+ *
+ * #GtkArrayStore is an opaque data structure and can only be accessed
+ * using the following functions.
+ **/
+
+struct _GtkArrayStore
+{
+ GObject parent_instance;
+
+ GType item_type;
+ GtkVector items;
+};
+
+enum
+{
+ PROP_0,
+ PROP_ITEM_TYPE,
+ N_PROPERTIES
+};
+
+static void gtk_array_store_iface_init (GListModelInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GtkArrayStore, gtk_array_store, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_array_store_iface_init));
+
+static void
+gtk_array_store_dispose (GObject *object)
+{
+ GtkArrayStore *self = GTK_ARRAY_STORE (object);
+
+ gtk_vector_clear (&self->items);
+
+ G_OBJECT_CLASS (gtk_array_store_parent_class)->dispose (object);
+}
+
+static void
+gtk_array_store_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkArrayStore *self = GTK_ARRAY_STORE (object);
+
+ switch (property_id)
+ {
+ case PROP_ITEM_TYPE:
+ g_value_set_gtype (value, self->item_type);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+gtk_array_store_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkArrayStore *self = GTK_ARRAY_STORE (object);
+
+ switch (property_id)
+ {
+ case PROP_ITEM_TYPE: /* construct-only */
+ g_assert (g_type_is_a (g_value_get_gtype (value), G_TYPE_OBJECT));
+ self->item_type = g_value_get_gtype (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+gtk_array_store_class_init (GtkArrayStoreClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = gtk_array_store_dispose;
+ object_class->get_property = gtk_array_store_get_property;
+ object_class->set_property = gtk_array_store_set_property;
+
+ /**
+ * GtkArrayStore:item-type:
+ *
+ * The type of items contained in this list self. Items must be
+ * subclasses of #GObject.
+ **/
+ g_object_class_install_property (object_class, PROP_ITEM_TYPE,
+ g_param_spec_gtype ("item-type", "", "", G_TYPE_OBJECT,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+}
+
+static GType
+gtk_array_store_get_item_type (GListModel *list)
+{
+ GtkArrayStore *self = GTK_ARRAY_STORE (list);
+
+ return self->item_type;
+}
+
+static guint
+gtk_array_store_get_n_items (GListModel *list)
+{
+ GtkArrayStore *self = GTK_ARRAY_STORE (list);
+
+ return gtk_vector_get_size (&self->items);
+}
+
+static gpointer
+gtk_array_store_get_item (GListModel *list,
+ guint position)
+{
+ GtkArrayStore *self = GTK_ARRAY_STORE (list);
+
+ if (position >= gtk_vector_get_size (&self->items))
+ return NULL;
+
+ return g_object_ref (gtk_vector_get (&self->items, position));
+}
+
+static void
+gtk_array_store_iface_init (GListModelInterface *iface)
+{
+ iface->get_item_type = gtk_array_store_get_item_type;
+ iface->get_n_items = gtk_array_store_get_n_items;
+ iface->get_item = gtk_array_store_get_item;
+}
+
+static void
+gtk_array_store_init (GtkArrayStore *self)
+{
+ gtk_vector_init (&self->items);
+}
+
+/**
+ * gtk_array_store_new:
+ * @item_type: the #GType of items in the list
+ *
+ * Creates a new #GtkArrayStore with items of type @item_type. @item_type
+ * must be a subclass of #GObject.
+ *
+ * Returns: a new #GtkArrayStore
+ */
+GtkArrayStore *
+gtk_array_store_new (GType item_type)
+{
+ g_return_val_if_fail (g_type_is_a (item_type, G_TYPE_OBJECT), NULL);
+
+ return g_object_new (GTK_TYPE_ARRAY_STORE,
+ "item-type", item_type,
+ NULL);
+}
+
+/**
+ * gtk_array_store_append:
+ * @self: a #GtkArrayStore
+ * @item: (type GObject): the new item
+ *
+ * Appends @item to @self. @item must be of type #GtkArrayStore:item-type.
+ *
+ * This function takes a ref on @item.
+ *
+ * Use gtk_array_store_splice() to append multiple items at the same time
+ * efficiently.
+ */
+void
+gtk_array_store_append (GtkArrayStore *self,
+ gpointer item)
+{
+ guint position;
+
+ g_return_if_fail (GTK_IS_ARRAY_STORE (self));
+ g_return_if_fail (g_type_is_a (G_OBJECT_TYPE (item), self->item_type));
+
+ position = gtk_vector_get_size (&self->items);
+ gtk_vector_append (&self->items, g_object_ref (item));
+ g_list_model_items_changed (G_LIST_MODEL (self), position, 1, 0);
+}
+
+/**
+ * gtk_array_store_remove_all:
+ * @self: a #GtkArrayStore
+ *
+ * Removes all items from @self.
+ *
+ * Since: 2.44
+ */
+void
+gtk_array_store_remove_all (GtkArrayStore *self)
+{
+ guint n_items;
+
+ g_return_if_fail (GTK_IS_ARRAY_STORE (self));
+
+ n_items = gtk_vector_get_size (&self->items);
+ gtk_vector_clear (&self->items);
+
+ g_list_model_items_changed (G_LIST_MODEL (self), 0, n_items, 0);
+}
+
+/**
+ * gtk_array_store_splice:
+ * @self: a #GtkArrayStore
+ * @position: the position at which to make the change
+ * @n_removals: the number of items to remove
+ * @additions: (array length=n_additions) (element-type GObject): the items to add
+ * @n_additions: the number of items to add
+ *
+ * Changes @self by removing @n_removals items and adding @n_additions
+ * items to it. @additions must contain @n_additions items of type
+ * #GtkArrayStore:item-type. %NULL is not permitted.
+ *
+ * This function is more efficient than gtk_array_store_insert() and
+ * gtk_array_store_remove(), because it only emits
+ * #GListModel::items-changed once for the change.
+ *
+ * This function takes a ref on each item in @additions.
+ *
+ * The parameters @position and @n_removals must be correct (ie:
+ * @position + @n_removals must be less than or equal to the length of
+ * the list at the time this function is called).
+ *
+ * Since: 2.44
+ */
+void
+gtk_array_store_splice (GtkArrayStore *self,
+ guint position,
+ guint n_removals,
+ gpointer *additions,
+ guint n_additions)
+{
+ guint i;
+
+ g_return_if_fail (GTK_IS_ARRAY_STORE (self));
+ g_return_if_fail (position + n_removals >= position); /* overflow */
+ g_return_if_fail (position + n_removals <= gtk_vector_get_size (&self->items));
+
+ for (i = 0; i < n_additions; i++)
+ g_object_ref (additions[i]);
+
+ gtk_vector_splice (&self->items, position, n_removals, (GObject **) additions, n_additions);
+
+ g_list_model_items_changed (G_LIST_MODEL (self), position, n_removals, n_additions);
+}
diff --git a/gtk/gtkarraystore.h b/gtk/gtkarraystore.h
new file mode 100644
index 0000000000..7f35d07e4d
--- /dev/null
+++ b/gtk/gtkarraystore.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 2020 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte gnome org>
+ */
+
+#ifndef __GTK_ARRAY_STORE_H__
+#define __GTK_ARRAY_STORE_H__
+
+#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_ARRAY_STORE (gtk_array_store_get_type ())
+GDK_AVAILABLE_IN_ALL
+G_DECLARE_FINAL_TYPE(GtkArrayStore, gtk_array_store, GTK, ARRAY_STORE, GObject)
+
+GDK_AVAILABLE_IN_ALL
+GtkArrayStore * gtk_array_store_new (GType item_type);
+
+GDK_AVAILABLE_IN_ALL
+void gtk_array_store_append (GtkArrayStore *store,
+ gpointer item);
+
+GDK_AVAILABLE_IN_ALL
+void gtk_array_store_remove_all (GtkArrayStore *store);
+
+GDK_AVAILABLE_IN_ALL
+void gtk_array_store_splice (GtkArrayStore *store,
+ guint position,
+ guint n_removals,
+ gpointer *additions,
+ guint n_additions);
+
+G_END_DECLS
+
+#endif /* __GTK_ARRAY_STORE_H__ */
diff --git a/gtk/meson.build b/gtk/meson.build
index 5a7ca5715f..4a23fd8689 100644
--- a/gtk/meson.build
+++ b/gtk/meson.build
@@ -160,6 +160,7 @@ gtk_public_sources = files([
'gtkappchooserwidget.c',
'gtkapplication.c',
'gtkapplicationwindow.c',
+ 'gtkarraystore.c',
'gtkaspectframe.c',
'gtkassistant.c',
'gtkbinlayout.c',
@@ -447,6 +448,7 @@ gtk_public_headers = files([
'gtkappchooserwidget.h',
'gtkapplication.h',
'gtkapplicationwindow.h',
+ 'gtkarraystore.h',
'gtkaspectframe.h',
'gtkassistant.h',
'gtkbinlayout.h',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]