comparison src/pan-item.c @ 105:de64a683d5d0

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