##### Note: GQview CVS on sourceforge is not always up to date, please use #####
[geeqie.git] / src / image-overlay.c
1 /*
2  * GQview
3  * (C) 2004 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 #include "gqview.h"
13 #include "image-overlay.h"
14
15 #include "collect.h"
16 #include "filelist.h"
17 #include "image.h"
18 #include "img-view.h"
19 #include "layout.h"
20 #include "pixbuf-renderer.h"
21 #include "pixbuf_util.h"
22
23
24 /*
25  *----------------------------------------------------------------------------
26  * image overlay
27  *----------------------------------------------------------------------------
28  */
29
30 typedef struct _OverlayUpdate OverlayUpdate;
31 struct _OverlayUpdate {
32         ImageWindow *imd;
33         gint id;
34         gint idle_id;
35         gulong destroy_id;
36 };
37
38 #define IMAGE_OVERLAY_UPDATE_KEY "image-overlay-update"
39
40 #define IMAGE_OVERLAY_X 10
41 #define IMAGE_OVERLAY_Y -10
42
43
44 static GdkPixbuf *image_overlay_info_render(ImageWindow *imd)
45 {
46         GdkPixbuf *pixbuf;
47         gint width, height;
48         PangoLayout *layout;
49         const gchar *name;
50         gchar *name_escaped;
51         gchar *text;
52         gchar *size;
53         gint n, t;
54         CollectionData *cd;
55         CollectInfo *info;
56         gchar *ct;
57
58         name = image_get_name(imd);
59         if (name)
60                 {
61                 name_escaped = g_markup_escape_text(name, -1);
62                 }
63         else
64                 {
65                 name_escaped = NULL;
66                 }
67
68         cd = image_get_collection(imd, &info);
69         if (cd)
70                 {
71                 gchar *buf;
72
73                 t = g_list_length(cd->list);
74                 n = g_list_index(cd->list, info) + 1;
75                 buf = g_markup_escape_text((cd->name) ? cd->name : _("Untitled"), -1);
76                 ct = g_strdup_printf("<i>%s</i>\n", buf);
77                 g_free(buf);
78                 }
79         else
80                 {
81                 LayoutWindow *lw;
82
83                 lw = layout_find_by_image(imd);
84                 if (lw)
85                         {
86                         if (lw->slideshow)
87                                 {
88                                 n = g_list_length(lw->slideshow->list_done);
89                                 t = n + g_list_length(lw->slideshow->list);
90                                 }
91                         else
92                                 {
93                                 t = layout_list_count(lw, NULL);
94                                 n = layout_list_get_index(lw, image_get_path(lw->image)) + 1;
95                                 }
96                         }
97                 else if (view_window_find_image(imd, &n, &t))
98                         {
99                         n++;
100                         }
101                 else
102                         {
103                         t = 1;
104                         n = 1;
105                         }
106
107                 if (n < 1) n = 1;
108                 if (t < 1) t = 1;
109
110                 ct = g_strdup("");
111                 }
112
113         size = text_from_size_abrev(imd->size);
114         if (!name_escaped)
115                 {
116                 text = g_strdup_printf(_("Untitled"));
117                 }
118         else if (imd->unknown)
119                 {
120                 text = g_strdup_printf("%s(%d/%d) <b>%s</b>\n%s - %s", ct,
121                                        n, t, name_escaped,
122                                        text_from_time(imd->mtime), size);
123                 }
124         else
125                 {
126                 gint w, h;
127
128                 if (imd->delay_flip &&
129                     imd->il && imd->il->pixbuf &&
130                     image_get_pixbuf(imd) != imd->il->pixbuf)
131                         {
132                         w = gdk_pixbuf_get_width(imd->il->pixbuf);
133                         h = gdk_pixbuf_get_height(imd->il->pixbuf);
134                         }
135                 else
136                         {
137                         pixbuf_renderer_get_image_size(PIXBUF_RENDERER(imd->pr), &w, &h);
138                         }
139
140                 text = g_strdup_printf("%s(%d/%d) <b>%s</b>\n%d x %d - %s - %s", ct,
141                                        n, t, name_escaped,
142                                        w, h,
143                                        text_from_time(imd->mtime), size);
144                 }
145         g_free(size);
146         g_free(ct);
147         g_free(name_escaped);
148
149         layout = gtk_widget_create_pango_layout(imd->pr, NULL);
150         pango_layout_set_markup(layout, text, -1);
151         g_free(text);
152
153         pango_layout_get_pixel_size(layout, &width, &height);
154
155         width += 10;
156         height += 10;
157
158         pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, width, height);
159         pixbuf_set_rect_fill(pixbuf, 3, 3, width-6, height-6, 240, 240, 240, 210);
160         pixbuf_set_rect(pixbuf, 0, 0, width, height, 240, 240, 240, 80, 1, 1, 1, 1);
161         pixbuf_set_rect(pixbuf, 1, 1, width-2, height-2, 240, 240, 240, 130, 1, 1, 1, 1);
162         pixbuf_set_rect(pixbuf, 2, 2, width-4, height-4, 240, 240, 240, 180, 1, 1, 1, 1);
163         pixbuf_pixel_set(pixbuf, 0, 0, 0, 0, 0, 0);
164         pixbuf_pixel_set(pixbuf, width - 1, 0, 0, 0, 0, 0);
165         pixbuf_pixel_set(pixbuf, 0, height - 1, 0, 0, 0, 0);
166         pixbuf_pixel_set(pixbuf, width - 1, height - 1, 0, 0, 0, 0);
167
168         pixbuf_draw_layout(pixbuf, layout, imd->pr, 5, 5, 0, 0, 0, 255);
169
170         g_object_unref(G_OBJECT(layout));
171
172         return pixbuf;
173 }
174
175 static void image_overlay_update_destroy_cb(GtkWidget *widget, gpointer data)
176 {
177         OverlayUpdate *ou = data;
178
179         g_source_remove(ou->idle_id);
180         g_free(ou);
181 }
182
183 static gint image_overlay_update_cb(gpointer data)
184 {
185         OverlayUpdate *ou = data;
186         GdkPixbuf *pixbuf;
187
188         pixbuf = image_overlay_info_render(ou->imd);
189         image_overlay_set(ou->imd, ou->id, pixbuf, IMAGE_OVERLAY_X, IMAGE_OVERLAY_Y);
190         g_object_unref(pixbuf);
191
192         g_object_set_data(G_OBJECT(ou->imd->pr), IMAGE_OVERLAY_UPDATE_KEY, NULL);
193         g_signal_handler_disconnect(ou->imd->pr, ou->destroy_id);
194         g_free(ou);
195
196         return FALSE;
197 }
198
199 static void image_overlay_update_schedule(ImageWindow *imd, gint id)
200 {
201         OverlayUpdate *ou;
202
203         ou = g_object_get_data(G_OBJECT(imd->pr), IMAGE_OVERLAY_UPDATE_KEY);
204         if (ou) return;
205
206         ou = g_new0(OverlayUpdate, 1);
207         ou->imd = imd;
208         ou->id = id;
209         ou->idle_id = g_idle_add_full(G_PRIORITY_HIGH, image_overlay_update_cb, ou, NULL);
210         ou->destroy_id = g_signal_connect(G_OBJECT(imd->pr), "destroy",
211                                           G_CALLBACK(image_overlay_update_destroy_cb), ou);
212         g_object_set_data(G_OBJECT(imd->pr), IMAGE_OVERLAY_UPDATE_KEY, ou);
213 }
214
215 void image_overlay_update(ImageWindow *imd, gint id)
216 {
217         if (id < 0) return;
218         image_overlay_update_schedule(imd, id);
219 }
220
221 static void image_overlay_upate_cb(ImageWindow *imd, gpointer data)
222 {
223         gint id;
224
225         id = GPOINTER_TO_INT(data);
226         image_overlay_update_schedule(imd, id);
227 }
228
229 gint image_overlay_info_enable(ImageWindow *imd)
230 {
231         gint id;
232         GdkPixbuf *pixbuf;
233
234         pixbuf = image_overlay_info_render(imd);
235         id = image_overlay_add(imd, pixbuf, IMAGE_OVERLAY_X, IMAGE_OVERLAY_Y, TRUE, FALSE);
236         g_object_unref(pixbuf);
237
238         image_set_new_func(imd, image_overlay_upate_cb, GINT_TO_POINTER(id));
239
240         return id;
241 }
242
243 void image_overlay_info_disable(ImageWindow *imd, gint id)
244 {
245         image_set_new_func(imd, NULL, NULL);
246         image_overlay_remove(imd, id);
247 }
248