4 * Copyright (C) 2008 - 2012 The Geeqie Team
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!
15 #include "pan-types.h"
19 *-----------------------------------------------------------------------------
21 *-----------------------------------------------------------------------------
24 void pan_item_free(PanItem *pi)
28 if (pi->pixbuf) g_object_unref(pi->pixbuf);
29 if (pi->fd) file_data_unref(pi->fd);
37 void pan_item_set_key(PanItem *pi, const gchar *key)
44 pi->key = g_strdup(key);
48 void pan_item_added(PanWindow *pw, PanItem *pi)
51 image_area_changed(pw->imd, pi->x, pi->y, pi->width, pi->height);
54 void pan_item_remove(PanWindow *pw, PanItem *pi)
58 if (pw->click_pi == pi) pw->click_pi = NULL;
59 if (pw->queue_pi == pi) pw->queue_pi = NULL;
60 if (pw->search_pi == pi) pw->search_pi = NULL;
61 pw->queue = g_list_remove(pw->queue, pi);
63 pw->list = g_list_remove(pw->list, pi);
64 image_area_changed(pw->imd, pi->x, pi->y, pi->width, pi->height);
68 void pan_item_size_by_item(PanItem *pi, PanItem *child, gint border)
70 if (!pi || !child) return;
72 if (pi->x + pi->width < child->x + child->width + border)
73 pi->width = child->x + child->width + border - pi->x;
75 if (pi->y + pi->height < child->y + child->height + border)
76 pi->height = child->y + child->height + border - pi->y;
79 void pan_item_size_coordinates(PanItem *pi, gint border, gint *w, gint *h)
83 if (*w < pi->x + pi->width + border) *w = pi->x + pi->width + border;
84 if (*h < pi->y + pi->height + border) *h = pi->y + pi->height + border;
89 *-----------------------------------------------------------------------------
91 *-----------------------------------------------------------------------------
94 PanItem *pan_item_box_new(PanWindow *pw, FileData *fd, gint x, gint y, gint width, gint height,
96 guint8 base_r, guint8 base_g, guint8 base_b, guint8 base_a,
97 guint8 bord_r, guint8 bord_g, guint8 bord_b, guint8 bord_a)
101 pi = g_new0(PanItem, 1);
102 pi->type = PAN_ITEM_BOX;
109 pi->color_r = base_r;
110 pi->color_g = base_g;
111 pi->color_b = base_b;
112 pi->color_a = base_a;
114 pi->color2_r = bord_r;
115 pi->color2_g = bord_g;
116 pi->color2_b = bord_b;
117 pi->color2_a = bord_a;
118 pi->border = border_size;
120 pw->list = g_list_prepend(pw->list, pi);
125 void pan_item_box_shadow(PanItem *pi, gint offset, gint fade)
129 if (!pi || pi->type != PAN_ITEM_BOX) return;
134 pi->width -= shadow[0];
135 pi->height -= shadow[0];
138 shadow = g_new0(gint, 2);
143 pi->height += offset;
149 gint pan_item_box_draw(PanWindow *pw, PanItem *pi, GdkPixbuf *pixbuf, PixbufRenderer *pr,
150 gint x, gint y, gint width, gint height)
165 if (pi->color_a > 254)
167 pixbuf_draw_shadow(pixbuf, pi->x - x + bw, pi->y - y + shadow[0],
168 shadow[0], bh - shadow[0],
169 pi->x - x + shadow[0], pi->y - y + shadow[0], bw, bh,
171 PAN_SHADOW_COLOR, PAN_SHADOW_ALPHA);
172 pixbuf_draw_shadow(pixbuf, pi->x - x + shadow[0], pi->y - y + bh,
174 pi->x - x + shadow[0], pi->y - y + shadow[0], bw, bh,
176 PAN_SHADOW_COLOR, PAN_SHADOW_ALPHA);
181 a = pi->color_a * PAN_SHADOW_ALPHA >> 8;
182 pixbuf_draw_shadow(pixbuf, pi->x - x + shadow[0], pi->y - y + shadow[0],
184 pi->x - x + shadow[0], pi->y - y + shadow[0], bw, bh,
186 PAN_SHADOW_COLOR, a);
190 if (util_clip_region(x, y, width, height,
191 pi->x, pi->y, bw, bh,
194 pixbuf_draw_rect_fill(pixbuf,
195 rx - x, ry - y, rw, rh,
196 pi->color_r, pi->color_g, pi->color_b, pi->color_a);
198 if (util_clip_region(x, y, width, height,
199 pi->x, pi->y, bw, pi->border,
202 pixbuf_draw_rect_fill(pixbuf,
203 rx - x, ry - y, rw, rh,
204 pi->color2_r, pi->color2_g, pi->color2_b, pi->color2_a);
206 if (util_clip_region(x, y, width, height,
207 pi->x, pi->y + pi->border, pi->border, bh - pi->border * 2,
210 pixbuf_draw_rect_fill(pixbuf,
211 rx - x, ry - y, rw, rh,
212 pi->color2_r, pi->color2_g, pi->color2_b, pi->color2_a);
214 if (util_clip_region(x, y, width, height,
215 pi->x + bw - pi->border, pi->y + pi->border,
216 pi->border, bh - pi->border * 2,
219 pixbuf_draw_rect_fill(pixbuf,
220 rx - x, ry - y, rw, rh,
221 pi->color2_r, pi->color2_g, pi->color2_b, pi->color2_a);
223 if (util_clip_region(x, y, width, height,
224 pi->x, pi->y + bh - pi->border,
228 pixbuf_draw_rect_fill(pixbuf,
229 rx - x, ry - y, rw, rh,
230 pi->color2_r, pi->color2_g, pi->color2_b, pi->color2_a);
238 *-----------------------------------------------------------------------------
240 *-----------------------------------------------------------------------------
243 PanItem *pan_item_tri_new(PanWindow *pw, FileData *fd, gint x, gint y, gint width, gint height,
244 gint x1, gint y1, gint x2, gint y2, gint x3, gint y3,
245 guint8 r, guint8 g, guint8 b, guint8 a)
250 pi = g_new0(PanItem, 1);
251 pi->type = PAN_ITEM_TRIANGLE;
262 coord = g_new0(gint, 6);
272 pi->border = PAN_BORDER_NONE;
274 pw->list = g_list_prepend(pw->list, pi);
279 void pan_item_tri_border(PanItem *pi, gint borders,
280 guint8 r, guint8 g, guint8 b, guint8 a)
282 if (!pi || pi->type != PAN_ITEM_TRIANGLE) return;
284 pi->border = borders;
292 gint pan_item_tri_draw(PanWindow *pw, PanItem *pi, GdkPixbuf *pixbuf, PixbufRenderer *pr,
293 gint x, gint y, gint width, gint height)
297 if (util_clip_region(x, y, width, height,
298 pi->x, pi->y, pi->width, pi->height,
299 &rx, &ry, &rw, &rh) && pi->data)
301 gint *coord = pi->data;
302 pixbuf_draw_triangle(pixbuf,
303 rx - x, ry - y, rw, rh,
304 coord[0] - x, coord[1] - y,
305 coord[2] - x, coord[3] - y,
306 coord[4] - x, coord[5] - y,
307 pi->color_r, pi->color_g, pi->color_b, pi->color_a);
309 if (pi->border & PAN_BORDER_1)
311 pixbuf_draw_line(pixbuf,
312 rx - x, ry - y, rw, rh,
313 coord[0] - x, coord[1] - y,
314 coord[2] - x, coord[3] - y,
315 pi->color2_r, pi->color2_g, pi->color2_b, pi->color2_a);
317 if (pi->border & PAN_BORDER_2)
319 pixbuf_draw_line(pixbuf,
320 rx - x, ry - y, rw, rh,
321 coord[2] - x, coord[3] - y,
322 coord[4] - x, coord[5] - y,
323 pi->color2_r, pi->color2_g, pi->color2_b, pi->color2_a);
325 if (pi->border & PAN_BORDER_3)
327 pixbuf_draw_line(pixbuf,
328 rx - x, ry - y, rw, rh,
329 coord[4] - x, coord[5] - y,
330 coord[0] - x, coord[1] - y,
331 pi->color2_r, pi->color2_g, pi->color2_b, pi->color2_a);
340 *-----------------------------------------------------------------------------
342 *-----------------------------------------------------------------------------
345 static PangoLayout *pan_item_text_layout(PanItem *pi, GtkWidget *widget)
349 layout = gtk_widget_create_pango_layout(widget, NULL);
351 if (pi->text_attr & PAN_TEXT_ATTR_MARKUP)
353 pango_layout_set_markup(layout, pi->text, -1);
357 if (pi->text_attr & PAN_TEXT_ATTR_BOLD ||
358 pi->text_attr & PAN_TEXT_ATTR_HEADING)
363 pal = pango_attr_list_new();
364 if (pi->text_attr & PAN_TEXT_ATTR_BOLD)
366 pa = pango_attr_weight_new(PANGO_WEIGHT_BOLD);
368 pa->end_index = G_MAXINT;
369 pango_attr_list_insert(pal, pa);
371 if (pi->text_attr & PAN_TEXT_ATTR_HEADING)
373 pa = pango_attr_scale_new(PANGO_SCALE_LARGE);
375 pa->end_index = G_MAXINT;
376 pango_attr_list_insert(pal, pa);
378 pango_layout_set_attributes(layout, pal);
379 pango_attr_list_unref(pal);
382 pango_layout_set_text(layout, pi->text, -1);
386 static void pan_item_text_compute_size(PanItem *pi, GtkWidget *widget)
390 if (!pi || !pi->text || !widget) return;
392 layout = pan_item_text_layout(pi, widget);
393 pango_layout_get_pixel_size(layout, &pi->width, &pi->height);
394 g_object_unref(G_OBJECT(layout));
396 pi->width += pi->border * 2;
397 pi->height += pi->border * 2;
400 PanItem *pan_item_text_new(PanWindow *pw, gint x, gint y, const gchar *text,
401 PanTextAttrType attr, PanBorderType border,
402 guint8 r, guint8 g, guint8 b, guint8 a)
406 pi = g_new0(PanItem, 1);
407 pi->type = PAN_ITEM_TEXT;
410 pi->text = g_strdup(text);
411 pi->text_attr = attr;
420 pan_item_text_compute_size(pi, pw->imd->pr);
422 pw->list = g_list_prepend(pw->list, pi);
427 gint pan_item_text_draw(PanWindow *pw, PanItem *pi, GdkPixbuf *pixbuf, PixbufRenderer *pr,
428 gint x, gint y, gint width, gint height)
432 layout = pan_item_text_layout(pi, (GtkWidget *)pr);
433 pixbuf_draw_layout(pixbuf, layout, (GtkWidget *)pr,
434 pi->x - x + pi->border, pi->y - y + pi->border,
435 pi->color_r, pi->color_g, pi->color_b, pi->color_a);
436 g_object_unref(G_OBJECT(layout));
443 *-----------------------------------------------------------------------------
444 * item thumbnail type
445 *-----------------------------------------------------------------------------
448 PanItem *pan_item_thumb_new(PanWindow *pw, FileData *fd, gint x, gint y)
452 pi = g_new0(PanItem, 1);
454 pi->type = PAN_ITEM_THUMB;
458 pi->width = PAN_THUMB_SIZE + PAN_SHADOW_OFFSET * 2;
459 pi->height = PAN_THUMB_SIZE + PAN_SHADOW_OFFSET * 2;
461 pw->list = g_list_prepend(pw->list, pi);
466 gint pan_item_thumb_draw(PanWindow *pw, PanItem *pi, GdkPixbuf *pixbuf, PixbufRenderer *pr,
467 gint x, gint y, gint width, gint height)
474 tw = gdk_pixbuf_get_width(pi->pixbuf);
475 th = gdk_pixbuf_get_height(pi->pixbuf);
477 tx = pi->x + (pi->width - tw) / 2;
478 ty = pi->y + (pi->height - th) / 2;
480 if (gdk_pixbuf_get_has_alpha(pi->pixbuf))
482 if (util_clip_region(x, y, width, height,
483 tx + PAN_SHADOW_OFFSET, ty + PAN_SHADOW_OFFSET, tw, th,
486 pixbuf_draw_shadow(pixbuf,
487 rx - x, ry - y, rw, rh,
488 tx + PAN_SHADOW_OFFSET - x, ty + PAN_SHADOW_OFFSET - y, tw, th,
490 PAN_SHADOW_COLOR, PAN_SHADOW_ALPHA);
495 if (util_clip_region(x, y, width, height,
496 tx + tw, ty + PAN_SHADOW_OFFSET,
497 PAN_SHADOW_OFFSET, th - PAN_SHADOW_OFFSET,
500 pixbuf_draw_shadow(pixbuf,
501 rx - x, ry - y, rw, rh,
502 tx + PAN_SHADOW_OFFSET - x, ty + PAN_SHADOW_OFFSET - y, tw, th,
504 PAN_SHADOW_COLOR, PAN_SHADOW_ALPHA);
506 if (util_clip_region(x, y, width, height,
507 tx + PAN_SHADOW_OFFSET, ty + th, tw, PAN_SHADOW_OFFSET,
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,
514 PAN_SHADOW_COLOR, PAN_SHADOW_ALPHA);
518 if (util_clip_region(x, y, width, height,
522 gdk_pixbuf_composite(pi->pixbuf, pixbuf, rx - x, ry - y, rw, rh,
525 1.0, 1.0, GDK_INTERP_NEAREST,
529 if (util_clip_region(x, y, width, height,
530 tx, ty, tw, PAN_OUTLINE_THICKNESS,
533 pixbuf_draw_rect_fill(pixbuf,
534 rx - x, ry - y, rw, rh,
535 PAN_OUTLINE_COLOR_1, PAN_OUTLINE_ALPHA);
537 if (util_clip_region(x, y, width, height,
538 tx, ty, PAN_OUTLINE_THICKNESS, th,
541 pixbuf_draw_rect_fill(pixbuf,
542 rx - x, ry - y, rw, rh,
543 PAN_OUTLINE_COLOR_1, PAN_OUTLINE_ALPHA);
545 if (util_clip_region(x, y, width, height,
546 tx + tw - PAN_OUTLINE_THICKNESS, ty + PAN_OUTLINE_THICKNESS,
547 PAN_OUTLINE_THICKNESS, th - PAN_OUTLINE_THICKNESS,
550 pixbuf_draw_rect_fill(pixbuf,
551 rx - x, ry - y, rw, rh,
552 PAN_OUTLINE_COLOR_2, PAN_OUTLINE_ALPHA);
554 if (util_clip_region(x, y, width, height,
555 tx + PAN_OUTLINE_THICKNESS, ty + th - PAN_OUTLINE_THICKNESS,
556 tw - PAN_OUTLINE_THICKNESS * 2, PAN_OUTLINE_THICKNESS,
559 pixbuf_draw_rect_fill(pixbuf,
560 rx - x, ry - y, rw, rh,
561 PAN_OUTLINE_COLOR_2, PAN_OUTLINE_ALPHA);
566 tw = pi->width - PAN_SHADOW_OFFSET * 2;
567 th = pi->height - PAN_SHADOW_OFFSET * 2;
568 tx = pi->x + PAN_SHADOW_OFFSET;
569 ty = pi->y + PAN_SHADOW_OFFSET;
571 if (util_clip_region(x, y, width, height,
577 d = (pw->size <= PAN_IMAGE_SIZE_THUMB_NONE) ? 2 : 8;
578 pixbuf_draw_rect_fill(pixbuf,
579 rx - x, ry - y, rw, rh,
581 PAN_SHADOW_ALPHA / d);
585 return (pi->pixbuf == NULL);
590 *-----------------------------------------------------------------------------
592 *-----------------------------------------------------------------------------
595 static void pan_item_image_find_size(PanWindow *pw, PanItem *pi, gint w, gint h)
604 work = pw->cache_list;
612 if (pc->cd && pc->cd->dimensions &&
613 pc->fd && pc->fd == pi->fd)
615 pi->width = MAX(1, pc->cd->width * pw->image_size / 100);
616 pi->height = MAX(1, pc->cd->height * pw->image_size / 100);
618 pw->cache_list = g_list_remove(pw->cache_list, pc);
619 cache_sim_data_free(pc->cd);
620 file_data_unref(pc->fd);
627 PanItem *pan_item_image_new(PanWindow *pw, FileData *fd, gint x, gint y, gint w, gint h)
631 pi = g_new0(PanItem, 1);
632 pi->type = PAN_ITEM_IMAGE;
642 pi->color2_a = PAN_SHADOW_ALPHA / 2;
644 pan_item_image_find_size(pw, pi, w, h);
646 pw->list = g_list_prepend(pw->list, pi);
651 gint pan_item_image_draw(PanWindow *pw, PanItem *pi, GdkPixbuf *pixbuf, PixbufRenderer *pr,
652 gint x, gint y, gint width, gint height)
656 if (util_clip_region(x, y, width, height,
657 pi->x, pi->y, pi->width, pi->height,
662 gdk_pixbuf_composite(pi->pixbuf, pixbuf, rx - x, ry - y, rw, rh,
665 1.0, 1.0, GDK_INTERP_NEAREST,
670 pixbuf_draw_rect_fill(pixbuf,
671 rx - x, ry - y, rw, rh,
672 pi->color2_r, pi->color2_g, pi->color2_b, pi->color2_a);
676 return (pi->pixbuf == NULL);
681 *-----------------------------------------------------------------------------
683 *-----------------------------------------------------------------------------
686 PanItem *pan_item_find_by_key(PanWindow *pw, PanItemType type, const gchar *key)
690 if (!key) return NULL;
692 work = g_list_last(pw->list);
698 if ((pi->type == type || type == PAN_ITEM_NONE) &&
699 pi->key && strcmp(pi->key, key) == 0)
705 work = g_list_last(pw->list_static);
711 if ((pi->type == type || type == PAN_ITEM_NONE) &&
712 pi->key && strcmp(pi->key, key) == 0)
722 /* when ignore_case and partial are TRUE, path should be converted to lower case */
723 static GList *pan_item_find_by_path_l(GList *list, GList *search_list,
724 PanItemType type, const gchar *path,
725 gboolean ignore_case, gboolean partial)
729 work = g_list_last(search_list);
735 if ((pi->type == type || type == PAN_ITEM_NONE) && pi->fd)
737 gboolean match = FALSE;
739 if (path[0] == G_DIR_SEPARATOR)
741 if (pi->fd->path && strcmp(path, pi->fd->path) == 0) match = TRUE;
743 else if (pi->fd->name)
751 haystack = g_utf8_strdown(pi->fd->name, -1);
752 match = (strstr(haystack, path) != NULL);
757 if (strstr(pi->fd->name, path)) match = TRUE;
760 else if (ignore_case)
762 if (g_ascii_strcasecmp(path, pi->fd->name) == 0) match = TRUE;
766 if (strcmp(path, pi->fd->name) == 0) match = TRUE;
770 if (match) list = g_list_prepend(list, pi);
778 /* when ignore_case and partial are TRUE, path should be converted to lower case */
779 GList *pan_item_find_by_path(PanWindow *pw, PanItemType type, const gchar *path,
780 gboolean ignore_case, gboolean partial)
784 if (!path) return NULL;
785 if (partial && path[0] == G_DIR_SEPARATOR) return NULL;
787 list = pan_item_find_by_path_l(list, pw->list_static, type, path, ignore_case, partial);
788 list = pan_item_find_by_path_l(list, pw->list, type, path, ignore_case, partial);
790 return g_list_reverse(list);
793 GList *pan_item_find_by_fd(PanWindow *pw, PanItemType type, FileData *fd,
794 gboolean ignore_case, gboolean partial)
796 if (!fd) return NULL;
797 return pan_item_find_by_path(pw, type, fd->path, ignore_case, partial);
801 static PanItem *pan_item_find_by_coord_l(GList *list, PanItemType type, gint x, gint y, const gchar *key)
811 if ((pi->type == type || type == PAN_ITEM_NONE) &&
812 x >= pi->x && x < pi->x + pi->width &&
813 y >= pi->y && y < pi->y + pi->height &&
814 (!key || (pi->key && strcmp(pi->key, key) == 0)))
824 PanItem *pan_item_find_by_coord(PanWindow *pw, PanItemType type,
825 gint x, gint y, const gchar *key)
829 pi = pan_item_find_by_coord_l(pw->list, type, x, y, key);
832 return pan_item_find_by_coord_l(pw->list_static, type, x, y, key);
837 *-----------------------------------------------------------------------------
839 *-----------------------------------------------------------------------------
842 PanTextAlignment *pan_text_alignment_new(PanWindow *pw, gint x, gint y, const gchar *key)
844 PanTextAlignment *ta;
846 ta = g_new0(PanTextAlignment, 1);
851 ta->key = g_strdup(key);
856 void pan_text_alignment_free(PanTextAlignment *ta)
860 g_list_free(ta->column1);
861 g_list_free(ta->column2);
866 PanItem *pan_text_alignment_add(PanTextAlignment *ta, const gchar *label, const gchar *text)
872 item = pan_item_text_new(ta->pw, ta->x, ta->y, label,
873 PAN_TEXT_ATTR_BOLD, 0,
874 PAN_POPUP_TEXT_COLOR, 255);
875 pan_item_set_key(item, ta->key);
881 ta->column1 = g_list_append(ta->column1, item);
885 item = pan_item_text_new(ta->pw, ta->x, ta->y, text,
886 PAN_TEXT_ATTR_NONE, 0,
887 PAN_POPUP_TEXT_COLOR, 255);
888 pan_item_set_key(item, ta->key);
894 ta->column2 = g_list_append(ta->column2, item);
899 void pan_text_alignment_calc(PanTextAlignment *ta, PanItem *box)
917 if (p && p->width > cw1) cw1 = p->width;
928 if (p && p->width > cw2) cw2 = p->width;
935 while (work1 && work2)
950 pan_item_size_by_item(box, p1, PREF_PAD_BORDER);
955 p2->x = x + cw1 + PREF_PAD_SPACE;
957 pan_item_size_by_item(box, p2, PREF_PAD_BORDER);
958 if (height < p2->height) height = p2->height;
961 if (!p1 && !p2) height = PREF_PAD_GROUP;
966 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */