9
|
1 /*
|
196
|
2 * Geeqie
|
9
|
3 * (C) 2004 John Ellis
|
475
|
4 * Copyright (C) 2008 The Geeqie Team
|
9
|
5 *
|
|
6 * Author: John Ellis
|
|
7 *
|
|
8 * This software is released under the GNU General Public License (GNU GPL).
|
|
9 * Please read the included file COPYING for more information.
|
|
10 * This software comes with no warranty of any kind, use at your own risk!
|
|
11 */
|
|
12
|
281
|
13 #include "main.h"
|
9
|
14 #include "layout_config.h"
|
|
15
|
|
16
|
|
17 #include "layout.h"
|
|
18
|
|
19 #include "ui_misc.h"
|
|
20
|
|
21
|
|
22 enum {
|
|
23 COLUMN_TEXT = 0,
|
|
24 COLUMN_KEY
|
|
25 };
|
|
26
|
|
27
|
|
28 typedef struct _LayoutStyle LayoutStyle;
|
|
29 struct _LayoutStyle
|
|
30 {
|
|
31 LayoutLocation a, b, c;
|
|
32 };
|
|
33
|
|
34 typedef struct _LayoutConfig LayoutConfig;
|
|
35 struct _LayoutConfig
|
|
36 {
|
|
37 GtkWidget *box;
|
|
38
|
|
39 GList *style_widgets;
|
|
40
|
|
41 GtkWidget *listview;
|
|
42
|
|
43 gint style;
|
|
44 gint a, b, c;
|
|
45 };
|
|
46
|
|
47
|
|
48 static LayoutStyle layout_config_styles[] = {
|
|
49 /* 1, 2, 3 */
|
|
50 { LAYOUT_LEFT | LAYOUT_TOP, LAYOUT_LEFT | LAYOUT_BOTTOM, LAYOUT_RIGHT },
|
|
51 { LAYOUT_LEFT | LAYOUT_TOP, LAYOUT_RIGHT | LAYOUT_TOP, LAYOUT_BOTTOM },
|
|
52 { LAYOUT_LEFT, LAYOUT_RIGHT | LAYOUT_TOP, LAYOUT_RIGHT | LAYOUT_BOTTOM },
|
|
53 { LAYOUT_TOP, LAYOUT_LEFT | LAYOUT_BOTTOM, LAYOUT_RIGHT | LAYOUT_BOTTOM }
|
|
54 };
|
|
55
|
|
56 static gint layout_config_style_count = sizeof(layout_config_styles) / sizeof (LayoutStyle);
|
|
57
|
|
58 static gchar *layout_titles[] = { N_("Tools"), N_("Files"), N_("Image") };
|
|
59
|
|
60
|
|
61 static void layout_config_destroy(GtkWidget *widget, gpointer data)
|
|
62 {
|
|
63 LayoutConfig * lc = data;
|
|
64
|
|
65 g_list_free(lc->style_widgets);
|
|
66 g_free(lc);
|
|
67 }
|
|
68
|
|
69 static void layout_config_set_order(LayoutLocation l, gint n,
|
|
70 LayoutLocation *a, LayoutLocation *b, LayoutLocation *c)
|
|
71 {
|
|
72 switch (n)
|
|
73 {
|
|
74 case 0:
|
|
75 *a = l;
|
|
76 break;
|
|
77 case 1:
|
|
78 *b = l;
|
|
79 break;
|
|
80 case 2: default:
|
|
81 *c = l;
|
|
82 break;
|
|
83 }
|
|
84 }
|
|
85
|
|
86 static void layout_config_from_data(gint style, gint oa, gint ob, gint oc,
|
|
87 LayoutLocation *la, LayoutLocation *lb, LayoutLocation *lc)
|
|
88 {
|
|
89 LayoutStyle ls;
|
|
90
|
|
91 style = CLAMP(style, 0, layout_config_style_count);
|
|
92
|
|
93 ls = layout_config_styles[style];
|
|
94
|
|
95 layout_config_set_order(ls.a, oa, la, lb, lc);
|
|
96 layout_config_set_order(ls.b, ob, la, lb, lc);
|
|
97 layout_config_set_order(ls.c, oc, la, lb, lc);
|
|
98 }
|
|
99
|
|
100 void layout_config_parse(gint style, const gchar *order,
|
|
101 LayoutLocation *a, LayoutLocation *b, LayoutLocation *c)
|
|
102 {
|
|
103 gint na, nb, nc;
|
|
104
|
|
105 layout_config_order_from_text(order, &na, &nb, &nc);
|
|
106 layout_config_from_data(style, na, nb, nc, a, b, c);
|
|
107 }
|
|
108
|
|
109 static void layout_config_list_order_set(LayoutConfig *lc, gint src, gint dest)
|
|
110 {
|
|
111 GtkListStore *store;
|
|
112 GtkTreeIter iter;
|
|
113 gint valid;
|
|
114 gint n;
|
|
115
|
|
116 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(lc->listview)));
|
|
117
|
|
118 n = 0;
|
|
119 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
|
|
120 while (valid)
|
|
121 {
|
|
122 if (n == dest)
|
|
123 {
|
|
124 gtk_list_store_set(store, &iter, COLUMN_TEXT, _(layout_titles[src]), COLUMN_KEY, src, -1);
|
|
125 return;
|
|
126 }
|
|
127 n++;
|
|
128 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
|
|
129 }
|
|
130 }
|
|
131
|
|
132 static gint layout_config_list_order_get(LayoutConfig *lc, gint n)
|
|
133 {
|
|
134 GtkTreeModel *store;
|
|
135 GtkTreeIter iter;
|
|
136 gint valid;
|
|
137 gint c = 0;
|
442
|
138
|
9
|
139 store = gtk_tree_view_get_model(GTK_TREE_VIEW(lc->listview));
|
442
|
140
|
9
|
141 valid = gtk_tree_model_get_iter_first(store, &iter);
|
|
142 while (valid)
|
|
143 {
|
|
144 if (c == n)
|
|
145 {
|
|
146 gint val;
|
|
147 gtk_tree_model_get(store, &iter, COLUMN_KEY, &val, -1);
|
|
148 return val;
|
|
149 }
|
|
150 c++;
|
|
151 valid = gtk_tree_model_iter_next(store, &iter);
|
|
152 }
|
|
153 return 0;
|
|
154 }
|
|
155
|
|
156 void layout_config_set(GtkWidget *widget, gint style, const gchar *order)
|
|
157 {
|
|
158 LayoutConfig *lc;
|
|
159 GtkWidget *button;
|
|
160 gint a, b, c;
|
|
161
|
|
162 lc = g_object_get_data(G_OBJECT(widget), "layout_config");
|
|
163
|
|
164 if (!lc) return;
|
|
165
|
|
166 style = CLAMP(style, 0, layout_config_style_count);
|
|
167 button = g_list_nth_data(lc->style_widgets, style);
|
|
168 if (!button) return;
|
|
169
|
|
170 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
|
|
171
|
|
172 layout_config_order_from_text(order, &a, &b, &c);
|
|
173
|
|
174 layout_config_list_order_set(lc, a, 0);
|
|
175 layout_config_list_order_set(lc, b, 1);
|
|
176 layout_config_list_order_set(lc, c, 2);
|
|
177 }
|
|
178
|
|
179 gchar *layout_config_get(GtkWidget *widget, gint *style)
|
|
180 {
|
|
181 LayoutConfig *lc;
|
|
182
|
|
183 lc = g_object_get_data(G_OBJECT(widget), "layout_config");
|
|
184
|
|
185 /* this should not happen */
|
|
186 if (!lc) return NULL;
|
|
187
|
|
188 *style = lc->style;
|
|
189
|
|
190 lc->a = layout_config_list_order_get(lc, 0);
|
|
191 lc->b = layout_config_list_order_get(lc, 1);
|
|
192 lc->c = layout_config_list_order_get(lc, 2);
|
|
193
|
|
194 return layout_config_order_to_text(lc->a, lc->b, lc->c);
|
|
195 }
|
|
196
|
|
197 static void layout_config_widget_click_cb(GtkWidget *widget, gpointer data)
|
|
198 {
|
|
199 LayoutConfig *lc;
|
|
200
|
|
201 lc = g_object_get_data(G_OBJECT(widget), "layout_config");
|
442
|
202
|
9
|
203 if (lc) lc->style = GPOINTER_TO_INT(data);
|
|
204 }
|
|
205
|
|
206 static void layout_config_table_button(GtkWidget *table, LayoutLocation l, const gchar *text)
|
|
207 {
|
|
208 GtkWidget *button;
|
|
209
|
|
210 gint x1, y1;
|
|
211 gint x2, y2;
|
|
212
|
|
213 x1 = 0;
|
|
214 y1 = 0;
|
|
215 x2 = 2;
|
|
216 y2 = 2;
|
|
217
|
|
218 if (l & LAYOUT_LEFT) x2 = 1;
|
|
219 if (l & LAYOUT_RIGHT) x1 = 1;
|
|
220 if (l & LAYOUT_TOP) y2 = 1;
|
|
221 if (l & LAYOUT_BOTTOM) y1 = 1;
|
|
222
|
|
223 button = gtk_button_new_with_label(text);
|
|
224 gtk_widget_set_sensitive(button, FALSE);
|
|
225 GTK_WIDGET_UNSET_FLAGS(button, GTK_CAN_FOCUS);
|
|
226 gtk_table_attach_defaults(GTK_TABLE(table), button, x1, x2, y1, y2);
|
|
227 gtk_widget_show(button);
|
|
228 }
|
|
229
|
|
230 #define LAYOUT_STYLE_SIZE 48
|
|
231
|
|
232 static GtkWidget *layout_config_widget(GtkWidget *group, GtkWidget *box, gint style, LayoutConfig *lc)
|
|
233 {
|
|
234 GtkWidget *table;
|
|
235 LayoutStyle ls;
|
|
236
|
|
237 ls = layout_config_styles[style];
|
|
238
|
|
239 if (group)
|
|
240 {
|
|
241 group = gtk_radio_button_new(gtk_radio_button_get_group(GTK_RADIO_BUTTON(group)));
|
|
242 }
|
|
243 else
|
|
244 {
|
|
245 group = gtk_radio_button_new(NULL);
|
|
246 }
|
|
247 g_object_set_data(G_OBJECT(group), "layout_config", lc);
|
|
248 g_signal_connect(G_OBJECT(group), "clicked",
|
|
249 G_CALLBACK(layout_config_widget_click_cb), GINT_TO_POINTER(style));
|
|
250 gtk_box_pack_start(GTK_BOX(box), group, FALSE, FALSE, 0);
|
|
251
|
|
252 table = gtk_table_new(2, 2, TRUE);
|
|
253
|
|
254 layout_config_table_button(table, ls.a, "1");
|
|
255 layout_config_table_button(table, ls.b, "2");
|
|
256 layout_config_table_button(table, ls.c, "3");
|
|
257
|
|
258 gtk_widget_set_size_request(table, LAYOUT_STYLE_SIZE, LAYOUT_STYLE_SIZE);
|
|
259 gtk_container_add(GTK_CONTAINER(group), table);
|
|
260 gtk_widget_show(table);
|
|
261
|
|
262 gtk_widget_show(group);
|
442
|
263
|
9
|
264 return group;
|
|
265 }
|
|
266
|
|
267 #if 0
|
|
268 static void layout_config_row_move(GtkWidget *clist, gint source_row, gint dest_row, gpointer data)
|
|
269 {
|
|
270 gchar *text;
|
|
271 gint i;
|
|
272
|
|
273 for (i = 0; i < 3; i++)
|
|
274 {
|
|
275 text = g_strdup_printf("%d", i + 1);
|
|
276 gtk_clist_set_text(GTK_CLIST(clist), i, 0, text);
|
|
277 g_free(text);
|
|
278 }
|
|
279 }
|
|
280 #endif
|
|
281
|
|
282 static void layout_config_number_cb(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
|
|
283 GtkTreeModel *store, GtkTreeIter *iter, gpointer data)
|
|
284 {
|
|
285 GtkTreePath *tpath;
|
|
286 gint *indices;
|
|
287 gchar *buf;
|
|
288
|
|
289 tpath = gtk_tree_model_get_path(store, iter);
|
|
290 indices = gtk_tree_path_get_indices(tpath);
|
|
291 buf = g_strdup_printf("%d", indices[0] + 1);
|
|
292 gtk_tree_path_free(tpath);
|
|
293 g_object_set(G_OBJECT(cell), "text", buf, NULL);
|
|
294 g_free(buf);
|
|
295 }
|
|
296
|
|
297 GtkWidget *layout_config_new(void)
|
|
298 {
|
|
299 LayoutConfig *lc;
|
|
300 GtkWidget *hbox;
|
|
301 GtkWidget *group = NULL;
|
|
302 GtkWidget *scrolled;
|
|
303 GtkListStore *store;
|
|
304 GtkTreeViewColumn *column;
|
|
305 GtkCellRenderer *renderer;
|
|
306 gint i;
|
|
307
|
|
308 lc = g_new0(LayoutConfig, 1);
|
|
309
|
|
310 lc->box = gtk_vbox_new(FALSE, PREF_PAD_GAP);
|
|
311 g_object_set_data(G_OBJECT(lc->box), "layout_config", lc);
|
|
312
|
|
313 g_signal_connect(G_OBJECT(lc->box), "destroy",
|
|
314 G_CALLBACK(layout_config_destroy), lc);
|
|
315
|
|
316 hbox = gtk_hbox_new(TRUE, PREF_PAD_SPACE);
|
|
317 gtk_box_pack_start(GTK_BOX(lc->box), hbox, FALSE, FALSE, 0);
|
|
318 for (i = 0; i < layout_config_style_count; i++)
|
|
319 {
|
|
320 group = layout_config_widget(group, hbox, i, lc);
|
|
321 lc->style_widgets = g_list_append(lc->style_widgets, group);
|
|
322 }
|
|
323 gtk_widget_show(hbox);
|
|
324
|
|
325 scrolled = gtk_scrolled_window_new(NULL, NULL);
|
|
326 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
|
|
327 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
|
|
328 GTK_POLICY_NEVER, GTK_POLICY_NEVER);
|
|
329 gtk_box_pack_start(GTK_BOX(lc->box), scrolled, FALSE, FALSE, 0);
|
|
330 gtk_widget_show(scrolled);
|
|
331
|
|
332 store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
|
|
333 lc->listview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
|
|
334 g_object_unref(store);
|
|
335
|
|
336 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(lc->listview), FALSE);
|
|
337 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(lc->listview), FALSE);
|
|
338 gtk_tree_view_set_reorderable(GTK_TREE_VIEW(lc->listview), TRUE);
|
|
339
|
|
340 column = gtk_tree_view_column_new();
|
|
341 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
|
|
342
|
|
343 renderer = gtk_cell_renderer_text_new();
|
|
344 gtk_tree_view_column_pack_start(column, renderer, FALSE);
|
|
345 gtk_tree_view_column_set_cell_data_func(column, renderer, layout_config_number_cb, lc, NULL);
|
|
346
|
|
347 renderer = gtk_cell_renderer_text_new();
|
|
348 gtk_tree_view_column_pack_start(column, renderer, TRUE);
|
|
349 gtk_tree_view_column_add_attribute(column, renderer, "text", COLUMN_TEXT);
|
|
350
|
|
351 gtk_tree_view_append_column(GTK_TREE_VIEW(lc->listview), column);
|
|
352
|
|
353 for (i = 0; i < 3; i++)
|
|
354 {
|
|
355 GtkTreeIter iter;
|
|
356
|
|
357 gtk_list_store_append(store, &iter);
|
|
358 gtk_list_store_set(store, &iter, COLUMN_TEXT, _(layout_titles[i]), COLUMN_KEY, i, -1);
|
|
359 }
|
442
|
360
|
9
|
361 gtk_container_add(GTK_CONTAINER(scrolled), lc->listview);
|
|
362 gtk_widget_show(lc->listview);
|
|
363
|
|
364 pref_label_new(lc->box, _("(drag to change order)"));
|
442
|
365
|
9
|
366 return lc->box;
|
|
367 }
|
|
368
|
|
369 static char num_to_text_char(gint n)
|
|
370 {
|
|
371 switch (n)
|
|
372 {
|
|
373 case 1:
|
|
374 return '2';
|
|
375 break;
|
|
376 case 2:
|
|
377 return '3';
|
|
378 break;
|
|
379 }
|
|
380 return '1';
|
|
381 }
|
|
382
|
|
383 gchar *layout_config_order_to_text(gint a, gint b, gint c)
|
|
384 {
|
|
385 gchar *text;
|
|
386
|
|
387 text = g_strdup(" ");
|
|
388
|
|
389 text[0] = num_to_text_char(a);
|
|
390 text[1] = num_to_text_char(b);
|
|
391 text[2] = num_to_text_char(c);
|
|
392
|
|
393 return text;
|
|
394 }
|
|
395
|
|
396 static gint text_char_to_num(const gchar *text, gint n)
|
|
397 {
|
|
398 if (text[n] == '3') return 2;
|
|
399 if (text[n] == '2') return 1;
|
|
400 return 0;
|
|
401 }
|
|
402
|
|
403 void layout_config_order_from_text(const gchar *text, gint *a, gint *b, gint *c)
|
|
404 {
|
|
405 if (!text || strlen(text) < 3)
|
|
406 {
|
|
407 *a = 0;
|
|
408 *b = 1;
|
|
409 *c = 2;
|
|
410 }
|
|
411 else
|
|
412 {
|
|
413 *a = text_char_to_num(text, 0);
|
|
414 *b = text_char_to_num(text, 1);
|
|
415 *c = text_char_to_num(text, 2);
|
|
416 }
|
|
417 }
|