/* RGBHistogramManipulator.c generated by valac 0.56.19, the Vala compiler
 * generated from RGBHistogramManipulator.vala, do not modify */

/* Copyright 2016 Software Freedom Conservancy Inc.
 *
 * This software is licensed under the GNU LGPL (version 2.1 or later).
 * See the COPYING file in this distribution.
 */

#include <gtk/gtk.h>
#include <glib-object.h>
#include <glib.h>
#include "shotwell-graphics-processor.h"
#include <gdk/gdk.h>
#include <cairo-gobject.h>
#include <string.h>
#include <float.h>
#include <math.h>
#include <gdk-pixbuf/gdk-pixbuf.h>

#define RGB_HISTOGRAM_MANIPULATOR_NUB_SIZE 13
#define RGB_HISTOGRAM_MANIPULATOR_NUB_HALF_WIDTH (RGB_HISTOGRAM_MANIPULATOR_NUB_SIZE / 2)
#define RGB_HISTOGRAM_MANIPULATOR_NUB_V_NUDGE 4
#define RGB_HISTOGRAM_MANIPULATOR_TROUGH_WIDTH (256 + (2 * RGB_HISTOGRAM_MANIPULATOR_NUB_HALF_WIDTH))
#define RGB_HISTOGRAM_MANIPULATOR_TROUGH_HEIGHT 4
#define RGB_HISTOGRAM_MANIPULATOR_TROUGH_BOTTOM_OFFSET 1
#define RGB_HISTOGRAM_MANIPULATOR_CONTROL_WIDTH (RGB_HISTOGRAM_MANIPULATOR_TROUGH_WIDTH + 2)
#define RGB_HISTOGRAM_MANIPULATOR_CONTROL_HEIGHT 118
#define RGB_HISTOGRAM_MANIPULATOR_NUB_V_POSITION (((((RGB_HISTOGRAM_MANIPULATOR_CONTROL_HEIGHT - RGB_HISTOGRAM_MANIPULATOR_TROUGH_HEIGHT) - RGB_HISTOGRAM_MANIPULATOR_TROUGH_BOTTOM_OFFSET) - ((RGB_HISTOGRAM_MANIPULATOR_NUB_SIZE - RGB_HISTOGRAM_MANIPULATOR_TROUGH_HEIGHT) / 2)) - RGB_HISTOGRAM_MANIPULATOR_NUB_V_NUDGE) - 2)
#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif
#if !defined(VALA_EXTERN)
#if defined(_MSC_VER)
#define VALA_EXTERN __declspec(dllexport) extern
#elif __GNUC__ >= 4
#define VALA_EXTERN __attribute__((visibility("default"))) extern
#else
#define VALA_EXTERN extern
#endif
#endif

#define TYPE_RGB_HISTOGRAM_MANIPULATOR (rgb_histogram_manipulator_get_type ())
#define RGB_HISTOGRAM_MANIPULATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_RGB_HISTOGRAM_MANIPULATOR, RGBHistogramManipulator))
#define RGB_HISTOGRAM_MANIPULATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_RGB_HISTOGRAM_MANIPULATOR, RGBHistogramManipulatorClass))
#define IS_RGB_HISTOGRAM_MANIPULATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_RGB_HISTOGRAM_MANIPULATOR))
#define IS_RGB_HISTOGRAM_MANIPULATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_RGB_HISTOGRAM_MANIPULATOR))
#define RGB_HISTOGRAM_MANIPULATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_RGB_HISTOGRAM_MANIPULATOR, RGBHistogramManipulatorClass))

typedef struct _RGBHistogramManipulator RGBHistogramManipulator;
typedef struct _RGBHistogramManipulatorClass RGBHistogramManipulatorClass;
typedef struct _RGBHistogramManipulatorPrivate RGBHistogramManipulatorPrivate;
enum  {
	RGB_HISTOGRAM_MANIPULATOR_0_PROPERTY,
	RGB_HISTOGRAM_MANIPULATOR_NUM_PROPERTIES
};
static GParamSpec* rgb_histogram_manipulator_properties[RGB_HISTOGRAM_MANIPULATOR_NUM_PROPERTIES];
typedef enum  {
	RGB_HISTOGRAM_MANIPULATOR_LOCATION_CODE_LEFT_NUB,
	RGB_HISTOGRAM_MANIPULATOR_LOCATION_CODE_RIGHT_NUB,
	RGB_HISTOGRAM_MANIPULATOR_LOCATION_CODE_LEFT_TROUGH,
	RGB_HISTOGRAM_MANIPULATOR_LOCATION_CODE_RIGHT_TROUGH,
	RGB_HISTOGRAM_MANIPULATOR_LOCATION_CODE_INSENSITIVE_AREA
} RGBHistogramManipulatorLocationCode;

#define RGB_HISTOGRAM_MANIPULATOR_TYPE_LOCATION_CODE (rgb_histogram_manipulator_location_code_get_type ())
#define _rgb_histogram_unref0(var) ((var == NULL) ? NULL : (var = (rgb_histogram_unref (var), NULL)))
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
enum  {
	RGB_HISTOGRAM_MANIPULATOR_NUB_POSITION_CHANGED_SIGNAL,
	RGB_HISTOGRAM_MANIPULATOR_NUM_SIGNALS
};
static guint rgb_histogram_manipulator_signals[RGB_HISTOGRAM_MANIPULATOR_NUM_SIGNALS] = {0};
#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);

struct _RGBHistogramManipulator {
	GtkDrawingArea parent_instance;
	RGBHistogramManipulatorPrivate * priv;
};

struct _RGBHistogramManipulatorClass {
	GtkDrawingAreaClass parent_class;
};

struct _RGBHistogramManipulatorPrivate {
	gint left_nub_max;
	gint right_nub_min;
	RGBHistogram* histogram;
	gint left_nub_position;
	gint right_nub_position;
	gboolean is_left_nub_tracking;
	gboolean is_right_nub_tracking;
	gint track_start_x;
	gint track_nub_start_position;
	gint offset;
};

static gint RGBHistogramManipulator_private_offset;
static gpointer rgb_histogram_manipulator_parent_class = NULL;
static GtkWidgetPath* rgb_histogram_manipulator_slider_draw_path;
static GtkWidgetPath* rgb_histogram_manipulator_slider_draw_path = NULL;
static GtkWidgetPath* rgb_histogram_manipulator_frame_draw_path;
static GtkWidgetPath* rgb_histogram_manipulator_frame_draw_path = NULL;
static gboolean rgb_histogram_manipulator_paths_setup;
static gboolean rgb_histogram_manipulator_paths_setup = FALSE;

VALA_EXTERN GType rgb_histogram_manipulator_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (RGBHistogramManipulator, g_object_unref)
static GType rgb_histogram_manipulator_location_code_get_type (void) G_GNUC_CONST  G_GNUC_UNUSED ;
VALA_EXTERN RGBHistogramManipulator* rgb_histogram_manipulator_new (void);
VALA_EXTERN RGBHistogramManipulator* rgb_histogram_manipulator_construct (GType object_type);
static gboolean rgb_histogram_manipulator_on_button_press (RGBHistogramManipulator* self,
                                                    GdkEventButton* event_record);
static gboolean _rgb_histogram_manipulator_on_button_press_gtk_widget_button_press_event (GtkWidget* _sender,
                                                                                   GdkEventButton* event,
                                                                                   gpointer self);
static gboolean rgb_histogram_manipulator_on_button_release (RGBHistogramManipulator* self,
                                                      GdkEventButton* event_record);
static gboolean _rgb_histogram_manipulator_on_button_release_gtk_widget_button_release_event (GtkWidget* _sender,
                                                                                       GdkEventButton* event,
                                                                                       gpointer self);
static gboolean rgb_histogram_manipulator_on_button_motion (RGBHistogramManipulator* self,
                                                     GdkEventMotion* event_record);
static gboolean _rgb_histogram_manipulator_on_button_motion_gtk_widget_motion_notify_event (GtkWidget* _sender,
                                                                                     GdkEventMotion* event,
                                                                                     gpointer self);
static void rgb_histogram_manipulator_on_size_allocate (RGBHistogramManipulator* self,
                                                 GtkAllocation* region);
static void _rgb_histogram_manipulator_on_size_allocate_gtk_widget_size_allocate (GtkWidget* _sender,
                                                                           GtkAllocation* allocation,
                                                                           gpointer self);
static RGBHistogramManipulatorLocationCode rgb_histogram_manipulator_hit_test_point (RGBHistogramManipulator* self,
                                                                              gint x,
                                                                              gint y);
static void rgb_histogram_manipulator_force_update (RGBHistogramManipulator* self);
static void rgb_histogram_manipulator_update_nub_extrema (RGBHistogramManipulator* self);
static gboolean rgb_histogram_manipulator_real_focus_out_event (GtkWidget* base,
                                                         GdkEventFocus* event);
static gboolean rgb_histogram_manipulator_real_key_press_event (GtkWidget* base,
                                                         GdkEventKey* event);
static gboolean rgb_histogram_manipulator_real_draw (GtkWidget* base,
                                              cairo_t* ctx);
static void rgb_histogram_manipulator_draw_histogram (RGBHistogramManipulator* self,
                                               cairo_t* ctx,
                                               GdkRectangle* area);
static void rgb_histogram_manipulator_draw_nub (RGBHistogramManipulator* self,
                                         cairo_t* ctx,
                                         GdkRectangle* area,
                                         gint position);
VALA_EXTERN void rgb_histogram_manipulator_update_histogram (RGBHistogramManipulator* self,
                                                 GdkPixbuf* source_pixbuf);
VALA_EXTERN gint rgb_histogram_manipulator_get_left_nub_position (RGBHistogramManipulator* self);
VALA_EXTERN gint rgb_histogram_manipulator_get_right_nub_position (RGBHistogramManipulator* self);
VALA_EXTERN void rgb_histogram_manipulator_set_left_nub_position (RGBHistogramManipulator* self,
                                                      gint user_nub_pos);
VALA_EXTERN void rgb_histogram_manipulator_set_right_nub_position (RGBHistogramManipulator* self,
                                                       gint user_nub_pos);
static void rgb_histogram_manipulator_finalize (GObject * obj);
static GType rgb_histogram_manipulator_get_type_once (void);

static inline gpointer
rgb_histogram_manipulator_get_instance_private (RGBHistogramManipulator* self)
{
	return G_STRUCT_MEMBER_P (self, RGBHistogramManipulator_private_offset);
}

static GType
rgb_histogram_manipulator_location_code_get_type_once (void)
{
	static const GEnumValue values[] = {{RGB_HISTOGRAM_MANIPULATOR_LOCATION_CODE_LEFT_NUB, "RGB_HISTOGRAM_MANIPULATOR_LOCATION_CODE_LEFT_NUB", "left-nub"}, {RGB_HISTOGRAM_MANIPULATOR_LOCATION_CODE_RIGHT_NUB, "RGB_HISTOGRAM_MANIPULATOR_LOCATION_CODE_RIGHT_NUB", "right-nub"}, {RGB_HISTOGRAM_MANIPULATOR_LOCATION_CODE_LEFT_TROUGH, "RGB_HISTOGRAM_MANIPULATOR_LOCATION_CODE_LEFT_TROUGH", "left-trough"}, {RGB_HISTOGRAM_MANIPULATOR_LOCATION_CODE_RIGHT_TROUGH, "RGB_HISTOGRAM_MANIPULATOR_LOCATION_CODE_RIGHT_TROUGH", "right-trough"}, {RGB_HISTOGRAM_MANIPULATOR_LOCATION_CODE_INSENSITIVE_AREA, "RGB_HISTOGRAM_MANIPULATOR_LOCATION_CODE_INSENSITIVE_AREA", "insensitive-area"}, {0, NULL, NULL}};
	GType rgb_histogram_manipulator_location_code_type_id;
	rgb_histogram_manipulator_location_code_type_id = g_enum_register_static ("RGBHistogramManipulatorLocationCode", values);
	return rgb_histogram_manipulator_location_code_type_id;
}

static GType
rgb_histogram_manipulator_location_code_get_type (void)
{
	static volatile gsize rgb_histogram_manipulator_location_code_type_id__once = 0;
	if (g_once_init_enter (&rgb_histogram_manipulator_location_code_type_id__once)) {
		GType rgb_histogram_manipulator_location_code_type_id;
		rgb_histogram_manipulator_location_code_type_id = rgb_histogram_manipulator_location_code_get_type_once ();
		g_once_init_leave (&rgb_histogram_manipulator_location_code_type_id__once, rgb_histogram_manipulator_location_code_type_id);
	}
	return rgb_histogram_manipulator_location_code_type_id__once;
}

static gboolean
_rgb_histogram_manipulator_on_button_press_gtk_widget_button_press_event (GtkWidget* _sender,
                                                                          GdkEventButton* event,
                                                                          gpointer self)
{
	gboolean result;
	result = rgb_histogram_manipulator_on_button_press ((RGBHistogramManipulator*) self, event);
	return result;
}

static gboolean
_rgb_histogram_manipulator_on_button_release_gtk_widget_button_release_event (GtkWidget* _sender,
                                                                              GdkEventButton* event,
                                                                              gpointer self)
{
	gboolean result;
	result = rgb_histogram_manipulator_on_button_release ((RGBHistogramManipulator*) self, event);
	return result;
}

static gboolean
_rgb_histogram_manipulator_on_button_motion_gtk_widget_motion_notify_event (GtkWidget* _sender,
                                                                            GdkEventMotion* event,
                                                                            gpointer self)
{
	gboolean result;
	result = rgb_histogram_manipulator_on_button_motion ((RGBHistogramManipulator*) self, event);
	return result;
}

static void
_rgb_histogram_manipulator_on_size_allocate_gtk_widget_size_allocate (GtkWidget* _sender,
                                                                      GtkAllocation* allocation,
                                                                      gpointer self)
{
	rgb_histogram_manipulator_on_size_allocate ((RGBHistogramManipulator*) self, allocation);
}

RGBHistogramManipulator*
rgb_histogram_manipulator_construct (GType object_type)
{
	RGBHistogramManipulator * self = NULL;
	self = (RGBHistogramManipulator*) g_object_new (object_type, NULL);
	gtk_widget_set_size_request (G_TYPE_CHECK_INSTANCE_CAST (self, gtk_widget_get_type (), GtkWidget), RGB_HISTOGRAM_MANIPULATOR_CONTROL_WIDTH, RGB_HISTOGRAM_MANIPULATOR_CONTROL_HEIGHT);
	gtk_widget_set_can_focus (G_TYPE_CHECK_INSTANCE_CAST (self, gtk_widget_get_type (), GtkWidget), TRUE);
	if (!rgb_histogram_manipulator_paths_setup) {
		GtkWidgetPath* _tmp0_;
		GtkWidgetPath* _tmp1_;
		GtkWidgetPath* _tmp2_;
		GtkWidgetPath* _tmp3_;
		GtkWidgetPath* _tmp4_;
		_tmp0_ = rgb_histogram_manipulator_slider_draw_path;
		gtk_widget_path_append_type (_tmp0_, gtk_scale_get_type ());
		_tmp1_ = rgb_histogram_manipulator_slider_draw_path;
		gtk_widget_path_iter_add_class (_tmp1_, 0, "scale");
		_tmp2_ = rgb_histogram_manipulator_slider_draw_path;
		gtk_widget_path_iter_add_class (_tmp2_, 0, "range");
		_tmp3_ = rgb_histogram_manipulator_frame_draw_path;
		gtk_widget_path_append_type (_tmp3_, gtk_frame_get_type ());
		_tmp4_ = rgb_histogram_manipulator_frame_draw_path;
		gtk_widget_path_iter_add_class (_tmp4_, 0, "default");
		rgb_histogram_manipulator_paths_setup = TRUE;
	}
	gtk_widget_add_events (G_TYPE_CHECK_INSTANCE_CAST (self, gtk_widget_get_type (), GtkWidget), (gint) GDK_BUTTON_PRESS_MASK);
	gtk_widget_add_events (G_TYPE_CHECK_INSTANCE_CAST (self, gtk_widget_get_type (), GtkWidget), (gint) GDK_BUTTON_RELEASE_MASK);
	gtk_widget_add_events (G_TYPE_CHECK_INSTANCE_CAST (self, gtk_widget_get_type (), GtkWidget), (gint) GDK_BUTTON_MOTION_MASK);
	gtk_widget_add_events (G_TYPE_CHECK_INSTANCE_CAST (self, gtk_widget_get_type (), GtkWidget), (gint) GDK_FOCUS_CHANGE_MASK);
	gtk_widget_add_events (G_TYPE_CHECK_INSTANCE_CAST (self, gtk_widget_get_type (), GtkWidget), (gint) GDK_KEY_PRESS_MASK);
	g_signal_connect_object (G_TYPE_CHECK_INSTANCE_CAST (self, gtk_widget_get_type (), GtkWidget), "button-press-event", (GCallback) _rgb_histogram_manipulator_on_button_press_gtk_widget_button_press_event, self, 0);
	g_signal_connect_object (G_TYPE_CHECK_INSTANCE_CAST (self, gtk_widget_get_type (), GtkWidget), "button-release-event", (GCallback) _rgb_histogram_manipulator_on_button_release_gtk_widget_button_release_event, self, 0);
	g_signal_connect_object (G_TYPE_CHECK_INSTANCE_CAST (self, gtk_widget_get_type (), GtkWidget), "motion-notify-event", (GCallback) _rgb_histogram_manipulator_on_button_motion_gtk_widget_motion_notify_event, self, 0);
	g_signal_connect_object (G_TYPE_CHECK_INSTANCE_CAST (self, gtk_widget_get_type (), GtkWidget), "size-allocate", (GCallback) _rgb_histogram_manipulator_on_size_allocate_gtk_widget_size_allocate, self, 0);
	return self;
}

RGBHistogramManipulator*
rgb_histogram_manipulator_new (void)
{
	return rgb_histogram_manipulator_construct (TYPE_RGB_HISTOGRAM_MANIPULATOR);
}

static void
rgb_histogram_manipulator_on_size_allocate (RGBHistogramManipulator* self,
                                            GtkAllocation* region)
{
	GtkAllocation _tmp0_;
	g_return_if_fail (IS_RGB_HISTOGRAM_MANIPULATOR (self));
	g_return_if_fail (region != NULL);
	_tmp0_ = *region;
	self->priv->offset = ((_tmp0_.width - RGB_HISTOGRAM_GRAPHIC_WIDTH) - RGB_HISTOGRAM_MANIPULATOR_NUB_SIZE) / 2;
}

static RGBHistogramManipulatorLocationCode
rgb_histogram_manipulator_hit_test_point (RGBHistogramManipulator* self,
                                          gint x,
                                          gint y)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	RGBHistogramManipulatorLocationCode result;
	g_return_val_if_fail (IS_RGB_HISTOGRAM_MANIPULATOR (self), 0);
	if (y < RGB_HISTOGRAM_MANIPULATOR_NUB_V_POSITION) {
		result = RGB_HISTOGRAM_MANIPULATOR_LOCATION_CODE_INSENSITIVE_AREA;
		return result;
	}
	if (x > self->priv->left_nub_position) {
		_tmp0_ = x < (self->priv->left_nub_position + RGB_HISTOGRAM_MANIPULATOR_NUB_SIZE);
	} else {
		_tmp0_ = FALSE;
	}
	if (_tmp0_) {
		result = RGB_HISTOGRAM_MANIPULATOR_LOCATION_CODE_LEFT_NUB;
		return result;
	}
	if (x > self->priv->right_nub_position) {
		_tmp1_ = x < (self->priv->right_nub_position + RGB_HISTOGRAM_MANIPULATOR_NUB_SIZE);
	} else {
		_tmp1_ = FALSE;
	}
	if (_tmp1_) {
		result = RGB_HISTOGRAM_MANIPULATOR_LOCATION_CODE_RIGHT_NUB;
		return result;
	}
	if (y < ((RGB_HISTOGRAM_MANIPULATOR_NUB_V_POSITION + RGB_HISTOGRAM_MANIPULATOR_NUB_V_NUDGE) + 1)) {
		result = RGB_HISTOGRAM_MANIPULATOR_LOCATION_CODE_INSENSITIVE_AREA;
		return result;
	}
	if (((x - self->priv->left_nub_position) * (x - self->priv->left_nub_position)) < ((x - self->priv->right_nub_position) * (x - self->priv->right_nub_position))) {
		result = RGB_HISTOGRAM_MANIPULATOR_LOCATION_CODE_LEFT_TROUGH;
		return result;
	} else {
		result = RGB_HISTOGRAM_MANIPULATOR_LOCATION_CODE_RIGHT_TROUGH;
		return result;
	}
}

static gboolean
rgb_histogram_manipulator_on_button_press (RGBHistogramManipulator* self,
                                           GdkEventButton* event_record)
{
	RGBHistogramManipulatorLocationCode loc = 0;
	gboolean retval = FALSE;
	gboolean result;
	g_return_val_if_fail (IS_RGB_HISTOGRAM_MANIPULATOR (self), FALSE);
	g_return_val_if_fail (event_record != NULL, FALSE);
	event_record->x = event_record->x - self->priv->offset;
	loc = rgb_histogram_manipulator_hit_test_point (self, (gint) event_record->x, (gint) event_record->y);
	retval = TRUE;
	switch (loc) {
		case RGB_HISTOGRAM_MANIPULATOR_LOCATION_CODE_LEFT_NUB:
		{
			self->priv->track_start_x = (gint) event_record->x;
			self->priv->track_nub_start_position = self->priv->left_nub_position;
			self->priv->is_left_nub_tracking = TRUE;
			break;
		}
		case RGB_HISTOGRAM_MANIPULATOR_LOCATION_CODE_RIGHT_NUB:
		{
			self->priv->track_start_x = (gint) event_record->x;
			self->priv->track_nub_start_position = self->priv->right_nub_position;
			self->priv->is_right_nub_tracking = TRUE;
			break;
		}
		case RGB_HISTOGRAM_MANIPULATOR_LOCATION_CODE_LEFT_TROUGH:
		{
			self->priv->left_nub_position = ((gint) event_record->x) - RGB_HISTOGRAM_MANIPULATOR_NUB_HALF_WIDTH;
			self->priv->left_nub_position = CLAMP (self->priv->left_nub_position, 0, self->priv->left_nub_max);
			rgb_histogram_manipulator_force_update (self);
			g_signal_emit (self, rgb_histogram_manipulator_signals[RGB_HISTOGRAM_MANIPULATOR_NUB_POSITION_CHANGED_SIGNAL], 0);
			rgb_histogram_manipulator_update_nub_extrema (self);
			break;
		}
		case RGB_HISTOGRAM_MANIPULATOR_LOCATION_CODE_RIGHT_TROUGH:
		{
			self->priv->right_nub_position = ((gint) event_record->x) - RGB_HISTOGRAM_MANIPULATOR_NUB_HALF_WIDTH;
			self->priv->right_nub_position = CLAMP (self->priv->right_nub_position, self->priv->right_nub_min, 255);
			rgb_histogram_manipulator_force_update (self);
			g_signal_emit (self, rgb_histogram_manipulator_signals[RGB_HISTOGRAM_MANIPULATOR_NUB_POSITION_CHANGED_SIGNAL], 0);
			rgb_histogram_manipulator_update_nub_extrema (self);
			break;
		}
		default:
		{
			retval = FALSE;
			break;
		}
	}
	event_record->x = event_record->x + self->priv->offset;
	result = retval;
	return result;
}

static gboolean
rgb_histogram_manipulator_on_button_release (RGBHistogramManipulator* self,
                                             GdkEventButton* event_record)
{
	gboolean _tmp0_ = FALSE;
	gboolean result;
	g_return_val_if_fail (IS_RGB_HISTOGRAM_MANIPULATOR (self), FALSE);
	g_return_val_if_fail (event_record != NULL, FALSE);
	if (self->priv->is_left_nub_tracking) {
		_tmp0_ = TRUE;
	} else {
		_tmp0_ = self->priv->is_right_nub_tracking;
	}
	if (_tmp0_) {
		g_signal_emit (self, rgb_histogram_manipulator_signals[RGB_HISTOGRAM_MANIPULATOR_NUB_POSITION_CHANGED_SIGNAL], 0);
		rgb_histogram_manipulator_update_nub_extrema (self);
	}
	self->priv->is_left_nub_tracking = FALSE;
	self->priv->is_right_nub_tracking = FALSE;
	result = FALSE;
	return result;
}

static gboolean
rgb_histogram_manipulator_on_button_motion (RGBHistogramManipulator* self,
                                            GdkEventMotion* event_record)
{
	gboolean _tmp0_ = FALSE;
	gboolean result;
	g_return_val_if_fail (IS_RGB_HISTOGRAM_MANIPULATOR (self), FALSE);
	g_return_val_if_fail (event_record != NULL, FALSE);
	if (!self->priv->is_left_nub_tracking) {
		_tmp0_ = !self->priv->is_right_nub_tracking;
	} else {
		_tmp0_ = FALSE;
	}
	if (_tmp0_) {
		result = FALSE;
		return result;
	}
	event_record->x = event_record->x - self->priv->offset;
	if (self->priv->is_left_nub_tracking) {
		gint track_x_delta = 0;
		track_x_delta = ((gint) event_record->x) - self->priv->track_start_x;
		self->priv->left_nub_position = self->priv->track_nub_start_position + track_x_delta;
		self->priv->left_nub_position = CLAMP (self->priv->left_nub_position, 0, self->priv->left_nub_max);
	} else {
		gint track_x_delta = 0;
		track_x_delta = ((gint) event_record->x) - self->priv->track_start_x;
		self->priv->right_nub_position = self->priv->track_nub_start_position + track_x_delta;
		self->priv->right_nub_position = CLAMP (self->priv->right_nub_position, self->priv->right_nub_min, 255);
	}
	rgb_histogram_manipulator_force_update (self);
	event_record->x = event_record->x + self->priv->offset;
	result = TRUE;
	return result;
}

static gboolean
rgb_histogram_manipulator_real_focus_out_event (GtkWidget* base,
                                                GdkEventFocus* event)
{
	RGBHistogramManipulator * self;
	gboolean result;
	self = G_TYPE_CHECK_INSTANCE_CAST (base, TYPE_RGB_HISTOGRAM_MANIPULATOR, RGBHistogramManipulator);
	g_return_val_if_fail (event != NULL, FALSE);
	if (GTK_WIDGET_CLASS (rgb_histogram_manipulator_parent_class)->focus_out_event (G_TYPE_CHECK_INSTANCE_CAST (G_TYPE_CHECK_INSTANCE_CAST (self, gtk_drawing_area_get_type (), GtkDrawingArea), gtk_widget_get_type (), GtkWidget), event)) {
		result = TRUE;
		return result;
	}
	gtk_widget_queue_draw (G_TYPE_CHECK_INSTANCE_CAST (self, gtk_widget_get_type (), GtkWidget));
	result = FALSE;
	return result;
}

static gboolean
rgb_histogram_manipulator_real_key_press_event (GtkWidget* base,
                                                GdkEventKey* event)
{
	RGBHistogramManipulator * self;
	gint delta = 0;
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	gboolean result;
	self = G_TYPE_CHECK_INSTANCE_CAST (base, TYPE_RGB_HISTOGRAM_MANIPULATOR, RGBHistogramManipulator);
	g_return_val_if_fail (event != NULL, FALSE);
	if (GTK_WIDGET_CLASS (rgb_histogram_manipulator_parent_class)->key_press_event (G_TYPE_CHECK_INSTANCE_CAST (G_TYPE_CHECK_INSTANCE_CAST (self, gtk_drawing_area_get_type (), GtkDrawingArea), gtk_widget_get_type (), GtkWidget), event)) {
		result = TRUE;
		return result;
	}
	delta = 0;
	if (event->keyval == GDK_KEY_Left) {
		_tmp0_ = TRUE;
	} else {
		_tmp0_ = event->keyval == GDK_KEY_Up;
	}
	if (_tmp0_) {
		delta = -1;
	}
	if (event->keyval == GDK_KEY_Right) {
		_tmp1_ = TRUE;
	} else {
		_tmp1_ = event->keyval == GDK_KEY_Down;
	}
	if (_tmp1_) {
		delta = 1;
	}
	if (!((event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)) {
		delta *= 5;
	}
	if (delta == 0) {
		result = FALSE;
		return result;
	}
	if ((event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK) {
		self->priv->right_nub_position = self->priv->right_nub_position + delta;
		self->priv->right_nub_position = CLAMP (self->priv->right_nub_position, self->priv->right_nub_min, 255);
	} else {
		self->priv->left_nub_position = self->priv->left_nub_position + delta;
		self->priv->left_nub_position = CLAMP (self->priv->left_nub_position, 0, self->priv->left_nub_max);
	}
	g_signal_emit (self, rgb_histogram_manipulator_signals[RGB_HISTOGRAM_MANIPULATOR_NUB_POSITION_CHANGED_SIGNAL], 0);
	rgb_histogram_manipulator_update_nub_extrema (self);
	rgb_histogram_manipulator_force_update (self);
	result = TRUE;
	return result;
}

static gboolean
rgb_histogram_manipulator_real_draw (GtkWidget* base,
                                     cairo_t* ctx)
{
	RGBHistogramManipulator * self;
	GtkBorder padding = {0};
	GtkStyleContext* _tmp0_;
	GtkBorder _tmp1_ = {0};
	GdkRectangle area = {0};
	GtkBorder _tmp2_;
	GtkBorder _tmp3_;
	GtkBorder _tmp4_;
	GtkBorder _tmp5_;
	gboolean _tmp6_;
	gboolean _tmp7_;
	GdkRectangle _tmp13_;
	GdkRectangle _tmp14_;
	GdkRectangle _tmp15_;
	gboolean result;
	self = G_TYPE_CHECK_INSTANCE_CAST (base, TYPE_RGB_HISTOGRAM_MANIPULATOR, RGBHistogramManipulator);
	g_return_val_if_fail (ctx != NULL, FALSE);
	_tmp0_ = gtk_widget_get_style_context (G_TYPE_CHECK_INSTANCE_CAST (self, gtk_widget_get_type (), GtkWidget));
	gtk_style_context_get_padding (_tmp0_, GTK_STATE_FLAG_NORMAL, &_tmp1_);
	padding = _tmp1_;
	memset (&area, 0, sizeof (GdkRectangle));
	_tmp2_ = padding;
	area.x = _tmp2_.left + self->priv->offset;
	_tmp3_ = padding;
	area.y = (gint) _tmp3_.top;
	_tmp4_ = padding;
	area.width = RGB_HISTOGRAM_GRAPHIC_WIDTH + _tmp4_.right;
	_tmp5_ = padding;
	area.height = RGB_HISTOGRAM_GRAPHIC_HEIGHT + _tmp5_.bottom;
	g_object_get (G_TYPE_CHECK_INSTANCE_CAST (self, gtk_widget_get_type (), GtkWidget), "has-focus", &_tmp6_, NULL);
	_tmp7_ = _tmp6_;
	if (_tmp7_) {
		GtkStyleContext* _tmp8_;
		GdkRectangle _tmp9_;
		GdkRectangle _tmp10_;
		GdkRectangle _tmp11_;
		GdkRectangle _tmp12_;
		_tmp8_ = gtk_widget_get_style_context (G_TYPE_CHECK_INSTANCE_CAST (self, gtk_widget_get_type (), GtkWidget));
		_tmp9_ = area;
		_tmp10_ = area;
		_tmp11_ = area;
		_tmp12_ = area;
		gtk_render_focus (_tmp8_, ctx, (gdouble) _tmp9_.x, (gdouble) _tmp10_.y, (gdouble) (_tmp11_.width + RGB_HISTOGRAM_MANIPULATOR_NUB_SIZE), (gdouble) ((_tmp12_.height + RGB_HISTOGRAM_MANIPULATOR_NUB_SIZE) + RGB_HISTOGRAM_MANIPULATOR_NUB_HALF_WIDTH));
	}
	_tmp13_ = area;
	rgb_histogram_manipulator_draw_histogram (self, ctx, &_tmp13_);
	_tmp14_ = area;
	rgb_histogram_manipulator_draw_nub (self, ctx, &_tmp14_, self->priv->left_nub_position);
	_tmp15_ = area;
	rgb_histogram_manipulator_draw_nub (self, ctx, &_tmp15_, self->priv->right_nub_position);
	result = TRUE;
	return result;
}

static void
rgb_histogram_manipulator_draw_histogram (RGBHistogramManipulator* self,
                                          cairo_t* ctx,
                                          GdkRectangle* area)
{
	RGBHistogram* _tmp0_;
	GdkPixbuf* histogram_graphic = NULL;
	RGBHistogram* _tmp1_;
	GdkPixbuf* _tmp2_;
	GdkPixbuf* _tmp3_;
	GdkRectangle _tmp4_;
	GdkRectangle _tmp5_;
	g_return_if_fail (IS_RGB_HISTOGRAM_MANIPULATOR (self));
	g_return_if_fail (ctx != NULL);
	g_return_if_fail (area != NULL);
	_tmp0_ = self->priv->histogram;
	if (_tmp0_ == NULL) {
		return;
	}
	_tmp1_ = self->priv->histogram;
	_tmp2_ = rgb_histogram_get_graphic (_tmp1_);
	histogram_graphic = _tmp2_;
	_tmp3_ = histogram_graphic;
	_tmp4_ = *area;
	_tmp5_ = *area;
	gdk_cairo_set_source_pixbuf (ctx, _tmp3_, (gdouble) (_tmp4_.x + RGB_HISTOGRAM_MANIPULATOR_NUB_HALF_WIDTH), (gdouble) (_tmp5_.y + 2));
	cairo_paint (ctx);
	if (self->priv->left_nub_position > 0) {
		GdkRectangle _tmp6_;
		GdkRectangle _tmp7_;
		GdkPixbuf* _tmp8_;
		gint _tmp9_;
		gint _tmp10_;
		_tmp6_ = *area;
		_tmp7_ = *area;
		_tmp8_ = histogram_graphic;
		_tmp9_ = gdk_pixbuf_get_height (_tmp8_);
		_tmp10_ = _tmp9_;
		cairo_rectangle (ctx, (gdouble) (_tmp6_.x + RGB_HISTOGRAM_MANIPULATOR_NUB_HALF_WIDTH), (gdouble) (_tmp7_.y + 2), (gdouble) self->priv->left_nub_position, (gdouble) _tmp10_);
		cairo_set_source_rgba (ctx, 0.0, 0.0, 0.0, 0.45);
		cairo_fill (ctx);
	}
	if (self->priv->right_nub_position < 255) {
		GdkRectangle _tmp11_;
		GdkRectangle _tmp12_;
		GdkPixbuf* _tmp13_;
		gint _tmp14_;
		gint _tmp15_;
		GdkPixbuf* _tmp16_;
		gint _tmp17_;
		gint _tmp18_;
		_tmp11_ = *area;
		_tmp12_ = *area;
		_tmp13_ = histogram_graphic;
		_tmp14_ = gdk_pixbuf_get_width (_tmp13_);
		_tmp15_ = _tmp14_;
		_tmp16_ = histogram_graphic;
		_tmp17_ = gdk_pixbuf_get_height (_tmp16_);
		_tmp18_ = _tmp17_;
		cairo_rectangle (ctx, (gdouble) ((_tmp11_.x + self->priv->right_nub_position) + RGB_HISTOGRAM_MANIPULATOR_NUB_HALF_WIDTH), (gdouble) (_tmp12_.y + 2), (gdouble) (_tmp15_ - self->priv->right_nub_position), (gdouble) _tmp18_);
		cairo_set_source_rgba (ctx, 1.0, 1.0, 1.0, 0.45);
		cairo_fill (ctx);
	}
	_g_object_unref0 (histogram_graphic);
}

static void
rgb_histogram_manipulator_draw_nub (RGBHistogramManipulator* self,
                                    cairo_t* ctx,
                                    GdkRectangle* area,
                                    gint position)
{
	GdkRectangle _tmp0_;
	GdkRectangle _tmp1_;
	GdkRectangle _tmp2_;
	GdkRectangle _tmp3_;
	GdkRectangle _tmp4_;
	GdkRectangle _tmp5_;
	g_return_if_fail (IS_RGB_HISTOGRAM_MANIPULATOR (self));
	g_return_if_fail (ctx != NULL);
	g_return_if_fail (area != NULL);
	_tmp0_ = *area;
	_tmp1_ = *area;
	cairo_move_to (ctx, (gdouble) (_tmp0_.x + position), (gdouble) ((_tmp1_.y + RGB_HISTOGRAM_MANIPULATOR_NUB_V_POSITION) + RGB_HISTOGRAM_MANIPULATOR_NUB_SIZE));
	_tmp2_ = *area;
	_tmp3_ = *area;
	cairo_line_to (ctx, (gdouble) ((_tmp2_.x + position) + RGB_HISTOGRAM_MANIPULATOR_NUB_HALF_WIDTH), (gdouble) (_tmp3_.y + RGB_HISTOGRAM_MANIPULATOR_NUB_V_POSITION));
	_tmp4_ = *area;
	_tmp5_ = *area;
	cairo_line_to (ctx, (gdouble) ((_tmp4_.x + position) + RGB_HISTOGRAM_MANIPULATOR_NUB_SIZE), (gdouble) ((_tmp5_.y + RGB_HISTOGRAM_MANIPULATOR_NUB_V_POSITION) + RGB_HISTOGRAM_MANIPULATOR_NUB_SIZE));
	cairo_close_path (ctx);
	cairo_set_source_rgb (ctx, 0.333, 0.333, 0.333);
	cairo_fill (ctx);
}

static void
rgb_histogram_manipulator_force_update (RGBHistogramManipulator* self)
{
	GdkWindow* _tmp0_;
	g_return_if_fail (IS_RGB_HISTOGRAM_MANIPULATOR (self));
	_tmp0_ = gtk_widget_get_window (G_TYPE_CHECK_INSTANCE_CAST (self, gtk_widget_get_type (), GtkWidget));
	gdk_window_invalidate_rect (_tmp0_, NULL, TRUE);
}

static void
rgb_histogram_manipulator_update_nub_extrema (RGBHistogramManipulator* self)
{
	g_return_if_fail (IS_RGB_HISTOGRAM_MANIPULATOR (self));
	self->priv->right_nub_min = (self->priv->left_nub_position + RGB_HISTOGRAM_MANIPULATOR_NUB_SIZE) + 1;
	self->priv->left_nub_max = (self->priv->right_nub_position - RGB_HISTOGRAM_MANIPULATOR_NUB_SIZE) - 1;
}

void
rgb_histogram_manipulator_update_histogram (RGBHistogramManipulator* self,
                                            GdkPixbuf* source_pixbuf)
{
	RGBHistogram* _tmp0_;
	g_return_if_fail (IS_RGB_HISTOGRAM_MANIPULATOR (self));
	g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (source_pixbuf, gdk_pixbuf_get_type ()));
	_tmp0_ = rgb_histogram_new (source_pixbuf);
	_rgb_histogram_unref0 (self->priv->histogram);
	self->priv->histogram = _tmp0_;
	rgb_histogram_manipulator_force_update (self);
}

gint
rgb_histogram_manipulator_get_left_nub_position (RGBHistogramManipulator* self)
{
	gint result;
	g_return_val_if_fail (IS_RGB_HISTOGRAM_MANIPULATOR (self), -1);
	result = self->priv->left_nub_position;
	return result;
}

gint
rgb_histogram_manipulator_get_right_nub_position (RGBHistogramManipulator* self)
{
	gint result;
	g_return_val_if_fail (IS_RGB_HISTOGRAM_MANIPULATOR (self), -1);
	result = self->priv->right_nub_position;
	return result;
}

void
rgb_histogram_manipulator_set_left_nub_position (RGBHistogramManipulator* self,
                                                 gint user_nub_pos)
{
	gboolean _tmp0_ = FALSE;
	g_return_if_fail (IS_RGB_HISTOGRAM_MANIPULATOR (self));
	if (user_nub_pos >= 0) {
		_tmp0_ = user_nub_pos <= 255;
	} else {
		_tmp0_ = FALSE;
	}
	_vala_assert (_tmp0_, "(user_nub_pos >= 0) && (user_nub_pos <= 255)");
	self->priv->left_nub_position = CLAMP (user_nub_pos, 0, self->priv->left_nub_max);
	rgb_histogram_manipulator_update_nub_extrema (self);
}

void
rgb_histogram_manipulator_set_right_nub_position (RGBHistogramManipulator* self,
                                                  gint user_nub_pos)
{
	gboolean _tmp0_ = FALSE;
	g_return_if_fail (IS_RGB_HISTOGRAM_MANIPULATOR (self));
	if (user_nub_pos >= 0) {
		_tmp0_ = user_nub_pos <= 255;
	} else {
		_tmp0_ = FALSE;
	}
	_vala_assert (_tmp0_, "(user_nub_pos >= 0) && (user_nub_pos <= 255)");
	self->priv->right_nub_position = CLAMP (user_nub_pos, self->priv->right_nub_min, 255);
	rgb_histogram_manipulator_update_nub_extrema (self);
}

static void
rgb_histogram_manipulator_class_init (RGBHistogramManipulatorClass * klass,
                                      gpointer klass_data)
{
	GtkWidgetPath* _tmp0_;
	GtkWidgetPath* _tmp1_;
	rgb_histogram_manipulator_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &RGBHistogramManipulator_private_offset);
	((GtkWidgetClass *) klass)->focus_out_event = (gboolean (*) (GtkWidget*, GdkEventFocus*)) rgb_histogram_manipulator_real_focus_out_event;
	((GtkWidgetClass *) klass)->key_press_event = (gboolean (*) (GtkWidget*, GdkEventKey*)) rgb_histogram_manipulator_real_key_press_event;
	((GtkWidgetClass *) klass)->draw = (gboolean (*) (GtkWidget*, cairo_t*)) rgb_histogram_manipulator_real_draw;
	G_OBJECT_CLASS (klass)->finalize = rgb_histogram_manipulator_finalize;
	rgb_histogram_manipulator_signals[RGB_HISTOGRAM_MANIPULATOR_NUB_POSITION_CHANGED_SIGNAL] = g_signal_new ("nub-position-changed", TYPE_RGB_HISTOGRAM_MANIPULATOR, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
	_tmp0_ = gtk_widget_path_new ();
	rgb_histogram_manipulator_slider_draw_path = _tmp0_;
	_tmp1_ = gtk_widget_path_new ();
	rgb_histogram_manipulator_frame_draw_path = _tmp1_;
}

static void
rgb_histogram_manipulator_instance_init (RGBHistogramManipulator * self,
                                         gpointer klass)
{
	self->priv = rgb_histogram_manipulator_get_instance_private (self);
	self->priv->left_nub_max = (255 - RGB_HISTOGRAM_MANIPULATOR_NUB_SIZE) - 1;
	self->priv->right_nub_min = RGB_HISTOGRAM_MANIPULATOR_NUB_SIZE + 1;
	self->priv->histogram = NULL;
	self->priv->left_nub_position = 0;
	self->priv->right_nub_position = 255;
	self->priv->is_left_nub_tracking = FALSE;
	self->priv->is_right_nub_tracking = FALSE;
	self->priv->track_start_x = 0;
	self->priv->track_nub_start_position = 0;
	self->priv->offset = 0;
}

static void
rgb_histogram_manipulator_finalize (GObject * obj)
{
	RGBHistogramManipulator * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_RGB_HISTOGRAM_MANIPULATOR, RGBHistogramManipulator);
	_rgb_histogram_unref0 (self->priv->histogram);
	G_OBJECT_CLASS (rgb_histogram_manipulator_parent_class)->finalize (obj);
}

static GType
rgb_histogram_manipulator_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (RGBHistogramManipulatorClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) rgb_histogram_manipulator_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (RGBHistogramManipulator), 0, (GInstanceInitFunc) rgb_histogram_manipulator_instance_init, NULL };
	GType rgb_histogram_manipulator_type_id;
	rgb_histogram_manipulator_type_id = g_type_register_static (gtk_drawing_area_get_type (), "RGBHistogramManipulator", &g_define_type_info, 0);
	RGBHistogramManipulator_private_offset = g_type_add_instance_private (rgb_histogram_manipulator_type_id, sizeof (RGBHistogramManipulatorPrivate));
	return rgb_histogram_manipulator_type_id;
}

GType
rgb_histogram_manipulator_get_type (void)
{
	static volatile gsize rgb_histogram_manipulator_type_id__once = 0;
	if (g_once_init_enter (&rgb_histogram_manipulator_type_id__once)) {
		GType rgb_histogram_manipulator_type_id;
		rgb_histogram_manipulator_type_id = rgb_histogram_manipulator_get_type_once ();
		g_once_init_leave (&rgb_histogram_manipulator_type_id__once, rgb_histogram_manipulator_type_id);
	}
	return rgb_histogram_manipulator_type_id__once;
}

