1 | /* |
2 | * Copyright (c) 2015 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 "strv-editor.h" |
22 | #include "gtkbutton.h" |
23 | #include "gtkentry.h" |
24 | #include "gtkbox.h" |
25 | #include "gtkorientable.h" |
26 | #include "gtkmarshalers.h" |
27 | |
28 | enum |
29 | { |
30 | CHANGED, |
31 | N_SIGNALS |
32 | }; |
33 | |
34 | static guint signals[N_SIGNALS] = { 0 }; |
35 | |
36 | G_DEFINE_TYPE (GtkInspectorStrvEditor, gtk_inspector_strv_editor, GTK_TYPE_BOX); |
37 | |
38 | static void |
39 | emit_changed (GtkInspectorStrvEditor *editor) |
40 | { |
41 | if (editor->blocked) |
42 | return; |
43 | |
44 | g_signal_emit (instance: editor, signal_id: signals[CHANGED], detail: 0); |
45 | } |
46 | |
47 | static void |
48 | remove_string (GtkButton *button, |
49 | GtkInspectorStrvEditor *editor) |
50 | { |
51 | GtkWidget *row; |
52 | |
53 | row = gtk_widget_get_parent (GTK_WIDGET (button)); |
54 | gtk_box_remove (GTK_BOX (gtk_widget_get_parent (row)), child: row); |
55 | emit_changed (editor); |
56 | } |
57 | |
58 | static void |
59 | add_string (GtkInspectorStrvEditor *editor, |
60 | const char *str) |
61 | { |
62 | GtkWidget *box; |
63 | GtkWidget *entry; |
64 | GtkWidget *button; |
65 | |
66 | box = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 0); |
67 | gtk_widget_add_css_class (widget: box, css_class: "linked" ); |
68 | gtk_widget_show (widget: box); |
69 | |
70 | entry = gtk_entry_new (); |
71 | gtk_editable_set_text (GTK_EDITABLE (entry), text: str); |
72 | gtk_widget_show (widget: entry); |
73 | gtk_box_append (GTK_BOX (box), child: entry); |
74 | g_object_set_data (G_OBJECT (box), key: "entry" , data: entry); |
75 | g_signal_connect_swapped (entry, "notify::text" , G_CALLBACK (emit_changed), editor); |
76 | |
77 | button = gtk_button_new_from_icon_name (icon_name: "user-trash-symbolic" ); |
78 | gtk_widget_add_css_class (widget: button, css_class: "image-button" ); |
79 | gtk_widget_show (widget: button); |
80 | gtk_box_append (GTK_BOX (box), child: button); |
81 | g_signal_connect (button, "clicked" , G_CALLBACK (remove_string), editor); |
82 | |
83 | gtk_box_append (GTK_BOX (editor->box), child: box); |
84 | |
85 | gtk_widget_grab_focus (widget: entry); |
86 | |
87 | emit_changed (editor); |
88 | } |
89 | |
90 | static void |
91 | add_cb (GtkButton *button, |
92 | GtkInspectorStrvEditor *editor) |
93 | { |
94 | add_string (editor, str: "" ); |
95 | } |
96 | |
97 | static void |
98 | gtk_inspector_strv_editor_init (GtkInspectorStrvEditor *editor) |
99 | { |
100 | gtk_box_set_spacing (GTK_BOX (editor), spacing: 6); |
101 | gtk_orientable_set_orientation (GTK_ORIENTABLE (editor), orientation: GTK_ORIENTATION_VERTICAL); |
102 | editor->box = gtk_box_new (orientation: GTK_ORIENTATION_VERTICAL, spacing: 6); |
103 | gtk_widget_show (widget: editor->box); |
104 | |
105 | editor->button = gtk_button_new_from_icon_name (icon_name: "list-add-symbolic" ); |
106 | gtk_widget_add_css_class (widget: editor->button, css_class: "image-button" ); |
107 | gtk_widget_set_focus_on_click (widget: editor->button, FALSE); |
108 | gtk_widget_set_halign (widget: editor->button, align: GTK_ALIGN_END); |
109 | gtk_widget_show (widget: editor->button); |
110 | g_signal_connect (editor->button, "clicked" , G_CALLBACK (add_cb), editor); |
111 | |
112 | gtk_box_append (GTK_BOX (editor), child: editor->box); |
113 | gtk_box_append (GTK_BOX (editor), child: editor->button); |
114 | } |
115 | |
116 | static void |
117 | gtk_inspector_strv_editor_class_init (GtkInspectorStrvEditorClass *class) |
118 | { |
119 | signals[CHANGED] = |
120 | g_signal_new (signal_name: "changed" , |
121 | G_TYPE_FROM_CLASS (class), |
122 | signal_flags: G_SIGNAL_RUN_FIRST, |
123 | G_STRUCT_OFFSET (GtkInspectorStrvEditorClass, changed), |
124 | NULL, NULL, |
125 | NULL, |
126 | G_TYPE_NONE, n_params: 0); |
127 | } |
128 | |
129 | void |
130 | gtk_inspector_strv_editor_set_strv (GtkInspectorStrvEditor *editor, |
131 | char **strv) |
132 | { |
133 | GtkWidget *child; |
134 | int i; |
135 | |
136 | editor->blocked = TRUE; |
137 | |
138 | while ((child = gtk_widget_get_first_child (GTK_WIDGET (editor->box)))) |
139 | gtk_box_remove (GTK_BOX (editor->box), child); |
140 | |
141 | if (strv) |
142 | { |
143 | for (i = 0; strv[i]; i++) |
144 | add_string (editor, str: strv[i]); |
145 | } |
146 | |
147 | editor->blocked = FALSE; |
148 | |
149 | emit_changed (editor); |
150 | } |
151 | |
152 | char ** |
153 | gtk_inspector_strv_editor_get_strv (GtkInspectorStrvEditor *editor) |
154 | { |
155 | GtkWidget *child; |
156 | GPtrArray *p; |
157 | |
158 | p = g_ptr_array_new (); |
159 | |
160 | for (child = gtk_widget_get_first_child (widget: editor->box); |
161 | child != NULL; |
162 | child = gtk_widget_get_next_sibling (widget: child)) |
163 | { |
164 | GtkEntry *entry; |
165 | |
166 | entry = GTK_ENTRY (g_object_get_data (G_OBJECT (child), "entry" )); |
167 | g_ptr_array_add (array: p, data: g_strdup (str: gtk_editable_get_text (GTK_EDITABLE (entry)))); |
168 | } |
169 | |
170 | g_ptr_array_add (array: p, NULL); |
171 | |
172 | return (char **)g_ptr_array_free (array: p, FALSE); |
173 | } |
174 | |