1 | /* |
2 | * Copyright © 2019 Zander Brown |
3 | * |
4 | * This library is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU Lesser General Public |
6 | * License as published by the Free Software Foundation; either |
7 | * version 2 of the License, or (at your option) any later version. |
8 | * |
9 | * This library is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * Lesser General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU Lesser General Public |
15 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
16 | */ |
17 | |
18 | #include "config.h" |
19 | #include <glib/gi18n-lib.h> |
20 | |
21 | #include "type-info.h" |
22 | |
23 | #include "gtkpopover.h" |
24 | |
25 | struct _GtkInspectorTypePopover |
26 | { |
27 | GtkPopover parent_instance; |
28 | }; |
29 | |
30 | typedef struct _GtkInspectorTypePopoverPrivate GtkInspectorTypePopoverPrivate; |
31 | |
32 | struct _GtkInspectorTypePopoverPrivate |
33 | { |
34 | GType type; |
35 | |
36 | GtkWidget *parents; |
37 | GtkWidget *interfaces; |
38 | }; |
39 | |
40 | enum |
41 | { |
42 | PROP_0, |
43 | PROP_TYPE |
44 | }; |
45 | |
46 | G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorTypePopover, gtk_inspector_type_popover, |
47 | GTK_TYPE_POPOVER) |
48 | |
49 | static void |
50 | add_row (GtkWidget *box, |
51 | const char *name) |
52 | { |
53 | GtkWidget *row; |
54 | GtkWidget *label; |
55 | |
56 | row = g_object_new (GTK_TYPE_LIST_BOX_ROW, |
57 | first_property_name: "selectable" , FALSE, |
58 | "activatable" , FALSE, |
59 | NULL); |
60 | |
61 | label = g_object_new (GTK_TYPE_LABEL, |
62 | first_property_name: "margin-start" , 6, |
63 | "margin-end" , 6, |
64 | "margin-top" , 6, |
65 | "margin-bottom" , 6, |
66 | "label" , name, |
67 | "selectable" , TRUE, |
68 | "xalign" , 0.0, |
69 | NULL); |
70 | |
71 | gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), child: label); |
72 | gtk_list_box_insert (GTK_LIST_BOX (box), child: row, position: -1); |
73 | } |
74 | |
75 | void |
76 | gtk_inspector_type_popover_set_gtype (GtkInspectorTypePopover *self, |
77 | GType gtype) |
78 | { |
79 | GtkInspectorTypePopoverPrivate *priv; |
80 | GHashTable *implements; |
81 | GHashTableIter iter; |
82 | const char *name; |
83 | GType *interfaces; |
84 | GType tmp; |
85 | int i; |
86 | GtkWidget *child; |
87 | |
88 | g_return_if_fail (GTK_IS_INSPECTOR_TYPE_POPOVER (self)); |
89 | |
90 | priv = gtk_inspector_type_popover_get_instance_private (self); |
91 | |
92 | if (priv->type == gtype) |
93 | return; |
94 | |
95 | priv->type = gtype; |
96 | |
97 | while ((child = gtk_widget_get_first_child (widget: priv->parents))) |
98 | gtk_list_box_remove (GTK_LIST_BOX (priv->parents), child); |
99 | while ((child = gtk_widget_get_first_child (widget: priv->interfaces))) |
100 | gtk_list_box_remove (GTK_LIST_BOX (priv->interfaces), child); |
101 | |
102 | implements = g_hash_table_new (hash_func: g_str_hash, key_equal_func: g_str_equal); |
103 | |
104 | tmp = gtype; |
105 | |
106 | do |
107 | { |
108 | add_row (box: priv->parents, name: g_type_name (type: tmp)); |
109 | |
110 | interfaces = g_type_interfaces (type: tmp, NULL); |
111 | |
112 | for (i = 0; interfaces[i]; i++) |
113 | g_hash_table_add (hash_table: implements, key: (char *) g_type_name (type: interfaces[i])); |
114 | |
115 | g_free (mem: interfaces); |
116 | } |
117 | while ((tmp = g_type_parent (type: tmp))); |
118 | |
119 | g_hash_table_iter_init (iter: &iter, hash_table: implements); |
120 | |
121 | while (g_hash_table_iter_next (iter: &iter, key: (gpointer *) &name, NULL)) |
122 | add_row (box: priv->interfaces, name); |
123 | |
124 | g_hash_table_unref (hash_table: implements); |
125 | } |
126 | |
127 | static void |
128 | gtk_inspector_type_popover_init (GtkInspectorTypePopover *self) |
129 | { |
130 | GtkInspectorTypePopoverPrivate *priv; |
131 | GtkWidget *label; |
132 | |
133 | gtk_widget_init_template (GTK_WIDGET (self)); |
134 | |
135 | priv = gtk_inspector_type_popover_get_instance_private (self); |
136 | |
137 | priv->type = G_TYPE_NONE; |
138 | |
139 | label = g_object_new (GTK_TYPE_LABEL, |
140 | first_property_name: "margin-start" , 12, |
141 | "margin-end" , 12, |
142 | "margin-top" , 12, |
143 | "margin-bottom" , 12, |
144 | "label" , "None" , |
145 | NULL); |
146 | |
147 | gtk_list_box_set_placeholder (GTK_LIST_BOX (priv->parents), placeholder: label); |
148 | |
149 | label = g_object_new (GTK_TYPE_LABEL, |
150 | first_property_name: "margin-start" , 12, |
151 | "margin-end" , 12, |
152 | "margin-top" , 12, |
153 | "margin-bottom" , 12, |
154 | "label" , "None" , |
155 | NULL); |
156 | |
157 | gtk_list_box_set_placeholder (GTK_LIST_BOX (priv->interfaces), placeholder: label); |
158 | } |
159 | |
160 | static void |
161 | gtk_inspector_type_popover_get_property (GObject *object, |
162 | guint param_id, |
163 | GValue *value, |
164 | GParamSpec *pspec) |
165 | { |
166 | GtkInspectorTypePopover *self = GTK_INSPECTOR_TYPE_POPOVER (ptr: object); |
167 | GtkInspectorTypePopoverPrivate *priv = gtk_inspector_type_popover_get_instance_private (self); |
168 | |
169 | switch (param_id) |
170 | { |
171 | case PROP_TYPE: |
172 | g_value_set_gtype (value, v_gtype: priv->type); |
173 | break; |
174 | |
175 | default: |
176 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); |
177 | break; |
178 | } |
179 | } |
180 | |
181 | static void |
182 | gtk_inspector_type_popover_set_property (GObject *object, |
183 | guint param_id, |
184 | const GValue *value, |
185 | GParamSpec *pspec) |
186 | { |
187 | GtkInspectorTypePopover *self = GTK_INSPECTOR_TYPE_POPOVER (ptr: object); |
188 | |
189 | switch (param_id) |
190 | { |
191 | case PROP_TYPE: |
192 | gtk_inspector_type_popover_set_gtype (self, gtype: g_value_get_gtype (value)); |
193 | break; |
194 | |
195 | default: |
196 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); |
197 | break; |
198 | } |
199 | } |
200 | |
201 | static void |
202 | gtk_inspector_type_popover_class_init (GtkInspectorTypePopoverClass *klass) |
203 | { |
204 | GObjectClass *object_class = G_OBJECT_CLASS (klass); |
205 | GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); |
206 | |
207 | object_class->get_property = gtk_inspector_type_popover_get_property; |
208 | object_class->set_property = gtk_inspector_type_popover_set_property; |
209 | |
210 | g_object_class_install_property (oclass: object_class, property_id: PROP_TYPE, |
211 | pspec: g_param_spec_gtype (name: "type" , nick: "Type" , blurb: "Type" , |
212 | G_TYPE_NONE, flags: G_PARAM_READWRITE)); |
213 | |
214 | gtk_widget_class_set_template_from_resource (widget_class, resource_name: "/org/gtk/libgtk/inspector/type-info.ui" ); |
215 | gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorTypePopover, parents); |
216 | gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorTypePopover, interfaces); |
217 | } |
218 | |