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!
14 #include "pan-types.h"
18 *-----------------------------------------------------------------------------
20 *-----------------------------------------------------------------------------
23 void pan_item_free(PanItem *pi)
27 if (pi->pixbuf) g_object_unref(pi->pixbuf);
28 if (pi->fd) file_data_free(pi->fd);
36 void pan_item_set_key(PanItem *pi, const gchar *key)
43 pi->key = g_strdup(key);
47 void pan_item_added(PanWindow *pw, PanItem *pi)
50 image_area_changed(pw->imd, pi->x, pi->y, pi->width, pi->height);
53 void pan_item_remove(PanWindow *pw, PanItem *pi)
57 if (pw->click_pi == pi) pw->click_pi = NULL;
58 if (pw->queue_pi == pi) pw->queue_pi = NULL;
59 if (pw->search_pi == pi) pw->search_pi = NULL;
60 pw->queue = g_list_remove(pw->queue, pi);
62 pw->list = g_list_remove(pw->list, pi);
63 image_area_changed(pw->imd, pi->x, pi->y, pi->width, pi->height);
67 void pan_item_size_by_item(PanItem *pi, PanItem *child, gint border)
69 if (!pi || !child) return;
71 if (pi->x + pi->width < child->x + child->width + border)
72 pi->width = child->x + child->width + border - pi->x;
74 if (pi->y + pi->height < child->y + child->height + border)
75 pi->height = child->y + child->height + border - pi->y;
78 void pan_item_size_coordinates(PanItem *pi, gint border, gint *w, gint *h)
82 if (*w < pi->x + pi->width + border) *w = pi->x + pi->width + border;
83 if (*h < pi->y + pi->height + border) *h = pi->y + pi->height + border;
88 *-----------------------------------------------------------------------------
90 *-----------------------------------------------------------------------------
93 PanItem *pan_item_box_new(PanWindow *pw, FileData *fd, gint x, gint y, gint width, gint height,
95 guint8 base_r, guint8 base_g, guint8 base_b, guint8 base_a,
96 guint8 bord_r, guint8 bord_g, guint8 bord_b, guint8 bord_a)
100 pi = g_new0(PanItem, 1);
101 pi->type = PAN_ITEM_BOX;
108 pi->color_r = base_r;
109 pi->color_g = base_g;
110 pi->color_b = base_b;
111 pi->color_a = base_a;
113 pi->color2_r = bord_r;
114 pi->color2_g = bord_g;
115 pi->color2_b = bord_b;
116 pi->color2_a = bord_a;
117 pi->border = border_size;
119 pw->list = g_list_prepend(pw->list, pi);
124 void pan_item_box_shadow(PanItem *pi, gint offset, gint fade)
128 if (!pi || pi->type != PAN_ITEM_BOX) return;
133 pi->width -= shadow[0];
134 pi->height -= shadow[0];
137 shadow = g_new0(gint, 2);
142 pi->height += offset;
148 gint pan_item_box_draw(PanWindow *pw, PanItem *pi, GdkPixbuf *pixbuf, PixbufRenderer *pr,
149 gint x, gint y, gint width, gint height)
164 if (pi->color_a > 254)
166 pixbuf_draw_shadow(pixbuf, pi->x - x + bw, pi->y - y + shadow[0],
167 shadow[0], bh - shadow[0],
168 pi->x - x + shadow[0], pi->y - y + shadow[0], bw, bh,
170 PAN_SHADOW_COLOR, PAN_SHADOW_ALPHA);
171 pixbuf_draw_shadow(pixbuf, pi->x - x + shadow[0], pi->y - y + bh,
173 pi->x - x + shadow[0], pi->y - y + shadow[0], bw, bh,
175 PAN_SHADOW_COLOR, PAN_SHADOW_ALPHA);
180 a = pi->color_a * PAN_SHADOW_ALPHA >> 8;
181 pixbuf_draw_shadow(pixbuf, pi->x - x + shadow[0], pi->y - y + shadow[0],
183 pi->x - x + shadow[0], pi->y - y + shadow[0], bw, bh,
185 PAN_SHADOW_COLOR, a);
189 if (util_clip_region(x, y, width, height,
190 pi->x, pi->y, bw, bh,
193 pixbuf_draw_rect_fill(pixbuf,
194 rx - x, ry - y, rw, rh,
195 pi->color_r, pi->color_g, pi->color_b, pi->color_a);
197 if (util_clip_region(x, y, width, height,
198 pi->x, pi->y, bw, pi->border,
201 pixbuf_draw_rect_fill(pixbuf,
202 rx - x, ry - y, rw, rh,
203 pi->color2_r, pi->color2_g, pi->color2_b, pi->color2_a);
205 if (util_clip_region(x, y, width, height,
206 pi->x, pi->y + pi->border, pi->border, bh - pi->border * 2,
209 pixbuf_draw_rect_fill(pixbuf,
210 rx - x, ry - y, rw, rh,
211 pi->color2_r, pi->color2_g, pi->color2_b, pi->color2_a);
213 if (util_clip_region(x, y, width, height,
214 pi->x + bw - pi->border, pi->y + pi->border,
215 pi->border, bh - pi->border * 2,
218 pixbuf_draw_rect_fill(pixbuf,
219 rx - x, ry - y, rw, rh,
220 pi->color2_r, pi->color2_g, pi->color2_b, pi->color2_a);
222 if (util_clip_region(x, y, width, height,
223 pi->x, pi->y + bh - pi->border,
227 pixbuf_draw_rect_fill(pixbuf,
228 rx - x, ry - y, rw, rh,
229 pi->color2_r, pi->color2_g, pi->color2_b, pi->color2_a);
237 *-----------------------------------------------------------------------------
239 *-----------------------------------------------------------------------------
242 PanItem *pan_item_tri_new(PanWindow *pw, FileData *fd, gint x, gint y, gint width, gint height,
243 gint x1, gint y1, gint x2, gint y2, gint x3, gint y3,
244 guint8 r, guint8 g, guint8 b, guint8 a)
249 pi = g_new0(PanItem, 1);
250 pi->type = PAN_ITEM_TRIANGLE;
261 coord = g_new0(gint, 6);
271 pi->border = PAN_BORDER_NONE;
273 pw->list = g_list_prepend(pw->list, pi);
278 void pan_item_tri_border(PanItem *pi, gint borders,
279 guint8 r, guint8 g, guint8 b, guint8 a)
281 if (!pi || pi->type != PAN_ITEM_TRIANGLE) return;
283 pi->border = borders;
291 gint pan_item_tri_draw(PanWindow *pw, PanItem *pi, GdkPixbuf *pixbuf, PixbufRenderer *pr,
292 gint x, gint y, gint width, gint height)
296 if (util_clip_region(x, y, width, height,
297 pi->x, pi->y, pi->width, pi->height,
298 &rx, &ry, &rw, &rh) && pi->data)
300 gint *coord = pi->data;
301 pixbuf_draw_triangle(pixbuf,
302 rx - x, ry - y, rw, rh,
303 coord[0] - x, coord[1] - y,
304 coord[2] - x, coord[3] - y,
305 coord[4] - x, coord[5] - y,
306 pi->color_r, pi->color_g, pi->color_b, pi->color_a);
308 if (pi->border & PAN_BORDER_1)
310 pixbuf_draw_line(pixbuf,
311 rx - x, ry - y, rw, rh,
312 coord[0] - x, coord[1] - y,
313 coord[2] - x, coord[3] - y,
314 pi->color2_r, pi->color2_g, pi->color2_b, pi->color2_a);
316 if (pi->border & PAN_BORDER_2)
318 pixbuf_draw_line(pixbuf,
319 rx - x, ry - y, rw, rh,
320 coord[2] - x, coord[3] - y,
321 coord[4] - x, coord[5] - y,
322 pi->color2_r, pi->color2_g, pi->color2_b, pi->color2_a);
324 if (pi->border & PAN_BORDER_3)
326 pixbuf_draw_line(pixbuf,
327 rx - x, ry - y, rw, rh,
328 coord[4] - x, coord[5] - y,
329 coord[0] - x, coord[1] - y,
330 pi->color2_r, pi->color2_g, pi->color2_b, pi->color2_a);
339 *-----------------------------------------------------------------------------
341 *-----------------------------------------------------------------------------
344 static PangoLayout *pan_item_text_layout(PanItem *pi, GtkWidget *widget)
348 layout = gtk_widget_create_pango_layout(widget, NULL);
350 if (pi->text_attr & PAN_TEXT_ATTR_MARKUP)
352 pango_layout_set_markup(layout, pi->text, -1);
356 if (pi->text_attr & PAN_TEXT_ATTR_BOLD ||
357 pi->text_attr & PAN_TEXT_ATTR_HEADING)
362 pal = pango_attr_list_new();
363 if (pi->text_attr & PAN_TEXT_ATTR_BOLD)
365 pa = pango_attr_weight_new(PANGO_WEIGHT_BOLD);
367 pa->end_index = G_MAXINT;
368 pango_attr_list_insert(pal, pa);
370 if (pi->text_attr & PAN_TEXT_ATTR_HEADING)
372 pa = pango_attr_scale_new(PANGO_SCALE_LARGE);
374 pa->end_index = G_MAXINT;
375 pango_attr_list_insert(pal, pa);
377 pango_layout_set_attributes(layout, pal);
378 pango_attr_list_unref(pal);
381 pango_layout_set_text(layout, pi->text, -1);
385 static void pan_item_text_compute_size(PanItem *pi, GtkWidget *widget)
389 if (!pi || !pi->text || !widget) return;
391 layout = pan_item_text_layout(pi, widget);
392 pango_layout_get_pixel_size(layout, &pi->width, &pi->height);
393 g_object_unref(G_OBJECT(layout));
395 pi->width += pi->border * 2;
396 pi->height += pi->border * 2;
399 PanItem *pan_item_text_new(PanWindow *pw, gint x, gint y, const gchar *text,
400 PanTextAttrType attr, PanBorderType border,
401 guint8 r, guint8 g, guint8 b, guint8 a)
405 pi = g_new0(PanItem, 1);
406 pi->type = PAN_ITEM_TEXT;
409 pi->text = g_strdup(text);
410 pi->text_attr = attr;
419 pan_item_text_compute_size(pi, pw->imd->pr);
421 pw->list = g_list_prepend(pw->list, pi);
426 gint pan_item_text_draw(PanWindow *pw, PanItem *pi, GdkPixbuf *pixbuf, PixbufRenderer *pr,
427 gint x, gint y, gint width, gint height)
431 layout = pan_item_text_layout(pi, (GtkWidget *)pr);
432 pixbuf_draw_layout(pixbuf, layout, (GtkWidget *)pr,
433 pi->x - x + pi->border, pi->y - y + pi->border,
434 pi->color_r, pi->color_g, pi->color_b, pi->color_a);
435 g_object_unref(G_OBJECT(layout));
442 *-----------------------------------------------------------------------------
443 * item thumbnail type
444 *-----------------------------------------------------------------------------
447 PanItem *pan_item_thumb_new(PanWindow *pw, FileData *fd, gint x, gint y)
451 pi = g_new0(PanItem, 1);
452 pi->type = PAN_ITEM_THUMB;
456 pi->width = PAN_THUMB_SIZE + PAN_SHADOW_OFFSET * 2;
457 pi->height = PAN_THUMB_SIZE + PAN_SHADOW_OFFSET * 2;
463 pw->list = g_list_prepend(pw->list, pi);
468 gint pan_item_thumb_draw(PanWindow *pw, PanItem *pi, GdkPixbuf *pixbuf, PixbufRenderer *pr,
469 gint x, gint y, gint width, gint height)
476 tw = gdk_pixbuf_get_width(pi->pixbuf);
477 th = gdk_pixbuf_get_height(pi->pixbuf);
479 tx = pi->x + (pi->width - tw) / 2;
480 ty = pi->y + (pi->height - th) / 2;
482 if (gdk_pixbuf_get_has_alpha(pi->pixbuf))
484 if (util_clip_region(x, y, width, height,
485 tx + PAN_SHADOW_OFFSET, ty + PAN_SHADOW_OFFSET, tw, th,
488 pixbuf_draw_shadow(pixbuf,
489 rx - x, ry - y, rw, rh,
490 tx + PAN_SHADOW_OFFSET - x, ty + PAN_SHADOW_OFFSET - y, tw, th,
492 PAN_SHADOW_COLOR, PAN_SHADOW_ALPHA);
497 if (util_clip_region(x, y, width, height,
498 tx + tw, ty + PAN_SHADOW_OFFSET,
499 PAN_SHADOW_OFFSET, th - PAN_SHADOW_OFFSET,
502 pixbuf_draw_shadow(pixbuf,
503 rx - x, ry - y, rw, rh,
504 tx + PAN_SHADOW_OFFSET - x, ty + PAN_SHADOW_OFFSET - y, tw, th,
506 PAN_SHADOW_COLOR, PAN_SHADOW_ALPHA);
508 if (util_clip_region(x, y, width, height,
509 tx + PAN_SHADOW_OFFSET, ty + th, tw, PAN_SHADOW_OFFSET,
512 pixbuf_draw_shadow(pixbuf,
513 rx - x, ry - y, rw, rh,
514 tx + PAN_SHADOW_OFFSET - x, ty + PAN_SHADOW_OFFSET - y, tw, th,
516 PAN_SHADOW_COLOR, PAN_SHADOW_ALPHA);
520 if (util_clip_region(x, y, width, height,
524 gdk_pixbuf_composite(pi->pixbuf, pixbuf, rx - x, ry - y, rw, rh,
527 1.0, 1.0, GDK_INTERP_NEAREST,
531 if (util_clip_region(x, y, width, height,
532 tx, ty, tw, PAN_OUTLINE_THICKNESS,
535 pixbuf_draw_rect_fill(pixbuf,
536 rx - x, ry - y, rw, rh,
537 PAN_OUTLINE_COLOR_1, PAN_OUTLINE_ALPHA);
539 if (util_clip_region(x, y, width, height,
540 tx, ty, PAN_OUTLINE_THICKNESS, th,
543 pixbuf_draw_rect_fill(pixbuf,
544 rx - x, ry - y, rw, rh,
545 PAN_OUTLINE_COLOR_1, PAN_OUTLINE_ALPHA);
547 if (util_clip_region(x, y, width, height,
548 tx + tw - PAN_OUTLINE_THICKNESS, ty + PAN_OUTLINE_THICKNESS,
549 PAN_OUTLINE_THICKNESS, th - PAN_OUTLINE_THICKNESS,
552 pixbuf_draw_rect_fill(pixbuf,
553 rx - x, ry - y, rw, rh,
554 PAN_OUTLINE_COLOR_2, PAN_OUTLINE_ALPHA);
556 if (util_clip_region(x, y, width, height,
557 tx + PAN_OUTLINE_THICKNESS, ty + th - PAN_OUTLINE_THICKNESS,
558 tw - PAN_OUTLINE_THICKNESS * 2, PAN_OUTLINE_THICKNESS,
561 pixbuf_draw_rect_fill(pixbuf,
562 rx - x, ry - y, rw, rh,
563 PAN_OUTLINE_COLOR_2, PAN_OUTLINE_ALPHA);
568 tw = pi->width - PAN_SHADOW_OFFSET * 2;
569 th = pi->height - PAN_SHADOW_OFFSET * 2;
570 tx = pi->x + PAN_SHADOW_OFFSET;
571 ty = pi->y + PAN_SHADOW_OFFSET;
573 if (util_clip_region(x, y, width, height,
579 d = (pw->size <= PAN_IMAGE_SIZE_THUMB_NONE) ? 2 : 8;
580 pixbuf_draw_rect_fill(pixbuf,
581 rx - x, ry - y, rw, rh,
583 PAN_SHADOW_ALPHA / d);
587 return (pi->pixbuf == NULL);
592 *-----------------------------------------------------------------------------
594 *-----------------------------------------------------------------------------
597 static void pan_item_image_find_size(PanWindow *pw, PanItem *pi, gint w, gint h)
606 work = pw->cache_list;
615 path = ((FileData *)pc)->path;
617 if (pc->cd && pc->cd->dimensions &&
618 path && strcmp(path, pi->fd->path) == 0)
620 pi->width = MAX(1, pc->cd->width * pw->image_size / 100);
621 pi->height = MAX(1, pc->cd->height * pw->image_size / 100);
623 pw->cache_list = g_list_remove(pw->cache_list, pc);
624 cache_sim_data_free(pc->cd);
625 file_data_free((FileData *)pc);
631 PanItem *pan_item_image_new(PanWindow *pw, FileData *fd, gint x, gint y, gint w, gint h)
635 pi = g_new0(PanItem, 1);
636 pi->type = PAN_ITEM_IMAGE;
646 pi->color2_a = PAN_SHADOW_ALPHA / 2;
648 pan_item_image_find_size(pw, pi, w, h);
650 pw->list = g_list_prepend(pw->list, pi);
655 gint pan_item_image_draw(PanWindow *pw, PanItem *pi, GdkPixbuf *pixbuf, PixbufRenderer *pr,
656 gint x, gint y, gint width, gint height)
660 if (util_clip_region(x, y, width, height,
661 pi->x, pi->y, pi->width, pi->height,
666 gdk_pixbuf_composite(pi->pixbuf, pixbuf, rx - x, ry - y, rw, rh,
669 1.0, 1.0, GDK_INTERP_NEAREST,
674 pixbuf_draw_rect_fill(pixbuf,
675 rx - x, ry - y, rw, rh,
676 pi->color2_r, pi->color2_g, pi->color2_b, pi->color2_a);
680 return (pi->pixbuf == NULL);
685 *-----------------------------------------------------------------------------
687 *-----------------------------------------------------------------------------
690 PanItem *pan_item_find_by_key(PanWindow *pw, PanItemType type, const gchar *key)
694 if (!key) return NULL;
696 work = g_list_last(pw->list);
702 if ((pi->type == type || type == PAN_ITEM_NONE) &&
703 pi->key && strcmp(pi->key, key) == 0)
709 work = g_list_last(pw->list_static);
715 if ((pi->type == type || type == PAN_ITEM_NONE) &&
716 pi->key && strcmp(pi->key, key) == 0)
726 /* when ignore_case and partial are TRUE, path should be converted to lower case */
727 static GList *pan_item_find_by_path_l(GList *list, GList *search_list,
728 PanItemType type, const gchar *path,
729 gint ignore_case, gint partial)
733 work = g_list_last(search_list);
739 if ((pi->type == type || type == PAN_ITEM_NONE) && pi->fd)
745 if (pi->fd->path && strcmp(path, pi->fd->path) == 0) match = TRUE;
747 else if (pi->fd->name)
755 haystack = g_utf8_strdown(pi->fd->name, -1);
756 match = (strstr(haystack, path) != NULL);
761 if (strstr(pi->fd->name, path)) match = TRUE;
764 else if (ignore_case)
766 if (strcasecmp(path, pi->fd->name) == 0) match = TRUE;
770 if (strcmp(path, pi->fd->name) == 0) match = TRUE;
774 if (match) list = g_list_prepend(list, pi);
782 /* when ignore_case and partial are TRUE, path should be converted to lower case */
783 GList *pan_item_find_by_path(PanWindow *pw, PanItemType type, const gchar *path,
784 gint ignore_case, gint partial)
788 if (!path) return NULL;
789 if (partial && path[0] == '/') return NULL;
791 list = pan_item_find_by_path_l(list, pw->list_static, type, path, ignore_case, partial);
792 list = pan_item_find_by_path_l(list, pw->list, type, path, ignore_case, partial);
794 return g_list_reverse(list);
797 static PanItem *pan_item_find_by_coord_l(GList *list, PanItemType type, gint x, gint y, const gchar *key)
807 if ((pi->type == type || type == PAN_ITEM_NONE) &&
808 x >= pi->x && x < pi->x + pi->width &&
809 y >= pi->y && y < pi->y + pi->height &&
810 (!key || (pi->key && strcmp(pi->key, key) == 0)))
820 PanItem *pan_item_find_by_coord(PanWindow *pw, PanItemType type,
821 gint x, gint y, const gchar *key)
825 pi = pan_item_find_by_coord_l(pw->list, type, x, y, key);
828 return pan_item_find_by_coord_l(pw->list_static, type, x, y, key);
833 *-----------------------------------------------------------------------------
835 *-----------------------------------------------------------------------------
838 PanTextAlignment *pan_text_alignment_new(PanWindow *pw, gint x, gint y, const gchar *key)
840 PanTextAlignment *ta;
842 ta = g_new0(PanTextAlignment, 1);
849 ta->key = g_strdup(key);
854 void pan_text_alignment_free(PanTextAlignment *ta)
858 g_list_free(ta->column1);
859 g_list_free(ta->column2);
864 PanItem *pan_text_alignment_add(PanTextAlignment *ta, const gchar *label, const gchar *text)
870 item = pan_item_text_new(ta->pw, ta->x, ta->y, label,
871 PAN_TEXT_ATTR_BOLD, 0,
872 PAN_POPUP_TEXT_COLOR, 255);
873 pan_item_set_key(item, ta->key);
879 ta->column1 = g_list_append(ta->column1, item);
883 item = pan_item_text_new(ta->pw, ta->x, ta->y, text,
884 PAN_TEXT_ATTR_NONE, 0,
885 PAN_POPUP_TEXT_COLOR, 255);
886 pan_item_set_key(item, ta->key);
892 ta->column2 = g_list_append(ta->column2, item);
897 void pan_text_alignment_calc(PanTextAlignment *ta, PanItem *box)
915 if (p && p->width > cw1) cw1 = p->width;
926 if (p && p->width > cw2) cw2 = p->width;
933 while (work1 && work2)
948 pan_item_size_by_item(box, p1, PREF_PAD_BORDER);
953 p2->x = x + cw1 + PREF_PAD_SPACE;
955 pan_item_size_by_item(box, p2, PREF_PAD_BORDER);
956 if (height < p2->height) height = p2->height;
959 if (!p1 && !p2) height = PREF_PAD_GROUP;