1 /*
2 * Copyright (C) 2006 John Ellis
3 * Copyright (C) 2008 - 2016 The Geeqie Team
4 *
5 * Author: John Ellis
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22 #include "pan-item.h"
23
24 #include "image.h"
25 #include "pixbuf_util.h"
26 #include "ui_misc.h"
27
28 /*
29 *-----------------------------------------------------------------------------
30 * item base functions
31 *-----------------------------------------------------------------------------
32 */
33
pan_item_free(PanItem * pi)34 void pan_item_free(PanItem *pi)
35 {
36 if (!pi) return;
37
38 if (pi->pixbuf) g_object_unref(pi->pixbuf);
39 if (pi->fd) file_data_unref(pi->fd);
40 g_free(pi->text);
41 g_free(pi->key);
42 g_free(pi->data);
43
44 g_free(pi);
45 }
46
pan_item_set_key(PanItem * pi,const gchar * key)47 void pan_item_set_key(PanItem *pi, const gchar *key)
48 {
49 gchar *tmp;
50
51 if (!pi) return;
52
53 tmp = pi->key;
54 pi->key = g_strdup(key);
55 g_free(tmp);
56 }
57
pan_item_added(PanWindow * pw,PanItem * pi)58 void pan_item_added(PanWindow *pw, PanItem *pi)
59 {
60 if (!pi) return;
61 image_area_changed(pw->imd, pi->x, pi->y, pi->width, pi->height);
62 }
63
pan_item_remove(PanWindow * pw,PanItem * pi)64 void pan_item_remove(PanWindow *pw, PanItem *pi)
65 {
66 if (!pi) return;
67
68 if (pw->click_pi == pi) pw->click_pi = NULL;
69 if (pw->queue_pi == pi) pw->queue_pi = NULL;
70 if (pw->search_pi == pi) pw->search_pi = NULL;
71 pw->queue = g_list_remove(pw->queue, pi);
72
73 pw->list = g_list_remove(pw->list, pi);
74 image_area_changed(pw->imd, pi->x, pi->y, pi->width, pi->height);
75 pan_item_free(pi);
76 }
77
pan_item_size_by_item(PanItem * pi,PanItem * child,gint border)78 void pan_item_size_by_item(PanItem *pi, PanItem *child, gint border)
79 {
80 if (!pi || !child) return;
81
82 if (pi->x + pi->width < child->x + child->width + border)
83 pi->width = child->x + child->width + border - pi->x;
84
85 if (pi->y + pi->height < child->y + child->height + border)
86 pi->height = child->y + child->height + border - pi->y;
87 }
88
pan_item_size_coordinates(PanItem * pi,gint border,gint * w,gint * h)89 void pan_item_size_coordinates(PanItem *pi, gint border, gint *w, gint *h)
90 {
91 if (!pi) return;
92
93 if (*w < pi->x + pi->width + border) *w = pi->x + pi->width + border;
94 if (*h < pi->y + pi->height + border) *h = pi->y + pi->height + border;
95 }
96
97
98 /*
99 *-----------------------------------------------------------------------------
100 * item box type
101 *-----------------------------------------------------------------------------
102 */
103
pan_item_box_new(PanWindow * pw,FileData * fd,gint x,gint y,gint width,gint height,gint border_size,guint8 base_r,guint8 base_g,guint8 base_b,guint8 base_a,guint8 bord_r,guint8 bord_g,guint8 bord_b,guint8 bord_a)104 PanItem *pan_item_box_new(PanWindow *pw, FileData *fd, gint x, gint y, gint width, gint height,
105 gint border_size,
106 guint8 base_r, guint8 base_g, guint8 base_b, guint8 base_a,
107 guint8 bord_r, guint8 bord_g, guint8 bord_b, guint8 bord_a)
108 {
109 PanItem *pi;
110
111 pi = g_new0(PanItem, 1);
112 pi->type = PAN_ITEM_BOX;
113 pi->fd = fd;
114 pi->x = x;
115 pi->y = y;
116 pi->width = width;
117 pi->height = height;
118
119 pi->color_r = base_r;
120 pi->color_g = base_g;
121 pi->color_b = base_b;
122 pi->color_a = base_a;
123
124 pi->color2_r = bord_r;
125 pi->color2_g = bord_g;
126 pi->color2_b = bord_b;
127 pi->color2_a = bord_a;
128 pi->border = border_size;
129
130 pw->list = g_list_prepend(pw->list, pi);
131
132 return pi;
133 }
134
pan_item_box_shadow(PanItem * pi,gint offset,gint fade)135 void pan_item_box_shadow(PanItem *pi, gint offset, gint fade)
136 {
137 gint *shadow;
138
139 if (!pi || pi->type != PAN_ITEM_BOX) return;
140
141 shadow = pi->data;
142 if (shadow)
143 {
144 pi->width -= shadow[0];
145 pi->height -= shadow[0];
146 }
147
148 shadow = g_new0(gint, 2);
149 shadow[0] = offset;
150 shadow[1] = fade;
151
152 pi->width += offset;
153 pi->height += offset;
154
155 g_free(pi->data);
156 pi->data = shadow;
157 }
158
pan_item_box_draw(PanWindow * pw,PanItem * pi,GdkPixbuf * pixbuf,PixbufRenderer * pr,gint x,gint y,gint width,gint height)159 gint pan_item_box_draw(PanWindow *pw, PanItem *pi, GdkPixbuf *pixbuf, PixbufRenderer *pr,
160 gint x, gint y, gint width, gint height)
161 {
162 gint bw, bh;
163 gint *shadow;
164 gint rx, ry, rw, rh;
165
166 bw = pi->width;
167 bh = pi->height;
168
169 shadow = pi->data;
170 if (shadow)
171 {
172 bw -= shadow[0];
173 bh -= shadow[0];
174
175 if (pi->color_a > 254)
176 {
177 pixbuf_draw_shadow(pixbuf, pi->x - x + bw, pi->y - y + shadow[0],
178 shadow[0], bh - shadow[0],
179 pi->x - x + shadow[0], pi->y - y + shadow[0], bw, bh,
180 shadow[1],
181 PAN_SHADOW_COLOR, PAN_SHADOW_ALPHA);
182 pixbuf_draw_shadow(pixbuf, pi->x - x + shadow[0], pi->y - y + bh,
183 bw, shadow[0],
184 pi->x - x + shadow[0], pi->y - y + shadow[0], bw, bh,
185 shadow[1],
186 PAN_SHADOW_COLOR, PAN_SHADOW_ALPHA);
187 }
188 else
189 {
190 gint a;
191 a = pi->color_a * PAN_SHADOW_ALPHA >> 8;
192 pixbuf_draw_shadow(pixbuf, pi->x - x + shadow[0], pi->y - y + shadow[0],
193 bw, bh,
194 pi->x - x + shadow[0], pi->y - y + shadow[0], bw, bh,
195 shadow[1],
196 PAN_SHADOW_COLOR, a);
197 }
198 }
199
200 if (util_clip_region(x, y, width, height,
201 pi->x, pi->y, bw, bh,
202 &rx, &ry, &rw, &rh))
203 {
204 pixbuf_draw_rect_fill(pixbuf,
205 rx - x, ry - y, rw, rh,
206 pi->color_r, pi->color_g, pi->color_b, pi->color_a);
207 }
208 if (util_clip_region(x, y, width, height,
209 pi->x, pi->y, bw, pi->border,
210 &rx, &ry, &rw, &rh))
211 {
212 pixbuf_draw_rect_fill(pixbuf,
213 rx - x, ry - y, rw, rh,
214 pi->color2_r, pi->color2_g, pi->color2_b, pi->color2_a);
215 }
216 if (util_clip_region(x, y, width, height,
217 pi->x, pi->y + pi->border, pi->border, bh - pi->border * 2,
218 &rx, &ry, &rw, &rh))
219 {
220 pixbuf_draw_rect_fill(pixbuf,
221 rx - x, ry - y, rw, rh,
222 pi->color2_r, pi->color2_g, pi->color2_b, pi->color2_a);
223 }
224 if (util_clip_region(x, y, width, height,
225 pi->x + bw - pi->border, pi->y + pi->border,
226 pi->border, bh - pi->border * 2,
227 &rx, &ry, &rw, &rh))
228 {
229 pixbuf_draw_rect_fill(pixbuf,
230 rx - x, ry - y, rw, rh,
231 pi->color2_r, pi->color2_g, pi->color2_b, pi->color2_a);
232 }
233 if (util_clip_region(x, y, width, height,
234 pi->x, pi->y + bh - pi->border,
235 bw, pi->border,
236 &rx, &ry, &rw, &rh))
237 {
238 pixbuf_draw_rect_fill(pixbuf,
239 rx - x, ry - y, rw, rh,
240 pi->color2_r, pi->color2_g, pi->color2_b, pi->color2_a);
241 }
242
243 return FALSE;
244 }
245
246
247 /*
248 *-----------------------------------------------------------------------------
249 * item triangle type
250 *-----------------------------------------------------------------------------
251 */
252
pan_item_tri_new(PanWindow * pw,FileData * fd,gint x,gint y,gint width,gint height,gint x1,gint y1,gint x2,gint y2,gint x3,gint y3,guint8 r,guint8 g,guint8 b,guint8 a)253 PanItem *pan_item_tri_new(PanWindow *pw, FileData *fd, gint x, gint y, gint width, gint height,
254 gint x1, gint y1, gint x2, gint y2, gint x3, gint y3,
255 guint8 r, guint8 g, guint8 b, guint8 a)
256 {
257 PanItem *pi;
258 gint *coord;
259
260 pi = g_new0(PanItem, 1);
261 pi->type = PAN_ITEM_TRIANGLE;
262 pi->x = x;
263 pi->y = y;
264 pi->width = width;
265 pi->height = height;
266
267 pi->color_r = r;
268 pi->color_g = g;
269 pi->color_b = b;
270 pi->color_a = a;
271
272 coord = g_new0(gint, 6);
273 coord[0] = x1;
274 coord[1] = y1;
275 coord[2] = x2;
276 coord[3] = y2;
277 coord[4] = x3;
278 coord[5] = y3;
279
280 pi->data = coord;
281
282 pi->border = PAN_BORDER_NONE;
283
284 pw->list = g_list_prepend(pw->list, pi);
285
286 return pi;
287 }
288
pan_item_tri_border(PanItem * pi,gint borders,guint8 r,guint8 g,guint8 b,guint8 a)289 void pan_item_tri_border(PanItem *pi, gint borders,
290 guint8 r, guint8 g, guint8 b, guint8 a)
291 {
292 if (!pi || pi->type != PAN_ITEM_TRIANGLE) return;
293
294 pi->border = borders;
295
296 pi->color2_r = r;
297 pi->color2_g = g;
298 pi->color2_b = b;
299 pi->color2_a = a;
300 }
301
pan_item_tri_draw(PanWindow * pw,PanItem * pi,GdkPixbuf * pixbuf,PixbufRenderer * pr,gint x,gint y,gint width,gint height)302 gint pan_item_tri_draw(PanWindow *pw, PanItem *pi, GdkPixbuf *pixbuf, PixbufRenderer *pr,
303 gint x, gint y, gint width, gint height)
304 {
305 gint rx, ry, rw, rh;
306
307 if (util_clip_region(x, y, width, height,
308 pi->x, pi->y, pi->width, pi->height,
309 &rx, &ry, &rw, &rh) && pi->data)
310 {
311 gint *coord = pi->data;
312 pixbuf_draw_triangle(pixbuf,
313 rx - x, ry - y, rw, rh,
314 coord[0] - x, coord[1] - y,
315 coord[2] - x, coord[3] - y,
316 coord[4] - x, coord[5] - y,
317 pi->color_r, pi->color_g, pi->color_b, pi->color_a);
318
319 if (pi->border & PAN_BORDER_1)
320 {
321 pixbuf_draw_line(pixbuf,
322 rx - x, ry - y, rw, rh,
323 coord[0] - x, coord[1] - y,
324 coord[2] - x, coord[3] - y,
325 pi->color2_r, pi->color2_g, pi->color2_b, pi->color2_a);
326 }
327 if (pi->border & PAN_BORDER_2)
328 {
329 pixbuf_draw_line(pixbuf,
330 rx - x, ry - y, rw, rh,
331 coord[2] - x, coord[3] - y,
332 coord[4] - x, coord[5] - y,
333 pi->color2_r, pi->color2_g, pi->color2_b, pi->color2_a);
334 }
335 if (pi->border & PAN_BORDER_3)
336 {
337 pixbuf_draw_line(pixbuf,
338 rx - x, ry - y, rw, rh,
339 coord[4] - x, coord[5] - y,
340 coord[0] - x, coord[1] - y,
341 pi->color2_r, pi->color2_g, pi->color2_b, pi->color2_a);
342 }
343 }
344
345 return FALSE;
346 }
347
348
349 /*
350 *-----------------------------------------------------------------------------
351 * item text type
352 *-----------------------------------------------------------------------------
353 */
354
pan_item_text_layout(PanItem * pi,GtkWidget * widget)355 static PangoLayout *pan_item_text_layout(PanItem *pi, GtkWidget *widget)
356 {
357 PangoLayout *layout;
358
359 layout = gtk_widget_create_pango_layout(widget, NULL);
360
361 if (pi->text_attr & PAN_TEXT_ATTR_MARKUP)
362 {
363 pango_layout_set_markup(layout, pi->text, -1);
364 return layout;
365 }
366
367 if (pi->text_attr & PAN_TEXT_ATTR_BOLD ||
368 pi->text_attr & PAN_TEXT_ATTR_HEADING)
369 {
370 PangoAttrList *pal;
371 PangoAttribute *pa;
372
373 pal = pango_attr_list_new();
374 if (pi->text_attr & PAN_TEXT_ATTR_BOLD)
375 {
376 pa = pango_attr_weight_new(PANGO_WEIGHT_BOLD);
377 pa->start_index = 0;
378 pa->end_index = G_MAXINT;
379 pango_attr_list_insert(pal, pa);
380 }
381 if (pi->text_attr & PAN_TEXT_ATTR_HEADING)
382 {
383 pa = pango_attr_scale_new(PANGO_SCALE_LARGE);
384 pa->start_index = 0;
385 pa->end_index = G_MAXINT;
386 pango_attr_list_insert(pal, pa);
387 }
388 pango_layout_set_attributes(layout, pal);
389 pango_attr_list_unref(pal);
390 }
391
392 pango_layout_set_text(layout, pi->text, -1);
393 return layout;
394 }
395
pan_item_text_compute_size(PanItem * pi,GtkWidget * widget)396 static void pan_item_text_compute_size(PanItem *pi, GtkWidget *widget)
397 {
398 PangoLayout *layout;
399
400 if (!pi || !pi->text || !widget) return;
401
402 layout = pan_item_text_layout(pi, widget);
403 pango_layout_get_pixel_size(layout, &pi->width, &pi->height);
404 g_object_unref(G_OBJECT(layout));
405
406 pi->width += pi->border * 2;
407 pi->height += pi->border * 2;
408 }
409
pan_item_text_new(PanWindow * pw,gint x,gint y,const gchar * text,PanTextAttrType attr,PanBorderType border,guint8 r,guint8 g,guint8 b,guint8 a)410 PanItem *pan_item_text_new(PanWindow *pw, gint x, gint y, const gchar *text,
411 PanTextAttrType attr, PanBorderType border,
412 guint8 r, guint8 g, guint8 b, guint8 a)
413 {
414 PanItem *pi;
415
416 pi = g_new0(PanItem, 1);
417 pi->type = PAN_ITEM_TEXT;
418 pi->x = x;
419 pi->y = y;
420 pi->text = g_strdup(text);
421 pi->text_attr = attr;
422
423 pi->color_r = r;
424 pi->color_g = g;
425 pi->color_b = b;
426 pi->color_a = a;
427
428 pi->border = border;
429
430 pan_item_text_compute_size(pi, pw->imd->pr);
431
432 pw->list = g_list_prepend(pw->list, pi);
433
434 return pi;
435 }
436
pan_item_text_draw(PanWindow * pw,PanItem * pi,GdkPixbuf * pixbuf,PixbufRenderer * pr,gint x,gint y,gint width,gint height)437 gint pan_item_text_draw(PanWindow *pw, PanItem *pi, GdkPixbuf *pixbuf, PixbufRenderer *pr,
438 gint x, gint y, gint width, gint height)
439 {
440 PangoLayout *layout;
441
442 layout = pan_item_text_layout(pi, (GtkWidget *)pr);
443 pixbuf_draw_layout(pixbuf, layout, (GtkWidget *)pr,
444 pi->x - x + pi->border, pi->y - y + pi->border,
445 pi->color_r, pi->color_g, pi->color_b, pi->color_a);
446 g_object_unref(G_OBJECT(layout));
447
448 return FALSE;
449 }
450
451
452 /*
453 *-----------------------------------------------------------------------------
454 * item thumbnail type
455 *-----------------------------------------------------------------------------
456 */
457
pan_item_thumb_new(PanWindow * pw,FileData * fd,gint x,gint y)458 PanItem *pan_item_thumb_new(PanWindow *pw, FileData *fd, gint x, gint y)
459 {
460 PanItem *pi;
461
462 pi = g_new0(PanItem, 1);
463
464 pi->type = PAN_ITEM_THUMB;
465 pi->fd = fd;
466 pi->x = x;
467 pi->y = y;
468 pi->width = PAN_THUMB_SIZE + PAN_SHADOW_OFFSET * 2;
469 pi->height = PAN_THUMB_SIZE + PAN_SHADOW_OFFSET * 2;
470
471 pw->list = g_list_prepend(pw->list, pi);
472
473 return pi;
474 }
475
pan_item_thumb_draw(PanWindow * pw,PanItem * pi,GdkPixbuf * pixbuf,PixbufRenderer * pr,gint x,gint y,gint width,gint height)476 gint pan_item_thumb_draw(PanWindow *pw, PanItem *pi, GdkPixbuf *pixbuf, PixbufRenderer *pr,
477 gint x, gint y, gint width, gint height)
478 {
479 gint tx, ty, tw, th;
480 gint rx, ry, rw, rh;
481
482 if (pi->pixbuf)
483 {
484 tw = gdk_pixbuf_get_width(pi->pixbuf);
485 th = gdk_pixbuf_get_height(pi->pixbuf);
486
487 tx = pi->x + (pi->width - tw) / 2;
488 ty = pi->y + (pi->height - th) / 2;
489
490 if (gdk_pixbuf_get_has_alpha(pi->pixbuf))
491 {
492 if (util_clip_region(x, y, width, height,
493 tx + PAN_SHADOW_OFFSET, ty + PAN_SHADOW_OFFSET, tw, th,
494 &rx, &ry, &rw, &rh))
495 {
496 pixbuf_draw_shadow(pixbuf,
497 rx - x, ry - y, rw, rh,
498 tx + PAN_SHADOW_OFFSET - x, ty + PAN_SHADOW_OFFSET - y, tw, th,
499 PAN_SHADOW_FADE,
500 PAN_SHADOW_COLOR, PAN_SHADOW_ALPHA);
501 }
502 }
503 else
504 {
505 if (util_clip_region(x, y, width, height,
506 tx + tw, ty + PAN_SHADOW_OFFSET,
507 PAN_SHADOW_OFFSET, th - PAN_SHADOW_OFFSET,
508 &rx, &ry, &rw, &rh))
509 {
510 pixbuf_draw_shadow(pixbuf,
511 rx - x, ry - y, rw, rh,
512 tx + PAN_SHADOW_OFFSET - x, ty + PAN_SHADOW_OFFSET - y, tw, th,
513 PAN_SHADOW_FADE,
514 PAN_SHADOW_COLOR, PAN_SHADOW_ALPHA);
515 }
516 if (util_clip_region(x, y, width, height,
517 tx + PAN_SHADOW_OFFSET, ty + th, tw, PAN_SHADOW_OFFSET,
518 &rx, &ry, &rw, &rh))
519 {
520 pixbuf_draw_shadow(pixbuf,
521 rx - x, ry - y, rw, rh,
522 tx + PAN_SHADOW_OFFSET - x, ty + PAN_SHADOW_OFFSET - y, tw, th,
523 PAN_SHADOW_FADE,
524 PAN_SHADOW_COLOR, PAN_SHADOW_ALPHA);
525 }
526 }
527
528 if (util_clip_region(x, y, width, height,
529 tx, ty, tw, th,
530 &rx, &ry, &rw, &rh))
531 {
532 gdk_pixbuf_composite(pi->pixbuf, pixbuf, rx - x, ry - y, rw, rh,
533 (gdouble) tx - x,
534 (gdouble) ty - y,
535 1.0, 1.0, GDK_INTERP_NEAREST,
536 255);
537 }
538
539 if (util_clip_region(x, y, width, height,
540 tx, ty, tw, PAN_OUTLINE_THICKNESS,
541 &rx, &ry, &rw, &rh))
542 {
543 pixbuf_draw_rect_fill(pixbuf,
544 rx - x, ry - y, rw, rh,
545 PAN_OUTLINE_COLOR_1, PAN_OUTLINE_ALPHA);
546 }
547 if (util_clip_region(x, y, width, height,
548 tx, ty, PAN_OUTLINE_THICKNESS, th,
549 &rx, &ry, &rw, &rh))
550 {
551 pixbuf_draw_rect_fill(pixbuf,
552 rx - x, ry - y, rw, rh,
553 PAN_OUTLINE_COLOR_1, PAN_OUTLINE_ALPHA);
554 }
555 if (util_clip_region(x, y, width, height,
556 tx + tw - PAN_OUTLINE_THICKNESS, ty + PAN_OUTLINE_THICKNESS,
557 PAN_OUTLINE_THICKNESS, th - PAN_OUTLINE_THICKNESS,
558 &rx, &ry, &rw, &rh))
559 {
560 pixbuf_draw_rect_fill(pixbuf,
561 rx - x, ry - y, rw, rh,
562 PAN_OUTLINE_COLOR_2, PAN_OUTLINE_ALPHA);
563 }
564 if (util_clip_region(x, y, width, height,
565 tx + PAN_OUTLINE_THICKNESS, ty + th - PAN_OUTLINE_THICKNESS,
566 tw - PAN_OUTLINE_THICKNESS * 2, PAN_OUTLINE_THICKNESS,
567 &rx, &ry, &rw, &rh))
568 {
569 pixbuf_draw_rect_fill(pixbuf,
570 rx - x, ry - y, rw, rh,
571 PAN_OUTLINE_COLOR_2, PAN_OUTLINE_ALPHA);
572 }
573 }
574 else
575 {
576 tw = pi->width - PAN_SHADOW_OFFSET * 2;
577 th = pi->height - PAN_SHADOW_OFFSET * 2;
578 tx = pi->x + PAN_SHADOW_OFFSET;
579 ty = pi->y + PAN_SHADOW_OFFSET;
580
581 if (util_clip_region(x, y, width, height,
582 tx, ty, tw, th,
583 &rx, &ry, &rw, &rh))
584 {
585 gint d;
586
587 d = (pw->size <= PAN_IMAGE_SIZE_THUMB_NONE) ? 2 : 8;
588 pixbuf_draw_rect_fill(pixbuf,
589 rx - x, ry - y, rw, rh,
590 PAN_SHADOW_COLOR,
591 PAN_SHADOW_ALPHA / d);
592 }
593 }
594
595 return (pi->pixbuf == NULL);
596 }
597
598
599 /*
600 *-----------------------------------------------------------------------------
601 * item image type
602 *-----------------------------------------------------------------------------
603 */
604
pan_item_image_find_size(PanWindow * pw,PanItem * pi,gint w,gint h)605 static void pan_item_image_find_size(PanWindow *pw, PanItem *pi, gint w, gint h)
606 {
607 GList *work;
608
609 pi->width = w;
610 pi->height = h;
611
612 if (!pi->fd) return;
613
614 work = pw->cache_list;
615 while (work)
616 {
617 PanCacheData *pc;
618
619 pc = work->data;
620 work = work->next;
621
622 if (pc->cd && pc->cd->dimensions &&
623 pc->fd && pc->fd == pi->fd)
624 {
625 pi->width = MAX(1, pc->cd->width * pw->image_size / 100);
626 pi->height = MAX(1, pc->cd->height * pw->image_size / 100);
627
628 pw->cache_list = g_list_remove(pw->cache_list, pc);
629 cache_sim_data_free(pc->cd);
630 file_data_unref(pc->fd);
631 g_free(pc);
632 return;
633 }
634 }
635 }
636
pan_item_image_new(PanWindow * pw,FileData * fd,gint x,gint y,gint w,gint h)637 PanItem *pan_item_image_new(PanWindow *pw, FileData *fd, gint x, gint y, gint w, gint h)
638 {
639 PanItem *pi;
640
641 pi = g_new0(PanItem, 1);
642 pi->type = PAN_ITEM_IMAGE;
643 pi->fd = fd;
644 pi->x = x;
645 pi->y = y;
646
647 pi->color_a = 255;
648
649 pi->color2_r = 0;
650 pi->color2_g = 0;
651 pi->color2_b = 0;
652 pi->color2_a = PAN_SHADOW_ALPHA / 2;
653
654 pan_item_image_find_size(pw, pi, w, h);
655
656 pw->list = g_list_prepend(pw->list, pi);
657
658 return pi;
659 }
660
pan_item_image_draw(PanWindow * pw,PanItem * pi,GdkPixbuf * pixbuf,PixbufRenderer * pr,gint x,gint y,gint width,gint height)661 gint pan_item_image_draw(PanWindow *pw, PanItem *pi, GdkPixbuf *pixbuf, PixbufRenderer *pr,
662 gint x, gint y, gint width, gint height)
663 {
664 gint rx, ry, rw, rh;
665
666 if (util_clip_region(x, y, width, height,
667 pi->x, pi->y, pi->width, pi->height,
668 &rx, &ry, &rw, &rh))
669 {
670 if (pi->pixbuf)
671 {
672 gdk_pixbuf_composite(pi->pixbuf, pixbuf, rx - x, ry - y, rw, rh,
673 (gdouble) pi->x - x,
674 (gdouble) pi->y - y,
675 1.0, 1.0, GDK_INTERP_NEAREST,
676 pi->color_a);
677 }
678 else
679 {
680 pixbuf_draw_rect_fill(pixbuf,
681 rx - x, ry - y, rw, rh,
682 pi->color2_r, pi->color2_g, pi->color2_b, pi->color2_a);
683 }
684 }
685
686 return (pi->pixbuf == NULL);
687 }
688
689
690 /*
691 *-----------------------------------------------------------------------------
692 * item lookup/search
693 *-----------------------------------------------------------------------------
694 */
695
pan_item_find_by_key(PanWindow * pw,PanItemType type,const gchar * key)696 PanItem *pan_item_find_by_key(PanWindow *pw, PanItemType type, const gchar *key)
697 {
698 GList *work;
699
700 if (!key) return NULL;
701
702 work = g_list_last(pw->list);
703 while (work)
704 {
705 PanItem *pi;
706
707 pi = work->data;
708 if ((pi->type == type || type == PAN_ITEM_NONE) &&
709 pi->key && strcmp(pi->key, key) == 0)
710 {
711 return pi;
712 }
713 work = work->prev;
714 }
715 work = g_list_last(pw->list_static);
716 while (work)
717 {
718 PanItem *pi;
719
720 pi = work->data;
721 if ((pi->type == type || type == PAN_ITEM_NONE) &&
722 pi->key && strcmp(pi->key, key) == 0)
723 {
724 return pi;
725 }
726 work = work->prev;
727 }
728
729 return NULL;
730 }
731
732 /* when ignore_case and partial are TRUE, path should be converted to lower case */
pan_item_find_by_path_l(GList * list,GList * search_list,PanItemType type,const gchar * path,gboolean ignore_case,gboolean partial)733 static GList *pan_item_find_by_path_l(GList *list, GList *search_list,
734 PanItemType type, const gchar *path,
735 gboolean ignore_case, gboolean partial)
736 {
737 GList *work;
738
739 work = g_list_last(search_list);
740 while (work)
741 {
742 PanItem *pi;
743
744 pi = work->data;
745 if ((pi->type == type || type == PAN_ITEM_NONE) && pi->fd)
746 {
747 gboolean match = FALSE;
748
749 if (path[0] == G_DIR_SEPARATOR)
750 {
751 if (pi->fd->path && strcmp(path, pi->fd->path) == 0) match = TRUE;
752 }
753 else if (pi->fd->name)
754 {
755 if (partial)
756 {
757 if (ignore_case)
758 {
759 gchar *haystack;
760
761 haystack = g_utf8_strdown(pi->fd->name, -1);
762 match = (strstr(haystack, path) != NULL);
763 g_free(haystack);
764 }
765 else
766 {
767 if (strstr(pi->fd->name, path)) match = TRUE;
768 }
769 }
770 else if (ignore_case)
771 {
772 if (g_ascii_strcasecmp(path, pi->fd->name) == 0) match = TRUE;
773 }
774 else
775 {
776 if (strcmp(path, pi->fd->name) == 0) match = TRUE;
777 }
778 }
779
780 if (match) list = g_list_prepend(list, pi);
781 }
782 work = work->prev;
783 }
784
785 return list;
786 }
787
788 /* when ignore_case and partial are TRUE, path should be converted to lower case */
pan_item_find_by_path(PanWindow * pw,PanItemType type,const gchar * path,gboolean ignore_case,gboolean partial)789 GList *pan_item_find_by_path(PanWindow *pw, PanItemType type, const gchar *path,
790 gboolean ignore_case, gboolean partial)
791 {
792 GList *list = NULL;
793
794 if (!path) return NULL;
795 if (partial && path[0] == G_DIR_SEPARATOR) return NULL;
796
797 list = pan_item_find_by_path_l(list, pw->list_static, type, path, ignore_case, partial);
798 list = pan_item_find_by_path_l(list, pw->list, type, path, ignore_case, partial);
799
800 return g_list_reverse(list);
801 }
802
pan_item_find_by_fd(PanWindow * pw,PanItemType type,FileData * fd,gboolean ignore_case,gboolean partial)803 GList *pan_item_find_by_fd(PanWindow *pw, PanItemType type, FileData *fd,
804 gboolean ignore_case, gboolean partial)
805 {
806 if (!fd) return NULL;
807 return pan_item_find_by_path(pw, type, fd->path, ignore_case, partial);
808 }
809
810
pan_item_find_by_coord_l(GList * list,PanItemType type,gint x,gint y,const gchar * key)811 static PanItem *pan_item_find_by_coord_l(GList *list, PanItemType type, gint x, gint y, const gchar *key)
812 {
813 GList *work;
814
815 work = list;
816 while (work)
817 {
818 PanItem *pi;
819
820 pi = work->data;
821 if ((pi->type == type || type == PAN_ITEM_NONE) &&
822 x >= pi->x && x < pi->x + pi->width &&
823 y >= pi->y && y < pi->y + pi->height &&
824 (!key || (pi->key && strcmp(pi->key, key) == 0)))
825 {
826 return pi;
827 }
828 work = work->next;
829 }
830
831 return NULL;
832 }
833
pan_item_find_by_coord(PanWindow * pw,PanItemType type,gint x,gint y,const gchar * key)834 PanItem *pan_item_find_by_coord(PanWindow *pw, PanItemType type,
835 gint x, gint y, const gchar *key)
836 {
837 PanItem *pi;
838
839 pi = pan_item_find_by_coord_l(pw->list, type, x, y, key);
840 if (pi) return pi;
841
842 return pan_item_find_by_coord_l(pw->list_static, type, x, y, key);
843 }
844
845
846 /*
847 *-----------------------------------------------------------------------------
848 * text alignments
849 *-----------------------------------------------------------------------------
850 */
851
pan_text_alignment_new(PanWindow * pw,gint x,gint y,const gchar * key)852 PanTextAlignment *pan_text_alignment_new(PanWindow *pw, gint x, gint y, const gchar *key)
853 {
854 PanTextAlignment *ta;
855
856 ta = g_new0(PanTextAlignment, 1);
857
858 ta->pw = pw;
859 ta->x = x;
860 ta->y = y;
861 ta->key = g_strdup(key);
862
863 return ta;
864 }
865
pan_text_alignment_free(PanTextAlignment * ta)866 void pan_text_alignment_free(PanTextAlignment *ta)
867 {
868 if (!ta) return;
869
870 g_list_free(ta->column1);
871 g_list_free(ta->column2);
872 g_free(ta->key);
873 g_free(ta);
874 }
875
pan_text_alignment_add(PanTextAlignment * ta,const gchar * label,const gchar * text)876 PanItem *pan_text_alignment_add(PanTextAlignment *ta, const gchar *label, const gchar *text)
877 {
878 PanItem *item;
879
880 if (label)
881 {
882 item = pan_item_text_new(ta->pw, ta->x, ta->y, label,
883 PAN_TEXT_ATTR_BOLD, 0,
884 PAN_POPUP_TEXT_COLOR, 255);
885 pan_item_set_key(item, ta->key);
886 }
887 else
888 {
889 item = NULL;
890 }
891 ta->column1 = g_list_append(ta->column1, item);
892
893 if (text)
894 {
895 item = pan_item_text_new(ta->pw, ta->x, ta->y, text,
896 PAN_TEXT_ATTR_NONE, 0,
897 PAN_POPUP_TEXT_COLOR, 255);
898 pan_item_set_key(item, ta->key);
899 }
900 else
901 {
902 item = NULL;
903 }
904 ta->column2 = g_list_append(ta->column2, item);
905
906 return item;
907 }
908
pan_text_alignment_calc(PanTextAlignment * ta,PanItem * box)909 void pan_text_alignment_calc(PanTextAlignment *ta, PanItem *box)
910 {
911 gint cw1, cw2;
912 gint x, y;
913 GList *work1;
914 GList *work2;
915
916 cw1 = 0;
917 cw2 = 0;
918
919 work1 = ta->column1;
920 while (work1)
921 {
922 PanItem *p;
923
924 p = work1->data;
925 work1 = work1->next;
926
927 if (p && p->width > cw1) cw1 = p->width;
928 }
929
930 work2 = ta->column2;
931 while (work2)
932 {
933 PanItem *p;
934
935 p = work2->data;
936 work2 = work2->next;
937
938 if (p && p->width > cw2) cw2 = p->width;
939 }
940
941 x = ta->x;
942 y = ta->y;
943 work1 = ta->column1;
944 work2 = ta->column2;
945 while (work1 && work2)
946 {
947 PanItem *p1;
948 PanItem *p2;
949 gint height = 0;
950
951 p1 = work1->data;
952 p2 = work2->data;
953 work1 = work1->next;
954 work2 = work2->next;
955
956 if (p1)
957 {
958 p1->x = x;
959 p1->y = y;
960 pan_item_size_by_item(box, p1, PREF_PAD_BORDER);
961 height = p1->height;
962 }
963 if (p2)
964 {
965 p2->x = x + cw1 + PREF_PAD_SPACE;
966 p2->y = y;
967 pan_item_size_by_item(box, p2, PREF_PAD_BORDER);
968 if (height < p2->height) height = p2->height;
969 }
970
971 if (!p1 && !p2) height = PREF_PAD_GROUP;
972
973 y += height;
974 }
975 }
976 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
977