bc689328b6745e504f1a6e5410d1d8af20452a64
[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_util.h"
21
22
23 /*
24  *----------------------------------------------------------------------------
25  * image overlay
26  *----------------------------------------------------------------------------
27  */
28
29 typedef struct _OverlayUpdate OverlayUpdate;
30 struct _OverlayUpdate {
31         ImageWindow *imd;
32         gint id;
33         gint idle_id;
34         gulong destroy_id;
35 };
36
37 #define IMAGE_OVERLAY_UPDATE_KEY "image-overlay-update"
38
39 #define IMAGE_OVERLAY_X 10
40 #define IMAGE_OVERLAY_Y -10
41
42
43 static GdkPixbuf *image_overlay_info_render(ImageWindow *imd)
44 {
45         GdkPixbuf *pixbuf;
46         gint width, height;
47         PangoLayout *layout;
48         const gchar *name;
49         gchar *name_escaped;
50         gchar *text;
51         gchar *size;
52         gint n, t;
53         CollectionData *cd;
54         CollectInfo *info;
55         gchar *ct;
56
57         name = image_get_name(imd);
58         if (name)
59                 {
60                 name_escaped = g_markup_escape_text(name, -1);
61                 }
62         else
63                 {
64                 name_escaped = NULL;
65                 }
66
67         cd = image_get_collection(imd, &info);
68         if (cd)
69                 {
70                 gchar *buf;
71
72                 t = g_list_length(cd->list);
73                 n = g_list_index(cd->list, info) + 1;
74                 buf = g_markup_escape_text((cd->name) ? cd->name : _("Untitled"), -1);
75                 ct = g_strdup_printf("<i>%s</i>\n", buf);
76                 g_free(buf);
77                 }
78         else
79                 {
80                 LayoutWindow *lw;
81
82                 lw = layout_find_by_image(imd);
83                 if (lw)
84                         {
85                         if (lw->slideshow)
86                                 {
87                                 n = g_list_length(lw->slideshow->list_done);
88                                 t = n + g_list_length(lw->slideshow->list);
89                                 }
90                         else
91                                 {
92                                 t = layout_list_count(lw, NULL);
93                                 n = layout_list_get_index(lw, image_get_path(lw->image)) + 1;
94                                 }
95                         }
96                 else if (view_window_find_image(imd, &n, &t))
97                         {
98                         n++;
99                         }
100                 else
101                         {
102                         t = 1;
103                         n = 1;
104                         }
105
106                 if (n < 1) n = 1;
107                 if (t < 1) t = 1;
108
109                 ct = g_strdup("");
110                 }
111
112         size = text_from_size_abrev(imd->size);
113         if (!name_escaped)
114                 {
115                 text = g_strdup_printf(_("Untitled"));
116                 }
117         else if (imd->unknown)
118                 {
119                 text = g_strdup_printf("%s(%d/%d) <b>%s</b>\n%s - %s", ct,
120                                        n, t, name_escaped,
121                                        text_from_time(imd->mtime), size);
122                 }
123         else
124                 {
125                 gint w, h;
126
127                 if (imd->delay_flip &&
128                     imd->il && imd->il->pixbuf &&
129                     imd->pixbuf != imd->il->pixbuf)
130                         {
131                         w = gdk_pixbuf_get_width(imd->il->pixbuf);
132                         h = gdk_pixbuf_get_height(imd->il->pixbuf);
133                         }
134                 else
135                         {
136                         w = imd->image_width;
137                         h = imd->image_height;
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->image, 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->image, 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->image), IMAGE_OVERLAY_UPDATE_KEY, NULL);
193         g_signal_handler_disconnect(ou->imd->image, 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->image), 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->image), "destroy",
211                                           G_CALLBACK(image_overlay_update_destroy_cb), ou);
212         g_object_set_data(G_OBJECT(imd->image), 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