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

/*
 * Copyright (c) 2025 focus-timer contributors
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 *
 * Authors: Kamil Prusko <kamilprusko@gmail.com>
 */

#include "ft_ui.h"
#include <glib.h>
#include <float.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "ft_core.h"
#include <glib-object.h>
#include <gdk/gdk.h>
#include <gtk/gtk.h>
#include <graphene-gobject.h>
#include <cairo-gobject.h>

#define FT_CHART_MIN_WIDTH 300
#define FT_CHART_MIN_HEIGHT 150
#define FT_CHART_EPSILON 0.00001
#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

#define _g_free0(var) (var = (g_free (var), NULL))

#define FT_TYPE_CATEGORY (ft_category_get_type ())
typedef struct _FtCategory FtCategory;

#define FT_TYPE_BUCKET (ft_bucket_get_type ())
typedef struct _FtBucket FtBucket;
enum  {
	FT_CHART_0_PROPERTY,
	FT_CHART_X_SPACING_PROPERTY,
	FT_CHART_Y_SPACING_PROPERTY,
	FT_CHART_ASPECT_RATIO_PROPERTY,
	FT_CHART_NUM_PROPERTIES
};
static GParamSpec* ft_chart_properties[FT_CHART_NUM_PROPERTIES];
typedef struct _FtCanvas FtCanvas;
typedef struct _FtCanvasClass FtCanvasClass;
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _gdk_event_unref0(var) ((var == NULL) ? NULL : (var = (gdk_event_unref (var), NULL)))
typedef struct _FtChartContents FtChartContents;
typedef struct _FtChartContentsClass FtChartContentsClass;
typedef struct _Block8Data Block8Data;
enum  {
	FT_CHART_ZOOM_IN_SIGNAL,
	FT_CHART_ZOOM_OUT_SIGNAL,
	FT_CHART_NUM_SIGNALS
};
static guint ft_chart_signals[FT_CHART_NUM_SIGNALS] = {0};

struct _FtCategory {
	gchar* label;
	GdkRGBA color;
	FtUnit unit;
	gboolean visible;
};

struct _FtBucket {
	gchar* label;
	gchar* tooltip_label;
};

struct _FtChartPrivate {
	GtkScrolledWindow* scrolled_window;
	FtChartAxis* y_axis;
	gfloat _x_spacing;
	gfloat _y_spacing;
	gfloat _aspect_ratio;
	gdouble drag_start_x;
	gboolean zooming;
	gdouble zoom_x_value;
	gdouble zoom_y_value;
	gdouble zoom_x;
	gdouble zoom_y;
	FtFormatValueFunc format_value_func;
	gpointer format_value_func_target;
	GDestroyNotify format_value_func_target_destroy_notify;
};

struct _Block8Data {
	int _ref_count_;
	FtChart* self;
	FtChart* _self_;
};

static gint FtChart_private_offset;
static gpointer ft_chart_parent_class = NULL;
static GtkBuildableIface * ft_chart_gtk_buildable_parent_iface = NULL;

VALA_EXTERN GType ft_category_get_type (void) G_GNUC_CONST ;
VALA_EXTERN FtCategory* ft_category_dup (const FtCategory* self);
VALA_EXTERN void ft_category_free (FtCategory* self);
VALA_EXTERN void ft_category_copy (const FtCategory* self,
                       FtCategory* dest);
VALA_EXTERN void ft_category_destroy (FtCategory* self);
VALA_EXTERN GType ft_bucket_get_type (void) G_GNUC_CONST ;
VALA_EXTERN FtBucket* ft_bucket_dup (const FtBucket* self);
VALA_EXTERN void ft_bucket_free (FtBucket* self);
VALA_EXTERN void ft_bucket_copy (const FtBucket* self,
                     FtBucket* dest);
VALA_EXTERN void ft_bucket_destroy (FtBucket* self);
static gchar* ft_chart_real_format_x_value (FtChart* self,
                                     gdouble value);
static gchar* ft_chart_real_format_y_value (FtChart* self,
                                     gdouble value);
static void ft_chart_on_drag_begin (FtChart* self,
                             gdouble start_x,
                             gdouble start_y);
static void _ft_chart_on_drag_begin_gtk_gesture_drag_drag_begin (GtkGestureDrag* _sender,
                                                          gdouble start_x,
                                                          gdouble start_y,
                                                          gpointer self);
static void ft_chart_on_pan (FtChart* self,
                      GtkGesturePan* gesture,
                      GtkPanDirection direction,
                      gdouble offset);
static void _ft_chart_on_pan_gtk_gesture_pan_pan (GtkGesturePan* _sender,
                                           GtkPanDirection direction,
                                           gdouble offset,
                                           gpointer self);
static gboolean ft_chart_get_pointer_position (FtChart* self,
                                        gdouble* x,
                                        gdouble* y);
static gboolean ft_chart_on_scroll (FtChart* self,
                             GtkEventControllerScroll* controller,
                             gdouble dx,
                             gdouble dy);
static gboolean _ft_chart_on_scroll_gtk_event_controller_scroll_scroll (GtkEventControllerScroll* _sender,
                                                                 gdouble dx,
                                                                 gdouble dy,
                                                                 gpointer self);
static GtkSizeRequestMode ft_chart_real_get_contents_request_mode (FtChart* self,
                                                            FtCanvas* canvas);
static void ft_chart_real_update_canvas (FtChart* self,
                                  FtCanvas* canvas);
static void ft_chart_real_measure_canvas (FtChart* self,
                                   FtCanvas* canvas,
                                   GtkOrientation orientation,
                                   gint for_size,
                                   gint* minimum,
                                   gint* natural);
static void ft_chart_real_measure_working_area (FtChart* self,
                                         FtCanvas* canvas,
                                         gint available_width,
                                         gint available_height,
                                         GdkRectangle* working_area);
static void ft_chart_real_zoom_begin (FtChart* self,
                               gdouble x_value,
                               gdouble y_value,
                               gdouble x,
                               gdouble y);
static void ft_chart_real_zoom_end (FtChart* self,
                             gdouble x_value,
                             gdouble y_value,
                             gdouble x,
                             gdouble y);
static GtkSizeRequestMode ft_chart_real_get_request_mode (GtkWidget* base);
static void ft_chart_real_measure (GtkWidget* base,
                            GtkOrientation orientation,
                            gint for_size,
                            gint* minimum,
                            gint* natural,
                            gint* minimum_baseline,
                            gint* natural_baseline);
static void ft_chart_real_size_allocate (GtkWidget* base,
                                  gint width,
                                  gint height,
                                  gint baseline);
VALA_EXTERN void ft_chart_contents_configure_axes (FtChartContents* self,
                                       gint chart_width,
                                       gint chart_height);
static void ft_chart_real_snapshot (GtkWidget* base,
                             GtkSnapshot* snapshot);
static void ft_chart_real_dispose (GObject* base);
static GObject * ft_chart_constructor (GType type,
                                guint n_construct_properties,
                                GObjectConstructParam * construct_properties);
static Block8Data* block8_data_ref (Block8Data* _data8_);
static void block8_data_unref (void * _userdata_);
static gchar* _ft_chart___lambda13_ (Block8Data* _data8_,
                              gdouble value);
static gchar* __ft_chart___lambda13__ft_format_value_func (gdouble value,
                                                    gpointer self);
static gchar* _ft_chart___lambda14_ (Block8Data* _data8_,
                              gdouble value);
static gchar* __ft_chart___lambda14__ft_format_value_func (gdouble value,
                                                    gpointer self);
static void ft_chart_finalize (GObject * obj);
static GType ft_chart_get_type_once (void);
static void _vala_ft_chart_get_property (GObject * object,
                                  guint property_id,
                                  GValue * value,
                                  GParamSpec * pspec);
static void _vala_ft_chart_set_property (GObject * object,
                                  guint property_id,
                                  const GValue * value,
                                  GParamSpec * pspec);
static inline gpointer _vala_memdup2 (gconstpointer mem,
                        gsize byte_size);

gchar*
ft_unit_format (FtUnit self,
                gdouble value)
{
	gchar* result;
	if (isnan (value)) {
		gchar* _tmp0_;
		_tmp0_ = g_strdup ("–");
		result = _tmp0_;
		return result;
	}
	switch (self) {
		case FT_UNIT_AMOUNT:
		{
			glong value_rounded = 0L;
			glong number = 0L;
			glong decimal = 0L;
			gchar* _tmp1_ = NULL;
			gchar* _tmp8_;
			value_rounded = (glong) round (value * 10.0);
			number = value_rounded / 10;
			decimal = labs (value_rounded) % 10;
			if (decimal == ((glong) 0)) {
				gchar* _tmp2_;
				_tmp2_ = g_strdup_printf ("%li", number);
				_g_free0 (_tmp1_);
				_tmp1_ = _tmp2_;
			} else {
				gchar* _tmp3_;
				gchar* _tmp4_;
				gchar* _tmp5_;
				gchar* _tmp6_;
				gchar* _tmp7_;
				_tmp3_ = g_strdup_printf ("%li", number);
				_tmp4_ = _tmp3_;
				_tmp5_ = g_strdup_printf ("%li", decimal);
				_tmp6_ = _tmp5_;
				_tmp7_ = g_strconcat (_tmp4_, ".", _tmp6_, NULL);
				_g_free0 (_tmp1_);
				_tmp1_ = _tmp7_;
				_g_free0 (_tmp6_);
				_g_free0 (_tmp4_);
			}
			_tmp8_ = _tmp1_;
			_tmp1_ = NULL;
			result = _tmp8_;
			_g_free0 (_tmp1_);
			return result;
		}
		case FT_UNIT_PERCENT:
		{
			gint value_rounded = 0;
			gchar* _tmp9_;
			gchar* _tmp10_;
			gchar* _tmp11_;
			gchar* _tmp12_;
			value_rounded = (gint) round (100.0 * value);
			_tmp9_ = g_strdup_printf ("%i", value_rounded);
			_tmp10_ = _tmp9_;
			_tmp11_ = g_strconcat (_tmp10_, "%", NULL);
			_tmp12_ = _tmp11_;
			_g_free0 (_tmp10_);
			result = _tmp12_;
			return result;
		}
		case FT_UNIT_INTERVAL:
		{
			gdouble value_rounded = 0.0;
			gchar* _tmp13_;
			value_rounded = 20.0 * round (value / 20.0);
			_tmp13_ = ft_interval_format_short (ft_interval_from_seconds (value_rounded), (gint64) -1);
			result = _tmp13_;
			return result;
		}
		default:
		{
			g_assert_not_reached ();
		}
	}
}

static GType
ft_unit_get_type_once (void)
{
	static const GEnumValue values[] = {{FT_UNIT_AMOUNT, "FT_UNIT_AMOUNT", "amount"}, {FT_UNIT_PERCENT, "FT_UNIT_PERCENT", "percent"}, {FT_UNIT_INTERVAL, "FT_UNIT_INTERVAL", "interval"}, {0, NULL, NULL}};
	GType ft_unit_type_id;
	ft_unit_type_id = g_enum_register_static ("FtUnit", values);
	return ft_unit_type_id;
}

GType
ft_unit_get_type (void)
{
	static volatile gsize ft_unit_type_id__once = 0;
	if (g_once_init_enter (&ft_unit_type_id__once)) {
		GType ft_unit_type_id;
		ft_unit_type_id = ft_unit_get_type_once ();
		g_once_init_leave (&ft_unit_type_id__once, ft_unit_type_id);
	}
	return ft_unit_type_id__once;
}

void
ft_category_copy (const FtCategory* self,
                  FtCategory* dest)
{
	const gchar* _tmp0_;
	gchar* _tmp1_;
	GdkRGBA _tmp2_;
	_tmp0_ = (*self).label;
	_tmp1_ = g_strdup (_tmp0_);
	_g_free0 ((*dest).label);
	(*dest).label = _tmp1_;
	_tmp2_ = (*self).color;
	(*dest).color = _tmp2_;
	(*dest).unit = (*self).unit;
	(*dest).visible = (*self).visible;
}

void
ft_category_destroy (FtCategory* self)
{
	_g_free0 ((*self).label);
}

FtCategory*
ft_category_dup (const FtCategory* self)
{
	FtCategory* dup;
	dup = g_new0 (FtCategory, 1);
	ft_category_copy (self, dup);
	return dup;
}

void
ft_category_free (FtCategory* self)
{
	ft_category_destroy (self);
	g_free (self);
}

static GType
ft_category_get_type_once (void)
{
	GType ft_category_type_id;
	ft_category_type_id = g_boxed_type_register_static ("FtCategory", (GBoxedCopyFunc) ft_category_dup, (GBoxedFreeFunc) ft_category_free);
	return ft_category_type_id;
}

GType
ft_category_get_type (void)
{
	static volatile gsize ft_category_type_id__once = 0;
	if (g_once_init_enter (&ft_category_type_id__once)) {
		GType ft_category_type_id;
		ft_category_type_id = ft_category_get_type_once ();
		g_once_init_leave (&ft_category_type_id__once, ft_category_type_id);
	}
	return ft_category_type_id__once;
}

void
ft_bucket_copy (const FtBucket* self,
                FtBucket* dest)
{
	const gchar* _tmp0_;
	gchar* _tmp1_;
	const gchar* _tmp2_;
	gchar* _tmp3_;
	_tmp0_ = (*self).label;
	_tmp1_ = g_strdup (_tmp0_);
	_g_free0 ((*dest).label);
	(*dest).label = _tmp1_;
	_tmp2_ = (*self).tooltip_label;
	_tmp3_ = g_strdup (_tmp2_);
	_g_free0 ((*dest).tooltip_label);
	(*dest).tooltip_label = _tmp3_;
}

void
ft_bucket_destroy (FtBucket* self)
{
	_g_free0 ((*self).label);
	_g_free0 ((*self).tooltip_label);
}

FtBucket*
ft_bucket_dup (const FtBucket* self)
{
	FtBucket* dup;
	dup = g_new0 (FtBucket, 1);
	ft_bucket_copy (self, dup);
	return dup;
}

void
ft_bucket_free (FtBucket* self)
{
	ft_bucket_destroy (self);
	g_free (self);
}

static GType
ft_bucket_get_type_once (void)
{
	GType ft_bucket_type_id;
	ft_bucket_type_id = g_boxed_type_register_static ("FtBucket", (GBoxedCopyFunc) ft_bucket_dup, (GBoxedFreeFunc) ft_bucket_free);
	return ft_bucket_type_id;
}

GType
ft_bucket_get_type (void)
{
	static volatile gsize ft_bucket_type_id__once = 0;
	if (g_once_init_enter (&ft_bucket_type_id__once)) {
		GType ft_bucket_type_id;
		ft_bucket_type_id = ft_bucket_get_type_once ();
		g_once_init_leave (&ft_bucket_type_id__once, ft_bucket_type_id);
	}
	return ft_bucket_type_id__once;
}

static inline gpointer
ft_chart_get_instance_private (FtChart* self)
{
	return G_STRUCT_MEMBER_P (self, FtChart_private_offset);
}

void
ft_chart_set_format_value_func (FtChart* self,
                                FtFormatValueFunc func,
                                gpointer func_target,
                                GDestroyNotify func_target_destroy_notify)
{
	FtFormatValueFunc _tmp0_;
	gpointer _tmp0__target;
	GDestroyNotify _tmp0__target_destroy_notify;
	g_return_if_fail (self != NULL);
	_tmp0_ = func;
	_tmp0__target = func_target;
	_tmp0__target_destroy_notify = func_target_destroy_notify;
	func = NULL;
	func_target = NULL;
	func_target_destroy_notify = NULL;
	(self->priv->format_value_func_target_destroy_notify == NULL) ? NULL : (self->priv->format_value_func_target_destroy_notify (self->priv->format_value_func_target), NULL);
	self->priv->format_value_func = NULL;
	self->priv->format_value_func_target = NULL;
	self->priv->format_value_func_target_destroy_notify = NULL;
	self->priv->format_value_func = _tmp0_;
	self->priv->format_value_func_target = _tmp0__target;
	self->priv->format_value_func_target_destroy_notify = _tmp0__target_destroy_notify;
	gtk_widget_queue_allocate ((GtkWidget*) self);
	(func_target_destroy_notify == NULL) ? NULL : (func_target_destroy_notify (func_target), NULL);
	func = NULL;
	func_target = NULL;
	func_target_destroy_notify = NULL;
}

static gchar*
ft_chart_real_format_x_value (FtChart* self,
                              gdouble value)
{
	gchar* _tmp0_ = NULL;
	FtFormatValueFunc _tmp1_;
	gpointer _tmp1__target;
	gchar* _tmp5_;
	gchar* result;
	_tmp1_ = self->priv->format_value_func;
	_tmp1__target = self->priv->format_value_func_target;
	if (_tmp1_ != NULL) {
		FtFormatValueFunc _tmp2_;
		gpointer _tmp2__target;
		gchar* _tmp3_;
		_tmp2_ = self->priv->format_value_func;
		_tmp2__target = self->priv->format_value_func_target;
		_tmp3_ = _tmp2_ (value, _tmp2__target);
		_g_free0 (_tmp0_);
		_tmp0_ = _tmp3_;
	} else {
		gchar* _tmp4_;
		_tmp4_ = g_strdup_printf ("%.2f", value);
		_g_free0 (_tmp0_);
		_tmp0_ = _tmp4_;
	}
	_tmp5_ = _tmp0_;
	_tmp0_ = NULL;
	result = _tmp5_;
	_g_free0 (_tmp0_);
	return result;
}

gchar*
ft_chart_format_x_value (FtChart* self,
                         gdouble value)
{
	FtChartClass* _klass_;
	g_return_val_if_fail (self != NULL, NULL);
	_klass_ = FT_CHART_GET_CLASS (self);
	if (_klass_->format_x_value) {
		return _klass_->format_x_value (self, value);
	}
	return NULL;
}

static gchar*
ft_chart_real_format_y_value (FtChart* self,
                              gdouble value)
{
	gchar* _tmp0_ = NULL;
	FtFormatValueFunc _tmp1_;
	gpointer _tmp1__target;
	gchar* _tmp5_;
	gchar* result;
	_tmp1_ = self->priv->format_value_func;
	_tmp1__target = self->priv->format_value_func_target;
	if (_tmp1_ != NULL) {
		FtFormatValueFunc _tmp2_;
		gpointer _tmp2__target;
		gchar* _tmp3_;
		_tmp2_ = self->priv->format_value_func;
		_tmp2__target = self->priv->format_value_func_target;
		_tmp3_ = _tmp2_ (value, _tmp2__target);
		_g_free0 (_tmp0_);
		_tmp0_ = _tmp3_;
	} else {
		gchar* _tmp4_;
		_tmp4_ = g_strdup_printf ("%.2f", value);
		_g_free0 (_tmp0_);
		_tmp0_ = _tmp4_;
	}
	_tmp5_ = _tmp0_;
	_tmp0_ = NULL;
	result = _tmp5_;
	_g_free0 (_tmp0_);
	return result;
}

gchar*
ft_chart_format_y_value (FtChart* self,
                         gdouble value)
{
	FtChartClass* _klass_;
	g_return_val_if_fail (self != NULL, NULL);
	_klass_ = FT_CHART_GET_CLASS (self);
	if (_klass_->format_y_value) {
		return _klass_->format_y_value (self, value);
	}
	return NULL;
}

static void
ft_chart_on_drag_begin (FtChart* self,
                        gdouble start_x,
                        gdouble start_y)
{
	GtkScrolledWindow* _tmp0_;
	GtkAdjustment* _tmp1_;
	GtkAdjustment* _tmp2_;
	gdouble _tmp3_;
	gdouble _tmp4_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->scrolled_window;
	_tmp1_ = gtk_scrolled_window_get_hadjustment (_tmp0_);
	_tmp2_ = _tmp1_;
	_tmp3_ = gtk_adjustment_get_value (_tmp2_);
	_tmp4_ = _tmp3_;
	self->priv->drag_start_x = _tmp4_;
}

static void
_ft_chart_on_drag_begin_gtk_gesture_drag_drag_begin (GtkGestureDrag* _sender,
                                                     gdouble start_x,
                                                     gdouble start_y,
                                                     gpointer self)
{
	ft_chart_on_drag_begin ((FtChart*) self, start_x, start_y);
}

static void
ft_chart_on_pan (FtChart* self,
                 GtkGesturePan* gesture,
                 GtkPanDirection direction,
                 gdouble offset)
{
	GtkScrolledWindow* _tmp0_;
	GtkAdjustment* _tmp1_;
	GtkAdjustment* _tmp2_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (gesture != NULL);
	if (direction == GTK_PAN_DIRECTION_LEFT) {
		offset = -offset;
	}
	_tmp0_ = self->priv->scrolled_window;
	_tmp1_ = gtk_scrolled_window_get_hadjustment (_tmp0_);
	_tmp2_ = _tmp1_;
	gtk_adjustment_set_value (_tmp2_, self->priv->drag_start_x - offset);
}

static void
_ft_chart_on_pan_gtk_gesture_pan_pan (GtkGesturePan* _sender,
                                      GtkPanDirection direction,
                                      gdouble offset,
                                      gpointer self)
{
	ft_chart_on_pan ((FtChart*) self, _sender, direction, offset);
}

static gpointer
_g_object_ref0 (gpointer self)
{
	return self ? g_object_ref (self) : NULL;
}

static gboolean
ft_chart_get_pointer_position (FtChart* self,
                               gdouble* x,
                               gdouble* y)
{
	gdouble _vala_x = 0.0;
	gdouble _vala_y = 0.0;
	gdouble px = 0.0;
	gdouble py = 0.0;
	gdouble nx = 0.0;
	gdouble ny = 0.0;
	graphene_point_t point = {0};
	GtkNative* native = NULL;
	GtkNative* _tmp0_;
	GtkNative* _tmp1_;
	GtkNative* _tmp2_ = NULL;
	GtkNative* _tmp3_;
	GdkSurface* _tmp4_ = NULL;
	GdkSurface* surface = NULL;
	GdkSurface* _tmp6_;
	GdkSurface* _tmp7_ = NULL;
	GdkSurface* _tmp8_;
	GdkDisplay* _tmp9_ = NULL;
	GdkSeat* _tmp11_ = NULL;
	GdkSeat* _tmp12_;
	GdkDevice* _tmp13_ = NULL;
	GdkDevice* pointer = NULL;
	GdkDevice* _tmp15_;
	GdkDevice* _tmp16_;
	GdkSurface* _tmp17_;
	GdkDevice* _tmp18_;
	gdouble _tmp19_ = 0.0;
	gdouble _tmp20_ = 0.0;
	GtkNative* _tmp21_;
	gdouble _tmp22_ = 0.0;
	gdouble _tmp23_ = 0.0;
	graphene_point_t surface_point = {0};
	GtkNative* _tmp24_;
	graphene_point_t _tmp25_;
	graphene_point_t _tmp26_ = {0};
	gboolean _tmp27_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_tmp0_ = gtk_widget_get_native ((GtkWidget*) self);
	_tmp1_ = _g_object_ref0 (_tmp0_);
	native = _tmp1_;
	_tmp3_ = native;
	_tmp2_ = _tmp3_;
	_tmp4_ = NULL;
	if (_tmp2_ != NULL) {
		GdkSurface* _tmp5_;
		_tmp5_ = gtk_native_get_surface (_tmp2_);
		_tmp4_ = _tmp5_;
	}
	_tmp6_ = _g_object_ref0 (_tmp4_);
	surface = _tmp6_;
	_tmp8_ = surface;
	_tmp7_ = _tmp8_;
	_tmp9_ = NULL;
	if (_tmp7_ != NULL) {
		GdkDisplay* _tmp10_;
		_tmp10_ = gdk_surface_get_display (_tmp7_);
		_tmp9_ = _tmp10_;
	}
	_tmp12_ = gdk_display_get_default_seat (_tmp9_);
	_tmp11_ = _tmp12_;
	_tmp13_ = NULL;
	if (_tmp11_ != NULL) {
		GdkDevice* _tmp14_;
		_tmp14_ = gdk_seat_get_pointer (_tmp11_);
		_tmp13_ = _tmp14_;
	}
	_tmp15_ = _g_object_ref0 (_tmp13_);
	pointer = _tmp15_;
	_tmp16_ = pointer;
	if (_tmp16_ == NULL) {
		_vala_x = ((double) NAN);
		_vala_y = ((double) NAN);
		result = FALSE;
		_g_object_unref0 (pointer);
		_g_object_unref0 (surface);
		_g_object_unref0 (native);
		if (x) {
			*x = _vala_x;
		}
		if (y) {
			*y = _vala_y;
		}
		return result;
	}
	_tmp17_ = surface;
	_tmp18_ = pointer;
	gdk_surface_get_device_position (_tmp17_, _tmp18_, &_tmp19_, &_tmp20_, NULL);
	px = _tmp19_;
	py = _tmp20_;
	_tmp21_ = native;
	gtk_native_get_surface_transform (_tmp21_, &_tmp22_, &_tmp23_);
	nx = _tmp22_;
	ny = _tmp23_;
	memset (&surface_point, 0, sizeof (graphene_point_t));
	graphene_point_init (&surface_point, (gfloat) (px - nx), (gfloat) (py - ny));
	_tmp24_ = native;
	_tmp25_ = surface_point;
	_tmp27_ = gtk_widget_compute_point ((GtkWidget*) _tmp24_, (GtkWidget*) self, &_tmp25_, &_tmp26_);
	point = _tmp26_;
	if (_tmp27_) {
		graphene_point_t _tmp28_;
		graphene_point_t _tmp29_;
		_tmp28_ = point;
		_vala_x = (gdouble) _tmp28_.x;
		_tmp29_ = point;
		_vala_y = (gdouble) _tmp29_.y;
		result = TRUE;
		_g_object_unref0 (pointer);
		_g_object_unref0 (surface);
		_g_object_unref0 (native);
		if (x) {
			*x = _vala_x;
		}
		if (y) {
			*y = _vala_y;
		}
		return result;
	} else {
		_vala_x = ((double) NAN);
		_vala_y = ((double) NAN);
		result = FALSE;
		_g_object_unref0 (pointer);
		_g_object_unref0 (surface);
		_g_object_unref0 (native);
		if (x) {
			*x = _vala_x;
		}
		if (y) {
			*y = _vala_y;
		}
		return result;
	}
}

static gpointer
_gdk_event_ref0 (gpointer self)
{
	return self ? gdk_event_ref (self) : NULL;
}

static gboolean
ft_chart_on_scroll (FtChart* self,
                    GtkEventControllerScroll* controller,
                    gdouble dx,
                    gdouble dy)
{
	GdkEvent* event = NULL;
	GdkEvent* _tmp0_;
	GdkEvent* _tmp1_;
	gdouble x = 0.0;
	gdouble y = 0.0;
	GdkEvent* _tmp2_;
	GdkEvent* _tmp3_;
	gdouble _tmp4_ = 0.0;
	gdouble _tmp5_ = 0.0;
	gboolean _tmp6_;
	graphene_point_t point = {0};
	graphene_point_t contents_point = {0};
	FtChartContents* _tmp7_;
	graphene_point_t _tmp8_;
	graphene_point_t _tmp9_ = {0};
	gboolean _tmp10_;
	FtChartContents* _tmp11_;
	FtCanvas* _tmp12_;
	FtCanvas* _tmp13_;
	graphene_point_t _tmp14_;
	graphene_point_t _tmp15_ = {0};
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (controller != NULL, FALSE);
	_tmp0_ = gtk_event_controller_get_current_event ((GtkEventController*) controller);
	_tmp1_ = _gdk_event_ref0 (_tmp0_);
	event = _tmp1_;
	_tmp2_ = event;
	if (_tmp2_ == NULL) {
		result = FALSE;
		_gdk_event_unref0 (event);
		return result;
	}
	_tmp3_ = event;
	if ((gdk_event_get_modifier_state (_tmp3_) & GDK_CONTROL_MASK) == 0) {
		result = FALSE;
		_gdk_event_unref0 (event);
		return result;
	}
	_tmp6_ = ft_chart_get_pointer_position (self, &_tmp4_, &_tmp5_);
	x = _tmp4_;
	y = _tmp5_;
	if (!_tmp6_) {
		result = FALSE;
		_gdk_event_unref0 (event);
		return result;
	}
	memset (&point, 0, sizeof (graphene_point_t));
	graphene_point_init (&point, (gfloat) x, (gfloat) y);
	memset (&contents_point, 0, sizeof (graphene_point_t));
	_tmp7_ = self->contents;
	_tmp8_ = point;
	_tmp10_ = gtk_widget_compute_point ((GtkWidget*) self, (GtkWidget*) _tmp7_, &_tmp8_, &_tmp9_);
	contents_point = _tmp9_;
	if (!_tmp10_) {
		result = FALSE;
		_gdk_event_unref0 (event);
		return result;
	}
	_tmp11_ = self->contents;
	_tmp12_ = ft_chart_contents_get_canvas (_tmp11_);
	_tmp13_ = _tmp12_;
	_tmp14_ = contents_point;
	ft_canvas_transform_point (_tmp13_, &_tmp14_, &_tmp15_);
	contents_point = _tmp15_;
	if (dy < 0.0) {
		graphene_point_t _tmp16_;
		graphene_point_t _tmp17_;
		_tmp16_ = contents_point;
		_tmp17_ = contents_point;
		ft_chart_zoom_begin (self, (gdouble) _tmp16_.x, (gdouble) _tmp17_.y, x, y);
		g_signal_emit (self, ft_chart_signals[FT_CHART_ZOOM_IN_SIGNAL], 0);
	} else {
		if (dy > 0.0) {
			graphene_point_t _tmp18_;
			graphene_point_t _tmp19_;
			_tmp18_ = contents_point;
			_tmp19_ = contents_point;
			ft_chart_zoom_begin (self, (gdouble) _tmp18_.x, (gdouble) _tmp19_.y, x, y);
			g_signal_emit (self, ft_chart_signals[FT_CHART_ZOOM_OUT_SIGNAL], 0);
		}
	}
	result = TRUE;
	_gdk_event_unref0 (event);
	return result;
}

static gboolean
_ft_chart_on_scroll_gtk_event_controller_scroll_scroll (GtkEventControllerScroll* _sender,
                                                        gdouble dx,
                                                        gdouble dy,
                                                        gpointer self)
{
	gboolean result;
	result = ft_chart_on_scroll ((FtChart*) self, _sender, dx, dy);
	return result;
}

static GtkSizeRequestMode
ft_chart_real_get_contents_request_mode (FtChart* self,
                                         FtCanvas* canvas)
{
	g_critical ("Type `%s' does not implement abstract method `ft_chart_get_contents_request_mode'", g_type_name (G_TYPE_FROM_INSTANCE (self)));
	return 0;
}

GtkSizeRequestMode
ft_chart_get_contents_request_mode (FtChart* self,
                                    FtCanvas* canvas)
{
	FtChartClass* _klass_;
	g_return_val_if_fail (self != NULL, 0);
	_klass_ = FT_CHART_GET_CLASS (self);
	if (_klass_->get_contents_request_mode) {
		return _klass_->get_contents_request_mode (self, canvas);
	}
	return 0;
}

/**
         * Create and position canvas items in the value space.
         */
static void
ft_chart_real_update_canvas (FtChart* self,
                             FtCanvas* canvas)
{
	g_critical ("Type `%s' does not implement abstract method `ft_chart_update_canvas'", g_type_name (G_TYPE_FROM_INSTANCE (self)));
	return;
}

void
ft_chart_update_canvas (FtChart* self,
                        FtCanvas* canvas)
{
	FtChartClass* _klass_;
	g_return_if_fail (self != NULL);
	_klass_ = FT_CHART_GET_CLASS (self);
	if (_klass_->update_canvas) {
		_klass_->update_canvas (self, canvas);
	}
}

static void
ft_chart_real_measure_canvas (FtChart* self,
                              FtCanvas* canvas,
                              GtkOrientation orientation,
                              gint for_size,
                              gint* minimum,
                              gint* natural)
{
	g_critical ("Type `%s' does not implement abstract method `ft_chart_measure_canvas'", g_type_name (G_TYPE_FROM_INSTANCE (self)));
	return;
}

void
ft_chart_measure_canvas (FtChart* self,
                         FtCanvas* canvas,
                         GtkOrientation orientation,
                         gint for_size,
                         gint* minimum,
                         gint* natural)
{
	FtChartClass* _klass_;
	g_return_if_fail (self != NULL);
	_klass_ = FT_CHART_GET_CLASS (self);
	if (_klass_->measure_canvas) {
		_klass_->measure_canvas (self, canvas, orientation, for_size, minimum, natural);
	}
}

/**
         * A method for calculating items size before allocation. It's expected that you update
         * items origin point for the widgets.
         *
         * At this point canvas scale is not calculated yet, nor we know items final positions
         * at the pixel-level.
         *
         * If size exceeds `available_width`, the content will be scrolled horizontally. The
         * `working_area` represents area available for drawing values.
         */
static void
ft_chart_real_measure_working_area (FtChart* self,
                                    FtCanvas* canvas,
                                    gint available_width,
                                    gint available_height,
                                    GdkRectangle* working_area)
{
	g_critical ("Type `%s' does not implement abstract method `ft_chart_measure_working_area'", g_type_name (G_TYPE_FROM_INSTANCE (self)));
	return;
}

void
ft_chart_measure_working_area (FtChart* self,
                               FtCanvas* canvas,
                               gint available_width,
                               gint available_height,
                               GdkRectangle* working_area)
{
	FtChartClass* _klass_;
	g_return_if_fail (self != NULL);
	_klass_ = FT_CHART_GET_CLASS (self);
	if (_klass_->measure_working_area) {
		_klass_->measure_working_area (self, canvas, available_width, available_height, working_area);
	}
}

void
ft_chart_queue_update (FtChart* self)
{
	g_return_if_fail (self != NULL);
	gtk_widget_queue_resize ((GtkWidget*) self);
}

static void
ft_chart_real_zoom_begin (FtChart* self,
                          gdouble x_value,
                          gdouble y_value,
                          gdouble x,
                          gdouble y)
{
	self->priv->zoom_x_value = x_value;
	self->priv->zoom_y_value = y_value;
	self->priv->zoom_x = x;
	self->priv->zoom_y = y;
	self->priv->zooming = TRUE;
}

void
ft_chart_zoom_begin (FtChart* self,
                     gdouble x_value,
                     gdouble y_value,
                     gdouble x,
                     gdouble y)
{
	FtChartClass* _klass_;
	g_return_if_fail (self != NULL);
	_klass_ = FT_CHART_GET_CLASS (self);
	if (_klass_->zoom_begin) {
		_klass_->zoom_begin (self, x_value, y_value, x, y);
	}
}

static void
ft_chart_real_zoom_end (FtChart* self,
                        gdouble x_value,
                        gdouble y_value,
                        gdouble x,
                        gdouble y)
{
	graphene_point_t contents_point = {0};
	FtChartContents* _tmp0_;
	FtCanvas* _tmp1_;
	FtCanvas* _tmp2_;
	graphene_point_t _tmp3_;
	graphene_point_t _tmp4_ = {0};
	graphene_point_t point = {0};
	FtChartContents* _tmp5_;
	graphene_point_t _tmp6_;
	graphene_point_t _tmp7_ = {0};
	gboolean _tmp8_;
	memset (&contents_point, 0, sizeof (graphene_point_t));
	graphene_point_init (&contents_point, (gfloat) x_value, (gfloat) y_value);
	_tmp0_ = self->contents;
	_tmp1_ = ft_chart_contents_get_canvas (_tmp0_);
	_tmp2_ = _tmp1_;
	_tmp3_ = contents_point;
	ft_canvas_transform_point_inv (_tmp2_, &_tmp3_, &_tmp4_);
	contents_point = _tmp4_;
	memset (&point, 0, sizeof (graphene_point_t));
	_tmp5_ = self->contents;
	_tmp6_ = contents_point;
	_tmp8_ = gtk_widget_compute_point ((GtkWidget*) _tmp5_, (GtkWidget*) self, &_tmp6_, &_tmp7_);
	point = _tmp7_;
	if (_tmp8_) {
		GtkAdjustment* hadjustment = NULL;
		GtkScrolledWindow* _tmp9_;
		GtkAdjustment* _tmp10_;
		GtkAdjustment* _tmp11_;
		GtkAdjustment* _tmp12_;
		GtkAdjustment* _tmp13_;
		GtkAdjustment* _tmp14_;
		gdouble _tmp15_;
		gdouble _tmp16_;
		graphene_point_t _tmp17_;
		GtkAdjustment* _tmp18_;
		gdouble _tmp19_;
		gdouble _tmp20_;
		GtkAdjustment* _tmp21_;
		gdouble _tmp22_;
		gdouble _tmp23_;
		_tmp9_ = self->priv->scrolled_window;
		_tmp10_ = gtk_scrolled_window_get_hadjustment (_tmp9_);
		_tmp11_ = _tmp10_;
		_tmp12_ = _g_object_ref0 (_tmp11_);
		hadjustment = _tmp12_;
		_tmp13_ = hadjustment;
		_tmp14_ = hadjustment;
		_tmp15_ = gtk_adjustment_get_value (_tmp14_);
		_tmp16_ = _tmp15_;
		_tmp17_ = point;
		_tmp18_ = hadjustment;
		_tmp19_ = gtk_adjustment_get_lower (_tmp18_);
		_tmp20_ = _tmp19_;
		_tmp21_ = hadjustment;
		_tmp22_ = gtk_adjustment_get_upper (_tmp21_);
		_tmp23_ = _tmp22_;
		gtk_adjustment_set_value (_tmp13_, CLAMP ((_tmp16_ + _tmp17_.x) - x, _tmp20_, _tmp23_));
		_g_object_unref0 (hadjustment);
	}
	self->priv->zooming = FALSE;
}

void
ft_chart_zoom_end (FtChart* self,
                   gdouble x_value,
                   gdouble y_value,
                   gdouble x,
                   gdouble y)
{
	FtChartClass* _klass_;
	g_return_if_fail (self != NULL);
	_klass_ = FT_CHART_GET_CLASS (self);
	if (_klass_->zoom_end) {
		_klass_->zoom_end (self, x_value, y_value, x, y);
	}
}

static GtkSizeRequestMode
ft_chart_real_get_request_mode (GtkWidget* base)
{
	FtChart * self;
	GtkSizeRequestMode result;
	self = (FtChart*) base;
	result = GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
	return result;
}

static void
ft_chart_real_measure (GtkWidget* base,
                       GtkOrientation orientation,
                       gint for_size,
                       gint* minimum,
                       gint* natural,
                       gint* minimum_baseline,
                       gint* natural_baseline)
{
	FtChart * self;
	gint _vala_minimum = 0;
	gint _vala_natural = 0;
	gint _vala_minimum_baseline = 0;
	gint _vala_natural_baseline = 0;
	GtkScrolledWindow* _tmp0_;
	gint _tmp1_ = 0;
	gint _tmp2_ = 0;
	self = (FtChart*) base;
	_tmp0_ = self->priv->scrolled_window;
	gtk_widget_measure ((GtkWidget*) _tmp0_, orientation, for_size, &_tmp1_, &_tmp2_, NULL, NULL);
	_vala_minimum = _tmp1_;
	_vala_natural = _tmp2_;
	if (orientation == GTK_ORIENTATION_HORIZONTAL) {
		gint _tmp3_;
		gint _tmp4_;
		_vala_minimum = MAX (FT_CHART_MIN_WIDTH, _vala_minimum);
		g_object_get ((GtkWidget*) self, "width-request", &_tmp3_, NULL);
		_tmp4_ = _tmp3_;
		_vala_natural = MAX (_vala_minimum, _tmp4_);
	} else {
		gint _tmp5_;
		gint _tmp6_;
		gboolean _tmp7_ = FALSE;
		_vala_minimum = MAX (FT_CHART_MIN_HEIGHT, _vala_minimum);
		g_object_get ((GtkWidget*) self, "height-request", &_tmp5_, NULL);
		_tmp6_ = _tmp5_;
		_vala_natural = MAX (_vala_minimum, _tmp6_);
		if (for_size > 0) {
			gfloat _tmp8_;
			gfloat _tmp9_;
			_tmp8_ = ft_chart_get_aspect_ratio (self);
			_tmp9_ = _tmp8_;
			_tmp7_ = _tmp9_ > 0.0f;
		} else {
			_tmp7_ = FALSE;
		}
		if (_tmp7_) {
			gfloat _tmp10_;
			gfloat _tmp11_;
			_tmp10_ = ft_chart_get_aspect_ratio (self);
			_tmp11_ = _tmp10_;
			_vala_natural = MAX ((gint) roundf (((gfloat) for_size) / _tmp11_), _vala_minimum);
		}
	}
	_vala_minimum_baseline = -1;
	_vala_natural_baseline = -1;
	if (minimum) {
		*minimum = _vala_minimum;
	}
	if (natural) {
		*natural = _vala_natural;
	}
	if (minimum_baseline) {
		*minimum_baseline = _vala_minimum_baseline;
	}
	if (natural_baseline) {
		*natural_baseline = _vala_natural_baseline;
	}
}

/**
         * Calculate chart layout
         *
         * Base class allocates axes, handles content sizing. Content may be scrolled horizontally
         * if there is not enough space.
         */
static void
ft_chart_real_size_allocate (GtkWidget* base,
                             gint width,
                             gint height,
                             gint baseline)
{
	FtChart * self;
	FtChartContents* _tmp0_;
	FtCanvas* _tmp1_;
	FtCanvas* _tmp2_;
	FtChartContents* _tmp3_;
	gint _tmp4_ = 0;
	FtChartAxis* _tmp5_;
	gint y_axis_width = 0;
	GtkAllocation scrolled_window_allocation = {0};
	GtkAllocation _tmp7_ = {0};
	GtkScrolledWindow* _tmp8_;
	GtkAllocation _tmp9_;
	FtChartAxis* _tmp10_;
	self = (FtChart*) base;
	_tmp0_ = self->contents;
	_tmp1_ = ft_chart_contents_get_canvas (_tmp0_);
	_tmp2_ = _tmp1_;
	ft_chart_update_canvas (self, _tmp2_);
	_tmp3_ = self->contents;
	ft_chart_contents_configure_axes (_tmp3_, width, height);
	_tmp5_ = self->priv->y_axis;
	if (_tmp5_ != NULL) {
		FtChartAxis* _tmp6_;
		_tmp6_ = self->priv->y_axis;
		_tmp4_ = _tmp6_->label_width;
	} else {
		_tmp4_ = 0;
	}
	y_axis_width = _tmp4_;
	memset (&_tmp7_, 0, sizeof (GtkAllocation));
	_tmp7_.x = y_axis_width;
	_tmp7_.y = 0;
	_tmp7_.width = width - y_axis_width;
	_tmp7_.height = height;
	scrolled_window_allocation = _tmp7_;
	_tmp8_ = self->priv->scrolled_window;
	_tmp9_ = scrolled_window_allocation;
	gtk_widget_size_allocate ((GtkWidget*) _tmp8_, &_tmp9_, -1);
	_tmp10_ = self->priv->y_axis;
	if (_tmp10_ != NULL) {
		GtkAllocation y_axis_allocation = {0};
		FtChartContents* _tmp11_;
		gint _tmp12_;
		gint _tmp13_;
		FtChartAxis* _tmp14_;
		gint _tmp15_;
		gint _tmp16_;
		GtkAllocation _tmp17_ = {0};
		FtChartAxis* _tmp18_;
		gint _tmp19_ = 0;
		FtChartAxis* _tmp20_;
		gint _tmp21_ = 0;
		FtChartAxis* _tmp22_;
		GtkAllocation _tmp23_;
		_tmp11_ = self->contents;
		_tmp12_ = ft_chart_contents_get_y_origin (_tmp11_);
		_tmp13_ = _tmp12_;
		_tmp14_ = self->priv->y_axis;
		_tmp15_ = ft_chart_axis_get_origin (_tmp14_);
		_tmp16_ = _tmp15_;
		memset (&_tmp17_, 0, sizeof (GtkAllocation));
		_tmp17_.x = 0;
		_tmp17_.y = _tmp13_ - _tmp16_;
		y_axis_allocation = _tmp17_;
		_tmp18_ = self->priv->y_axis;
		gtk_widget_measure ((GtkWidget*) _tmp18_, GTK_ORIENTATION_HORIZONTAL, -1, NULL, &_tmp19_, NULL, NULL);
		y_axis_allocation.width = _tmp19_;
		_tmp20_ = self->priv->y_axis;
		gtk_widget_measure ((GtkWidget*) _tmp20_, GTK_ORIENTATION_VERTICAL, -1, NULL, &_tmp21_, NULL, NULL);
		y_axis_allocation.height = _tmp21_;
		_tmp22_ = self->priv->y_axis;
		_tmp23_ = y_axis_allocation;
		gtk_widget_size_allocate ((GtkWidget*) _tmp22_, &_tmp23_, -1);
	}
	if (self->priv->zooming) {
		ft_chart_zoom_end (self, self->priv->zoom_x_value, self->priv->zoom_y_value, self->priv->zoom_x, self->priv->zoom_y);
	}
}

static void
ft_chart_real_snapshot (GtkWidget* base,
                        GtkSnapshot* snapshot)
{
	FtChart * self;
	GtkScrolledWindow* _tmp0_;
	FtChartAxis* _tmp1_;
	self = (FtChart*) base;
	g_return_if_fail (snapshot != NULL);
	_tmp0_ = self->priv->scrolled_window;
	gtk_widget_snapshot_child ((GtkWidget*) self, (GtkWidget*) _tmp0_, snapshot);
	_tmp1_ = self->priv->y_axis;
	if (_tmp1_ != NULL) {
		FtChartAxis* _tmp2_;
		_tmp2_ = self->priv->y_axis;
		gtk_widget_snapshot_child ((GtkWidget*) self, (GtkWidget*) _tmp2_, snapshot);
	}
}

static void
ft_chart_real_dispose (GObject* base)
{
	FtChart * self;
	FtChartAxis* _tmp0_;
	FtChartContents* _tmp2_;
	FtChartAxis* _tmp3_;
	FtChartAxis* _tmp4_;
	FtChartContents* _tmp5_;
	FtChartAxis* _tmp6_;
	FtChartAxis* _tmp7_;
	GtkScrolledWindow* _tmp8_;
	self = (FtChart*) base;
	_tmp0_ = self->priv->y_axis;
	if (_tmp0_ != NULL) {
		FtChartAxis* _tmp1_;
		_tmp1_ = self->priv->y_axis;
		gtk_widget_unparent ((GtkWidget*) _tmp1_);
		_g_object_unref0 (self->priv->y_axis);
		self->priv->y_axis = NULL;
	}
	g_object_ref ((GObject*) self);
	_tmp2_ = self->contents;
	_tmp3_ = ft_chart_contents_get_x_axis (_tmp2_);
	_tmp4_ = _tmp3_;
	ft_chart_axis_set_format_value_func (_tmp4_, NULL, NULL, NULL);
	_tmp5_ = self->contents;
	_tmp6_ = ft_chart_contents_get_y_axis (_tmp5_);
	_tmp7_ = _tmp6_;
	ft_chart_axis_set_format_value_func (_tmp7_, NULL, NULL, NULL);
	_tmp8_ = self->priv->scrolled_window;
	gtk_scrolled_window_set_child (_tmp8_, NULL);
	(self->priv->format_value_func_target_destroy_notify == NULL) ? NULL : (self->priv->format_value_func_target_destroy_notify (self->priv->format_value_func_target), NULL);
	self->priv->format_value_func = NULL;
	self->priv->format_value_func_target = NULL;
	self->priv->format_value_func_target_destroy_notify = NULL;
	self->priv->format_value_func = NULL;
	self->priv->format_value_func_target = NULL;
	self->priv->format_value_func_target_destroy_notify = NULL;
	gtk_widget_dispose_template ((GtkWidget*) self, FT_TYPE_CHART);
	G_OBJECT_CLASS (ft_chart_parent_class)->dispose ((GObject*) G_TYPE_CHECK_INSTANCE_CAST (self, gtk_widget_get_type (), GtkWidget));
}

FtChart*
ft_chart_construct (GType object_type)
{
	FtChart * self = NULL;
	self = (FtChart*) g_object_new (object_type, NULL);
	return self;
}

gfloat
ft_chart_get_x_spacing (FtChart* self)
{
	gfloat result;
	g_return_val_if_fail (self != NULL, -1.0F);
	result = self->priv->_x_spacing;
	return result;
}

void
ft_chart_set_x_spacing (FtChart* self,
                        gfloat value)
{
	g_return_if_fail (self != NULL);
	if (self->priv->_x_spacing == value) {
		return;
	}
	self->priv->_x_spacing = value;
	gtk_widget_queue_allocate ((GtkWidget*) self);
	g_object_notify_by_pspec ((GObject *) self, ft_chart_properties[FT_CHART_X_SPACING_PROPERTY]);
}

gfloat
ft_chart_get_y_spacing (FtChart* self)
{
	gfloat result;
	g_return_val_if_fail (self != NULL, -1.0F);
	result = self->priv->_y_spacing;
	return result;
}

void
ft_chart_set_y_spacing (FtChart* self,
                        gfloat value)
{
	g_return_if_fail (self != NULL);
	if (self->priv->_y_spacing == value) {
		return;
	}
	self->priv->_y_spacing = value;
	gtk_widget_queue_allocate ((GtkWidget*) self);
	g_object_notify_by_pspec ((GObject *) self, ft_chart_properties[FT_CHART_Y_SPACING_PROPERTY]);
}

gfloat
ft_chart_get_aspect_ratio (FtChart* self)
{
	gfloat result;
	g_return_val_if_fail (self != NULL, -1.0F);
	result = self->priv->_aspect_ratio;
	return result;
}

void
ft_chart_set_aspect_ratio (FtChart* self,
                           gfloat value)
{
	g_return_if_fail (self != NULL);
	self->priv->_aspect_ratio = value;
	gtk_widget_queue_resize ((GtkWidget*) self);
	g_object_notify_by_pspec ((GObject *) self, ft_chart_properties[FT_CHART_ASPECT_RATIO_PROPERTY]);
}

static Block8Data*
block8_data_ref (Block8Data* _data8_)
{
	g_atomic_int_inc (&_data8_->_ref_count_);
	return _data8_;
}

static void
block8_data_unref (void * _userdata_)
{
	Block8Data* _data8_;
	_data8_ = (Block8Data*) _userdata_;
	if (g_atomic_int_dec_and_test (&_data8_->_ref_count_)) {
		FtChart* self;
		self = _data8_->self;
		_g_object_unref0 (self);
		g_slice_free (Block8Data, _data8_);
	}
}

static gchar*
_ft_chart___lambda13_ (Block8Data* _data8_,
                       gdouble value)
{
	FtChart* self;
	FtChart* _tmp0_;
	gchar* _tmp1_;
	gchar* result;
	self = _data8_->self;
	_tmp0_ = _data8_->_self_;
	_tmp1_ = ft_chart_format_x_value (_tmp0_, value);
	result = _tmp1_;
	return result;
}

static gchar*
__ft_chart___lambda13__ft_format_value_func (gdouble value,
                                             gpointer self)
{
	gchar* result;
	result = _ft_chart___lambda13_ (self, value);
	return result;
}

static gchar*
_ft_chart___lambda14_ (Block8Data* _data8_,
                       gdouble value)
{
	FtChart* self;
	FtChart* _tmp0_;
	gchar* _tmp1_;
	gchar* result;
	self = _data8_->self;
	_tmp0_ = _data8_->_self_;
	_tmp1_ = ft_chart_format_y_value (_tmp0_, value);
	result = _tmp1_;
	return result;
}

static gchar*
__ft_chart___lambda14__ft_format_value_func (gdouble value,
                                             gpointer self)
{
	gchar* result;
	result = _ft_chart___lambda14_ (self, value);
	return result;
}

static GObject *
ft_chart_constructor (GType type,
                      guint n_construct_properties,
                      GObjectConstructParam * construct_properties)
{
	GObject * obj;
	GObjectClass * parent_class;
	FtChart * self;
	Block8Data* _data8_;
	FtChartContents* _tmp0_;
	FtChartAxis* _tmp1_;
	FtChartAxis* _tmp2_;
	FtChartContents* _tmp3_;
	FtChartAxis* _tmp4_;
	FtChartAxis* _tmp5_;
	FtChartContents* _tmp6_;
	FtChartAxis* _tmp7_;
	FtChartAxis* _tmp8_;
	FtChartAxis* _tmp9_;
	FtChartAxis* _tmp10_;
	parent_class = G_OBJECT_CLASS (ft_chart_parent_class);
	obj = parent_class->constructor (type, n_construct_properties, construct_properties);
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, FT_TYPE_CHART, FtChart);
	_data8_ = g_slice_new0 (Block8Data);
	_data8_->_ref_count_ = 1;
	_data8_->self = g_object_ref (self);
	_data8_->_self_ = self;
	_tmp0_ = self->contents;
	_tmp1_ = ft_chart_contents_get_x_axis (_tmp0_);
	_tmp2_ = _tmp1_;
	ft_chart_axis_set_format_value_func (_tmp2_, __ft_chart___lambda13__ft_format_value_func, block8_data_ref (_data8_), block8_data_unref);
	_tmp3_ = self->contents;
	_tmp4_ = ft_chart_contents_get_y_axis (_tmp3_);
	_tmp5_ = _tmp4_;
	ft_chart_axis_set_format_value_func (_tmp5_, __ft_chart___lambda14__ft_format_value_func, block8_data_ref (_data8_), block8_data_unref);
	_tmp6_ = self->contents;
	_tmp7_ = ft_chart_contents_get_y_axis (_tmp6_);
	_tmp8_ = _tmp7_;
	_tmp9_ = ft_chart_axis_detach (_tmp8_);
	_g_object_unref0 (self->priv->y_axis);
	self->priv->y_axis = _tmp9_;
	_tmp10_ = self->priv->y_axis;
	gtk_widget_insert_before ((GtkWidget*) _tmp10_, (GtkWidget*) self, NULL);
	g_object_unref ((GObject*) self);
	block8_data_unref (_data8_);
	_data8_ = NULL;
	return obj;
}

static void
ft_chart_class_init (FtChartClass * klass,
                     gpointer klass_data)
{
	ft_chart_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &FtChart_private_offset);
	((FtChartClass *) klass)->format_x_value = (gchar* (*) (FtChart*, gdouble)) ft_chart_real_format_x_value;
	((FtChartClass *) klass)->format_y_value = (gchar* (*) (FtChart*, gdouble)) ft_chart_real_format_y_value;
	((FtChartClass *) klass)->get_contents_request_mode = (GtkSizeRequestMode (*) (FtChart*, FtCanvas*)) ft_chart_real_get_contents_request_mode;
	((FtChartClass *) klass)->update_canvas = (void (*) (FtChart*, FtCanvas*)) ft_chart_real_update_canvas;
	((FtChartClass *) klass)->measure_canvas = (void (*) (FtChart*, FtCanvas*, GtkOrientation, gint, gint*, gint*)) ft_chart_real_measure_canvas;
	((FtChartClass *) klass)->measure_working_area = (void (*) (FtChart*, FtCanvas*, gint, gint, GdkRectangle*)) ft_chart_real_measure_working_area;
	((FtChartClass *) klass)->zoom_begin = (void (*) (FtChart*, gdouble, gdouble, gdouble, gdouble)) ft_chart_real_zoom_begin;
	((FtChartClass *) klass)->zoom_end = (void (*) (FtChart*, gdouble, gdouble, gdouble, gdouble)) ft_chart_real_zoom_end;
	((GtkWidgetClass *) klass)->get_request_mode = (GtkSizeRequestMode (*) (GtkWidget*)) ft_chart_real_get_request_mode;
	((GtkWidgetClass *) klass)->measure = (void (*) (GtkWidget*, GtkOrientation, gint, gint*, gint*, gint*, gint*)) ft_chart_real_measure;
	((GtkWidgetClass *) klass)->size_allocate = (void (*) (GtkWidget*, gint, gint, gint)) ft_chart_real_size_allocate;
	((GtkWidgetClass *) klass)->snapshot = (void (*) (GtkWidget*, GtkSnapshot*)) ft_chart_real_snapshot;
	((GObjectClass *) klass)->dispose = (void (*) (GObject*)) ft_chart_real_dispose;
	G_OBJECT_CLASS (klass)->get_property = _vala_ft_chart_get_property;
	G_OBJECT_CLASS (klass)->set_property = _vala_ft_chart_set_property;
	G_OBJECT_CLASS (klass)->constructor = ft_chart_constructor;
	G_OBJECT_CLASS (klass)->finalize = ft_chart_finalize;
	/**
	         * Interval between ticks on x axis
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), FT_CHART_X_SPACING_PROPERTY, ft_chart_properties[FT_CHART_X_SPACING_PROPERTY] = g_param_spec_float ("x-spacing", "x-spacing", "x-spacing", -G_MAXFLOAT, G_MAXFLOAT, 0.0F, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE));
	/**
	         * Interval between ticks on y axis
	         */
	g_object_class_install_property (G_OBJECT_CLASS (klass), FT_CHART_Y_SPACING_PROPERTY, ft_chart_properties[FT_CHART_Y_SPACING_PROPERTY] = g_param_spec_float ("y-spacing", "y-spacing", "y-spacing", -G_MAXFLOAT, G_MAXFLOAT, 0.0F, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE));
	g_object_class_install_property (G_OBJECT_CLASS (klass), FT_CHART_ASPECT_RATIO_PROPERTY, ft_chart_properties[FT_CHART_ASPECT_RATIO_PROPERTY] = g_param_spec_float ("aspect-ratio", "aspect-ratio", "aspect-ratio", -G_MAXFLOAT, G_MAXFLOAT, 0.0F, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE));
	gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass), "/io/github/focustimerhq/FocusTimer/ui/main/stats/charts/chart.ui");
	ft_chart_signals[FT_CHART_ZOOM_IN_SIGNAL] = g_signal_new ("zoom-in", FT_TYPE_CHART, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
	ft_chart_signals[FT_CHART_ZOOM_OUT_SIGNAL] = g_signal_new ("zoom-out", FT_TYPE_CHART, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
	gtk_widget_class_bind_template_child_full (GTK_WIDGET_CLASS (klass), "contents", FALSE, G_STRUCT_OFFSET (FtChart, contents));
	gtk_widget_class_bind_template_child_full (GTK_WIDGET_CLASS (klass), "scrolled_window", FALSE, FtChart_private_offset + G_STRUCT_OFFSET (FtChartPrivate, scrolled_window));
	gtk_widget_class_bind_template_callback_full (GTK_WIDGET_CLASS (klass), "on_drag_begin", G_CALLBACK(_ft_chart_on_drag_begin_gtk_gesture_drag_drag_begin));
	gtk_widget_class_bind_template_callback_full (GTK_WIDGET_CLASS (klass), "on_pan", G_CALLBACK(_ft_chart_on_pan_gtk_gesture_pan_pan));
	gtk_widget_class_bind_template_callback_full (GTK_WIDGET_CLASS (klass), "on_scroll", G_CALLBACK(_ft_chart_on_scroll_gtk_event_controller_scroll_scroll));
	gtk_widget_class_set_css_name (GTK_WIDGET_CLASS (klass), "chart");
}

static void
ft_chart_gtk_buildable_interface_init (GtkBuildableIface * iface,
                                       gpointer iface_data)
{
	ft_chart_gtk_buildable_parent_iface = g_type_interface_peek_parent (iface);
}

static void
ft_chart_instance_init (FtChart * self,
                        gpointer klass)
{
	self->priv = ft_chart_get_instance_private (self);
	self->priv->y_axis = NULL;
	self->priv->_x_spacing = 1.0f;
	self->priv->_y_spacing = 1.0f;
	self->priv->_aspect_ratio = 1.0f;
	self->priv->zooming = FALSE;
	self->priv->format_value_func = NULL;
	self->priv->format_value_func_target = NULL;
	self->priv->format_value_func_target_destroy_notify = NULL;
	g_type_ensure (FT_TYPE_CHART_CONTENTS);
	gtk_widget_init_template (GTK_WIDGET (self));
}

static void
ft_chart_finalize (GObject * obj)
{
	FtChart * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, FT_TYPE_CHART, FtChart);
	_g_object_unref0 (self->priv->y_axis);
	(self->priv->format_value_func_target_destroy_notify == NULL) ? NULL : (self->priv->format_value_func_target_destroy_notify (self->priv->format_value_func_target), NULL);
	self->priv->format_value_func = NULL;
	self->priv->format_value_func_target = NULL;
	self->priv->format_value_func_target_destroy_notify = NULL;
	G_OBJECT_CLASS (ft_chart_parent_class)->finalize (obj);
}

/**
     * Base class for drawing a 2D charts with X and Y axes.
     *
     * The content is scrollable horizontally.
     */
static GType
ft_chart_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (FtChartClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) ft_chart_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (FtChart), 0, (GInstanceInitFunc) ft_chart_instance_init, NULL };
	static const GInterfaceInfo gtk_buildable_info = { (GInterfaceInitFunc) ft_chart_gtk_buildable_interface_init, (GInterfaceFinalizeFunc) NULL, NULL};
	GType ft_chart_type_id;
	ft_chart_type_id = g_type_register_static (gtk_widget_get_type (), "FtChart", &g_define_type_info, G_TYPE_FLAG_ABSTRACT);
	g_type_add_interface_static (ft_chart_type_id, gtk_buildable_get_type (), &gtk_buildable_info);
	FtChart_private_offset = g_type_add_instance_private (ft_chart_type_id, sizeof (FtChartPrivate));
	return ft_chart_type_id;
}

GType
ft_chart_get_type (void)
{
	static volatile gsize ft_chart_type_id__once = 0;
	if (g_once_init_enter (&ft_chart_type_id__once)) {
		GType ft_chart_type_id;
		ft_chart_type_id = ft_chart_get_type_once ();
		g_once_init_leave (&ft_chart_type_id__once, ft_chart_type_id);
	}
	return ft_chart_type_id__once;
}

static void
_vala_ft_chart_get_property (GObject * object,
                             guint property_id,
                             GValue * value,
                             GParamSpec * pspec)
{
	FtChart * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, FT_TYPE_CHART, FtChart);
	switch (property_id) {
		case FT_CHART_X_SPACING_PROPERTY:
		g_value_set_float (value, ft_chart_get_x_spacing (self));
		break;
		case FT_CHART_Y_SPACING_PROPERTY:
		g_value_set_float (value, ft_chart_get_y_spacing (self));
		break;
		case FT_CHART_ASPECT_RATIO_PROPERTY:
		g_value_set_float (value, ft_chart_get_aspect_ratio (self));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static void
_vala_ft_chart_set_property (GObject * object,
                             guint property_id,
                             const GValue * value,
                             GParamSpec * pspec)
{
	FtChart * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (object, FT_TYPE_CHART, FtChart);
	switch (property_id) {
		case FT_CHART_X_SPACING_PROPERTY:
		ft_chart_set_x_spacing (self, g_value_get_float (value));
		break;
		case FT_CHART_Y_SPACING_PROPERTY:
		ft_chart_set_y_spacing (self, g_value_get_float (value));
		break;
		case FT_CHART_ASPECT_RATIO_PROPERTY:
		ft_chart_set_aspect_ratio (self, g_value_get_float (value));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}

static inline gpointer
_vala_memdup2 (gconstpointer mem,
               gsize byte_size)
{
	gpointer new_mem;
	if (mem && byte_size != 0) {
		new_mem = g_malloc (byte_size);
		memcpy (new_mem, mem, byte_size);
	} else {
		new_mem = NULL;
	}
	return new_mem;
}

