view src/bar_histogram.c @ 1532:fffb62c7ba1e

Add pgettext for some ambiguous strings There are some strings which are ambiguous to translate. There is the pgettext function to solf that problem. For example, locations can be translated to german by Ortsangaben (geographical) or by Pfad (filesystem). I am sure there are also some ambiguous in other languages.
author mow
date Fri, 10 Apr 2009 09:47:20 +0000
parents 24a12aa0cb54
children 7f91f906f9c2
line wrap: on
line source

/*
 * Geeqie
 * (C) 2004 John Ellis
 * Copyright (C) 2008 - 2009 The Geeqie Team
 *
 * Author: Vladimir Nadvornik
 *
 * This software is released under the GNU General Public License (GNU GPL).
 * Please read the included file COPYING for more information.
 * This software comes with no warranty of any kind, use at your own risk!
 */


#include "main.h"
#include "bar_histogram.h"

#include "bar.h"
#include "metadata.h"
#include "filedata.h"
#include "menu.h"
#include "ui_menu.h"
#include "ui_misc.h"
#include "histogram.h"
#include "rcfile.h"

/*
 *-------------------------------------------------------------------
 * keyword / comment utils
 *-------------------------------------------------------------------
 */



typedef struct _PaneHistogramData PaneHistogramData;
struct _PaneHistogramData
{
	PaneData pane;
	GtkWidget *widget;
	GtkWidget *drawing_area;
	Histogram *histogram;
	gint histogram_width;
	gint histogram_height;
	GdkPixbuf *pixbuf;
	FileData *fd;
	gboolean need_update;
	guint idle_id; /* event source id */
};

static gboolean bar_pane_histogram_update_cb(gpointer data);


static void bar_pane_histogram_update(PaneHistogramData *phd)
{
	if (phd->pixbuf) g_object_unref(phd->pixbuf);
	phd->pixbuf = NULL;

	gtk_label_set_text(GTK_LABEL(phd->pane.title), histogram_label(phd->histogram));

	if (!phd->histogram_width || !phd->histogram_height || !phd->fd) return;

	/* histmap_get is relatively expensive, run it only when we really need it
	   and with lower priority than pixbuf_renderer 
	   FIXME: this does not work for fullscreen*/
	if (GTK_WIDGET_DRAWABLE(phd->drawing_area))
		{
		if (!phd->idle_id)
			{
			phd->idle_id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, bar_pane_histogram_update_cb, phd, NULL);
			}
		}
	else
		{
		phd->need_update = TRUE;
		}
}

static gboolean bar_pane_histogram_update_cb(gpointer data)
{
	const HistMap *histmap;
	PaneHistogramData *phd = data;

	phd->idle_id = 0;
	phd->need_update = FALSE;
	
	gtk_widget_queue_draw_area(GTK_WIDGET(phd->drawing_area), 0, 0, phd->histogram_width, phd->histogram_height);
	
	if (phd->fd == NULL) return FALSE;
	histmap = histmap_get(phd->fd);
	
	if (!histmap) 
		{
		histmap_start_idle(phd->fd);
		return FALSE;
		}
	
	phd->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, phd->histogram_width, phd->histogram_height);
	gdk_pixbuf_fill(phd->pixbuf, 0xffffffff);
	histogram_draw(phd->histogram, histmap, phd->pixbuf, 0, 0, phd->histogram_width, phd->histogram_height);

	return FALSE;
}


static void bar_pane_histogram_set_fd(GtkWidget *pane, FileData *fd)
{
	PaneHistogramData *phd;

	phd = g_object_get_data(G_OBJECT(pane), "pane_data");
	if (!phd) return;

	file_data_unref(phd->fd);
	phd->fd = file_data_ref(fd);

	bar_pane_histogram_update(phd);
}

static void bar_pane_histogram_write_config(GtkWidget *pane, GString *outstr, gint indent)
{
	PaneHistogramData *phd;

	phd = g_object_get_data(G_OBJECT(pane), "pane_data");
	if (!phd) return;

	WRITE_NL(); WRITE_STRING("<pane_histogram ");
	write_char_option(outstr, indent, "id", phd->pane.id);
	write_char_option(outstr, indent, "title", gtk_label_get_text(GTK_LABEL(phd->pane.title)));
	WRITE_BOOL(phd->pane, expanded);
	WRITE_INT(*phd->histogram, histogram_channel);
	WRITE_INT(*phd->histogram, histogram_mode);
	WRITE_STRING("/>");
}

static void bar_pane_histogram_notify_cb(FileData *fd, NotifyType type, gpointer data)
{
	PaneHistogramData *phd = data;
	if ((type & (NOTIFY_REREAD | NOTIFY_CHANGE | NOTIFY_HISTMAP | NOTIFY_PIXBUF)) && fd == phd->fd) 
		{
		DEBUG_1("Notify pane_histogram: %s %04x", fd->path, type);
		bar_pane_histogram_update(phd);
		}
}

static gboolean bar_pane_histogram_expose_event_cb(GtkWidget *widget, GdkEventExpose *event, gpointer data)
{
	PaneHistogramData *phd = data;
	if (!phd) return TRUE;
	
	if (phd->need_update)
		{
		bar_pane_histogram_update(phd);
		}
	
	if (!phd->pixbuf) return TRUE;
	
	gdk_draw_pixbuf(widget->window,
			widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
			phd->pixbuf,
			0, 0,
			0, 0,
			-1, -1,
			GDK_RGB_DITHER_NORMAL, 0, 0);
	return TRUE;
}

static void bar_pane_histogram_size_cb(GtkWidget *widget, GtkAllocation *allocation, gpointer data)
{
	PaneHistogramData *phd = data;

	phd->histogram_width = allocation->width;
	phd->histogram_height = allocation->height;
	bar_pane_histogram_update(phd);
}

static void bar_pane_histogram_close(GtkWidget *pane)
{
	PaneHistogramData *phd;

	phd = g_object_get_data(G_OBJECT(pane), "pane_data");
	if (!phd) return;

	gtk_widget_destroy(phd->widget);
}

static void bar_pane_histogram_destroy(GtkWidget *widget, gpointer data)
{
	PaneHistogramData *phd = data;
	
	if (phd->idle_id) g_source_remove(phd->idle_id);
	file_data_unregister_notify_func(bar_pane_histogram_notify_cb, phd);

	file_data_unref(phd->fd);
	histogram_free(phd->histogram);
	if (phd->pixbuf) g_object_unref(phd->pixbuf);
	g_free(phd->pane.id);

	g_free(phd);
}

static void bar_pane_histogram_popup_channels_cb(GtkWidget *widget, gpointer data)
{
	PaneHistogramData *phd;
	gint channel;

	if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) return;

	phd = submenu_item_get_data(widget);

	if (!phd) return;

	channel = GPOINTER_TO_INT(data);
	if (channel == histogram_get_channel(phd->histogram)) return;

	histogram_set_channel(phd->histogram, channel);
	bar_pane_histogram_update(phd);
}

static void bar_pane_histogram_popup_logmode_cb(GtkWidget *widget, gpointer data)
{
	PaneHistogramData *phd;
	gint logmode;
	
	if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) return;

	phd = submenu_item_get_data(widget);

	if (!phd) return;

	logmode = GPOINTER_TO_INT(data);
	if (logmode == histogram_get_mode(phd->histogram)) return;

	histogram_set_mode(phd->histogram, logmode);
	bar_pane_histogram_update(phd);
}

static GtkWidget *bar_pane_histogram_add_radio(GtkWidget *menu, GtkWidget *parent,
					const gchar *label,
					GCallback func, gint value,
					gboolean show_current, gint current_value)
{
	GtkWidget *item;

	if (show_current)
		{
		item = menu_item_add_radio(menu, parent,
					   label, (value == current_value),
					   func, GINT_TO_POINTER((gint)value));
		}
	else
		{
		item = menu_item_add(menu, label,
				     func, GINT_TO_POINTER((gint)value));
		}

	return item;
}

GtkWidget *bar_pane_histogram_add_channels(GtkWidget *menu, GCallback func, gpointer data,
			    		   gboolean show_current, gint current_value)
{
	GtkWidget *submenu;
	GtkWidget *parent;

	submenu = gtk_menu_new();
	g_object_set_data(G_OBJECT(submenu), "submenu_data", data);

	parent = bar_pane_histogram_add_radio(submenu, NULL, _("_Red"), func, HCHAN_R, show_current, current_value);
	bar_pane_histogram_add_radio(submenu, parent, _("_Green"), func, HCHAN_G, show_current, current_value);
	bar_pane_histogram_add_radio(submenu, parent, _("_Blue"),func, HCHAN_B, show_current, current_value);
	bar_pane_histogram_add_radio(submenu, parent, _("_RGB"),func, HCHAN_RGB, show_current, current_value);
	bar_pane_histogram_add_radio(submenu, parent, _("_Value"),func, HCHAN_MAX, show_current, current_value);

	if (menu)
		{
		GtkWidget *item;

		item = menu_item_add(menu, _("Channels"), NULL, NULL);
		gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
		return item;
		}

	return submenu;
}
GtkWidget *bar_pane_histogram_add_logmode(GtkWidget *menu, GCallback func, gpointer data,
			    		   gboolean show_current, gint current_value)
{
	GtkWidget *submenu;
	GtkWidget *parent;

	submenu = gtk_menu_new();
	g_object_set_data(G_OBJECT(submenu), "submenu_data", data);

	parent = bar_pane_histogram_add_radio(submenu, NULL, _("_Linear"), func, 0, show_current, current_value);
	bar_pane_histogram_add_radio(submenu, parent, _("Lo_garithmical"), func, 1, show_current, current_value);

	if (menu)
		{
		GtkWidget *item;

		item = menu_item_add(menu, _("Mode"), NULL, NULL);
		gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
		return item;
		}

	return submenu;
}


static GtkWidget *bar_pane_histogram_menu(PaneHistogramData *phd)
{
	GtkWidget *menu;
	static gboolean show_current = TRUE;

	menu = popup_menu_short_lived();
	bar_pane_histogram_add_channels(menu, G_CALLBACK(bar_pane_histogram_popup_channels_cb), phd,
					show_current, histogram_get_channel(phd->histogram));
	bar_pane_histogram_add_logmode(menu, G_CALLBACK(bar_pane_histogram_popup_logmode_cb), phd,
				       show_current, histogram_get_mode(phd->histogram));

	return menu;
}

static gboolean bar_pane_histogram_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
{
	PaneHistogramData *phd = data;

	if (bevent->button == MOUSE_BUTTON_RIGHT)
		{
		GtkWidget *menu;

		menu = bar_pane_histogram_menu(phd);
		gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, bevent->button, bevent->time);
		return TRUE;
	}

	return FALSE;
}


static GtkWidget *bar_pane_histogram_new(const gchar *id, const gchar *title, gint height, gboolean expanded, gint histogram_channel, gint histogram_mode)
{
	PaneHistogramData *phd;

	phd = g_new0(PaneHistogramData, 1);
	
	phd->pane.pane_set_fd = bar_pane_histogram_set_fd;
	phd->pane.pane_write_config = bar_pane_histogram_write_config;
	phd->pane.title = bar_pane_expander_title(title);
	phd->pane.id = g_strdup(id);
	phd->pane.type = PANE_HISTOGRAM;

	phd->pane.expanded = expanded;
	
	phd->histogram = histogram_new();

	histogram_set_channel(phd->histogram, histogram_channel);
	histogram_set_mode(phd->histogram, histogram_mode);

	phd->widget = gtk_vbox_new(FALSE, PREF_PAD_GAP);

	g_object_set_data(G_OBJECT(phd->widget), "pane_data", phd);
	g_signal_connect(G_OBJECT(phd->widget), "destroy",
			 G_CALLBACK(bar_pane_histogram_destroy), phd);
	

	gtk_widget_set_size_request(GTK_WIDGET(phd->widget), -1, height);

	phd->drawing_area = gtk_drawing_area_new();
	g_signal_connect_after(G_OBJECT(phd->drawing_area), "size_allocate",
                               G_CALLBACK(bar_pane_histogram_size_cb), phd);

	g_signal_connect(G_OBJECT(phd->drawing_area), "expose_event",  
			 G_CALLBACK(bar_pane_histogram_expose_event_cb), phd);
			 
	gtk_box_pack_start(GTK_BOX(phd->widget), phd->drawing_area, TRUE, TRUE, 0);
	gtk_widget_show(phd->drawing_area);
	gtk_widget_add_events(phd->drawing_area, GDK_BUTTON_PRESS_MASK);

	g_signal_connect(G_OBJECT(phd->drawing_area), "button_press_event", G_CALLBACK(bar_pane_histogram_press_cb), phd);

	gtk_widget_show(phd->widget);

	file_data_register_notify_func(bar_pane_histogram_notify_cb, phd, NOTIFY_PRIORITY_LOW);

	return phd->widget;
}

GtkWidget *bar_pane_histogram_new_from_config(const gchar **attribute_names, const gchar **attribute_values)
{
	gchar *title = NULL;
	gchar *id = g_strdup("histogram");
	gboolean expanded = TRUE;
	gint height = 80;
	gint histogram_channel = HCHAN_RGB;
	gint histogram_mode = 0;
	GtkWidget *ret;

	while (*attribute_names)
		{
		const gchar *option = *attribute_names++;
		const gchar *value = *attribute_values++;

		if (READ_CHAR_FULL("id", id)) continue;
		if (READ_CHAR_FULL("title", title)) continue;
		if (READ_BOOL_FULL("expanded", expanded)) continue;
		if (READ_INT_FULL("histogram_channel", histogram_channel)) continue;
		if (READ_INT_FULL("histogram_mode", histogram_mode)) continue;

		log_printf("unknown attribute %s = %s\n", option, value);
		}
	
	bar_pane_translate_title(PANE_HISTOGRAM, id, &title);
	ret = bar_pane_histogram_new(id, title, height, expanded, histogram_channel, histogram_mode);
	g_free(title);
	g_free(id);
	return ret;
}

void bar_pane_histogram_update_from_config(GtkWidget *pane, const gchar **attribute_names, const gchar **attribute_values)
{
	PaneHistogramData *phd;

	phd = g_object_get_data(G_OBJECT(pane), "pane_data");
	if (!phd) return;

	gint histogram_channel = phd->histogram->histogram_channel;
	gint histogram_mode = phd->histogram->histogram_mode;

	while (*attribute_names)
		{
		const gchar *option = *attribute_names++;
		const gchar *value = *attribute_values++;

		if (READ_CHAR_FULL("id", phd->pane.id)) continue;
//		if (READ_CHAR_FULL("pane.title", title)) continue;
		if (READ_BOOL_FULL("expanded", phd->pane.expanded)) continue;
		if (READ_INT_FULL("histogram_channel", histogram_channel)) continue;
		if (READ_INT_FULL("histogram_mode", histogram_mode)) continue;
		

		log_printf("unknown attribute %s = %s\n", option, value);
		}
	
	histogram_set_channel(phd->histogram, histogram_channel);
	histogram_set_mode(phd->histogram, histogram_mode);

	bar_update_expander(pane);
	bar_pane_histogram_update(phd);
}


/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */