1 | /* |
2 | * Copyright (c) 2020 Red Hat, Inc. |
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 "list-data.h" |
22 | |
23 | #include "gtkcolumnview.h" |
24 | #include "gtktogglebutton.h" |
25 | #include "gtklabel.h" |
26 | #include "gtkstack.h" |
27 | #include "gtkboxlayout.h" |
28 | #include "gtkorientable.h" |
29 | #include "gtknoselection.h" |
30 | #include "gtksignallistitemfactory.h" |
31 | #include "gtklistitem.h" |
32 | #include "window.h" |
33 | |
34 | |
35 | struct _GtkInspectorListData |
36 | { |
37 | GtkWidget parent_instance; |
38 | |
39 | GListModel *object; |
40 | GtkColumnView *view; |
41 | GtkWidget *items_label; |
42 | }; |
43 | |
44 | struct _GtkInspectorListDataClass |
45 | { |
46 | GtkWidgetClass parent_class; |
47 | }; |
48 | |
49 | G_DEFINE_TYPE (GtkInspectorListData, gtk_inspector_list_data, GTK_TYPE_WIDGET) |
50 | |
51 | static void |
52 | gtk_inspector_list_data_init (GtkInspectorListData *sl) |
53 | { |
54 | gtk_widget_init_template (GTK_WIDGET (sl)); |
55 | |
56 | gtk_orientable_set_orientation (GTK_ORIENTABLE (gtk_widget_get_layout_manager (GTK_WIDGET (sl))), |
57 | orientation: GTK_ORIENTATION_VERTICAL); |
58 | } |
59 | |
60 | void |
61 | gtk_inspector_list_data_set_object (GtkInspectorListData *sl, |
62 | GObject *object) |
63 | { |
64 | GtkWidget *stack; |
65 | GtkStackPage *page; |
66 | char *text; |
67 | GtkNoSelection *selection; |
68 | |
69 | stack = gtk_widget_get_parent (GTK_WIDGET (sl)); |
70 | page = gtk_stack_get_page (GTK_STACK (stack), GTK_WIDGET (sl)); |
71 | |
72 | gtk_column_view_set_model (self: sl->view, NULL); |
73 | sl->object = NULL; |
74 | |
75 | if (!G_IS_LIST_MODEL (ptr: object)) |
76 | { |
77 | g_object_set (object: page, first_property_name: "visible" , FALSE, NULL); |
78 | return; |
79 | } |
80 | |
81 | text = g_strdup_printf (format: "%u items" , g_list_model_get_n_items (list: G_LIST_MODEL (ptr: object))); |
82 | gtk_label_set_label (GTK_LABEL (sl->items_label), str: text); |
83 | g_free (mem: text); |
84 | |
85 | g_object_set (object: page, first_property_name: "visible" , TRUE, NULL); |
86 | |
87 | sl->object = G_LIST_MODEL (ptr: object); |
88 | selection = gtk_no_selection_new (g_object_ref (sl->object)); |
89 | gtk_column_view_set_model (self: sl->view, model: GTK_SELECTION_MODEL (ptr: selection)); |
90 | g_object_unref (object: selection); |
91 | } |
92 | |
93 | static void |
94 | setup_object (GtkSignalListItemFactory *factory, |
95 | GtkListItem *item) |
96 | { |
97 | GtkWidget *label; |
98 | |
99 | label = gtk_label_new (str: "" ); |
100 | gtk_label_set_xalign (GTK_LABEL (label), xalign: 0); |
101 | gtk_widget_add_css_class (widget: label, css_class: "cell" ); |
102 | gtk_list_item_set_child (self: item, child: label); |
103 | } |
104 | |
105 | static void |
106 | bind_object (GtkSignalListItemFactory *factory, |
107 | GtkListItem *item) |
108 | { |
109 | GtkWidget *label; |
110 | gpointer obj; |
111 | char *text; |
112 | |
113 | label = gtk_list_item_get_child (self: item); |
114 | obj = gtk_list_item_get_item (self: item); |
115 | |
116 | text = g_strdup_printf (format: "%p" , obj); |
117 | gtk_label_set_label (GTK_LABEL (label), str: text); |
118 | g_free (mem: text); |
119 | } |
120 | |
121 | static void |
122 | setup_type (GtkSignalListItemFactory *factory, |
123 | GtkListItem *item) |
124 | { |
125 | GtkWidget *label; |
126 | |
127 | label = gtk_label_new (str: "" ); |
128 | gtk_label_set_xalign (GTK_LABEL (label), xalign: 0); |
129 | gtk_widget_add_css_class (widget: label, css_class: "cell" ); |
130 | gtk_list_item_set_child (self: item, child: label); |
131 | } |
132 | |
133 | static void |
134 | bind_type (GtkSignalListItemFactory *factory, |
135 | GtkListItem *item) |
136 | { |
137 | GtkWidget *label; |
138 | gpointer obj; |
139 | |
140 | label = gtk_list_item_get_child (self: item); |
141 | obj = gtk_list_item_get_item (self: item); |
142 | |
143 | gtk_label_set_label (GTK_LABEL (label), G_OBJECT_TYPE_NAME (obj)); |
144 | } |
145 | |
146 | static void |
147 | setup_props (GtkSignalListItemFactory *factory, |
148 | GtkListItem *item) |
149 | { |
150 | GtkWidget *button; |
151 | |
152 | button = gtk_button_new_with_label (label: "Properties" ); |
153 | gtk_widget_add_css_class (widget: button, css_class: "cell" ); |
154 | gtk_widget_set_halign (widget: button, align: GTK_ALIGN_START); |
155 | gtk_list_item_set_child (self: item, child: button); |
156 | } |
157 | |
158 | static void |
159 | object_properties (GtkWidget *button, |
160 | GtkListItem *item) |
161 | { |
162 | GtkInspectorWindow *iw; |
163 | GObject *obj; |
164 | guint pos; |
165 | |
166 | iw = GTK_INSPECTOR_WINDOW (gtk_widget_get_ancestor (button, GTK_TYPE_INSPECTOR_WINDOW)); |
167 | |
168 | obj = gtk_list_item_get_item (self: item); |
169 | pos = gtk_list_item_get_position (self: item); |
170 | gtk_inspector_window_push_object (iw, object: obj, kind: CHILD_KIND_LISTITEM, position: pos); |
171 | } |
172 | |
173 | static void |
174 | bind_props (GtkSignalListItemFactory *factory, |
175 | GtkListItem *item, |
176 | GtkInspectorListData *sl) |
177 | { |
178 | g_signal_connect (gtk_list_item_get_child (item), "clicked" , |
179 | G_CALLBACK (object_properties), item); |
180 | } |
181 | |
182 | static void |
183 | unbind_props (GtkSignalListItemFactory *factory, |
184 | GtkListItem *item) |
185 | { |
186 | g_signal_handlers_disconnect_by_func (gtk_list_item_get_child (item), object_properties, item); |
187 | } |
188 | |
189 | static void |
190 | dispose (GObject *object) |
191 | { |
192 | GtkInspectorListData *sl = GTK_INSPECTOR_LIST_DATA (ptr: object); |
193 | GtkWidget *child; |
194 | |
195 | while ((child = gtk_widget_get_first_child (GTK_WIDGET (sl)))) |
196 | gtk_widget_unparent (widget: child); |
197 | |
198 | G_OBJECT_CLASS (gtk_inspector_list_data_parent_class)->dispose (object); |
199 | } |
200 | |
201 | static void |
202 | gtk_inspector_list_data_class_init (GtkInspectorListDataClass *klass) |
203 | { |
204 | GObjectClass *object_class = G_OBJECT_CLASS (klass); |
205 | GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); |
206 | |
207 | object_class->dispose = dispose; |
208 | |
209 | gtk_widget_class_set_template_from_resource (widget_class, resource_name: "/org/gtk/libgtk/inspector/list-data.ui" ); |
210 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorListData, view); |
211 | gtk_widget_class_bind_template_child (widget_class, GtkInspectorListData, items_label); |
212 | |
213 | gtk_widget_class_bind_template_callback (widget_class, setup_object); |
214 | gtk_widget_class_bind_template_callback (widget_class, bind_object); |
215 | gtk_widget_class_bind_template_callback (widget_class, setup_type); |
216 | gtk_widget_class_bind_template_callback (widget_class, bind_type); |
217 | gtk_widget_class_bind_template_callback (widget_class, setup_props); |
218 | gtk_widget_class_bind_template_callback (widget_class, bind_props); |
219 | gtk_widget_class_bind_template_callback (widget_class, unbind_props); |
220 | |
221 | gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT); |
222 | } |
223 | |
224 | // vim: set et sw=2 ts=2: |
225 | |