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