/*
 * Remmina - The GTK+ Remote Desktop Client
 * Copyright (C) 2009 - Vic Lee 
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, 
 * Boston, MA 02111-1307, USA.
 *
 *  In addition, as a special exception, the copyright holders give
 *  permission to link the code of portions of this program with the
 *  OpenSSL library under certain conditions as described in each
 *  individual source file, and distribute linked combinations
 *  including the two.
 *  You must obey the GNU General Public License in all respects
 *  for all of the code used other than OpenSSL. *  If you modify
 *  file(s) with this exception, you may extend this exception to your
 *  version of the file(s), but you are not obligated to do so. *  If you
 *  do not wish to do so, delete this exception statement from your
 *  version. *  If you delete this exception statement from all source
 *  files in the program, then also delete it here.
 *
 */

#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include "config.h"
#include "remmina_chain_button.h"
#include "remmina_scaler.h"

G_DEFINE_TYPE( RemminaScaler, remmina_scaler, GTK_TYPE_TABLE)

#define MIN_SCALE_VALUE 0.05

struct _RemminaScalerPriv
{
	GtkWidget *hscale_widget;
	GtkWidget *vscale_widget;
	GtkWidget *aspectscale_button;
};

enum
{
	SCALED_SIGNAL, LAST_SIGNAL
};

static guint remmina_scaler_signals[LAST_SIGNAL] =
{ 0 };

static void remmina_scaler_class_init(RemminaScalerClass *klass)
{
	remmina_scaler_signals[SCALED_SIGNAL] = g_signal_new("scaled", G_TYPE_FROM_CLASS(klass),
			G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET(RemminaScalerClass, scaled), NULL, NULL,
			g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
}

static gchar*
remmina_scaler_format_scale_value(GtkScale *scale, gdouble value, gpointer user_data)
{
	if (value <= MIN_SCALE_VALUE)
	{
		return g_strdup(_("Fit window size"));
	}
	else
	{
		return g_strdup_printf("%.2f", value);
	}
}

static void remmina_scaler_on_chain_changed(RemminaChainButton *cb, RemminaScaler *scaler)
{
	scaler->aspectscale = cb->chained;
	if (cb->chained)
	{
		gtk_range_set_value(GTK_RANGE(scaler->priv->vscale_widget),
				gtk_range_get_value(GTK_RANGE(scaler->priv->hscale_widget)));
	}
	g_signal_emit(G_OBJECT(scaler), remmina_scaler_signals[SCALED_SIGNAL], 0);
}

static void remmina_scaler_on_hscale_value_changed(GtkWidget *widget, RemminaScaler *scaler)
{
	gdouble value;

	value = gtk_range_get_value(GTK_RANGE(scaler->priv->hscale_widget));
	scaler->hscale = (value <= MIN_SCALE_VALUE ? 0 : (gint)(value * 100.0));
	if (REMMINA_CHAIN_BUTTON(scaler->priv->aspectscale_button)->chained
			&& gtk_range_get_value(GTK_RANGE(scaler->priv->hscale_widget))
					!= gtk_range_get_value(GTK_RANGE(scaler->priv->vscale_widget)))
	{
		gtk_range_set_value(GTK_RANGE(scaler->priv->vscale_widget),
				gtk_range_get_value(GTK_RANGE(scaler->priv->hscale_widget)));
	}
	g_signal_emit(G_OBJECT(scaler), remmina_scaler_signals[SCALED_SIGNAL], 0);
}

static void remmina_scaler_on_vscale_value_changed(GtkWidget *widget, RemminaScaler *scaler)
{
	gdouble value;

	value = gtk_range_get_value(GTK_RANGE(scaler->priv->vscale_widget));
	scaler->vscale = (value <= MIN_SCALE_VALUE ? 0 : (gint)(value * 100.0));
	if (REMMINA_CHAIN_BUTTON(scaler->priv->aspectscale_button)->chained
			&& gtk_range_get_value(GTK_RANGE(scaler->priv->hscale_widget))
					!= gtk_range_get_value(GTK_RANGE(scaler->priv->vscale_widget)))
	{
		gtk_range_set_value(GTK_RANGE(scaler->priv->hscale_widget),
				gtk_range_get_value(GTK_RANGE(scaler->priv->vscale_widget)));
	}
	g_signal_emit(G_OBJECT(scaler), remmina_scaler_signals[SCALED_SIGNAL], 0);
}

static void remmina_scaler_destroy(RemminaScaler *scaler, gpointer data)
{
	g_free(scaler->priv);
}

static void remmina_scaler_init(RemminaScaler *scaler)
{
	RemminaScalerPriv *priv;
	GtkWidget *widget = NULL;

	priv = g_new(RemminaScalerPriv, 1);
	scaler->priv = priv;
	scaler->hscale = 0;
	scaler->vscale = 0;
	scaler->aspectscale = FALSE;

	gtk_table_resize(GTK_TABLE(scaler), 2, 2);

#if GTK_VERSION == 3
	widget = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, MIN_SCALE_VALUE, 1.0, 0.01);
#elif GTK_VERSION == 2
	widget = gtk_hscale_new_with_range(MIN_SCALE_VALUE, 1.0, 0.01);
#endif
	gtk_widget_show(widget);
	gtk_widget_set_tooltip_text(widget, _("Horizontal scale"));
	gtk_table_attach_defaults(GTK_TABLE(scaler), widget, 1, 2, 0, 1);
	g_signal_connect(G_OBJECT(widget), "format-value", G_CALLBACK(remmina_scaler_format_scale_value), NULL);
	priv->hscale_widget = widget;

#if GTK_VERSION == 3
	widget = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, MIN_SCALE_VALUE, 1.0, 0.01);
#elif GTK_VERSION == 2
	widget = gtk_hscale_new_with_range(MIN_SCALE_VALUE, 1.0, 0.01);
#endif
	gtk_widget_show(widget);
	gtk_widget_set_tooltip_text(widget, _("Vertical scale"));
	gtk_table_attach_defaults(GTK_TABLE(scaler), widget, 1, 2, 1, 2);
	g_signal_connect(G_OBJECT(widget), "format-value", G_CALLBACK(remmina_scaler_format_scale_value), NULL);
	priv->vscale_widget = widget;

	g_signal_connect(G_OBJECT(priv->hscale_widget), "value-changed", G_CALLBACK(remmina_scaler_on_hscale_value_changed),
			scaler);
	g_signal_connect(G_OBJECT(priv->vscale_widget), "value-changed", G_CALLBACK(remmina_scaler_on_vscale_value_changed),
			scaler);

	widget = remmina_chain_button_new();
	gtk_widget_show(widget);
	gtk_table_attach(GTK_TABLE(scaler), widget, 2, 3, 0, 2, 0, 0, 0, 0);
	g_signal_connect(G_OBJECT(widget), "chain-toggled", G_CALLBACK(remmina_scaler_on_chain_changed), scaler);
	priv->aspectscale_button = widget;

	g_signal_connect(G_OBJECT(scaler), "destroy", G_CALLBACK(remmina_scaler_destroy), NULL);
}

GtkWidget*
remmina_scaler_new(void)
{
	return GTK_WIDGET(g_object_new(REMMINA_TYPE_SCALER, NULL));
}

void remmina_scaler_set(RemminaScaler *scaler, gint hscale, gint vscale, gboolean chained)
{
	gtk_range_set_value(GTK_RANGE(scaler->priv->hscale_widget), ((gdouble) hscale) / 100.0);
	gtk_range_set_value(GTK_RANGE(scaler->priv->vscale_widget), ((gdouble) vscale) / 100.0);
	remmina_chain_button_set(REMMINA_CHAIN_BUTTON(scaler->priv->aspectscale_button), chained);
}

void remmina_scaler_set_draw_value(RemminaScaler *scaler, gboolean draw_value)
{
	gtk_scale_set_draw_value(GTK_SCALE(scaler->priv->hscale_widget), draw_value);
	gtk_scale_set_draw_value(GTK_SCALE(scaler->priv->vscale_widget), draw_value);
}

