1 /*
2 * Copyright (C) 2021 Purism SPC
3 *
4 * SPDX-License-Identifier: LGPL-2.1+
5 *
6 * Author: Alexander Mikhaylenko <alexander.mikhaylenko@puri.sm>
7 */
8
9 #include "config.h"
10 #include "adw-bin.h"
11
12 /**
13 * SECTION:adwbin
14 * @Short_description: A widget with one child
15 * @Title: AdwBin
16 *
17 * The #AdwBin widget has only one child, set with the #AdwBin:child property.
18 *
19 * It is useful for deriving subclasses, since it provides common code needed
20 * for handling a single child widget.
21 *
22 * Since: 1.0
23 */
24
25 typedef struct
26 {
27 GtkWidget *child;
28 } AdwBinPrivate;
29
30 static void adw_bin_buildable_init (GtkBuildableIface *iface);
31
32 G_DEFINE_TYPE_WITH_CODE (AdwBin, adw_bin, GTK_TYPE_WIDGET,
33 G_ADD_PRIVATE (AdwBin)
34 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, adw_bin_buildable_init))
35
36 static GtkBuildableIface *parent_buildable_iface;
37
38 enum {
39 PROP_0,
40 PROP_CHILD,
41 LAST_PROP
42 };
43
44 static GParamSpec *props[LAST_PROP];
45
46 static void
adw_bin_dispose(GObject * object)47 adw_bin_dispose (GObject *object)
48 {
49 AdwBin *self = ADW_BIN (object);
50 AdwBinPrivate *priv = adw_bin_get_instance_private (self);
51
52 g_clear_pointer (&priv->child, gtk_widget_unparent);
53
54 G_OBJECT_CLASS (adw_bin_parent_class)->dispose (object);
55 }
56
57 static void
adw_bin_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)58 adw_bin_get_property (GObject *object,
59 guint prop_id,
60 GValue *value,
61 GParamSpec *pspec)
62 {
63 AdwBin *self = ADW_BIN (object);
64
65 switch (prop_id) {
66 case PROP_CHILD:
67 g_value_set_object (value, adw_bin_get_child (self));
68 break;
69 default:
70 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
71 }
72 }
73
74 static void
adw_bin_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)75 adw_bin_set_property (GObject *object,
76 guint prop_id,
77 const GValue *value,
78 GParamSpec *pspec)
79 {
80 AdwBin *self = ADW_BIN (object);
81
82 switch (prop_id) {
83 case PROP_CHILD:
84 adw_bin_set_child (self, g_value_get_object (value));
85 break;
86 default:
87 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
88 }
89 }
90
91 static void
adw_bin_class_init(AdwBinClass * klass)92 adw_bin_class_init (AdwBinClass *klass)
93 {
94 GObjectClass *object_class = G_OBJECT_CLASS (klass);
95 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
96
97 object_class->dispose = adw_bin_dispose;
98 object_class->get_property = adw_bin_get_property;
99 object_class->set_property = adw_bin_set_property;
100
101 /**
102 * AdwBin:child:
103 *
104 * The child widget of the #AdwBin.
105 *
106 * Since: 1.0
107 */
108 props[PROP_CHILD] =
109 g_param_spec_object ("child",
110 "Child",
111 "The child widget",
112 GTK_TYPE_WIDGET,
113 G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
114
115 g_object_class_install_properties (object_class, LAST_PROP, props);
116
117 gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
118 }
119
120 static void
adw_bin_init(AdwBin * self)121 adw_bin_init (AdwBin *self)
122 {
123 }
124
125 static void
adw_bin_buildable_add_child(GtkBuildable * buildable,GtkBuilder * builder,GObject * child,const char * type)126 adw_bin_buildable_add_child (GtkBuildable *buildable,
127 GtkBuilder *builder,
128 GObject *child,
129 const char *type)
130 {
131 if (GTK_IS_WIDGET (child))
132 adw_bin_set_child (ADW_BIN (buildable), GTK_WIDGET (child));
133 else
134 parent_buildable_iface->add_child (buildable, builder, child, type);
135 }
136
137 static void
adw_bin_buildable_init(GtkBuildableIface * iface)138 adw_bin_buildable_init (GtkBuildableIface *iface)
139 {
140 parent_buildable_iface = g_type_interface_peek_parent (iface);
141
142 iface->add_child = adw_bin_buildable_add_child;
143 }
144
145 /**
146 * adw_bin_new:
147 *
148 * Creates a new #AdwBin.
149 *
150 * Returns: a new #AdwBin
151 *
152 * Since: 1.0
153 */
154 GtkWidget *
adw_bin_new(void)155 adw_bin_new (void)
156 {
157 return g_object_new (ADW_TYPE_BIN, NULL);
158 }
159
160 /**
161 * adw_bin_get_child:
162 * @self: an #AdwBin
163 *
164 * Gets the child widget of @self.
165 *
166 * Returns: (nullable) (transfer none): the child widget of @self
167 *
168 * Since: 1.0
169 */
170 GtkWidget *
adw_bin_get_child(AdwBin * self)171 adw_bin_get_child (AdwBin *self)
172 {
173 AdwBinPrivate *priv;
174
175 g_return_val_if_fail (ADW_IS_BIN (self), NULL);
176
177 priv = adw_bin_get_instance_private (self);
178
179 return priv->child;
180 }
181
182 /**
183 * adw_bin_set_child:
184 * @self: an #AdwBin
185 * @child: (nullable): the child widget
186 *
187 * Sets the child widget of @self.
188 *
189 * Since: 1.0
190 */
191 void
adw_bin_set_child(AdwBin * self,GtkWidget * child)192 adw_bin_set_child (AdwBin *self,
193 GtkWidget *child)
194 {
195 AdwBinPrivate *priv;
196
197 g_return_if_fail (ADW_IS_BIN (self));
198 g_return_if_fail (child == NULL || GTK_IS_WIDGET (child));
199
200 priv = adw_bin_get_instance_private (self);
201
202 if (priv->child == child)
203 return;
204
205 if (priv->child)
206 gtk_widget_unparent (priv->child);
207
208 priv->child = child;
209
210 if (priv->child)
211 gtk_widget_set_parent (priv->child, GTK_WIDGET (self));
212
213 g_object_notify_by_pspec (G_OBJECT (self), props[PROP_CHILD]);
214 }
215