updated copyright in source files
[geeqie.git] / src / image-overlay.c
index 2053442..51b5e39 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Geeqie
  * (C) 2006 John Ellis
+ * Copyright (C) 2008 The Geeqie Team
  *
  * Author: John Ellis
  *
@@ -9,7 +10,7 @@
  * This software comes with no warranty of any kind, use at your own risk!
  */
 
-#include "gqview.h"
+#include "main.h"
 #include "image-overlay.h"
 
 #include "collect.h"
@@ -20,6 +21,7 @@
 #include "layout.h"
 #include "pixbuf-renderer.h"
 #include "pixbuf_util.h"
+#include "histogram.h"
 
 
 /*
@@ -73,6 +75,58 @@ static OSDIcon osd_icons[] = {
 
 #define IMAGE_OSD_DEFAULT_DURATION 30
 
+#define HISTOGRAM_HEIGHT 140
+
+void set_default_image_overlay_template_string(ConfOptions *options)
+{
+       if (options->image_overlay.common.template_string) g_free(options->image_overlay.common.template_string);
+       options->image_overlay.common.template_string = g_strdup(DEFAULT_OVERLAY_INFO);
+}
+
+/*
+ *----------------------------------------------------------------------------
+ * image histogram
+ *----------------------------------------------------------------------------
+ */
+
+
+#define HIST_PREPARE(imd, lw)                          \
+       LayoutWindow *lw = NULL;                        \
+       if (imd)                                        \
+              lw = layout_find_by_image(imd);
+
+void image_osd_histogram_onoff_toggle(ImageWindow *imd, gint x)
+{
+       HIST_PREPARE(imd, lw)
+       if (lw)
+               {
+               lw->histogram_enabled = !!(x);
+               if (lw->histogram_enabled && !lw->histogram)
+                       lw->histogram = histogram_new();
+               }
+}
+
+gint image_osd_histogram_onoff_status(ImageWindow *imd)
+{
+       HIST_PREPARE(imd, lw)
+       return lw ?  lw->histogram_enabled : FALSE;
+}
+
+void image_osd_histogram_chan_toggle(ImageWindow *imd)
+{
+       HIST_PREPARE(imd, lw)
+       if (lw && lw->histogram)
+              histogram_set_channel(lw->histogram, (histogram_get_channel(lw->histogram) +1)%HCHAN_COUNT);
+}
+
+void image_osd_histogram_log_toggle(ImageWindow *imd)
+{
+       HIST_PREPARE(imd,lw)
+       if (lw && lw->histogram)
+              histogram_set_mode(lw->histogram, !histogram_get_mode(lw->histogram));
+}
+
+
 
 static void image_osd_timer_schedule(OverlayStateData *osd);
 
@@ -83,16 +137,25 @@ static gchar *image_osd_mkinfo(const gchar *str, ImageWindow *imd, GHashTable *v
        gint pos, prev;
        gint last;
        gchar *name, *data;
-       GString *new = g_string_new(str);
+       GString *new;
        gchar *ret;
        ExifData *exif;
 
-       exif = exif_read_fd(imd->image_fd, FALSE);
+       if (!str || !*str) return g_strdup("");
+
+       new = g_string_new(str);
+
+       exif = exif_read_fd(imd->image_fd);
        prev = 0;
        last = FALSE;
 
        while (TRUE)
                {
+               gint was_digit = 0;
+               gint limit = 0;
+               gchar *trunc = NULL;
+               gchar *p;
+
                start = strchr(new->str, delim);
                if (!start)
                        break;
@@ -100,11 +163,31 @@ static gchar *image_osd_mkinfo(const gchar *str, ImageWindow *imd, GHashTable *v
                if (!end)
                        break;
 
-               name = g_strndup(start+1, end-start-1);
+               for (p = end; p > start; p--)
+                       {
+                       if (*p == ':' && was_digit)
+                               {
+                               trunc = p;
+                               break;
+                               }
+                       was_digit = g_ascii_isdigit(*p);
+                       }
+
+               if (trunc) limit = atoi(trunc+1);
+
+               name = g_strndup(start+1, ((limit > 0) ? trunc : end)-start-1);
+
                pos = start-new->str;
                data = g_strdup(g_hash_table_lookup(vars, name));
+               if (data && strcmp(name, "zoom") == 0) imd->overlay_show_zoom = TRUE;
                if (!data && exif)
                        data = exif_get_data_as_text(exif, name);
+               if (data && *data && limit > 0 && strlen(data) > limit + 3)
+                       {
+                       gchar *new_data = g_strdup_printf("%-*.*s...", limit, limit, data);
+                       g_free(data);
+                       data = new_data;
+                       }
 
                g_string_erase(new, pos, end-start+1);
                if (data)
@@ -124,7 +207,7 @@ static gchar *image_osd_mkinfo(const gchar *str, ImageWindow *imd, GHashTable *v
                g_free(name);
                g_free(data);
                }
-       
+
        /* search and destroy empty lines */
        end = new->str;
        while ((start = strchr(end, '\n')))
@@ -145,19 +228,21 @@ static gchar *image_osd_mkinfo(const gchar *str, ImageWindow *imd, GHashTable *v
 
 static GdkPixbuf *image_osd_info_render(ImageWindow *imd)
 {
-       GdkPixbuf *pixbuf;
+       GdkPixbuf *pixbuf = NULL;
        gint width, height;
        PangoLayout *layout;
        const gchar *name;
        gchar *name_escaped;
-       gchar *text, *text2;
+       gchar *text;
        gchar *size;
        gint n, t;
        CollectionData *cd;
        CollectInfo *info;
+       GdkPixbuf *imgpixbuf = NULL;
+       LayoutWindow *lw = NULL;
+       gint with_hist = 0;
        gchar *ct;
-       int i;
-       gint w, h;
+       gint w, h;
        GHashTable *vars;
 
        vars = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
@@ -185,8 +270,6 @@ static GdkPixbuf *image_osd_info_render(ImageWindow *imd)
                }
        else
                {
-               LayoutWindow *lw;
-
                lw = layout_find_by_image(imd);
                if (lw)
                        {
@@ -227,31 +310,40 @@ static GdkPixbuf *image_osd_info_render(ImageWindow *imd)
                        {
                        w = gdk_pixbuf_get_width(imd->il->pixbuf);
                        h = gdk_pixbuf_get_height(imd->il->pixbuf);
+                       imgpixbuf = imd->il->pixbuf;
                        }
                else
                        {
                        pixbuf_renderer_get_image_size(PIXBUF_RENDERER(imd->pr), &w, &h);
+                       imgpixbuf = (PIXBUF_RENDERER(imd->pr))->pixbuf;
                        }
+               if (!lw)
+                       lw = layout_find_by_image(imd);
+
+               if (imgpixbuf && lw && lw->histogram && lw->histogram_enabled
+                             && (!imd->il || imd->il->done))
+                       with_hist=1;
 
                g_hash_table_insert(vars, "width", g_strdup_printf("%d", w));
                g_hash_table_insert(vars, "height", g_strdup_printf("%d", h));
                g_hash_table_insert(vars, "res", g_strdup_printf("%d × %d", w, h));
                }
-  
+
        g_hash_table_insert(vars, "collection", g_strdup(ct));
        g_hash_table_insert(vars, "number", g_strdup_printf("%d", n));
        g_hash_table_insert(vars, "total", g_strdup_printf("%d", t));
        g_hash_table_insert(vars, "name", g_strdup(name_escaped));
        g_hash_table_insert(vars, "date", g_strdup(text_from_time(imd->mtime)));
        g_hash_table_insert(vars, "size", g_strdup(size));
-  
+       g_hash_table_insert(vars, "zoom", image_zoom_get_as_text(imd));
+
        if (!name_escaped)
                {
                text = g_strdup_printf(_("Untitled"));
                }
        else
                {
-               text = image_osd_mkinfo(fullscreen_info, imd, vars);
+               text = image_osd_mkinfo(options->image_overlay.common.template_string, imd, vars);
                }
 
        g_free(size);
@@ -260,39 +352,88 @@ static GdkPixbuf *image_osd_info_render(ImageWindow *imd)
        g_hash_table_destroy(vars);
 
        {
-       GString *buf = g_string_sized_new(FILEDATA_MARKS_SIZE * 2);
        FileData *fd = image_get_fd(imd);
-        
-       for (i=0; i < FILEDATA_MARKS_SIZE; i++) 
+
+       if (fd) /* fd may be null after file deletion */
                {
-                       
-               g_string_append_printf(buf, fd->marks[i] ? " <span background='#FF00FF'>%c</span>" : " %c", '1' + i);
-               }
-       text2 = g_strdup_printf("%s\n%s", text, buf->str);
+               gint active_marks = 0;
+               gint mark;
+               gchar *text2;
+
+               for (mark = 0; mark < FILEDATA_MARKS_SIZE; mark++)
+                       {
+                       active_marks += fd->marks[mark];
+                       }
+
+
+               if (active_marks > 0)
+                       {
+                       GString *buf = g_string_sized_new(FILEDATA_MARKS_SIZE * 2);
+
+                       for (mark = 0; mark < FILEDATA_MARKS_SIZE; mark++)
+                               {
+                               g_string_append_printf(buf, fd->marks[mark] ? " <span background='#FF00FF'>%c</span>" : " %c", '1' + mark);
+                               }
+
+                       if (*text)
+                               text2 = g_strdup_printf("%s\n%s", text, buf->str);
+                       else
+                               text2 = g_strdup(buf->str);
+                       g_string_free(buf, TRUE);
+                       g_free(text);
+                       text = text2;
+                       }
+
+               if (with_hist)
+                       {
+                       if (*text)
+                               text2 = g_strdup_printf("%s\n%s", text, histogram_label(lw->histogram));
+                       else
+                               text2 = g_strdup(histogram_label(lw->histogram));
+                       g_free(text);
+                       text = text2;
+                       }
+               }
        }
-        
+
        layout = gtk_widget_create_pango_layout(imd->pr, NULL);
-       pango_layout_set_markup(layout, text2, -1);
-       g_free(text2);
+       pango_layout_set_markup(layout, text, -1);
        g_free(text);
-    
-       pango_layout_get_pixel_size(layout, &width, &height);
 
-       width += 10;
-       height += 10;
-
-       /* TODO: make osd color configurable --Zas */
-       pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, width, height);
-       pixbuf_set_rect_fill(pixbuf, 3, 3, width-6, height-6, 240, 240, 240, 210);
-       pixbuf_set_rect(pixbuf, 0, 0, width, height, 240, 240, 240, 80, 1, 1, 1, 1);
-       pixbuf_set_rect(pixbuf, 1, 1, width-2, height-2, 240, 240, 240, 130, 1, 1, 1, 1);
-       pixbuf_set_rect(pixbuf, 2, 2, width-4, height-4, 240, 240, 240, 180, 1, 1, 1, 1);
-       pixbuf_pixel_set(pixbuf, 0, 0, 0, 0, 0, 0);
-       pixbuf_pixel_set(pixbuf, width - 1, 0, 0, 0, 0, 0);
-       pixbuf_pixel_set(pixbuf, 0, height - 1, 0, 0, 0, 0);
-       pixbuf_pixel_set(pixbuf, width - 1, height - 1, 0, 0, 0, 0);
+       pango_layout_get_pixel_size(layout, &width, &height);
+       /* with empty text width is set to 0, but not height) */
+       if (width == 0)
+               height = 0;
+       else if (height == 0)
+               width = 0;
+       if (width > 0) width += 10;
+       if (height > 0) height += 10;
+
+       if (with_hist)
+               {
+               histogram_read(lw->histogram, imgpixbuf);
+               if (width < 266) width = 266;
+               height += HISTOGRAM_HEIGHT + 5;
+               }
 
-       pixbuf_draw_layout(pixbuf, layout, imd->pr, 5, 5, 0, 0, 0, 255);
+       if (width > 0 && height > 0)
+               {
+               /* TODO: make osd color configurable --Zas */
+               pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, width, height);
+               pixbuf_set_rect_fill(pixbuf, 3, 3, width-6, height-6, 240, 240, 240, 210);
+               pixbuf_set_rect(pixbuf, 0, 0, width, height, 240, 240, 240, 80, 1, 1, 1, 1);
+               pixbuf_set_rect(pixbuf, 1, 1, width-2, height-2, 240, 240, 240, 130, 1, 1, 1, 1);
+               pixbuf_set_rect(pixbuf, 2, 2, width-4, height-4, 240, 240, 240, 180, 1, 1, 1, 1);
+               pixbuf_pixel_set(pixbuf, 0, 0, 0, 0, 0, 0);
+               pixbuf_pixel_set(pixbuf, width - 1, 0, 0, 0, 0, 0);
+               pixbuf_pixel_set(pixbuf, 0, height - 1, 0, 0, 0, 0);
+               pixbuf_pixel_set(pixbuf, width - 1, height - 1, 0, 0, 0, 0);
+
+               if (with_hist)
+                       histogram_draw(lw->histogram, pixbuf, 5, height - HISTOGRAM_HEIGHT - 5 , width - 10, HISTOGRAM_HEIGHT);
+
+               pixbuf_draw_layout(pixbuf, layout, imd->pr, 5, 5, 0, 0, 0, 255);
+       }
 
        g_object_unref(G_OBJECT(layout));
 
@@ -387,6 +528,8 @@ static gint image_osd_update_cb(gpointer data)
 {
        OverlayStateData *osd = data;
 
+       osd->imd->overlay_show_zoom = FALSE;
+
        if (osd->show_info)
                {
                if (osd->changed_states & IMAGE_STATE_IMAGE)
@@ -394,16 +537,24 @@ static gint image_osd_update_cb(gpointer data)
                        GdkPixbuf *pixbuf;
 
                        pixbuf = image_osd_info_render(osd->imd);
-                       if (osd->ovl_info == 0)
+                       if (pixbuf)
                                {
-                               osd->ovl_info = image_overlay_add(osd->imd, pixbuf,
-                                                                 OSD_INFO_X, OSD_INFO_Y, TRUE, FALSE);
+                               if (osd->ovl_info == 0)
+                                       {
+                                       osd->ovl_info = image_overlay_add(osd->imd, pixbuf,
+                                                                         OSD_INFO_X, OSD_INFO_Y, TRUE, FALSE);
+                                       }
+                               else
+                                       {
+                                       image_overlay_set(osd->imd, osd->ovl_info, pixbuf, OSD_INFO_X, OSD_INFO_Y);
+                                       }
+                               g_object_unref(pixbuf);
                                }
-                       else
+                       else if (osd->ovl_info)
                                {
-                               image_overlay_set(osd->imd, osd->ovl_info, pixbuf, OSD_INFO_X, OSD_INFO_Y);
+                               image_overlay_remove(osd->imd, osd->ovl_info);
+                               osd->ovl_info = 0;
                                }
-                       g_object_unref(pixbuf);
                        }
                }
        else
@@ -469,7 +620,8 @@ static gint image_osd_update_cb(gpointer data)
                        }
                }
 
-       osd->changed_states = IMAGE_STATE_NONE;
+       if (osd->imd->il && osd->imd->il->done)
+               osd->changed_states = IMAGE_STATE_NONE;
        osd->idle_id = -1;
        return FALSE;
 }