1#include <gtk/gtk.h>
2
3static GdkContentProvider *
4prepare (GtkDragSource *source,
5 double x,
6 double y,
7 GtkWidget *row)
8{
9 return gdk_content_provider_new_typed (GTK_TYPE_LIST_BOX_ROW, row);
10}
11
12static void
13drag_begin (GtkDragSource *source,
14 GdkDrag *drag,
15 GtkWidget *widget)
16{
17 GtkWidget *row;
18 GtkAllocation alloc;
19 GdkPaintable *paintable;
20 double x, y;
21
22 row = gtk_widget_get_ancestor (widget, GTK_TYPE_LIST_BOX_ROW);
23 gtk_widget_get_allocation (widget: row, allocation: &alloc);
24
25 paintable = gtk_widget_paintable_new (widget: row);
26 gtk_widget_translate_coordinates (src_widget: widget, dest_widget: row, src_x: 0, src_y: 0, dest_x: &x, dest_y: &y);
27 gtk_drag_source_set_icon (source, paintable, hot_x: -x, hot_y: -y);
28
29 g_object_unref (object: paintable);
30}
31
32static gboolean
33drag_drop (GtkDropTarget *dest,
34 const GValue *value,
35 double x,
36 double y,
37 gpointer data)
38{
39 GtkWidget *target = data;
40 GtkWidget *source;
41 int pos;
42
43 source = g_value_get_object (value);
44 if (source == NULL)
45 return FALSE;
46
47 pos = gtk_list_box_row_get_index (GTK_LIST_BOX_ROW (target));
48 if (source == target)
49 return FALSE;
50
51 g_object_ref (source);
52 gtk_box_remove (GTK_BOX (gtk_widget_get_parent (source)), child: source);
53 gtk_list_box_insert (GTK_LIST_BOX (gtk_widget_get_parent (target)), child: source, position: pos);
54 g_object_unref (object: source);
55
56 return TRUE;
57}
58
59static GtkWidget *
60create_row (const char *text)
61{
62 GtkWidget *row, *box, *label, *image;
63 GtkDragSource *source;
64 GtkDropTarget *dest;
65
66 row = gtk_list_box_row_new ();
67 image = gtk_image_new_from_icon_name (icon_name: "open-menu-symbolic");
68 box = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 10);
69 g_object_set (object: box, first_property_name: "margin-start", 10, "margin-end", 10, NULL);
70 label = gtk_label_new (str: text);
71 gtk_list_box_row_set_child (GTK_LIST_BOX_ROW (row), child: box);
72 gtk_widget_set_hexpand (widget: label, TRUE);
73 gtk_box_append (GTK_BOX (box), child: label);
74 gtk_box_append (GTK_BOX (box), child: image);
75
76 source = gtk_drag_source_new ();
77 gtk_drag_source_set_actions (source, actions: GDK_ACTION_MOVE);
78 g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image);
79 g_signal_connect (source, "prepare", G_CALLBACK (prepare), row);
80 gtk_widget_add_controller (widget: image, GTK_EVENT_CONTROLLER (source));
81
82 dest = gtk_drop_target_new (GTK_TYPE_LIST_BOX_ROW, actions: GDK_ACTION_MOVE);
83 g_signal_connect (dest, "drop", G_CALLBACK (drag_drop), row);
84 gtk_widget_add_controller (GTK_WIDGET (row), GTK_EVENT_CONTROLLER (dest));
85
86 return row;
87}
88
89static void
90on_row_activated (GtkListBox *self,
91 GtkWidget *child)
92{
93 const char *id;
94 id = g_object_get_data (G_OBJECT (gtk_list_box_row_get_child (GTK_LIST_BOX_ROW (child))), key: "id");
95 g_message ("Row activated %p: %s", child, id);
96}
97
98static void
99on_selected_children_changed (GtkListBox *self)
100{
101 g_message ("Selection changed");
102}
103
104static void
105selection_mode_changed (GtkComboBox *combo, gpointer data)
106{
107 GtkListBox *list = data;
108
109 gtk_list_box_set_selection_mode (box: list, mode: gtk_combo_box_get_active (combo_box: combo));
110}
111
112static const char *css =
113 ".during-dnd { "
114 " background: white; "
115 " border: 1px solid black; "
116 "}";
117
118int
119main (int argc, char *argv[])
120{
121 GtkWidget *window, *list, *sw, *row;
122 GtkWidget *hbox, *vbox, *combo, *button;
123 int i;
124 char *text;
125 GtkCssProvider *provider;
126
127 gtk_init ();
128
129 provider = gtk_css_provider_new ();
130 gtk_css_provider_load_from_data (css_provider: provider, data: css, length: -1);
131 gtk_style_context_add_provider_for_display (display: gdk_display_get_default (), GTK_STYLE_PROVIDER (provider), priority: 800);
132 window = gtk_window_new ();
133 gtk_window_set_default_size (GTK_WINDOW (window), width: -1, height: 300);
134
135 hbox = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 12);
136 gtk_window_set_child (GTK_WINDOW (window), child: hbox);
137 vbox = gtk_box_new (orientation: GTK_ORIENTATION_VERTICAL, spacing: 6);
138 gtk_widget_set_margin_start (widget: vbox, margin: 12);
139 gtk_widget_set_margin_end (widget: vbox, margin: 12);
140 gtk_widget_set_margin_top (widget: vbox, margin: 12);
141 gtk_widget_set_margin_bottom (widget: vbox, margin: 12);
142 gtk_box_append (GTK_BOX (hbox), child: vbox);
143
144 list = gtk_list_box_new ();
145 gtk_list_box_set_selection_mode (GTK_LIST_BOX (list), mode: GTK_SELECTION_NONE);
146
147 g_signal_connect (list, "row-activated", G_CALLBACK (on_row_activated), NULL);
148 g_signal_connect (list, "selected-rows-changed", G_CALLBACK (on_selected_children_changed), NULL);
149
150 sw = gtk_scrolled_window_new ();
151 gtk_widget_set_hexpand (widget: sw, TRUE);
152 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), hscrollbar_policy: GTK_POLICY_NEVER, vscrollbar_policy: GTK_POLICY_ALWAYS);
153 gtk_box_append (GTK_BOX (hbox), child: sw);
154 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), child: list);
155
156 button = gtk_check_button_new_with_label (label: "Activate on single click");
157 g_object_bind_property (source: list, source_property: "activate-on-single-click",
158 target: button, target_property: "active",
159 flags: G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
160 gtk_box_append (GTK_BOX (vbox), child: button);
161
162 combo = gtk_combo_box_text_new ();
163 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), text: "None");
164 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), text: "Single");
165 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), text: "Browse");
166 gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), text: "Multiple");
167 g_signal_connect (combo, "changed", G_CALLBACK (selection_mode_changed), list);
168 gtk_box_append (GTK_BOX (vbox), child: combo);
169 gtk_combo_box_set_active (GTK_COMBO_BOX (combo), index_: gtk_list_box_get_selection_mode (GTK_LIST_BOX (list)));
170
171 for (i = 0; i < 20; i++)
172 {
173 text = g_strdup_printf (format: "Row %d", i);
174 row = create_row (text);
175 gtk_list_box_insert (GTK_LIST_BOX (list), child: row, position: -1);
176 }
177
178 gtk_widget_show (widget: window);
179
180 while (TRUE)
181 g_main_context_iteration (NULL, TRUE);
182
183 return 0;
184}
185

source code of gtk/tests/testlist3.c