diff options
Diffstat (limited to 'gtk/gtkcanvasitem.c')
-rw-r--r-- | gtk/gtkcanvasitem.c | 353 |
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); +} |