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_unref(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;
614 if (pc->cd && pc->cd->dimensions &&
615 pc->fd && pc->fd == pi->fd)
617 pi->width = MAX(1, pc->cd->width * pw->image_size / 100);
618 pi->height = MAX(1, pc->cd->height * pw->image_size / 100);
620 pw->cache_list = g_list_remove(pw->cache_list, pc);
621 cache_sim_data_free(pc->cd);
622 file_data_unref(pc->fd);
629 PanItem *pan_item_image_new(PanWindow *pw, FileData *fd, gint x, gint y, gint w, gint h)
633 pi = g_new0(PanItem, 1);
634 pi->type = PAN_ITEM_IMAGE;
644 pi->color2_a = PAN_SHADOW_ALPHA / 2;
646 pan_item_image_find_size(pw, pi, w, h);
648 pw->list = g_list_prepend(pw->list, pi);
653 gint pan_item_image_draw(PanWindow *pw, PanItem *pi, GdkPixbuf *pixbuf, PixbufRenderer *pr,
654 gint x, gint y, gint width, gint height)
658 if (util_clip_region(x, y, width, height,
659 pi->x, pi->y, pi->width, pi->height,
664 gdk_pixbuf_composite(pi->pixbuf, pixbuf, rx - x, ry - y, rw, rh,
667 1.0, 1.0, GDK_INTERP_NEAREST,
672 pixbuf_draw_rect_fill(pixbuf,
673 rx - x, ry - y, rw, rh,
674 pi->color2_r, pi->color2_g, pi->color2_b, pi->color2_a);
678 return (pi->pixbuf == NULL);
683 *-----------------------------------------------------------------------------
685 *-----------------------------------------------------------------------------
688 PanItem *pan_item_find_by_key(PanWindow *pw, PanItemType type, const gchar *key)
692 if (!key) return NULL;
694 work = g_list_last(pw->list);
700 if ((pi->type == type || type == PAN_ITEM_NONE) &&
701 pi->key && strcmp(pi->key, key) == 0)
707 work = g_list_last(pw->list_static);
713 if ((pi->type == type || type == PAN_ITEM_NONE) &&
714 pi->key && strcmp(pi->key, key) == 0)
724 /* when ignore_case and partial are TRUE, path should be converted to lower case */
725 static GList *pan_item_find_by_path_l(GList *list, GList *search_list,
726 PanItemType type, const gchar *path,
727 gint ignore_case, gint partial)
731 work = g_list_last(search_list);
737 if ((pi->type == type || type == PAN_ITEM_NONE) && pi->fd)
743 if (pi->fd->path && strcmp(path, pi->fd->path) == 0) match = TRUE;
745 else if (pi->fd->name)
753 haystack = g_utf8_strdown(pi->fd->name, -1);
754 match = (strstr(haystack, path) != NULL);
759 if (strstr(pi->fd->name, path)) match = TRUE;
762 else if (ignore_case)
764 if (strcasecmp(path, pi->fd->name) == 0) match = TRUE;
768 if (strcmp(path, pi->fd->name) == 0) match = TRUE;
772 if (match) list = g_list_prepend(list, pi);
780 /* when ignore_case and partial are TRUE, path should be converted to lower case */
781 GList *pan_item_find_by_path(PanWindow *pw, PanItemType type, const gchar *path,
782 gint ignore_case, gint partial)
786 if (!path) return NULL;
787 if (partial && path[0] == '/') return NULL;
789 list = pan_item_find_by_path_l(list, pw->list_static, type, path, ignore_case, partial);
790 list = pan_item_find_by_path_l(list, pw->list, type, path, ignore_case, partial);
792 return g_list_reverse(list);
795 static PanItem *pan_item_find_by_coord_l(GList *list, PanItemType type, gint x, gint y, const gchar *key)
805 if ((pi->type == type || type == PAN_ITEM_NONE) &&
806 x >= pi->x && x < pi->x + pi->width &&
807 y >= pi->y && y < pi->y + pi->height &&
808 (!key || (pi->key && strcmp(pi->key, key) == 0)))
818 PanItem *pan_item_find_by_coord(PanWindow *pw, PanItemType type,
819 gint x, gint y, const gchar *key)
823 pi = pan_item_find_by_coord_l(pw->list, type, x, y, key);
826 return pan_item_find_by_coord_l(pw->list_static, type, x, y, key);
831 *-----------------------------------------------------------------------------
833 *-----------------------------------------------------------------------------
836 PanTextAlignment *pan_text_alignment_new(PanWindow *pw, gint x, gint y, const gchar *key)
838 PanTextAlignment *ta;
840 ta = g_new0(PanTextAlignment, 1);
847 ta->key = g_strdup(key);
852 void pan_text_alignment_free(PanTextAlignment *ta)
856 g_list_free(ta->column1);
857 g_list_free(ta->column2);
862 PanItem *pan_text_alignment_add(PanTextAlignment *ta, const gchar *label, const gchar *text)
868 item = pan_item_text_new(ta->pw, ta->x, ta->y, label,
869 PAN_TEXT_ATTR_BOLD, 0,
870 PAN_POPUP_TEXT_COLOR, 255);
871 pan_item_set_key(item, ta->key);
877 ta->column1 = g_list_append(ta->column1, item);
881 item = pan_item_text_new(ta->pw, ta->x, ta->y, text,
882 PAN_TEXT_ATTR_NONE, 0,
883 PAN_POPUP_TEXT_COLOR, 255);
884 pan_item_set_key(item, ta->key);
890 ta->column2 = g_list_append(ta->column2, item);
895 void pan_text_alignment_calc(PanTextAlignment *ta, PanItem *box)
913 if (p && p->width > cw1) cw1 = p->width;
924 if (p && p->width > cw2) cw2 = p->width;
931 while (work1 && work2)
946 pan_item_size_by_item(box, p1, PREF_PAD_BORDER);
951 p2->x = x + cw1 + PREF_PAD_SPACE;
953 pan_item_size_by_item(box, p2, PREF_PAD_BORDER);
954 if (height < p2->height) height = p2->height;
957 if (!p1 && !p2) height = PREF_PAD_GROUP;