summaryrefslogtreecommitdiff
path: root/gtk/gtkcanvasitem.c
diff options
context:
space:
mode:
Diffstat (limited to 'gtk/gtkcanvasitem.c')
-rw-r--r--gtk/gtkcanvasitem.c353
1 files changed, 353 insertions, 0 deletions
diff --git a/gtk/gtkcanvasitem.c b/gtk/gtkcanvasitem.c
new file mode 100644
index 0000000000..1a56374a9b
--- /dev/null
+++ b/gtk/gtkcanvasitem.c
@@ -0,0 +1,353 @@
+/*
+ * Copyright © 2022 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 "gtkcanvasitemprivate.h"
+
+#include "gtkcanvas.h"
+#include "gtkcanvasboxprivate.h"
+#include "gtkcanvaspointprivate.h"
+#include "gtkcanvassizeprivate.h"
+#include "gtkintl.h"
+#include "gtklistitemfactoryprivate.h"
+#include "gtkwidget.h"
+
+/**
+ * GtkCanvasItem:
+ *
+ * `GtkCanvasItem` holds all information relevant for placing a widget
+ * onto the canvas.
+ */
+
+struct _GtkCanvasItem
+{
+ GObject parent_instance;
+
+ GtkCanvas *canvas;
+ gpointer item;
+ GtkWidget *widget;
+ GtkCanvasBox bounds;
+};
+
+enum
+{
+ PROP_0,
+ PROP_BOUNDS,
+ PROP_CANVAS,
+ PROP_ITEM,
+ PROP_WIDGET,
+
+ N_PROPS
+};
+
+G_DEFINE_FINAL_TYPE (GtkCanvasItem, gtk_canvas_item, G_TYPE_OBJECT)
+
+static GParamSpec *properties[N_PROPS] = { NULL, };
+
+static void
+gtk_canvas_item_dispose (GObject *object)
+{
+ GtkCanvasItem *self = GTK_CANVAS_ITEM (object);
+
+ /* holds a reference */
+ g_assert (self->canvas == NULL);
+ /* must have been deleted in teardown */
+ g_assert (self->item == NULL);
+ g_assert (self->widget == NULL);
+
+ gtk_canvas_box_finish (&self->bounds);
+
+ G_OBJECT_CLASS (gtk_canvas_item_parent_class)->dispose (object);
+}
+
+static void
+gtk_canvas_item_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkCanvasItem *self = GTK_CANVAS_ITEM (object);
+
+ switch (property_id)
+ {
+ case PROP_BOUNDS:
+ g_value_set_boxed (value, &self->bounds);
+ break;
+
+ case PROP_CANVAS:
+ g_value_set_object (value, self->canvas);
+ break;
+
+ case PROP_ITEM:
+ g_value_set_object (value, self->item);
+ break;
+
+ case PROP_WIDGET:
+ g_value_set_object (value, self->widget);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_canvas_item_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkCanvasItem *self = GTK_CANVAS_ITEM (object);
+
+ switch (property_id)
+ {
+ case PROP_BOUNDS:
+ gtk_canvas_item_set_bounds (self, g_value_get_boxed (value));
+ break;
+
+ case PROP_WIDGET:
+ gtk_canvas_item_set_widget (self, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_canvas_item_class_init (GtkCanvasItemClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->dispose = gtk_canvas_item_dispose;
+ gobject_class->get_property = gtk_canvas_item_get_property;
+ gobject_class->set_property = gtk_canvas_item_set_property;
+
+ /**
+ * GtkCanvasItem:bounds: (attributes org.gtk.Property.get=gtk_canvas_item_get_bounds org.gtk.Property.set=gtk_canvas_item_set_bounds)
+ *
+ * The bounds to place the widget into.
+ */
+ properties[PROP_BOUNDS] =
+ g_param_spec_boxed ("bounds", NULL, NULL,
+ GTK_TYPE_CANVAS_BOX,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * GtkCanvasItem:canvas: (attributes org.gtk.Property.get=gtk_canvas_item_get_canvas org.gtk.Property.set=gtk_canvas_item_set_canvas)
+ *
+ * The canvas this item belongs to or %NULL if the canvas has been destroyed
+ */
+ properties[PROP_CANVAS] =
+ g_param_spec_object ("canvas", NULL, NULL,
+ GTK_TYPE_CANVAS,
+ G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * GtkCanvasItem:item: (attributes org.gtk.Property.get=gtk_canvas_item_get_item org.gtk.Property.set=gtk_canvas_item_set_item)
+ *
+ * The item represented by this canvas item.
+ */
+ properties[PROP_ITEM] =
+ g_param_spec_object ("item", NULL, NULL,
+ G_TYPE_OBJECT,
+ G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * GtkCanvasItem:widget: (attributes org.gtk.Property.get=gtk_canvas_item_get_widget org.gtk.Property.set=gtk_canvas_item_set_widget)
+ *
+ * The widget managed.
+ */
+ properties[PROP_WIDGET] =
+ g_param_spec_object ("widget", NULL, NULL,
+ GTK_TYPE_WIDGET,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (gobject_class, N_PROPS, properties);
+}
+
+static void
+gtk_canvas_item_init (GtkCanvasItem *self)
+{
+ GtkCanvasPoint point;
+ GtkCanvasSize size;
+
+ gtk_canvas_point_init (&point, 0, 0);
+ gtk_canvas_size_init_measure_item (&size, self, GTK_CANVAS_ITEM_MEASURE_NAT_FOR_NAT);
+ gtk_canvas_box_init (&self->bounds, &point, &size, 0, 0);
+ gtk_canvas_size_finish (&size);
+ gtk_canvas_point_finish (&point);
+}
+
+GtkCanvasItem *
+gtk_canvas_item_new (GtkCanvas *canvas,
+ gpointer item)
+{
+ GtkCanvasItem *self;
+
+ self = g_object_new (GTK_TYPE_CANVAS_ITEM,
+ NULL);
+
+ /* no reference, the canvas references us */
+ self->canvas = canvas;
+ /* transfer full */
+ self->item = item;
+
+ return self;
+}
+
+/**
+ * gtk_canvas_item_get_canvas: (attributes org.gtk.Method.get_property=canvas)
+ * @self: a `GtkCanvasItem`
+ *
+ * Gets the canvas this item belongs to.
+ *
+ * If the canvas has discarded this item, this property willbe set to %NULL.
+ *
+ * Returns: (nullable) (transfer none): The canvas
+ */
+GtkCanvas *
+gtk_canvas_item_get_canvas (GtkCanvasItem *self)
+{
+ g_return_val_if_fail (GTK_IS_CANVAS_ITEM (self), NULL);
+
+ return self->canvas;
+}
+
+/**
+ * gtk_canvas_item_get_item: (attributes org.gtk.Method.get_property=item)
+ * @self: a `GtkCanvasItem`
+ *
+ * Gets the item that is associated with this canvasitem or %NULL if the canvas has
+ * discarded this canvasitem.
+ *
+ * Returns: (transfer none) (nullable) (type GObject): The item.
+ */
+gpointer
+gtk_canvas_item_get_item (GtkCanvasItem *self)
+{
+ g_return_val_if_fail (GTK_IS_CANVAS_ITEM (self), NULL);
+
+ return self->item;
+}
+
+/**
+ * gtk_canvas_item_set_bounds: (attributes org.gtk.Method.set_property=bounds)
+ * @self: a `GtkCanvasItem`
+ * @bounds: (transfer none): the bounds to allocate the widget in
+ *
+ * Sets the box to allocate the widget into.
+ */
+void
+gtk_canvas_item_set_bounds (GtkCanvasItem *self,
+ const GtkCanvasBox *bounds)
+{
+ g_return_if_fail (GTK_IS_CANVAS_ITEM (self));
+ g_return_if_fail (bounds != NULL);
+
+ gtk_canvas_box_init_copy (&self->bounds, bounds);
+ if (self->canvas)
+ gtk_widget_queue_allocate (GTK_WIDGET (self->canvas));
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_BOUNDS]);
+}
+
+/**
+ * gtk_canvas_item_get_bounds: (attributes org.gtk.Method.get_property=bounds)
+ * @self: a `GtkCanvasItem`
+ *
+ * Gets the bounds that are used to allocate the widget
+ *
+ * Returns: (transfer none): The bounds
+ */
+const GtkCanvasBox *
+gtk_canvas_item_get_bounds (GtkCanvasItem *self)
+{
+ g_return_val_if_fail (GTK_IS_CANVAS_ITEM (self), NULL);
+
+ return &self->bounds;
+}
+
+/**
+ * gtk_canvas_item_set_widget: (attributes org.gtk.Method.set_property=widget)
+ * @self: a `GtkCanvasItem`
+ * @widget: (nullable) (transfer none): the widget to use
+ *
+ * Sets the widget to be displayed by this item.
+ */
+void
+gtk_canvas_item_set_widget (GtkCanvasItem *self,
+ GtkWidget *widget)
+{
+ g_return_if_fail (GTK_IS_CANVAS_ITEM (self));
+ g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
+
+ if (self->widget == widget)
+ return;
+
+ if (self->widget)
+ {
+ if (self->canvas)
+ gtk_widget_unparent (self->widget);
+ g_object_unref (self->widget);
+ }
+
+ self->widget = g_object_ref_sink (widget);
+
+ if (self->canvas)
+ {
+ /* FIXME: Put in right spot */
+ gtk_widget_set_parent (widget, GTK_WIDGET (self->canvas));
+ }
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_WIDGET]);
+}
+
+/**
+ * gtk_canvas_item_get_widget: (attributes org.gtk.Method.get_property=widget)
+ * @self: a `GtkCanvasItem`
+ *
+ * Gets the widget that's currently displayed by this canvasitem
+ *
+ * Returns: (nullable) (transfer none): The widget in use
+ */
+GtkWidget *
+gtk_canvas_item_get_widget (GtkCanvasItem *self)
+{
+ g_return_val_if_fail (GTK_IS_CANVAS_ITEM (self), NULL);
+
+ return self->widget;
+}
+
+void
+gtk_canvas_item_setup (GtkCanvasItem *self,
+ GtkListItemFactory *factory)
+{
+ gtk_list_item_factory_setup (factory, G_OBJECT (self), TRUE, NULL, NULL);
+}
+
+void
+gtk_canvas_item_teardown (GtkCanvasItem *self,
+ GtkListItemFactory *factory)
+{
+ gtk_list_item_factory_teardown (factory, G_OBJECT (self), TRUE, NULL, NULL);
+}