105
|
1 /*
|
196
|
2 * Geeqie
|
105
|
3 * (C) 2006 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
|
|
12
|
|
13 #include "gqview.h"
|
|
14 #include "pan-types.h"
|
|
15
|
|
16 #include <math.h>
|
|
17
|
|
18
|
|
19 static void pan_flower_size(PanWindow *pw, gint *width, gint *height)
|
|
20 {
|
|
21 GList *work;
|
|
22 gint x1, y1, x2, y2;
|
|
23
|
|
24 x1 = 0;
|
|
25 y1 = 0;
|
|
26 x2 = 0;
|
|
27 y2 = 0;
|
|
28
|
|
29 work = pw->list;
|
|
30 while (work)
|
|
31 {
|
|
32 PanItem *pi;
|
|
33
|
|
34 pi = work->data;
|
|
35 work = work->next;
|
|
36
|
|
37 if (x1 > pi->x) x1 = pi->x;
|
|
38 if (y1 > pi->y) y1 = pi->y;
|
|
39 if (x2 < pi->x + pi->width) x2 = pi->x + pi->width;
|
|
40 if (y2 < pi->y + pi->height) y2 = pi->y + pi->height;
|
|
41 }
|
|
42
|
|
43 x1 -= PAN_BOX_BORDER;
|
|
44 y1 -= PAN_BOX_BORDER;
|
|
45 x2 += PAN_BOX_BORDER;
|
|
46 y2 += PAN_BOX_BORDER;
|
|
47
|
|
48 work = pw->list;
|
|
49 while (work)
|
|
50 {
|
|
51 PanItem *pi;
|
|
52
|
|
53 pi = work->data;
|
|
54 work = work->next;
|
|
55
|
|
56 pi->x -= x1;
|
|
57 pi->y -= y1;
|
|
58
|
|
59 if (pi->type == PAN_ITEM_TRIANGLE && pi->data)
|
|
60 {
|
|
61 gint *coord;
|
|
62
|
|
63 coord = pi->data;
|
|
64 coord[0] -= x1;
|
|
65 coord[1] -= y1;
|
|
66 coord[2] -= x1;
|
|
67 coord[3] -= y1;
|
|
68 coord[4] -= x1;
|
|
69 coord[5] -= y1;
|
|
70 }
|
|
71 }
|
|
72
|
|
73 if (width) *width = x2 - x1;
|
|
74 if (height) *height = y2 - y1;
|
|
75 }
|
|
76
|
|
77 typedef struct _FlowerGroup FlowerGroup;
|
|
78 struct _FlowerGroup {
|
|
79 GList *items;
|
|
80 GList *children;
|
|
81 gint x;
|
|
82 gint y;
|
|
83 gint width;
|
|
84 gint height;
|
|
85
|
|
86 gdouble angle;
|
|
87 gint circumference;
|
|
88 gint diameter;
|
|
89 };
|
|
90
|
|
91 static void pan_flower_move(FlowerGroup *group, gint x, gint y)
|
|
92 {
|
|
93 GList *work;
|
|
94
|
|
95 work = group->items;
|
|
96 while (work)
|
|
97 {
|
|
98 PanItem *pi;
|
|
99
|
|
100 pi = work->data;
|
|
101 work = work->next;
|
|
102
|
|
103 pi->x += x;
|
|
104 pi->y += y;
|
|
105 }
|
|
106
|
|
107 group->x += x;
|
|
108 group->y += y;
|
|
109 }
|
|
110
|
|
111 #define PI 3.14159
|
|
112
|
|
113 static void pan_flower_position(FlowerGroup *group, FlowerGroup *parent,
|
|
114 gint *result_x, gint *result_y)
|
|
115 {
|
|
116 gint x, y;
|
|
117 gint radius;
|
|
118 gdouble a;
|
|
119
|
|
120 radius = parent->circumference / (2*PI);
|
|
121 radius = MAX(radius, parent->diameter / 2 + group->diameter / 2);
|
|
122
|
|
123 a = 2*PI * group->diameter / parent->circumference;
|
|
124
|
|
125 x = (gint)((double)radius * cos(parent->angle + a / 2));
|
|
126 y = (gint)((double)radius * sin(parent->angle + a / 2));
|
|
127
|
|
128 parent->angle += a;
|
|
129
|
|
130 x += parent->x;
|
|
131 y += parent->y;
|
|
132
|
|
133 x += parent->width / 2;
|
|
134 y += parent->height / 2;
|
|
135
|
|
136 x -= group->width / 2;
|
|
137 y -= group->height / 2;
|
|
138
|
|
139 *result_x = x;
|
|
140 *result_y = y;
|
|
141 }
|
|
142
|
|
143 static void pan_flower_build(PanWindow *pw, FlowerGroup *group, FlowerGroup *parent)
|
|
144 {
|
|
145 GList *work;
|
|
146 gint x, y;
|
|
147
|
|
148 if (!group) return;
|
|
149
|
|
150 if (parent && parent->children)
|
|
151 {
|
|
152 pan_flower_position(group, parent, &x, &y);
|
|
153 }
|
|
154 else
|
|
155 {
|
|
156 x = 0;
|
|
157 y = 0;
|
|
158 }
|
|
159
|
|
160 pan_flower_move(group, x, y);
|
|
161
|
|
162 if (parent)
|
|
163 {
|
|
164 PanItem *pi;
|
|
165 gint px, py, gx, gy;
|
|
166 gint x1, y1, x2, y2;
|
|
167
|
|
168 px = parent->x + parent->width / 2;
|
|
169 py = parent->y + parent->height / 2;
|
|
170
|
|
171 gx = group->x + group->width / 2;
|
|
172 gy = group->y + group->height / 2;
|
|
173
|
|
174 x1 = MIN(px, gx);
|
|
175 y1 = MIN(py, gy);
|
|
176
|
|
177 x2 = MAX(px, gx + 5);
|
|
178 y2 = MAX(py, gy + 5);
|
|
179
|
|
180 pi = pan_item_tri_new(pw, NULL, x1, y1, x2 - x1, y2 - y1,
|
|
181 px, py, gx, gy, gx + 5, gy + 5,
|
|
182 255, 40, 40, 128);
|
|
183 pan_item_tri_border(pi, PAN_BORDER_1 | PAN_BORDER_3,
|
|
184 255, 0, 0, 128);
|
|
185 }
|
|
186
|
|
187 pw->list = g_list_concat(group->items, pw->list);
|
|
188 group->items = NULL;
|
|
189
|
|
190 group->circumference = 0;
|
|
191 work = group->children;
|
|
192 while (work)
|
|
193 {
|
|
194 FlowerGroup *child;
|
|
195
|
|
196 child = work->data;
|
|
197 work = work->next;
|
|
198
|
|
199 group->circumference += child->diameter;
|
|
200 }
|
|
201
|
|
202 work = g_list_last(group->children);
|
|
203 while (work)
|
|
204 {
|
|
205 FlowerGroup *child;
|
|
206
|
|
207 child = work->data;
|
|
208 work = work->prev;
|
|
209
|
|
210 pan_flower_build(pw, child, group);
|
|
211 }
|
|
212
|
|
213 g_list_free(group->children);
|
|
214 g_free(group);
|
|
215 }
|
|
216
|
|
217 static FlowerGroup *pan_flower_group(PanWindow *pw, const gchar *path, gint x, gint y)
|
|
218 {
|
|
219 FlowerGroup *group;
|
|
220 GList *f;
|
|
221 GList *d;
|
|
222 GList *work;
|
|
223 PanItem *pi_box;
|
|
224 gint x_start;
|
|
225 gint y_height;
|
|
226 gint grid_size;
|
|
227 gint grid_count;
|
|
228
|
|
229 if (!filelist_read(path, &f, &d)) return NULL;
|
|
230 if (!f && !d) return NULL;
|
|
231
|
|
232 f = filelist_sort(f, SORT_NAME, TRUE);
|
|
233 d = filelist_sort(d, SORT_NAME, TRUE);
|
|
234
|
|
235 pi_box = pan_item_text_new(pw, x, y, path, PAN_TEXT_ATTR_NONE,
|
|
236 PAN_TEXT_BORDER_SIZE,
|
|
237 PAN_TEXT_COLOR, 255);
|
|
238
|
|
239 y += pi_box->height;
|
|
240
|
|
241 pi_box = pan_item_box_new(pw, file_data_new_simple(path),
|
|
242 x, y,
|
|
243 PAN_BOX_BORDER * 2, PAN_BOX_BORDER * 2,
|
|
244 PAN_BOX_OUTLINE_THICKNESS,
|
|
245 PAN_BOX_COLOR, PAN_BOX_ALPHA,
|
|
246 PAN_BOX_OUTLINE_COLOR, PAN_BOX_OUTLINE_ALPHA);
|
|
247
|
|
248 x += PAN_BOX_BORDER;
|
|
249 y += PAN_BOX_BORDER;
|
|
250
|
|
251 grid_size = (gint)(sqrt(g_list_length(f)) + 0.9);
|
|
252 grid_count = 0;
|
|
253 x_start = x;
|
|
254 y_height = y;
|
|
255
|
|
256 work = f;
|
|
257 while (work)
|
|
258 {
|
|
259 FileData *fd;
|
|
260 PanItem *pi;
|
|
261
|
|
262 fd = work->data;
|
|
263 work = work->next;
|
|
264
|
|
265 if (pw->size > PAN_IMAGE_SIZE_THUMB_LARGE)
|
|
266 {
|
|
267 pi = pan_item_image_new(pw, fd, x, y, 10, 10);
|
|
268 x += pi->width + PAN_THUMB_GAP;
|
|
269 if (pi->height > y_height) y_height = pi->height;
|
|
270 }
|
|
271 else
|
|
272 {
|
|
273 pi = pan_item_thumb_new(pw, fd, x, y);
|
|
274 x += PAN_THUMB_SIZE + PAN_THUMB_GAP;
|
|
275 y_height = PAN_THUMB_SIZE;
|
|
276 }
|
|
277
|
|
278 grid_count++;
|
|
279 if (grid_count >= grid_size)
|
|
280 {
|
|
281 grid_count = 0;
|
|
282 x = x_start;
|
|
283 y += y_height + PAN_THUMB_GAP;
|
|
284 y_height = 0;
|
|
285 }
|
|
286
|
|
287 pan_item_size_by_item(pi_box, pi, PAN_BOX_BORDER);
|
|
288 }
|
|
289
|
|
290 group = g_new0(FlowerGroup, 1);
|
|
291 group->items = pw->list;
|
|
292 pw->list = NULL;
|
|
293
|
|
294 group->width = pi_box->width;
|
|
295 group->height = pi_box->y + pi_box->height;
|
|
296 group->diameter = (int)sqrt(group->width * group->width + group->height * group->height);
|
|
297
|
|
298 group->children = NULL;
|
|
299
|
|
300 work = d;
|
|
301 while (work)
|
|
302 {
|
|
303 FileData *fd;
|
|
304 FlowerGroup *child;
|
|
305
|
|
306 fd = work->data;
|
|
307 work = work->next;
|
|
308
|
|
309 if (!pan_is_ignored(fd->path, pw->ignore_symlinks))
|
|
310 {
|
|
311 child = pan_flower_group(pw, fd->path, 0, 0);
|
|
312 if (child) group->children = g_list_prepend(group->children, child);
|
|
313 }
|
|
314 }
|
|
315
|
|
316 if (!f && !group->children)
|
|
317 {
|
|
318 work = group->items;
|
|
319 while (work)
|
|
320 {
|
|
321 PanItem *pi;
|
|
322
|
|
323 pi = work->data;
|
|
324 work = work->next;
|
|
325
|
|
326 pan_item_free(pi);
|
|
327 }
|
|
328
|
|
329 g_list_free(group->items);
|
|
330 g_free(group);
|
|
331 group = NULL;
|
|
332 }
|
|
333
|
|
334 g_list_free(f);
|
|
335 filelist_free(d);
|
|
336
|
|
337 return group;
|
|
338 }
|
|
339
|
|
340 void pan_flower_compute(PanWindow *pw, const gchar *path,
|
|
341 gint *width, gint *height,
|
|
342 gint *scroll_x, gint *scroll_y)
|
|
343 {
|
|
344 FlowerGroup *group;
|
|
345 GList *list;
|
|
346
|
|
347 group = pan_flower_group(pw, path, 0, 0);
|
|
348 pan_flower_build(pw, group, NULL);
|
|
349
|
|
350 pan_flower_size(pw, width, height);
|
|
351
|
|
352 list = pan_item_find_by_path(pw, PAN_ITEM_BOX, path, FALSE, FALSE);
|
|
353 if (list)
|
|
354 {
|
|
355 PanItem *pi = list->data;
|
|
356 *scroll_x = pi->x + pi->width / 2;
|
|
357 *scroll_y = pi->y + pi->height / 2;
|
|
358 }
|
|
359 g_list_free(list);
|
|
360 }
|
|
361
|
|
362 static void pan_folder_tree_path(PanWindow *pw, const gchar *path,
|
|
363 gint *x, gint *y, gint *level,
|
|
364 PanItem *parent,
|
|
365 gint *width, gint *height)
|
|
366 {
|
|
367 GList *f;
|
|
368 GList *d;
|
|
369 GList *work;
|
|
370 PanItem *pi_box;
|
|
371 gint y_height = 0;
|
|
372
|
|
373 if (!filelist_read(path, &f, &d)) return;
|
|
374 if (!f && !d) return;
|
|
375
|
|
376 f = filelist_sort(f, SORT_NAME, TRUE);
|
|
377 d = filelist_sort(d, SORT_NAME, TRUE);
|
|
378
|
|
379 *x = PAN_BOX_BORDER + ((*level) * MAX(PAN_BOX_BORDER, PAN_THUMB_GAP));
|
|
380
|
|
381 pi_box = pan_item_text_new(pw, *x, *y, path, PAN_TEXT_ATTR_NONE,
|
|
382 PAN_TEXT_BORDER_SIZE,
|
|
383 PAN_TEXT_COLOR, 255);
|
|
384
|
|
385 *y += pi_box->height;
|
|
386
|
|
387 pi_box = pan_item_box_new(pw, file_data_new_simple(path),
|
|
388 *x, *y,
|
|
389 PAN_BOX_BORDER, PAN_BOX_BORDER,
|
|
390 PAN_BOX_OUTLINE_THICKNESS,
|
|
391 PAN_BOX_COLOR, PAN_BOX_ALPHA,
|
|
392 PAN_BOX_OUTLINE_COLOR, PAN_BOX_OUTLINE_ALPHA);
|
|
393
|
|
394 *x += PAN_BOX_BORDER;
|
|
395 *y += PAN_BOX_BORDER;
|
|
396
|
|
397 work = f;
|
|
398 while (work)
|
|
399 {
|
|
400 FileData *fd;
|
|
401 PanItem *pi;
|
|
402
|
|
403 fd = work->data;
|
|
404 work = work->next;
|
|
405
|
|
406 if (pw->size > PAN_IMAGE_SIZE_THUMB_LARGE)
|
|
407 {
|
|
408 pi = pan_item_image_new(pw, fd, *x, *y, 10, 10);
|
|
409 *x += pi->width + PAN_THUMB_GAP;
|
|
410 if (pi->height > y_height) y_height = pi->height;
|
|
411 }
|
|
412 else
|
|
413 {
|
|
414 pi = pan_item_thumb_new(pw, fd, *x, *y);
|
|
415 *x += PAN_THUMB_SIZE + PAN_THUMB_GAP;
|
|
416 y_height = PAN_THUMB_SIZE;
|
|
417 }
|
|
418
|
|
419 pan_item_size_by_item(pi_box, pi, PAN_BOX_BORDER);
|
|
420 }
|
|
421
|
|
422 if (f) *y = pi_box->y + pi_box->height;
|
|
423
|
|
424 g_list_free(f);
|
|
425
|
|
426 work = d;
|
|
427 while (work)
|
|
428 {
|
|
429 FileData *fd;
|
|
430
|
|
431 fd = work->data;
|
|
432 work = work->next;
|
|
433
|
|
434 if (!pan_is_ignored(fd->path, pw->ignore_symlinks))
|
|
435 {
|
|
436 *level = *level + 1;
|
|
437 pan_folder_tree_path(pw, fd->path, x, y, level, pi_box, width, height);
|
|
438 *level = *level - 1;
|
|
439 }
|
|
440 }
|
|
441
|
|
442 filelist_free(d);
|
|
443
|
|
444 pan_item_size_by_item(parent, pi_box, PAN_BOX_BORDER);
|
|
445
|
|
446 if (*y < pi_box->y + pi_box->height + PAN_BOX_BORDER)
|
|
447 *y = pi_box->y + pi_box->height + PAN_BOX_BORDER;
|
|
448
|
|
449 pan_item_size_coordinates(pi_box, PAN_BOX_BORDER, width, height);
|
|
450 }
|
|
451
|
|
452 void pan_folder_tree_compute(PanWindow *pw, const gchar *path, gint *width, gint *height)
|
|
453 {
|
|
454 gint x, y;
|
|
455 gint level;
|
|
456 gint w, h;
|
|
457
|
|
458 level = 0;
|
|
459 x = PAN_BOX_BORDER;
|
|
460 y = PAN_BOX_BORDER;
|
|
461 w = PAN_BOX_BORDER * 2;
|
|
462 h = PAN_BOX_BORDER * 2;
|
|
463
|
|
464 pan_folder_tree_path(pw, path, &x, &y, &level, NULL, &w, &h);
|
|
465
|
|
466 if (width) *width = w;
|
|
467 if (height) *height = h;
|
|
468 }
|
|
469
|
|
470
|