Display pixel coordinates and rgb - patch by Ruben Stein
authorVladimir Nadvornik <nadvornik@suse.cz>
Wed, 4 Mar 2009 18:53:47 +0000 (18:53 +0000)
committerVladimir Nadvornik <nadvornik@suse.cz>
Wed, 4 Mar 2009 18:53:47 +0000 (18:53 +0000)
src/layout.c
src/layout.h
src/layout_image.c
src/layout_util.c
src/options.c
src/pixbuf-renderer.c
src/pixbuf-renderer.h
src/typedefs.h

index 3e3fadf..7ea5155 100644 (file)
@@ -51,6 +51,7 @@
 #define TOOLWINDOW_DEF_HEIGHT 450
 
 #define PROGRESS_WIDTH 150
+#define PIXEL_LABEL_WIDTH 130
 #define ZOOM_LABEL_WIDTH 64
 
 #define PANE_DIVIDER_SIZE 10
@@ -705,6 +706,8 @@ void layout_status_update_image(LayoutWindow *lw)
                                               width, height, b);
                        }
 
+               g_signal_emit_by_name (lw->image->pr, "update-pixel");
+               
                g_free(b);
                
                gtk_label_set_text(GTK_LABEL(lw->info_details), text);
@@ -805,6 +808,8 @@ static void layout_status_setup(LayoutWindow *lw, GtkWidget *box, gint small_for
        lw->info_details = layout_status_label(NULL, hbox, TRUE, 0, TRUE);
        if (!small_format) gtk_box_pack_start(GTK_BOX(hbox), lw->info_color, FALSE, FALSE, 0);
        if (!small_format) gtk_box_pack_start(GTK_BOX(hbox), lw->info_write, FALSE, FALSE, 0);
+       lw->info_pixel = layout_status_label(NULL, hbox, FALSE, PIXEL_LABEL_WIDTH, TRUE);
+       if (lw->options.info_pixel_hidden) gtk_widget_hide(gtk_widget_get_parent(lw->info_pixel));
        lw->info_zoom = layout_status_label(NULL, hbox, FALSE, ZOOM_LABEL_WIDTH, FALSE);
 }
 
@@ -1742,6 +1747,7 @@ void layout_style_set(LayoutWindow *lw, gint style, const gchar *order)
        lw->info_color = NULL;
        lw->info_status = NULL;
        lw->info_details = NULL;
+       lw->info_pixel = NULL;
        lw->info_zoom = NULL;
 
        if (lw->ui_manager) g_object_unref(lw->ui_manager);
@@ -1900,6 +1906,33 @@ gint layout_toolbar_hidden(LayoutWindow *lw)
        return lw->options.toolbar_hidden;
 }
 
+void layout_info_pixel_toggle(LayoutWindow *lw)
+{
+       GtkWidget *frame;
+       
+       if (!layout_valid(&lw)) return;
+       if (!lw->info_pixel) return;
+
+       lw->options.info_pixel_hidden = !lw->options.info_pixel_hidden;
+
+       frame = gtk_widget_get_parent(lw->info_pixel);
+       if (lw->options.info_pixel_hidden)
+               {
+               if (GTK_WIDGET_VISIBLE(frame)) gtk_widget_hide(frame);
+               }
+       else
+               {
+               if (!GTK_WIDGET_VISIBLE(frame)) gtk_widget_show(frame);
+               }
+}
+
+gint layout_info_pixel_hidden(LayoutWindow *lw)
+{
+       if (!layout_valid(&lw)) return TRUE;
+
+       return lw->options.info_pixel_hidden;
+}
+
 /*
  *-----------------------------------------------------------------------------
  * base
@@ -2164,7 +2197,8 @@ void layout_write_attributes(LayoutOptions *layout, GString *outstr, gint indent
        WRITE_SEPARATOR();
 
        WRITE_BOOL(*layout, toolbar_hidden);
-       
+       WRITE_BOOL(*layout, info_pixel_hidden);
+
        WRITE_UINT(*layout, image_overlay.state);
        WRITE_INT(*layout, image_overlay.histogram_channel);
        WRITE_INT(*layout, image_overlay.histogram_mode);
@@ -2231,6 +2265,7 @@ void layout_load_attributes(LayoutOptions *layout, const gchar **attribute_names
                if (READ_BOOL(*layout, tools_hidden)) continue;
                if (READ_BOOL(*layout, tools_restore_state)) continue;
                if (READ_BOOL(*layout, toolbar_hidden)) continue;
+               if (READ_BOOL(*layout, info_pixel_hidden)) continue;
 
                if (READ_UINT(*layout, image_overlay.state)) continue;
                if (READ_INT(*layout, image_overlay.histogram_channel)) continue;
index 1ce668d..0344662 100644 (file)
@@ -101,6 +101,8 @@ void layout_tools_hide_toggle(LayoutWindow *lw);
 
 void layout_toolbar_toggle(LayoutWindow *lw);
 gint layout_toolbar_hidden(LayoutWindow *lw);
+void layout_info_pixel_toggle(LayoutWindow *lw);
+gint layout_info_pixel_hidden(LayoutWindow *lw);
 
 void layout_split_change(LayoutWindow *lw, ImageSplitMode mode);
 
index caedd22..bc190f8 100644 (file)
@@ -26,6 +26,7 @@
 #include "menu.h"
 #include "misc.h"
 #include "pixbuf_util.h"
+#include "pixbuf-renderer.h"
 #include "slideshow.h"
 #include "ui_fileops.h"
 #include "ui_menu.h"
@@ -1481,6 +1482,46 @@ static void layout_image_set_buttons_inactive(LayoutWindow *lw, gint i)
        image_set_scroll_func(lw->split_images[i], layout_image_scroll_cb, lw);
 }
 
+
+void layout_status_update_pixel_cb(PixbufRenderer *pr, gpointer data)
+{
+       LayoutWindow *lw = data;
+       gchar *text;
+       
+       if (!data || !layout_valid(&lw) || !lw->image || lw->options.info_pixel_hidden) return;
+
+       if (!lw->image->unknown)
+               {
+               gint x_pixel, y_pixel;
+               
+               pixbuf_renderer_get_mouse_position(pr, &x_pixel, &y_pixel);
+               
+               if(x_pixel > 0 && y_pixel > 0)
+                       {
+                       gint r_mouse, g_mouse, b_mouse;
+                       gint width, height, slen_width, slen_height;
+                       gchar str_temp[10];
+
+                       pixbuf_renderer_get_pixel_colors(pr, x_pixel, y_pixel,
+                                                        &r_mouse, &g_mouse, &b_mouse);                 
+                       pixbuf_renderer_get_image_size(pr, &width, &height);
+                       slen_width = sprintf(str_temp, "%d", width - 1);
+                       slen_height = sprintf(str_temp, "%d", height - 1);
+                       
+                       text = g_strdup_printf(_("<tt>pos(%*d,%*d) rgb(%3d,%3d,%3d)</tt>"), 
+                                                slen_width, x_pixel, slen_height, y_pixel,
+                                                r_mouse, g_mouse, b_mouse);
+                       }
+               else
+                       {
+                       text = g_strdup("");
+                       }
+               gtk_label_set_markup(GTK_LABEL(lw->info_pixel), text);
+               g_free(text);
+               }
+}
+
+
 /*
  *----------------------------------------------------------------------------
  * setup
@@ -1506,6 +1547,10 @@ GtkWidget *layout_image_new(LayoutWindow *lw, gint i)
 #else
                gtk_widget_ref(lw->split_images[i]->widget);
 #endif
+
+               g_signal_connect(G_OBJECT(lw->split_images[i]->pr), "update-pixel",
+                                G_CALLBACK(layout_status_update_pixel_cb), lw);
+
                image_background_set_color(lw->split_images[i], options->image.use_custom_border_color ? &options->image.border_color : NULL);
 
                image_auto_refresh_enable(lw->split_images[i], TRUE);
index fa163a5..6eee3ad 100644 (file)
@@ -666,6 +666,16 @@ static void layout_menu_toolbar_cb(GtkToggleAction *action, gpointer data)
        layout_toolbar_toggle(lw);
 }
 
+static void layout_menu_info_pixel_cb(GtkToggleAction *action, gpointer data)
+{
+       LayoutWindow *lw = data;
+
+       if (lw->options.info_pixel_hidden == gtk_toggle_action_get_active(action)) return;
+
+       layout_exit_fullscreen(lw);
+       layout_info_pixel_toggle(lw);
+}
+
 /* NOTE: these callbacks are called also from layout_util_sync_views */
 static void layout_menu_bar_cb(GtkToggleAction *action, gpointer data)
 {
@@ -1260,6 +1270,7 @@ static GtkToggleActionEntry menu_toggle_entries[] = {
   { "ShowMarks",        NULL,          N_("Show _Marks"),      "M",            NULL,   CB(layout_menu_marks_cb),        FALSE  },
   { "FloatTools",      PIXBUF_INLINE_ICON_FLOAT,               N_("_Float file list"), "L",            NULL,   CB(layout_menu_float_cb),        FALSE  },
   { "HideToolbar",     NULL,           N_("Hide tool_bar"),    NULL,           NULL,   CB(layout_menu_toolbar_cb),      FALSE  },
+  { "HideInfoPixel",   NULL,           N_("Hide Pi_xel Info"), NULL,           NULL,   CB(layout_menu_info_pixel_cb),   FALSE  },
   { "SBar",            NULL,           N_("_Info"),            "<control>K",   NULL,   CB(layout_menu_bar_cb),          FALSE  },
   { "ExifWin",         NULL,           N_("E_xif window"),     "<control>E",   NULL,   CB(layout_menu_bar_exif_cb),     FALSE  },
   { "SBarSort",                NULL,           N_("Sort _manager"),    "<control>S",   NULL,   CB(layout_menu_bar_sort_cb),     FALSE  },
@@ -1418,6 +1429,7 @@ static const gchar *menu_ui_description =
 "      <menuitem action='FloatTools'/>"
 "      <menuitem action='HideTools'/>"
 "      <menuitem action='HideToolbar'/>"
+"      <menuitem action='HideInfoPixel'/>"
 "      <placeholder name='ToolsSection'/>"
 "      <separator/>"
 "      <menuitem action='SBar'/>"
@@ -1852,6 +1864,9 @@ static void layout_util_sync_views(LayoutWindow *lw)
 
        action = gtk_action_group_get_action(lw->action_group, "HideToolbar");
        gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.toolbar_hidden);
+       
+       action = gtk_action_group_get_action(lw->action_group, "HideInfoPixel");
+       gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.info_pixel_hidden);
 
        action = gtk_action_group_get_action(lw->action_group, "ShowMarks");
        gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.show_marks);
index e8e30dd..029bfc0 100644 (file)
@@ -105,6 +105,7 @@ ConfOptions *init_options(ConfOptions *options)
        options->layout.show_marks = FALSE;
        options->layout.show_thumbnails = FALSE;
        options->layout.style = 0;
+       options->layout.info_pixel_hidden = TRUE;
        options->layout.toolbar_hidden = FALSE;
        options->layout.tools_float = FALSE;
        options->layout.tools_hidden = FALSE;
index ad65d95..668c045 100644 (file)
 #include <string.h>
 #include <math.h>
 
+#include "main.h"
 #include "pixbuf-renderer.h"
+
 #include "intl.h"
+#include "layout.h"
 
 #include <gtk/gtk.h>
 
@@ -151,6 +154,7 @@ enum {
        SIGNAL_SCROLL_NOTIFY,
        SIGNAL_RENDER_COMPLETE,
        SIGNAL_DRAG,
+       SIGNAL_UPDATE_PIXEL,
        SIGNAL_COUNT
 };
 
@@ -475,6 +479,15 @@ static void pixbuf_renderer_class_init(PixbufRendererClass *class)
                             g_cclosure_marshal_VOID__BOXED,
                             G_TYPE_NONE, 1,
                             GDK_TYPE_EVENT);
+                            
+       signals[SIGNAL_UPDATE_PIXEL] =
+               g_signal_new("update-pixel",
+                            G_OBJECT_CLASS_TYPE(gobject_class),
+                            G_SIGNAL_RUN_LAST,
+                            G_STRUCT_OFFSET(PixbufRendererClass, update_pixel),
+                            NULL, NULL,
+                            g_cclosure_marshal_VOID__VOID,
+                            G_TYPE_NONE, 0);
 }
 
 static void pixbuf_renderer_init(PixbufRenderer *pr)
@@ -507,6 +520,9 @@ static void pixbuf_renderer_init(PixbufRenderer *pr)
 
        pr->scroller_id = -1;
        pr->scroller_overlay = -1;
+       
+       pr->x_mouse = -1;
+       pr->y_mouse = -1;
 
        pr->source_tiles_enabled = FALSE;
        pr->source_tiles = NULL;
@@ -3129,6 +3145,11 @@ static void pr_drag_signal(PixbufRenderer *pr, GdkEventButton *bevent)
        g_signal_emit(pr, signals[SIGNAL_DRAG], 0, bevent);
 }
 
+static void pr_update_pixel_signal(PixbufRenderer *pr)
+{
+       g_signal_emit(pr, signals[SIGNAL_UPDATE_PIXEL], 0);
+}
+
 /*
  *-------------------------------------------------------------------
  * sync and clamp
@@ -3672,7 +3693,6 @@ void pixbuf_renderer_set_scroll_center(PixbufRenderer *pr, gdouble x, gdouble y)
        pixbuf_renderer_scroll(pr, (gint)dst_x, (gint)dst_y);
 }
 
-
 /*
  *-------------------------------------------------------------------
  * mouse
@@ -3691,7 +3711,11 @@ static gint pr_mouse_motion_cb(GtkWidget *widget, GdkEventButton *bevent, gpoint
                pr->scroller_xpos = bevent->x;
                pr->scroller_ypos = bevent->y;
                }
-
+       
+       pr->x_mouse = bevent->x;
+       pr->y_mouse = bevent->y;
+       pr_update_pixel_signal(pr);
+       
        if (!pr->in_drag || !gdk_pointer_is_grabbed()) return FALSE;
 
        if (pr->drag_moved < PR_DRAG_SCROLL_THRESHHOLD)
@@ -3980,6 +4004,8 @@ void pixbuf_renderer_move(PixbufRenderer *pr, PixbufRenderer *source)
 
        pr->x_scroll = source->x_scroll;
        pr->y_scroll = source->y_scroll;
+       pr->x_mouse  = source->x_mouse;
+       pr->y_mouse  = source->y_mouse;
 
        scroll_reset = pr->scroll_reset;
        pr->scroll_reset = PR_SCROLL_RESET_NOCHANGE;
@@ -4110,6 +4136,82 @@ void pixbuf_renderer_zoom_set_limits(PixbufRenderer *pr, gdouble min, gdouble ma
                }
 }
 
+gint pixbuf_renderer_get_pixel_colors(PixbufRenderer *pr, gint x_pixel, gint y_pixel, 
+                                      gint *r_mouse, gint *g_mouse, gint *b_mouse)
+{
+       GdkPixbuf *pb = pr->pixbuf;
+       gint p_alpha, prs;
+       guchar *p_pix, *pp;
+       gint map_x, map_y, map_w, map_h;
+       
+       g_return_val_if_fail(IS_PIXBUF_RENDERER(pr), FALSE);
+       g_return_val_if_fail(r_mouse != NULL && g_mouse != NULL && b_mouse != NULL, FALSE);
+
+       if (!pr->pixbuf && !pr->source_tiles_enabled)
+               {
+               *r_mouse = -1;
+               *g_mouse = -1;
+               *b_mouse = -1;
+               return FALSE;
+               }
+       
+       if (!pb) return FALSE;
+
+       pr_tile_region_map_orientation(pr,
+                                       x_pixel, y_pixel,
+                                       pr->image_width, pr->image_height,
+                                       1, 1, /*single pixel */
+                                       &map_x, &map_y,
+                                       &map_w, &map_h);
+
+       if (map_x < 0 || map_x > gdk_pixbuf_get_width(pr->pixbuf) - 1) return  FALSE;
+       if (map_y < 0 || map_y > gdk_pixbuf_get_height(pr->pixbuf) - 1) return  FALSE;
+       
+       p_alpha = gdk_pixbuf_get_has_alpha(pb);
+       prs = gdk_pixbuf_get_rowstride(pb);
+       p_pix = gdk_pixbuf_get_pixels(pb);
+
+       pp = p_pix + map_y * prs + (map_x * (p_alpha ? 4 : 3));
+       *r_mouse = *pp;
+       pp++;
+       *g_mouse = *pp;
+       pp++;
+       *b_mouse = *pp;
+       
+       return TRUE;
+}
+
+gint pixbuf_renderer_get_mouse_position(PixbufRenderer *pr, gint *x_pixel_return, gint *y_pixel_return)
+{
+       gint x_pixel, y_pixel, x_pixel_clamped, y_pixel_clamped;
+            
+       g_return_val_if_fail(IS_PIXBUF_RENDERER(pr), FALSE);
+       g_return_val_if_fail(x_pixel_return != NULL && y_pixel_return != NULL, FALSE);
+
+       if (!pr->pixbuf && !pr->source_tiles_enabled)
+               {
+               *x_pixel_return = -1;
+               *y_pixel_return = -1;
+               return FALSE;
+               }
+       
+       x_pixel = (gint)((gdouble)(pr->x_mouse - pr->x_offset + pr->x_scroll) / pr->scale);
+       y_pixel = (gint)((gdouble)(pr->y_mouse - pr->y_offset + pr->y_scroll) / pr->scale);
+       x_pixel_clamped = CLAMP(x_pixel, 0, pr->image_width - 1);
+       y_pixel_clamped = CLAMP(y_pixel, 0, pr->image_height - 1);
+       
+       if(x_pixel != x_pixel_clamped || y_pixel != y_pixel_clamped)
+               {
+               /* mouse is not on pr */
+               x_pixel = y_pixel = -1;
+               }
+
+       *x_pixel_return = x_pixel;
+       *y_pixel_return = y_pixel;
+       
+       return TRUE;
+}
+
 gint pixbuf_renderer_get_image_size(PixbufRenderer *pr, gint *width, gint *height)
 {
        g_return_val_if_fail(IS_PIXBUF_RENDERER(pr), FALSE);
index ad484a2..6fc84ee 100644 (file)
@@ -58,6 +58,9 @@ struct _PixbufRenderer
 
        gint x_offset;          /* offset of image start (non-zero when image < window) */
        gint y_offset;
+       
+       gint x_mouse; /* coordinates of the mouse taken from GtkEvent */
+       gint y_mouse;
 
        gint vis_width;         /* dimensions of visible part of image */
        gint vis_height;
@@ -163,6 +166,7 @@ struct _PixbufRendererClass
        void (*zoom)(PixbufRenderer *pr, gdouble zoom);
        void (*clicked)(PixbufRenderer *pr, GdkEventButton *event);
        void (*scroll_notify)(PixbufRenderer *pr);
+       void (*update_pixel)(PixbufRenderer *pr);
 
        void (*render_complete)(PixbufRenderer *pr);
        void (*drag)(PixbufRenderer *pr, GdkEventButton *event);
@@ -258,6 +262,10 @@ void pixbuf_renderer_overlay_set(PixbufRenderer *pr, gint id, GdkPixbuf *pixbuf,
 gint pixbuf_renderer_overlay_get(PixbufRenderer *pr, gint id, GdkPixbuf **pixbuf, gint *x, gint *y);
 void pixbuf_renderer_overlay_remove(PixbufRenderer *pr, gint id);
 
+gint pixbuf_renderer_get_mouse_position(PixbufRenderer *pr, gint *x_pixel, gint *y_pixel);
+/* x_pixel and y_pixel are the pixel coordinates \see pixbuf_renderer_get_mouse_position */
+gint pixbuf_renderer_get_pixel_colors(PixbufRenderer *pr, gint x_pixel, gint y_pixel,
+                                                                                                                                                       gint *r_mouse, gint *g_mouse, gint *b_mouse);
 
 #endif
 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */
index 06a26f5..bc05f85 100644 (file)
@@ -532,7 +532,8 @@ struct _LayoutOptions
        gboolean tools_restore_state;
 
        gboolean toolbar_hidden;
-       
+       gboolean info_pixel_hidden;
+
        gchar *home_path;
 };
 
@@ -625,7 +626,8 @@ struct _LayoutWindow
        GtkWidget *info_details;
        GtkWidget *info_zoom;
        GtkWidget *info_write;
-
+       GtkWidget *info_pixel;
+       
        /* slide show */
 
        SlideShowData *slideshow;