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