1 | #include <gtk/gtk.h> |
2 | |
3 | static gboolean |
4 | clicked_icon (GtkTreeView *tv, |
5 | int x, |
6 | int y, |
7 | GtkTreePath **path) |
8 | { |
9 | GtkTreeViewColumn *col; |
10 | int cell_x, cell_y; |
11 | int cell_pos, cell_width; |
12 | GList *cells, *l; |
13 | int depth; |
14 | int level_indentation; |
15 | int expander_size; |
16 | int indent; |
17 | |
18 | if (gtk_tree_view_get_path_at_pos (tree_view: tv, x, y, path, column: &col, cell_x: &cell_x, cell_y: &cell_y)) |
19 | { |
20 | cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (col)); |
21 | |
22 | #if 1 |
23 | /* ugly workaround to fix the problem: |
24 | * manually calculate the indent for the row |
25 | */ |
26 | depth = gtk_tree_path_get_depth (path: *path); |
27 | level_indentation = gtk_tree_view_get_level_indentation (tree_view: tv); |
28 | expander_size = 16; /* Hardcoded in gtktreeview.c */ |
29 | expander_size += 4; |
30 | indent = (depth - 1) * level_indentation + depth * expander_size; |
31 | #else |
32 | indent = 0; |
33 | #endif |
34 | |
35 | for (l = cells; l; l = l->next) |
36 | { |
37 | gtk_tree_view_column_cell_get_position (tree_column: col, cell_renderer: l->data, x_offset: &cell_pos, width: &cell_width); |
38 | if (cell_pos + indent <= cell_x && cell_x <= cell_pos + indent + cell_width) |
39 | { |
40 | g_print (format: "clicked in %s\n" , g_type_name_from_instance (instance: l->data)); |
41 | if (GTK_IS_CELL_RENDERER_PIXBUF (l->data)) |
42 | { |
43 | g_list_free (list: cells); |
44 | return TRUE; |
45 | } |
46 | } |
47 | } |
48 | |
49 | g_list_free (list: cells); |
50 | } |
51 | |
52 | return FALSE; |
53 | } |
54 | |
55 | static void |
56 | release_event (GtkGestureClick *gesture, |
57 | guint n_press, |
58 | double x, |
59 | double y, |
60 | GtkTreeView *tv) |
61 | { |
62 | GtkTreePath *path; |
63 | int tx, ty; |
64 | |
65 | gtk_tree_view_convert_widget_to_tree_coords (tree_view: tv, wx: x, wy: y, tx: &tx, ty: &ty); |
66 | |
67 | if (clicked_icon (tv, x: tx, y: ty, path: &path)) |
68 | { |
69 | GtkTreeModel *model; |
70 | GtkTreeIter iter; |
71 | char *text; |
72 | |
73 | model = gtk_tree_view_get_model (tree_view: tv); |
74 | gtk_tree_model_get_iter (tree_model: model, iter: &iter, path); |
75 | gtk_tree_model_get (tree_model: model, iter: &iter, 0, &text, -1); |
76 | |
77 | g_print (format: "text was: %s\n" , text); |
78 | g_free (mem: text); |
79 | gtk_tree_path_free (path); |
80 | } |
81 | } |
82 | |
83 | int main (int argc, char *argv[]) |
84 | { |
85 | GtkWidget *window; |
86 | GtkWidget *sw; |
87 | GtkWidget *tv; |
88 | GtkTreeViewColumn *col; |
89 | GtkCellRenderer *cell; |
90 | GtkTreeStore *store; |
91 | GtkTreeIter iter; |
92 | GtkGesture *gesture; |
93 | |
94 | gtk_init (); |
95 | |
96 | window = gtk_window_new (); |
97 | sw = gtk_scrolled_window_new (); |
98 | gtk_window_set_child (GTK_WINDOW (window), child: sw); |
99 | tv = gtk_tree_view_new (); |
100 | gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), child: tv); |
101 | |
102 | col = gtk_tree_view_column_new (); |
103 | cell = gtk_cell_renderer_text_new (); |
104 | gtk_tree_view_column_pack_start (tree_column: col, cell, TRUE); |
105 | gtk_tree_view_column_add_attribute (tree_column: col, cell_renderer: cell, attribute: "text" , column: 0); |
106 | |
107 | cell = gtk_cell_renderer_toggle_new (); |
108 | gtk_tree_view_column_pack_start (tree_column: col, cell, FALSE); |
109 | gtk_tree_view_column_add_attribute (tree_column: col, cell_renderer: cell, attribute: "active" , column: 1); |
110 | |
111 | cell = gtk_cell_renderer_text_new (); |
112 | gtk_tree_view_column_pack_start (tree_column: col, cell, TRUE); |
113 | gtk_tree_view_column_add_attribute (tree_column: col, cell_renderer: cell, attribute: "text" , column: 0); |
114 | |
115 | cell = gtk_cell_renderer_pixbuf_new (); |
116 | gtk_tree_view_column_pack_start (tree_column: col, cell, FALSE); |
117 | gtk_tree_view_column_add_attribute (tree_column: col, cell_renderer: cell, attribute: "icon-name" , column: 2); |
118 | |
119 | cell = gtk_cell_renderer_toggle_new (); |
120 | gtk_tree_view_column_pack_start (tree_column: col, cell, FALSE); |
121 | gtk_tree_view_column_add_attribute (tree_column: col, cell_renderer: cell, attribute: "active" , column: 1); |
122 | |
123 | gtk_tree_view_append_column (GTK_TREE_VIEW (tv), column: col); |
124 | |
125 | store = gtk_tree_store_new (n_columns: 3, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_STRING); |
126 | gtk_tree_store_insert_with_values (tree_store: store, NULL, NULL, position: 0, 0, "One row" , 1, FALSE, 2, "document-open" , -1); |
127 | gtk_tree_store_insert_with_values (tree_store: store, iter: &iter, NULL, position: 1, 0, "Two row" , 1, FALSE, 2, "dialog-warning" , -1); |
128 | gtk_tree_store_insert_with_values (tree_store: store, NULL, parent: &iter, position: 0, 0, "Three row" , 1, FALSE, 2, "dialog-error" , -1); |
129 | |
130 | gtk_tree_view_set_model (GTK_TREE_VIEW (tv), GTK_TREE_MODEL (store)); |
131 | |
132 | gesture = gtk_gesture_click_new (); |
133 | gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (gesture), |
134 | phase: GTK_PHASE_CAPTURE); |
135 | g_signal_connect (gesture, "released" , |
136 | G_CALLBACK (release_event), tv); |
137 | gtk_widget_add_controller (widget: tv, GTK_EVENT_CONTROLLER (gesture)); |
138 | |
139 | gtk_widget_show (widget: window); |
140 | |
141 | while (TRUE) |
142 | g_main_context_iteration (NULL, TRUE); |
143 | |
144 | return 0; |
145 | } |
146 | |