Mercurial > hg > forks > geeqie
annotate src/ui_tree_edit.c @ 2916:ae6cdcd69d9f default tip
Merge with upstream/master.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 14 May 2019 11:46:50 +0300 |
parents | b7228e6b2a02 |
children |
rev | line source |
---|---|
9 | 1 /* |
2350
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2095
diff
changeset
|
2 * Copyright (C) 2004 John Ellis |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2095
diff
changeset
|
3 * Copyright (C) 2008 - 2016 The Geeqie Team |
9 | 4 * |
5 * Author: John Ellis | |
6 * | |
2350
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2095
diff
changeset
|
7 * This program is free software; you can redistribute it and/or modify |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2095
diff
changeset
|
8 * it under the terms of the GNU General Public License as published by |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2095
diff
changeset
|
9 * the Free Software Foundation; either version 2 of the License, or |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2095
diff
changeset
|
10 * (at your option) any later version. |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2095
diff
changeset
|
11 * |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2095
diff
changeset
|
12 * This program is distributed in the hope that it will be useful, |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2095
diff
changeset
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2095
diff
changeset
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2095
diff
changeset
|
15 * GNU General Public License for more details. |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2095
diff
changeset
|
16 * |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2095
diff
changeset
|
17 * You should have received a copy of the GNU General Public License along |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2095
diff
changeset
|
18 * with this program; if not, write to the Free Software Foundation, Inc., |
95507e596256
Update copyright in all files
Klaus Ethgen <Klaus@Ethgen.de>
parents:
2095
diff
changeset
|
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
9 | 20 */ |
21 | |
22 #ifdef HAVE_CONFIG_H | |
23 # include "config.h" | |
24 #endif | |
25 #include "intl.h" | |
26 | |
27 #include <stdio.h> | |
28 #include <stdlib.h> | |
29 #include <string.h> | |
30 | |
31 #include <gtk/gtk.h> | |
32 #include <gdk/gdkkeysyms.h> | |
33 | |
2044
a1bd12a58ac0
fixed compilation with gtk 2.20
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2036
diff
changeset
|
34 #include "compat.h" |
a1bd12a58ac0
fixed compilation with gtk 2.20
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2036
diff
changeset
|
35 |
9 | 36 #include "ui_tree_edit.h" |
37 | |
38 /* | |
39 *------------------------------------------------------------------- | |
40 * cell popup editor | |
41 *------------------------------------------------------------------- | |
42 */ | |
43 | |
44 static void tree_edit_close(TreeEditData *ted) | |
45 { | |
46 gtk_grab_remove(ted->window); | |
47 gdk_keyboard_ungrab(GDK_CURRENT_TIME); | |
48 gdk_pointer_ungrab(GDK_CURRENT_TIME); | |
49 | |
50 gtk_widget_destroy(ted->window); | |
51 | |
52 g_free(ted->old_name); | |
53 g_free(ted->new_name); | |
54 gtk_tree_path_free(ted->path); | |
55 | |
56 g_free(ted); | |
57 } | |
58 | |
59 static void tree_edit_do(TreeEditData *ted) | |
60 { | |
61 ted->new_name = g_strdup(gtk_entry_get_text(GTK_ENTRY(ted->entry))); | |
62 | |
63 if (strcmp(ted->new_name, ted->old_name) != 0) | |
64 { | |
65 if (ted->edit_func) | |
66 { | |
67 if (ted->edit_func(ted, ted->old_name, ted->new_name, ted->edit_data)) | |
68 { | |
69 /* hmm, should the caller be required to set text instead ? */ | |
70 } | |
71 } | |
72 } | |
73 } | |
74 | |
1448 | 75 static gboolean tree_edit_click_end_cb(GtkWidget *widget, GdkEventButton *event, gpointer data) |
9 | 76 { |
77 TreeEditData *ted = data; | |
78 | |
79 tree_edit_do(ted); | |
80 tree_edit_close(ted); | |
81 | |
82 return TRUE; | |
83 } | |
84 | |
1448 | 85 static gboolean tree_edit_click_cb(GtkWidget *widget, GdkEventButton *event, gpointer data) |
9 | 86 { |
87 TreeEditData *ted = data; | |
2034
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
88 GdkWindow *window = gtk_widget_get_window(ted->window); |
9 | 89 |
90 gint x, y; | |
91 gint w, h; | |
92 | |
93 gint xr, yr; | |
94 | |
95 xr = (gint)event->x_root; | |
96 yr = (gint)event->y_root; | |
97 | |
2034
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
98 gdk_window_get_origin(window, &x, &y); |
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
99 w = gdk_window_get_width(window); |
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
100 h = gdk_window_get_height(window); |
9 | 101 |
102 if (xr < x || yr < y || xr > x + w || yr > y + h) | |
103 { | |
104 /* gobble the release event, so it does not propgate to an underlying widget */ | |
105 g_signal_connect(G_OBJECT(ted->window), "button_release_event", | |
106 G_CALLBACK(tree_edit_click_end_cb), ted); | |
107 return TRUE; | |
108 } | |
109 return FALSE; | |
110 } | |
111 | |
1448 | 112 static gboolean tree_edit_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer data) |
9 | 113 { |
114 TreeEditData *ted = data; | |
115 | |
116 switch (event->keyval) | |
117 { | |
2036
472c094c0154
changed GDK_<key> to GDK_KEY_<key>
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2035
diff
changeset
|
118 case GDK_KEY_Return: |
472c094c0154
changed GDK_<key> to GDK_KEY_<key>
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2035
diff
changeset
|
119 case GDK_KEY_KP_Enter: |
472c094c0154
changed GDK_<key> to GDK_KEY_<key>
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2035
diff
changeset
|
120 case GDK_KEY_Tab: /* ok, we are going to intercept the focus change |
9 | 121 from keyboard and act like return was hit */ |
2036
472c094c0154
changed GDK_<key> to GDK_KEY_<key>
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2035
diff
changeset
|
122 case GDK_KEY_ISO_Left_Tab: |
472c094c0154
changed GDK_<key> to GDK_KEY_<key>
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2035
diff
changeset
|
123 case GDK_KEY_Up: |
472c094c0154
changed GDK_<key> to GDK_KEY_<key>
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2035
diff
changeset
|
124 case GDK_KEY_Down: |
472c094c0154
changed GDK_<key> to GDK_KEY_<key>
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2035
diff
changeset
|
125 case GDK_KEY_KP_Up: |
472c094c0154
changed GDK_<key> to GDK_KEY_<key>
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2035
diff
changeset
|
126 case GDK_KEY_KP_Down: |
472c094c0154
changed GDK_<key> to GDK_KEY_<key>
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2035
diff
changeset
|
127 case GDK_KEY_KP_Left: |
472c094c0154
changed GDK_<key> to GDK_KEY_<key>
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2035
diff
changeset
|
128 case GDK_KEY_KP_Right: |
9 | 129 tree_edit_do(ted); |
130 tree_edit_close(ted); | |
131 break; | |
2036
472c094c0154
changed GDK_<key> to GDK_KEY_<key>
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2035
diff
changeset
|
132 case GDK_KEY_Escape: |
9 | 133 tree_edit_close(ted); |
134 break; | |
135 default: | |
136 break; | |
137 } | |
138 | |
139 return FALSE; | |
140 } | |
141 | |
142 static gboolean tree_edit_by_path_idle_cb(gpointer data) | |
143 { | |
144 TreeEditData *ted = data; | |
145 GdkRectangle rect; | |
146 gint x, y, w, h; /* geometry of cell within tree */ | |
147 gint wx, wy; /* geometry of tree from root window */ | |
148 gint sx, sw; | |
149 | |
150 gtk_tree_view_get_cell_area(ted->tree, ted->path, ted->column, &rect); | |
151 | |
152 x = rect.x; | |
153 y = rect.y; | |
154 w = rect.width + 4; | |
155 h = rect.height + 4; | |
156 | |
157 if (gtk_tree_view_column_cell_get_position(ted->column, ted->cell, &sx, &sw)) | |
158 { | |
159 x += sx; | |
160 w = MAX(w - sx, sw); | |
161 } | |
162 | |
163 gdk_window_get_origin(gtk_tree_view_get_bin_window(ted->tree), &wx, &wy); | |
164 | |
165 x += wx - 2; /* the -val is to 'fix' alignment of entry position */ | |
166 y += wy - 2; | |
167 | |
168 /* now show it */ | |
169 gtk_widget_set_size_request(ted->window, w, h); | |
170 gtk_widget_realize(ted->window); | |
171 gtk_window_move(GTK_WINDOW(ted->window), x, y); | |
172 gtk_window_resize(GTK_WINDOW(ted->window), w, h); | |
173 gtk_widget_show(ted->window); | |
174 | |
175 /* grab it */ | |
176 gtk_widget_grab_focus(ted->entry); | |
177 /* explicitely set the focus flag for the entry, for some reason on popup windows this | |
178 * is not set, and causes no edit cursor to appear ( popups not allowed focus? ) | |
179 */ | |
2034
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
180 gtk_widget_grab_focus(ted->entry); |
9 | 181 gtk_grab_add(ted->window); |
2034
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
182 gdk_pointer_grab(gtk_widget_get_window(ted->window), TRUE, |
9 | 183 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_MOTION_MASK, |
184 NULL, NULL, GDK_CURRENT_TIME); | |
2034
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
185 gdk_keyboard_grab(gtk_widget_get_window(ted->window), TRUE, GDK_CURRENT_TIME); |
9 | 186 |
187 return FALSE; | |
188 } | |
189 | |
1448 | 190 gboolean tree_edit_by_path(GtkTreeView *tree, GtkTreePath *tpath, gint column, const gchar *text, |
191 gboolean (*edit_func)(TreeEditData *, const gchar *, const gchar *, gpointer), gpointer data) | |
9 | 192 { |
193 TreeEditData *ted; | |
194 GtkTreeViewColumn *tcolumn; | |
195 GtkCellRenderer *cell = NULL; | |
196 GList *list; | |
197 GList *work; | |
198 | |
199 if (!edit_func) return FALSE; | |
2034
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
200 if (!gtk_widget_get_visible(GTK_WIDGET(tree))) return FALSE; |
9 | 201 |
202 tcolumn = gtk_tree_view_get_column(tree, column); | |
203 if (!tcolumn) return FALSE; | |
204 | |
1767
96381fd3d133
Add compatibility for GTK 2.18
Klaus Ethgen <Klaus@Ethgen.de>
parents:
1631
diff
changeset
|
205 list = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(tcolumn)); |
9 | 206 work = list; |
207 while (work && !cell) | |
208 { | |
209 cell = work->data; | |
210 if (!GTK_IS_CELL_RENDERER_TEXT(cell)) | |
211 { | |
212 cell = NULL; | |
213 } | |
214 work = work->next; | |
215 } | |
216 | |
217 g_list_free(list); | |
218 if (!cell) return FALSE; | |
219 | |
220 if (!text) text = ""; | |
221 | |
222 ted = g_new0(TreeEditData, 1); | |
223 | |
224 ted->old_name = g_strdup(text); | |
225 | |
226 ted->edit_func = edit_func; | |
227 ted->edit_data = data; | |
228 | |
229 ted->tree = tree; | |
230 ted->path = gtk_tree_path_copy(tpath); | |
231 ted->column = tcolumn; | |
232 ted->cell = cell; | |
233 | |
234 gtk_tree_view_scroll_to_cell(ted->tree, ted->path, ted->column, FALSE, 0.0, 0.0); | |
235 | |
236 /* create the window */ | |
237 | |
238 ted->window = gtk_window_new(GTK_WINDOW_POPUP); | |
239 gtk_window_set_resizable(GTK_WINDOW(ted->window), FALSE); | |
240 g_signal_connect(G_OBJECT(ted->window), "button_press_event", | |
241 G_CALLBACK(tree_edit_click_cb), ted); | |
242 g_signal_connect(G_OBJECT(ted->window), "key_press_event", | |
243 G_CALLBACK(tree_edit_key_press_cb), ted); | |
244 | |
245 ted->entry = gtk_entry_new(); | |
246 gtk_entry_set_text(GTK_ENTRY(ted->entry), ted->old_name); | |
247 gtk_editable_select_region(GTK_EDITABLE(ted->entry), 0, strlen(ted->old_name)); | |
248 gtk_container_add(GTK_CONTAINER(ted->window), ted->entry); | |
249 gtk_widget_show(ted->entry); | |
250 | |
251 /* due to the fact that gtktreeview scrolls in an idle loop, we cannot | |
252 * reliably get the cell position until those scroll priority signals are processed | |
253 */ | |
254 g_idle_add_full(G_PRIORITY_DEFAULT_IDLE - 2, tree_edit_by_path_idle_cb, ted, NULL); | |
255 | |
256 return TRUE; | |
257 } | |
258 | |
259 /* | |
260 *------------------------------------------------------------------- | |
261 * tree cell position retrieval | |
262 *------------------------------------------------------------------- | |
263 */ | |
264 | |
1448 | 265 gboolean tree_view_get_cell_origin(GtkTreeView *widget, GtkTreePath *tpath, gint column, gboolean text_cell_only, |
266 gint *x, gint *y, gint *width, gint *height) | |
9 | 267 { |
268 gint x_origin, y_origin; | |
269 gint x_offset, y_offset; | |
270 gint header_size; | |
271 GtkTreeViewColumn *tv_column; | |
272 GdkRectangle rect; | |
273 | |
274 tv_column = gtk_tree_view_get_column(widget, column); | |
275 if (!tv_column || !tpath) return FALSE; | |
276 | |
277 /* hmm, appears the rect will not account for X scroll, but does for Y scroll | |
278 * use x_offset instead for X scroll (sigh) | |
279 */ | |
280 gtk_tree_view_get_cell_area(widget, tpath, tv_column, &rect); | |
1147
0e787bf84aea
fixed usage of deprecated functions - patch by Omari Stephens
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1055
diff
changeset
|
281 gtk_tree_view_convert_tree_to_widget_coords(widget, 0, 0, &x_offset, &y_offset); |
2034
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
282 gdk_window_get_origin(gtk_widget_get_window(GTK_WIDGET(widget)), &x_origin, &y_origin); |
9 | 283 |
284 if (gtk_tree_view_get_headers_visible(widget)) | |
285 { | |
2034
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
286 GtkAllocation allocation; |
2035
4321c486aec7
use cairo for drawing
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2034
diff
changeset
|
287 #if GTK_CHECK_VERSION(3,0,0) |
4321c486aec7
use cairo for drawing
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2034
diff
changeset
|
288 gtk_widget_get_allocation(gtk_tree_view_column_get_button(tv_column), &allocation); |
4321c486aec7
use cairo for drawing
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2034
diff
changeset
|
289 #else |
2034
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
290 gtk_widget_get_allocation(tv_column->button, &allocation); |
2035
4321c486aec7
use cairo for drawing
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2034
diff
changeset
|
291 #endif |
2034
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
292 header_size = allocation.height; |
9 | 293 } |
294 else | |
295 { | |
296 header_size = 0; | |
297 } | |
298 | |
299 if (text_cell_only) | |
300 { | |
301 GtkCellRenderer *cell = NULL; | |
302 GList *renderers; | |
303 GList *work; | |
304 gint cell_x; | |
305 gint cell_width; | |
306 | |
1767
96381fd3d133
Add compatibility for GTK 2.18
Klaus Ethgen <Klaus@Ethgen.de>
parents:
1631
diff
changeset
|
307 renderers = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(tv_column)); |
9 | 308 work = renderers; |
309 while (work && !cell) | |
310 { | |
311 cell = work->data; | |
312 work = work->next; | |
313 if (!GTK_IS_CELL_RENDERER_TEXT(cell)) cell = NULL; | |
314 } | |
315 g_list_free(renderers); | |
316 | |
317 if (!cell) return FALSE; | |
442 | 318 |
9 | 319 if (!gtk_tree_view_column_cell_get_position(tv_column, cell, &cell_x, &cell_width)) |
320 { | |
321 cell_x = 0; | |
322 cell_width = rect.width; | |
323 } | |
324 *x = x_origin + x_offset + rect.x + cell_x; | |
325 *width = cell_width; | |
326 } | |
327 else | |
328 { | |
329 *x = x_origin + x_offset + rect.x; | |
330 *width = rect.width; | |
331 } | |
332 *y = y_origin + rect.y + header_size; | |
333 *height = rect.height; | |
334 return TRUE; | |
335 } | |
336 | |
1448 | 337 void tree_view_get_cell_clamped(GtkTreeView *widget, GtkTreePath *tpath, gint column, gboolean text_cell_only, |
9 | 338 gint *x, gint *y, gint *width, gint *height) |
339 { | |
340 gint wx, wy, ww, wh; | |
341 GdkWindow *window; | |
342 | |
2034
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
343 window = gtk_widget_get_window(GTK_WIDGET(widget)); |
9 | 344 gdk_window_get_origin(window, &wx, &wy); |
2034
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
345 |
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
346 ww = gdk_window_get_width(window); |
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
347 wh = gdk_window_get_height(window); |
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
348 |
9 | 349 if (!tree_view_get_cell_origin(widget, tpath, column, text_cell_only, x, y, width, height)) |
350 { | |
351 *x = wx; | |
352 *y = wy; | |
353 *width = ww; | |
354 *height = wh; | |
355 return; | |
356 } | |
357 | |
358 *width = MIN(*width, ww); | |
359 *x = CLAMP(*x, wx, wx + ww - (*width)); | |
360 *y = CLAMP(*y, wy, wy + wh); | |
361 *height = MIN(*height, wy + wh - (*y)); | |
362 } | |
363 | |
1631
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
364 /* an implementation that uses gtk_tree_view_get_visible_range */ |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
365 gint tree_view_row_get_visibility(GtkTreeView *widget, GtkTreeIter *iter, gboolean fully_visible) |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
366 { |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
367 GtkTreeModel *store; |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
368 GtkTreePath *tpath, *start_path, *end_path; |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
369 gint ret = 0; |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
370 |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
371 if (!gtk_tree_view_get_visible_range(widget, &start_path, &end_path)) return -1; /* we will most probably scroll down, needed for tree_view_row_make_visible */ |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
372 |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
373 store = gtk_tree_view_get_model(widget); |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
374 tpath = gtk_tree_model_get_path(store, iter); |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
375 |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
376 if (fully_visible) |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
377 { |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
378 if (gtk_tree_path_compare(tpath, start_path) <= 0) |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
379 { |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
380 ret = -1; |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
381 } |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
382 else if (gtk_tree_path_compare(tpath, end_path) >= 0) |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
383 { |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
384 ret = 1; |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
385 } |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
386 } |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
387 else |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
388 { |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
389 if (gtk_tree_path_compare(tpath, start_path) < 0) |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
390 { |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
391 ret = -1; |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
392 } |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
393 else if (gtk_tree_path_compare(tpath, end_path) > 0) |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
394 { |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
395 ret = 1; |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
396 } |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
397 } |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
398 |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
399 gtk_tree_path_free(tpath); |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
400 gtk_tree_path_free(start_path); |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
401 gtk_tree_path_free(end_path); |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
402 return ret; |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
403 } |
d80c4b8b3179
better implementation of tree_view_row_get_visibility,
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1523
diff
changeset
|
404 |
1448 | 405 gint tree_view_row_make_visible(GtkTreeView *widget, GtkTreeIter *iter, gboolean center) |
9 | 406 { |
407 GtkTreePath *tpath; | |
408 gint vis; | |
409 | |
410 vis = tree_view_row_get_visibility(widget, iter, TRUE); | |
411 | |
412 tpath = gtk_tree_model_get_path(gtk_tree_view_get_model(widget), iter); | |
413 if (center && vis != 0) | |
414 { | |
415 gtk_tree_view_scroll_to_cell(widget, tpath, NULL, TRUE, 0.5, 0.0); | |
416 } | |
417 else if (vis < 0) | |
418 { | |
419 gtk_tree_view_scroll_to_cell(widget, tpath, NULL, TRUE, 0.0, 0.0); | |
420 } | |
421 else if (vis > 0) | |
422 { | |
423 gtk_tree_view_scroll_to_cell(widget, tpath, NULL, TRUE, 1.0, 0.0); | |
424 } | |
425 gtk_tree_path_free(tpath); | |
426 | |
427 return vis; | |
428 } | |
429 | |
1448 | 430 gboolean tree_view_move_cursor_away(GtkTreeView *widget, GtkTreeIter *iter, gboolean only_selected) |
9 | 431 { |
432 GtkTreeModel *store; | |
433 GtkTreePath *tpath; | |
434 GtkTreePath *fpath; | |
1437 | 435 gboolean move = FALSE; |
9 | 436 |
437 if (!iter) return FALSE; | |
438 | |
439 store = gtk_tree_view_get_model(widget); | |
440 tpath = gtk_tree_model_get_path(store, iter); | |
441 gtk_tree_view_get_cursor(widget, &fpath, NULL); | |
442 | |
443 if (fpath && gtk_tree_path_compare(tpath, fpath) == 0) | |
444 { | |
445 GtkTreeSelection *selection; | |
446 | |
447 selection = gtk_tree_view_get_selection(widget); | |
448 | |
449 if (!only_selected || | |
450 gtk_tree_selection_path_is_selected(selection, tpath)) | |
451 { | |
452 GtkTreeIter current; | |
453 | |
454 current = *iter; | |
455 if (gtk_tree_model_iter_next(store, ¤t)) | |
456 { | |
457 gtk_tree_path_next(tpath); | |
458 move = TRUE; | |
459 } | |
460 else if (gtk_tree_path_prev(tpath) && | |
461 gtk_tree_model_get_iter(store, ¤t, tpath)) | |
462 { | |
463 move = TRUE; | |
464 } | |
465 | |
466 if (move) | |
467 { | |
468 gtk_tree_view_set_cursor(widget, tpath, NULL, FALSE); | |
469 } | |
470 } | |
471 } | |
472 | |
473 gtk_tree_path_free(tpath); | |
474 if (fpath) gtk_tree_path_free(fpath); | |
475 | |
476 return move; | |
477 } | |
478 | |
479 gint tree_path_to_row(GtkTreePath *tpath) | |
480 { | |
481 gint *indices; | |
442 | 482 |
9 | 483 indices = gtk_tree_path_get_indices(tpath); |
484 if (indices) return indices[0]; | |
442 | 485 |
9 | 486 return -1; |
487 } | |
488 | |
489 | |
490 /* | |
491 *------------------------------------------------------------------- | |
492 * color utilities | |
493 *------------------------------------------------------------------- | |
494 */ | |
495 | |
496 void shift_color(GdkColor *src, gshort val, gint direction) | |
497 { | |
498 gshort cs; | |
499 | |
500 if (val == -1) | |
501 { | |
502 val = STYLE_SHIFT_STANDARD; | |
503 } | |
504 else | |
505 { | |
506 val = CLAMP(val, 1, 100); | |
507 } | |
508 cs = 0xffff / 100 * val; | |
509 | |
510 /* up or down ? */ | |
511 if (direction < 0 || | |
512 (direction == 0 &&((gint)src->red + (gint)src->green + (gint)src->blue) / 3 > 0xffff / 2)) | |
513 { | |
514 src->red = MAX(0 , src->red - cs); | |
515 src->green = MAX(0 , src->green - cs); | |
516 src->blue = MAX(0 , src->blue - cs); | |
517 } | |
518 else | |
519 { | |
520 src->red = MIN(0xffff, src->red + cs); | |
521 src->green = MIN(0xffff, src->green + cs); | |
522 src->blue = MIN(0xffff, src->blue + cs); | |
523 } | |
524 } | |
525 | |
526 /* darkens or lightens a style's color for given state | |
527 * esp. useful for alternating dark/light in (c)lists | |
528 */ | |
529 void style_shift_color(GtkStyle *style, GtkStateType type, gshort shift_value, gint direction) | |
530 { | |
531 if (!style) return; | |
532 | |
533 shift_color(&style->base[type], shift_value, direction); | |
534 shift_color(&style->bg[type], shift_value, direction); | |
535 } | |
536 | |
537 /* | |
538 *------------------------------------------------------------------- | |
539 * auto scroll by mouse position | |
540 *------------------------------------------------------------------- | |
541 */ | |
542 | |
543 #define AUTO_SCROLL_DEFAULT_SPEED 100 | |
544 #define AUTO_SCROLL_DEFAULT_REGION 20 | |
545 | |
546 typedef struct _AutoScrollData AutoScrollData; | |
547 struct _AutoScrollData | |
548 { | |
1523
e52aabe8fc7a
Fix up event source ids type: gint -> guint.
Laurent Monin <geeqie@norz.org>
parents:
1448
diff
changeset
|
549 guint timer_id; /* event source id */ |
9 | 550 gint region_size; |
551 GtkWidget *widget; | |
552 GtkAdjustment *adj; | |
553 gint max_step; | |
554 | |
555 gint (*notify_func)(GtkWidget *, gint, gint, gpointer); | |
556 gpointer notify_data; | |
557 }; | |
558 | |
559 void widget_auto_scroll_stop(GtkWidget *widget) | |
560 { | |
561 AutoScrollData *sd; | |
562 | |
563 sd = g_object_get_data(G_OBJECT(widget), "autoscroll"); | |
564 if (!sd) return; | |
565 g_object_set_data(G_OBJECT(widget), "autoscroll", NULL); | |
566 | |
1523
e52aabe8fc7a
Fix up event source ids type: gint -> guint.
Laurent Monin <geeqie@norz.org>
parents:
1448
diff
changeset
|
567 if (sd->timer_id) g_source_remove(sd->timer_id); |
9 | 568 g_free(sd); |
569 } | |
570 | |
1448 | 571 static gboolean widget_auto_scroll_cb(gpointer data) |
9 | 572 { |
573 AutoScrollData *sd = data; | |
574 GdkWindow *window; | |
575 gint x, y; | |
576 gint w, h; | |
577 gint amt = 0; | |
2373
b7228e6b2a02
Fix deprecated - gdk_window_get_pointer
Colin Clark <cclark@mcb.net>
parents:
2350
diff
changeset
|
578 #if GTK_CHECK_VERSION(3,0,0) |
b7228e6b2a02
Fix deprecated - gdk_window_get_pointer
Colin Clark <cclark@mcb.net>
parents:
2350
diff
changeset
|
579 GdkDeviceManager *device_manager; |
b7228e6b2a02
Fix deprecated - gdk_window_get_pointer
Colin Clark <cclark@mcb.net>
parents:
2350
diff
changeset
|
580 GdkDevice *device; |
b7228e6b2a02
Fix deprecated - gdk_window_get_pointer
Colin Clark <cclark@mcb.net>
parents:
2350
diff
changeset
|
581 #endif |
9 | 582 |
583 if (sd->max_step < sd->region_size) | |
584 { | |
585 sd->max_step = MIN(sd->region_size, sd->max_step + 2); | |
586 } | |
587 | |
2034
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
588 window = gtk_widget_get_window(sd->widget); |
2373
b7228e6b2a02
Fix deprecated - gdk_window_get_pointer
Colin Clark <cclark@mcb.net>
parents:
2350
diff
changeset
|
589 #if GTK_CHECK_VERSION(3,0,0) |
b7228e6b2a02
Fix deprecated - gdk_window_get_pointer
Colin Clark <cclark@mcb.net>
parents:
2350
diff
changeset
|
590 device_manager = gdk_display_get_device_manager(gdk_window_get_display(window)); |
b7228e6b2a02
Fix deprecated - gdk_window_get_pointer
Colin Clark <cclark@mcb.net>
parents:
2350
diff
changeset
|
591 device = gdk_device_manager_get_client_pointer(device_manager); |
b7228e6b2a02
Fix deprecated - gdk_window_get_pointer
Colin Clark <cclark@mcb.net>
parents:
2350
diff
changeset
|
592 gdk_window_get_device_position(window, device, &x, &y, NULL); |
b7228e6b2a02
Fix deprecated - gdk_window_get_pointer
Colin Clark <cclark@mcb.net>
parents:
2350
diff
changeset
|
593 #else |
9 | 594 gdk_window_get_pointer(window, &x, &y, NULL); |
2373
b7228e6b2a02
Fix deprecated - gdk_window_get_pointer
Colin Clark <cclark@mcb.net>
parents:
2350
diff
changeset
|
595 #endif |
2034
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
596 w = gdk_window_get_width(window); |
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
597 h = gdk_window_get_height(window); |
9 | 598 |
599 if (x < 0 || x >= w || y < 0 || y >= h) | |
600 { | |
1523
e52aabe8fc7a
Fix up event source ids type: gint -> guint.
Laurent Monin <geeqie@norz.org>
parents:
1448
diff
changeset
|
601 sd->timer_id = 0; |
9 | 602 widget_auto_scroll_stop(sd->widget); |
603 return FALSE; | |
604 } | |
605 | |
606 if (h < sd->region_size * 3) | |
607 { | |
608 /* height is cramped, nicely divide into three equal regions */ | |
609 if (y < h / 3 || y > h / 3 * 2) | |
610 { | |
611 amt = (y < h / 2) ? 0 - ((h / 2) - y) : y - (h / 2); | |
612 } | |
613 } | |
614 else if (y < sd->region_size) | |
615 { | |
616 amt = 0 - (sd->region_size - y); | |
617 } | |
618 else if (y >= h - sd->region_size) | |
619 { | |
620 amt = y - (h - sd->region_size); | |
621 } | |
622 | |
623 if (amt != 0) | |
624 { | |
625 amt = CLAMP(amt, 0 - sd->max_step, sd->max_step); | |
626 | |
2034
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
627 if (gtk_adjustment_get_value(sd->adj) != CLAMP(gtk_adjustment_get_value(sd->adj) + amt, gtk_adjustment_get_lower(sd->adj), gtk_adjustment_get_upper(sd->adj) - gtk_adjustment_get_page_size(sd->adj))) |
9 | 628 { |
629 /* only notify when scrolling is needed */ | |
630 if (sd->notify_func && !sd->notify_func(sd->widget, x, y, sd->notify_data)) | |
631 { | |
1523
e52aabe8fc7a
Fix up event source ids type: gint -> guint.
Laurent Monin <geeqie@norz.org>
parents:
1448
diff
changeset
|
632 sd->timer_id = 0; |
9 | 633 widget_auto_scroll_stop(sd->widget); |
634 return FALSE; | |
635 } | |
636 | |
637 gtk_adjustment_set_value(sd->adj, | |
2034
9297985567b5
use accessor functions
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
2021
diff
changeset
|
638 CLAMP(gtk_adjustment_get_value(sd->adj) + amt, gtk_adjustment_get_lower(sd->adj), gtk_adjustment_get_upper(sd->adj) - gtk_adjustment_get_page_size(sd->adj))); |
9 | 639 } |
640 } | |
641 | |
642 return TRUE; | |
643 } | |
644 | |
645 gint widget_auto_scroll_start(GtkWidget *widget, GtkAdjustment *v_adj, gint scroll_speed, gint region_size, | |
646 gint (*notify_func)(GtkWidget *widget, gint x, gint y, gpointer data), gpointer notify_data) | |
647 { | |
648 AutoScrollData *sd; | |
649 | |
650 if (!widget || !v_adj) return 0; | |
651 if (g_object_get_data(G_OBJECT(widget), "autoscroll")) return 0; | |
652 if (scroll_speed < 1) scroll_speed = AUTO_SCROLL_DEFAULT_SPEED; | |
653 if (region_size < 1) region_size = AUTO_SCROLL_DEFAULT_REGION; | |
654 | |
655 sd = g_new0(AutoScrollData, 1); | |
656 sd->widget = widget; | |
657 sd->adj = v_adj; | |
658 sd->region_size = region_size; | |
659 sd->max_step = 1; | |
660 sd->timer_id = g_timeout_add(scroll_speed, widget_auto_scroll_cb, sd); | |
661 | |
662 sd->notify_func = notify_func; | |
663 sd->notify_data = notify_data; | |
664 | |
665 g_object_set_data(G_OBJECT(widget), "autoscroll", sd); | |
666 | |
667 return scroll_speed; | |
668 } | |
669 | |
670 | |
671 /* | |
672 *------------------------------------------------------------------- | |
673 * GList utils | |
674 *------------------------------------------------------------------- | |
675 */ | |
676 | |
677 GList *uig_list_insert_link(GList *list, GList *link, gpointer data) | |
678 { | |
679 GList *new_list; | |
680 | |
681 if (!list || link == list) return g_list_prepend(list, data); | |
682 if (!link) return g_list_append(list, data); | |
683 | |
513
6743a5928e09
Remove whitespace between function name and first parenthesis for the sake of consistency. (pass 2)
Laurent Monin <geeqie@norz.org>
parents:
475
diff
changeset
|
684 new_list = g_list_alloc(); |
9 | 685 new_list->data = data; |
686 | |
687 if (link->prev) | |
688 { | |
689 link->prev->next = new_list; | |
690 new_list->prev = link->prev; | |
691 } | |
692 else | |
693 { | |
694 list = new_list; | |
695 } | |
696 link->prev = new_list; | |
697 new_list->next = link; | |
698 | |
699 return list; | |
700 } | |
701 | |
702 GList *uig_list_insert_list(GList *parent, GList *insert_link, GList *list) | |
703 { | |
704 GList *end; | |
705 | |
706 if (!insert_link) return g_list_concat(parent, list); | |
707 if (insert_link == parent) return g_list_concat(list, parent); | |
708 if (!parent) return list; | |
709 if (!list) return parent; | |
710 | |
711 end = g_list_last(list); | |
712 | |
713 if (insert_link->prev) insert_link->prev->next = list; | |
714 list->prev = insert_link->prev; | |
715 insert_link->prev = end; | |
716 end->next = insert_link; | |
717 | |
718 return parent; | |
719 } | |
1055
4bbdfab3c89a
Adding a vim modeline to all files - patch by Klaus Ethgen
Vladimir Nadvornik <nadvornik@suse.cz>
parents:
1046
diff
changeset
|
720 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ |