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