1 | #include <gtk/gtk.h> |
2 | |
3 | static void |
4 | row_unrevealed (GObject *revealer, GParamSpec *pspec, gpointer data) |
5 | { |
6 | GtkWidget *row, *list; |
7 | |
8 | row = gtk_widget_get_parent (GTK_WIDGET (revealer)); |
9 | list = gtk_widget_get_parent (widget: row); |
10 | |
11 | gtk_list_box_remove (GTK_LIST_BOX (list), child: row); |
12 | } |
13 | |
14 | static void |
15 | remove_this_row (GtkButton *button, GtkWidget *child) |
16 | { |
17 | GtkWidget *row, *revealer; |
18 | |
19 | row = gtk_widget_get_parent (widget: child); |
20 | revealer = gtk_revealer_new (); |
21 | gtk_revealer_set_reveal_child (GTK_REVEALER (revealer), TRUE); |
22 | g_object_ref (child); |
23 | gtk_box_remove (GTK_BOX (gtk_widget_get_parent (child)), child); |
24 | gtk_revealer_set_child (GTK_REVEALER (revealer), child); |
25 | g_object_unref (object: child); |
26 | gtk_box_append (GTK_BOX (row), child: revealer); |
27 | g_signal_connect (revealer, "notify::child-revealed" , |
28 | G_CALLBACK (row_unrevealed), NULL); |
29 | gtk_revealer_set_reveal_child (GTK_REVEALER (revealer), FALSE); |
30 | } |
31 | |
32 | static GtkWidget *create_row (const char *label); |
33 | |
34 | static void |
35 | row_revealed (GObject *revealer, GParamSpec *pspec, gpointer data) |
36 | { |
37 | GtkWidget *row, *child; |
38 | |
39 | row = gtk_widget_get_parent (GTK_WIDGET (revealer)); |
40 | child = gtk_revealer_get_child (GTK_REVEALER (revealer)); |
41 | g_object_ref (child); |
42 | gtk_revealer_set_child (GTK_REVEALER (revealer), NULL); |
43 | |
44 | gtk_widget_unparent (GTK_WIDGET (revealer)); |
45 | gtk_box_append (GTK_BOX (row), child); |
46 | g_object_unref (object: child); |
47 | } |
48 | |
49 | static void |
50 | add_row_below (GtkButton *button, GtkWidget *child) |
51 | { |
52 | GtkWidget *revealer, *row, *list; |
53 | int index; |
54 | |
55 | row = gtk_widget_get_parent (widget: child); |
56 | index = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (row)); |
57 | list = gtk_widget_get_parent (widget: row); |
58 | row = create_row (label: "Extra row" ); |
59 | revealer = gtk_revealer_new (); |
60 | gtk_revealer_set_child (GTK_REVEALER (revealer), child: row); |
61 | g_signal_connect (revealer, "notify::child-revealed" , |
62 | G_CALLBACK (row_revealed), NULL); |
63 | gtk_list_box_insert (GTK_LIST_BOX (list), child: revealer, position: index + 1); |
64 | gtk_revealer_set_reveal_child (GTK_REVEALER (revealer), TRUE); |
65 | } |
66 | |
67 | static void |
68 | add_separator (GtkListBoxRow *row, GtkListBoxRow *before, gpointer data) |
69 | { |
70 | if (!before) |
71 | return; |
72 | |
73 | gtk_list_box_row_set_header (row, header: gtk_separator_new (orientation: GTK_ORIENTATION_HORIZONTAL)); |
74 | } |
75 | |
76 | static GtkWidget * |
77 | create_row (const char *text) |
78 | { |
79 | GtkWidget *row, *label, *button; |
80 | |
81 | row = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 10); |
82 | label = gtk_label_new (str: text); |
83 | gtk_box_append (GTK_BOX (row), child: label); |
84 | button = gtk_button_new_with_label (label: "x" ); |
85 | gtk_widget_set_hexpand (widget: button, TRUE); |
86 | gtk_widget_set_halign (widget: button, align: GTK_ALIGN_END); |
87 | gtk_widget_set_valign (widget: button, align: GTK_ALIGN_CENTER); |
88 | gtk_box_append (GTK_BOX (row), child: button); |
89 | g_signal_connect (button, "clicked" , G_CALLBACK (remove_this_row), row); |
90 | button = gtk_button_new_with_label (label: "+" ); |
91 | gtk_widget_set_valign (widget: button, align: GTK_ALIGN_CENTER); |
92 | gtk_box_append (GTK_BOX (row), child: button); |
93 | g_signal_connect (button, "clicked" , G_CALLBACK (add_row_below), row); |
94 | |
95 | return row; |
96 | } |
97 | |
98 | static void |
99 | quit_cb (GtkWidget *widget, |
100 | gpointer data) |
101 | { |
102 | gboolean *done = data; |
103 | |
104 | *done = TRUE; |
105 | |
106 | g_main_context_wakeup (NULL); |
107 | } |
108 | |
109 | int main (int argc, char *argv[]) |
110 | { |
111 | GtkWidget *window, *list, *sw, *row; |
112 | int i; |
113 | char *text; |
114 | gboolean done = FALSE; |
115 | |
116 | gtk_init (); |
117 | |
118 | window = gtk_window_new (); |
119 | gtk_window_set_default_size (GTK_WINDOW (window), width: 300, height: 300); |
120 | |
121 | list = gtk_list_box_new (); |
122 | gtk_list_box_set_selection_mode (GTK_LIST_BOX (list), mode: GTK_SELECTION_NONE); |
123 | gtk_list_box_set_header_func (GTK_LIST_BOX (list), update_header: add_separator, NULL, NULL); |
124 | sw = gtk_scrolled_window_new (); |
125 | gtk_window_set_child (GTK_WINDOW (window), child: sw); |
126 | gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), child: list); |
127 | |
128 | for (i = 0; i < 20; i++) |
129 | { |
130 | text = g_strdup_printf (format: "Row %d" , i); |
131 | row = create_row (text); |
132 | gtk_list_box_insert (GTK_LIST_BOX (list), child: row, position: -1); |
133 | } |
134 | |
135 | g_signal_connect (window, "destroy" , G_CALLBACK (quit_cb), &done); |
136 | gtk_widget_show (widget: window); |
137 | |
138 | while (!done) |
139 | g_main_context_iteration (NULL, TRUE); |
140 | |
141 | return 0; |
142 | } |
143 | |