/*
 *  Copyright (C) 2003 Ricardo Fernández Pascual
 *
 *  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, 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.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <gtk/gtkspinbutton.h>
#include <gtk/gtktoolitem.h>

#include "galeon-action-zoom.h"
#include "gul-gobject-misc.h"
#include "pixbuf-cache.h"
#include "galeon-shell.h"
#include <glib/gi18n.h>
#include <string.h>

/* This should be longer than the initial delay in the gtkspinbutton.c */
#define ZOOM_DELAY 250

static void		galeon_action_zoom_init				(GaleonActionZoom *action);
static void		galeon_action_zoom_class_init			(GaleonActionClass *class);
static void		galeon_action_zoom_finalize			(GObject *object);
static void		galeon_action_zoom_connect_proxy		(GtkAction *action, GtkWidget *proxy);
static void		galeon_action_zoom_update			(GaleonAction *action);
static void		galeon_action_zoom_current_embed_changed	(GaleonAction *action, 
									 GaleonEmbed *old_embed, GaleonEmbed *new_embed);
static GtkWidget *	galeon_action_zoom_create_toolitem		(GtkAction *action);

static GtkActionClass *parent_class = NULL;

MAKE_GET_TYPE (galeon_action_zoom, "GaleonActionZoom", GaleonActionZoom, galeon_action_zoom_class_init, 
	       galeon_action_zoom_init, GALEON_TYPE_ACTION);


static void
galeon_action_zoom_class_init (GaleonActionClass *class)
{
	GObjectClass *object_class = G_OBJECT_CLASS (class);
	GtkActionClass *action_class = GTK_ACTION_CLASS (class);
	GaleonActionClass *galeon_action_class = GALEON_ACTION_CLASS (class);

	object_class->finalize = galeon_action_zoom_finalize;

	action_class->create_tool_item = galeon_action_zoom_create_toolitem;
	action_class->connect_proxy = galeon_action_zoom_connect_proxy;

	galeon_action_class->update = galeon_action_zoom_update;
	galeon_action_class->current_embed_changed = galeon_action_zoom_current_embed_changed;

	parent_class = g_type_class_peek_parent (class);
}

static void
galeon_action_zoom_init (GaleonActionZoom *action)
{
	g_object_set (G_OBJECT (action), "tooltip", _("Zoom"), NULL);
	g_object_set (G_OBJECT (action), "stock_id", STOCK_ZOOM, NULL);
	g_object_set (G_OBJECT (action), "label", _("Zoom"), NULL);
	action->lock = 0;
	action->value = 100;
	action->timeout_id = 0;
}

static void
galeon_action_zoom_finalize (GObject *object)
{
	GaleonActionZoom *a = GALEON_ACTION_ZOOM (object);

	if (a->timeout_id != 0)
	{
		g_source_remove (a->timeout_id);
	}

	G_OBJECT_CLASS (parent_class)->finalize (object);
}

static void
galeon_action_zoom_update (GaleonAction *action)
{
	GaleonWindow *window;
	GaleonTab *tab;
	int zoom;
	GSList *sli;

	GALEON_ACTION_ZOOM (action)->lock++;

	window = galeon_action_get_window (GALEON_ACTION (action));
	g_return_if_fail (IS_GALEON_WINDOW (window));

	tab = galeon_window_get_active_tab (window);
	if (tab)
	{
		zoom = galeon_tab_get_zoom (GALEON_TAB (tab));
	}
	else
	{
		zoom = 100;
	}
	
	for (sli = gtk_action_get_proxies (GTK_ACTION (action)); sli; sli = sli->next)
	{
		GtkSpinButton *spin = GTK_SPIN_BUTTON (GTK_BIN (sli->data)->child);
		gtk_spin_button_set_value (spin, zoom);
	}

	GALEON_ACTION_ZOOM (action)->lock--;
}

static void
galeon_action_zoom_zoom_change_cb (GaleonEmbed *embed, gint new_zoom, GaleonAction *action)
{
	galeon_action_zoom_update (action);
}

static void
galeon_action_zoom_current_embed_changed (GaleonAction *action, 
					  GaleonEmbed *old_embed, GaleonEmbed *new_embed)
{
	if (old_embed)
	{
		g_signal_handlers_disconnect_matched (old_embed, G_SIGNAL_MATCH_DATA, 
						      0, 0, NULL, NULL, action);
	}
	
	if (new_embed)
	{
		g_signal_connect_object (new_embed, "ge-zoom-change", 
					 G_CALLBACK (galeon_action_zoom_zoom_change_cb),
					 action, 0);
	}

	galeon_action_zoom_update (action);
}

static gboolean
galeon_action_zoom_timeout_cb (gpointer data)
{
	GaleonActionZoom *t = data;
	gint zoom = t->value;
	GaleonWindow *window = galeon_action_get_window (GALEON_ACTION (t));

	g_return_val_if_fail (IS_GALEON_WINDOW (window), FALSE);

	galeon_window_set_zoom (window, zoom);

	t->timeout_id = 0;

	return FALSE;
}

static void
galeon_action_zoom_value_changed_cb (GtkSpinButton *sb, GaleonActionZoom *t)
{
	if (t->timeout_id != 0)
	{
		g_source_remove (t->timeout_id);
		t->timeout_id = 0;
	}

	if (t->lock == 0)
	{
		t->value = gtk_spin_button_get_value_as_int (sb);
		t->timeout_id = g_timeout_add (ZOOM_DELAY, galeon_action_zoom_timeout_cb, t);
	}
}

static gboolean
toolitem_create_menu_proxy_cb (GtkToolItem *toolitem, gpointer dummy)
{
	/* Don't show item in overflow menu */
	gtk_tool_item_set_proxy_menu_item (toolitem, "galeon-zoom-menu-item", NULL);
	return TRUE;
}

static GtkWidget *
galeon_action_zoom_create_toolitem (GtkAction *action)
{
	GtkToolItem *ti = gtk_tool_item_new ();
	GtkWidget *spin = gtk_spin_button_new_with_range (10, 990, 10);
	gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), 100);
	gtk_container_add (GTK_CONTAINER (ti), spin);
	gtk_widget_show (spin);

	g_signal_connect_object (spin, "value-changed",
				 G_CALLBACK (galeon_action_zoom_value_changed_cb),
				 action, 0);
	g_signal_connect (ti, "create-menu-proxy",
			  G_CALLBACK (toolitem_create_menu_proxy_cb), NULL);


	return GTK_WIDGET (ti);
}

static void
galeon_action_zoom_connect_proxy (GtkAction *action, GtkWidget *proxy)
{
	(* GTK_ACTION_CLASS (parent_class)->connect_proxy) (action, proxy);
}

