? compile
? cut-n-paste/zoom-control
Index: configure.ac
===================================================================
RCS file: /cvs/gnome/evince/configure.ac,v
retrieving revision 1.51
diff -u -r1.51 configure.ac
--- configure.ac	23 Apr 2005 00:28:14 -0000	1.51
+++ configure.ac	25 Apr 2005 19:48:44 -0000
@@ -32,6 +32,7 @@
 
 PKG_CHECK_MODULES(LIBEVPRIVATE, gtk+-2.0 >= 2.4.0)
 PKG_CHECK_MODULES(RECENT_FILES, gtk+-2.0 >= 2.4.0 libgnomeui-2.0 >= 2.4.0)
+PKG_CHECK_MODULES(ZOOM_CONTROL, gtk+-2.0 >= 2.4.0)
 PKG_CHECK_MODULES(SHELL, gtk+-2.0 >= 2.6.0 libgnomeui-2.0 gnome-vfs-2.0 libgnomeprint-2.2 libgnomeprintui-2.2 libglade-2.0 gconf-2.0 poppler-glib >= 0.1.1)
 PKG_CHECK_MODULES(THUMBNAILER, gtk+-2.0 >= 2.6.0 gnome-vfs-2.0 poppler-glib >= 0.1.1)
 PKG_CHECK_MODULES(DVI, gtk+-2.0 >= 2.6.0)
@@ -215,6 +216,7 @@
 Makefile
 cut-n-paste/Makefile
 cut-n-paste/recent-files/Makefile
+cut-n-paste/zoom-control/Makefile
 data/Makefile
 lib/Makefile
 pdf/Makefile
Index: cut-n-paste/Makefile.am
===================================================================
RCS file: /cvs/gnome/evince/cut-n-paste/Makefile.am,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 Makefile.am
--- cut-n-paste/Makefile.am	21 Dec 2004 17:40:59 -0000	1.1.1.1
+++ cut-n-paste/Makefile.am	25 Apr 2005 19:48:44 -0000
@@ -1 +1 @@
-SUBDIRS = recent-files
+SUBDIRS = recent-files zoom-control
Index: data/evince-ui.xml
===================================================================
RCS file: /cvs/gnome/evince/data/evince-ui.xml,v
retrieving revision 1.18
diff -u -r1.18 evince-ui.xml
--- data/evince-ui.xml	23 Apr 2005 17:13:40 -0000	1.18
+++ data/evince-ui.xml	25 Apr 2005 19:48:44 -0000
@@ -58,10 +58,7 @@
     <separator/>
     <toolitem action="PageSelector"/>
     <separator/>
-    <toolitem action="ViewZoomIn"/>
-    <toolitem action="ViewZoomOut"/>
-    <toolitem action="ViewBestFit"/>
-    <toolitem action="ViewPageWidth"/>
+    <toolitem action="ViewZoom"/>
 <!--
     <separator/>
     <toolitem action="SinglePage"/>
@@ -75,10 +72,7 @@
     <separator/>
     <toolitem action="PageSelector"/>
     <separator/>
-    <toolitem action="ViewZoomIn"/>
-    <toolitem action="ViewZoomOut"/>
-    <toolitem action="ViewBestFit"/>
-    <toolitem action="ViewPageWidth"/>
+    <toolitem action="ViewZoom"/>
   </toolbar>
 
   <accelerator name="EscapeAccel" action="Escape"/>
Index: shell/Makefile.am
===================================================================
RCS file: /cvs/gnome/evince/shell/Makefile.am,v
retrieving revision 1.31
diff -u -r1.31 Makefile.am
--- shell/Makefile.am	19 Apr 2005 08:57:50 -0000	1.31
+++ shell/Makefile.am	25 Apr 2005 19:48:44 -0000
@@ -5,6 +5,7 @@
 	-DGNOMEDATADIR=\"$(datadir)\"			\
 	-I$(top_srcdir)/lib				\
 	-I$(top_srcdir)/cut-n-paste/recent-files/	\
+	-I$(top_srcdir)/cut-n-paste/zoom-control/	\
 	-I$(top_srcdir)/backend				\
 	-I$(top_srcdir)/pdf				\
 	-I$(top_srcdir)/pixbuf				\
@@ -84,11 +85,13 @@
 	main.c				\
 	$(NULL)
 
-evince_LDADD=							\
-	$(SHELL_LIBS)						\
-	$(top_builddir)/cut-n-paste/recent-files/librecent.la	\
-	$(top_builddir)/lib/libev.la				\
-	libevbackendfactory.la					\
+evince_LDADD=								\
+	$(SHELL_LIBS)							\
+	$(top_builddir)/cut-n-paste/recent-files/librecent.la		\
+	$(top_builddir)/cut-n-paste/zoom-control/libephymisc.la		\
+	$(top_builddir)/cut-n-paste/zoom-control/libephywidgets.la	\
+	$(top_builddir)/lib/libev.la					\
+	libevbackendfactory.la						\
 	$(NULL)
 
 BUILT_SOURCES = ev-marshal.h ev-marshal.c
Index: shell/ev-view.c
===================================================================
RCS file: /cvs/gnome/evince/shell/ev-view.c,v
retrieving revision 1.90
diff -u -r1.90 ev-view.c
--- shell/ev-view.c	24 Apr 2005 21:26:58 -0000	1.90
+++ shell/ev-view.c	25 Apr 2005 19:48:44 -0000
@@ -1994,10 +1994,10 @@
 }
 
 #define EPSILON 0.0000001
-static void
-ev_view_zoom (EvView   *view,
-	      double    factor,
-	      gboolean  relative)
+void
+ev_view_set_zoom (EvView   *view,
+		  double    factor,
+		  gboolean  relative)
 {
 	double scale;
 
@@ -2014,6 +2014,11 @@
 	gtk_widget_queue_resize (GTK_WIDGET (view));
 }
 
+double
+ev_view_get_zoom (EvView *view)
+{
+	return view->scale;
+}
 
 void
 ev_view_set_continuous (EvView   *view,
@@ -2114,7 +2119,7 @@
 {
 	g_return_if_fail (view->sizing_mode == EV_SIZING_FREE);
 
-	ev_view_zoom (view, ZOOM_IN_FACTOR, TRUE);
+	ev_view_set_zoom (view, ZOOM_IN_FACTOR, TRUE);
 }
 
 void
@@ -2122,7 +2127,7 @@
 {
 	g_return_if_fail (view->sizing_mode == EV_SIZING_FREE);
 
-	ev_view_zoom (view, ZOOM_OUT_FACTOR, TRUE);
+	ev_view_set_zoom (view, ZOOM_OUT_FACTOR, TRUE);
 }
 
 
@@ -2199,7 +2204,7 @@
 	else
 		g_assert_not_reached ();
 
-	ev_view_zoom (view, scale, FALSE);
+	ev_view_set_zoom (view, scale, FALSE);
 }
 
 static void
@@ -2234,7 +2239,7 @@
 	else
 		g_assert_not_reached ();
 
-	ev_view_zoom (view, scale, FALSE);
+	ev_view_set_zoom (view, scale, FALSE);
 }
 
 static void
@@ -2281,7 +2286,7 @@
 	else
 		g_assert_not_reached ();
 
-	ev_view_zoom (view, scale, FALSE);
+	ev_view_set_zoom (view, scale, FALSE);
 }
 
 static void
@@ -2313,14 +2318,14 @@
 	else
 		g_assert_not_reached ();
 
-	ev_view_zoom (view, scale, FALSE);
+	ev_view_set_zoom (view, scale, FALSE);
 }
 
 
 void
 ev_view_zoom_normal (EvView *view)
 {
-	ev_view_zoom (view, 1.0, FALSE);
+	ev_view_set_zoom (view, 1.0, FALSE);
 }
 
 void
Index: shell/ev-view.h
===================================================================
RCS file: /cvs/gnome/evince/shell/ev-view.h,v
retrieving revision 1.26
diff -u -r1.26 ev-view.h
--- shell/ev-view.h	24 Apr 2005 05:16:30 -0000	1.26
+++ shell/ev-view.h	25 Apr 2005 19:48:44 -0000
@@ -73,6 +73,11 @@
 void		ev_view_zoom_in		(EvView     *view);
 gboolean        ev_view_can_zoom_out    (EvView     *view);
 void		ev_view_zoom_out	(EvView     *view);
+void		ev_view_set_zoom	(EvView     *view,
+					 double      factor,
+					 gboolean    relative);
+double		ev_view_get_zoom	(EvView      *view);
+
 void		ev_view_set_zoom_for_size (EvView     *view,
 					   int         width,
 					   int         height,
Index: shell/ev-window.c
===================================================================
RCS file: /cvs/gnome/evince/shell/ev-window.c,v
retrieving revision 1.116
diff -u -r1.116 ev-window.c
--- shell/ev-window.c	24 Apr 2005 20:40:54 -0000	1.116
+++ shell/ev-window.c	25 Apr 2005 19:48:44 -0000
@@ -47,6 +47,8 @@
 #include "egg-recent-view-gtk.h"
 #include "egg-recent-view.h"
 #include "egg-recent-model.h"
+#include "ephy-zoom.h"
+#include "ephy-zoom-action.h"
 
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
@@ -127,6 +129,7 @@
 	(G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_WINDOW, EvWindowPrivate))
 
 #define PAGE_SELECTOR_ACTION	"PageSelector"
+#define ZOOM_CONTROL_ACTION	"ViewZoom"
 
 #define GCONF_CHROME_TOOLBAR	"/apps/evince/show_toolbar"
 #define GCONF_CHROME_SIDEBAR	"/apps/evince/show_sidebar"
@@ -235,6 +238,21 @@
 
 	/* Toolbar-specific actions: */
 	set_action_sensitive (ev_window, PAGE_SELECTOR_ACTION, has_pages);
+	set_action_sensitive (ev_window, ZOOM_CONTROL_ACTION,  has_pages);
+
+	if (has_pages) {
+		GtkAction *action;
+		float      real_zoom;
+		float      zoom;
+
+		action = gtk_action_group_get_action (ev_window->priv->action_group, 
+						      ZOOM_CONTROL_ACTION);
+
+		real_zoom = ev_view_get_zoom (EV_VIEW (ev_window->priv->view));
+		zoom = ephy_zoom_get_nearest_zoom_level (real_zoom);
+
+		ephy_zoom_action_set_zoom_level (EPHY_ZOOM_ACTION (action), zoom);
+	}
 }
 
 static void
@@ -1981,6 +1999,18 @@
 }
 
 static void
+zoom_control_changed_cb (EphyZoomAction *action,
+			 float           zoom,
+			 EvWindow       *ev_window)
+{
+	g_return_if_fail (EV_IS_WINDOW (ev_window));
+	
+	ev_view_set_sizing_mode (EV_VIEW (ev_window->priv->view), EV_SIZING_FREE);
+	ev_view_set_zoom (EV_VIEW (ev_window->priv->view), zoom, FALSE);
+	update_action_sensitivity (ev_window);
+}
+
+static void
 ev_window_dispose (GObject *object)
 {
 	EvWindow *window = EV_WINDOW (object);
@@ -2197,6 +2227,18 @@
 			       "label", _("Page"),
 			       "tooltip", _("Select Page"),
 			       NULL);
+	gtk_action_group_add_action (group, action);
+	g_object_unref (action);
+
+	action = g_object_new (EPHY_TYPE_ZOOM_ACTION,
+			       "name", ZOOM_CONTROL_ACTION,
+			       "label", _("Zoom"),
+			       "stock_id", GTK_STOCK_ZOOM_IN,
+			       "tooltip", _("Adjust the zoom level"),
+			       "zoom", 1.0,
+			       NULL);
+	g_signal_connect (action, "zoom_to_level",
+			  G_CALLBACK (zoom_control_changed_cb), window);
 	gtk_action_group_add_action (group, action);
 	g_object_unref (action);
 }
--- /dev/null	2005-04-22 17:55:38.547441544 -0300
+++ cut-n-paste/zoom-control/Makefile.am	2005-04-25 15:07:31.000000000 -0300
@@ -0,0 +1,36 @@
+noinst_LTLIBRARIES = libephymisc.la libephywidgets.la
+
+libephywidgets_la_SOURCES = \
+	ephy-zoom-action.h			\
+	ephy-zoom-action.c			\
+	ephy-zoom-control.c			\
+	ephy-zoom-control.h
+
+libephywidgets_la_CPPFLAGS = \
+	-I$(top_builddir)/lib		\
+	-I$(top_srcdir)/lib		\
+	-DSHARE_DIR=\"$(pkgdatadir)\"	\
+	$(AM_CPPFLAGS)
+
+libephywidgets_la_CFLAGS = \
+	$(ZOOM_CONTROL_CFLAGS)	\
+	$(AM_CFLAGS)
+
+libephywidgets_la_LIBADD = \
+	libephymisc.la
+
+NOINST_H_FILES = \
+	ephy-zoom.h
+
+libephymisc_la_SOURCES = \
+	ephy-zoom.c				\
+	$(NOINST_H_FILES)
+
+libephymisc_la_CPPFLAGS = \
+	-I$(top_builddir)/lib			\
+	-DSHARE_DIR=\"$(pkgdatadir)\" 		\
+	$(AM_CPPFLAGS)
+
+libephymisc_la_CFLAGS = \
+        $(ZOOM_CONTROL_CFLAGS)	\
+	$(AM_CFLAGS)
\ No newline at end of file
--- /dev/null	2005-04-22 17:55:38.547441544 -0300
+++ cut-n-paste/zoom-control/ephy-zoom.h	2005-04-25 15:31:05.000000000 -0300
@@ -0,0 +1,81 @@
+/*
+ *  Copyright (C) 2003 Christian Persch
+ *
+ *  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.
+ *
+ *  $Id: ephy-zoom.h,v 1.3 2003/11/19 19:19:52 chpe Exp $
+ */
+
+#ifndef EPHY_ZOOM_H
+#define EPHY_ZOOM_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+  EPHY_ZOOM_50,
+  EPHY_ZOOM_75,
+  EPHY_ZOOM_100,
+  EPHY_ZOOM_150,
+  EPHY_ZOOM_200,
+  EPHY_ZOOM_300,
+  EPHY_ZOOM_400,
+  EPHY_ZOOM_BEST_FIT,
+  EPHY_ZOOM_PAGE_WIDTH
+} EphyZoomLevels;
+
+static const
+struct
+{
+	gchar *name;
+	float level;
+}
+
+zoom_levels[] =
+{
+	{ N_("50%"), 0.7071067811 },
+	{ N_("75%"), 0.8408964152 },
+	{ N_("100%"), 1.0 },
+	{ N_("125%"), 1.1892071149 },
+	{ N_("150%"), 1.4142135623 },
+	{ N_("175%"), 1.6817928304 },
+	{ N_("200%"), 2.0 },
+	{ N_("300%"), 2.8284271247 },
+	{ N_("400%"), 4.0 },
+	{ N_("Best Fit"), 0.0 },
+	{ N_("Fit Page Width"), 0.0 }
+};
+static const guint n_zoom_levels = G_N_ELEMENTS (zoom_levels);
+
+#define ZOOM_MINIMAL	(zoom_levels[0].level)
+#define ZOOM_MAXIMAL	(zoom_levels[n_zoom_levels - 3].level)
+#define ZOOM_IN		(-1.0)
+#define ZOOM_OUT	(-2.0)
+
+guint	ephy_zoom_get_zoom_level_index	 (float level);
+
+float	ephy_zoom_get_changed_zoom_level (float level, gint steps);
+
+float	ephy_zoom_get_nearest_zoom_level (float level);
+
+G_END_DECLS
+
+#endif
--- /dev/null	2005-04-22 17:55:38.547441544 -0300
+++ cut-n-paste/zoom-control/ephy-zoom.c	2005-04-25 11:52:42.000000000 -0300
@@ -0,0 +1,61 @@
+/*
+ *  Copyright (C) 2003 Christian Persch
+ *
+ *  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.
+ *
+ *  $Id: ephy-zoom.c,v 1.3 2004/11/02 20:57:20 chpe Exp $
+ */
+
+#include "config.h"
+
+#include "ephy-zoom.h"
+
+#include <math.h>
+
+guint
+ephy_zoom_get_zoom_level_index (float level)
+{
+	guint i;
+	float previous, current, mean;
+
+	previous = zoom_levels[0].level;
+
+	for (i = 1; i < n_zoom_levels; i++)
+	{
+		current = zoom_levels[i].level;
+		mean = sqrt (previous * current);
+
+		if (level <= mean) return i - 1;
+
+		previous = current;
+	}
+
+	return n_zoom_levels - 1;
+}
+
+
+float
+ephy_zoom_get_changed_zoom_level (float level, gint steps)
+{
+	guint index;
+
+	index = ephy_zoom_get_zoom_level_index (level);
+	return zoom_levels[CLAMP(index + steps, 0, n_zoom_levels - 1)].level;
+}
+
+float	ephy_zoom_get_nearest_zoom_level (float level)
+{
+	return ephy_zoom_get_changed_zoom_level (level, 0);
+}
--- /dev/null	2005-04-22 17:55:38.547441544 -0300
+++ cut-n-paste/zoom-control/ephy-zoom-action.h	2005-04-25 11:51:15.000000000 -0300
@@ -0,0 +1,63 @@
+/*
+ *  Copyright (C) 2003 Marco Pesenti Gritti
+ *  Copyright (C) 2003 Christian Persch
+ *
+ *  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.
+ *
+ *  $Id: ephy-zoom-action.h,v 1.6 2005/01/08 19:41:47 chpe Exp $
+ */
+
+#ifndef EPHY_ZOOM_ACTION_H
+#define EPHY_ZOOM_ACTION_H
+
+#include <gtk/gtkaction.h>
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_ZOOM_ACTION            (ephy_zoom_action_get_type ())
+#define EPHY_ZOOM_ACTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), EPHY_TYPE_ZOOM_ACTION, EphyZoomAction))
+#define EPHY_ZOOM_ACTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), EPHY_TYPE_ZOOM_ACTION, EphyZoomActionClass))
+#define EPHY_IS_ZOOM_ACTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EPHY_TYPE_ZOOM_ACTION))
+#define EPHY_IS_ZOOM_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EPHY_TYPE_ZOOM_ACTION))
+#define EPHY_ZOOM_ACTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), EPHY_TYPE_ZOOM_ACTION, EphyZoomActionClass))
+
+typedef struct _EphyZoomAction		EphyZoomAction;
+typedef struct _EphyZoomActionClass	EphyZoomActionClass;
+typedef struct _EphyZoomActionPrivate	EphyZoomActionPrivate;
+
+struct _EphyZoomAction
+{
+	GtkAction parent;
+	
+	/*< private >*/
+	EphyZoomActionPrivate *priv;
+};
+
+struct _EphyZoomActionClass
+{
+	GtkActionClass parent_class;
+
+	void (* zoom_to_level)	(EphyZoomAction *action, float level);
+};
+
+GType	ephy_zoom_action_get_type	(void);
+
+void	ephy_zoom_action_set_zoom_level	(EphyZoomAction *action, float zoom);
+
+float	ephy_zoom_action_get_zoom_level	(EphyZoomAction *action);
+
+G_END_DECLS
+
+#endif
--- /dev/null	2005-04-22 17:55:38.547441544 -0300
+++ cut-n-paste/zoom-control/ephy-zoom-action.c	2005-04-25 11:51:15.000000000 -0300
@@ -0,0 +1,276 @@
+/*
+ *  Copyright (C) 2003 Marco Pesenti Gritti
+ *  Copyright (C) 2003, 2004 Christian Persch
+ *
+ *  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.
+ *
+ *  $Id: ephy-zoom-action.c,v 1.11 2005/01/08 19:41:47 chpe Exp $
+ */
+
+#include "config.h"
+
+#include "ephy-zoom-action.h"
+#include "ephy-zoom-control.h"
+#include "ephy-zoom.h"
+
+#include <glib-object.h>
+#include <glib/gi18n.h>
+#include <gtk/gtkmenu.h>
+#include <gtk/gtkmenuitem.h>
+#include <gtk/gtkcheckmenuitem.h>
+#include <gtk/gtkradiomenuitem.h>
+
+#define EPHY_ZOOM_ACTION_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_ZOOM_ACTION, EphyZoomActionPrivate))
+
+struct _EphyZoomActionPrivate
+{
+	float zoom;
+};
+
+enum
+{
+	PROP_0,
+	PROP_ZOOM
+};
+
+
+static void ephy_zoom_action_init       (EphyZoomAction *action);
+static void ephy_zoom_action_class_init (EphyZoomActionClass *class);
+
+enum
+{
+	ZOOM_TO_LEVEL_SIGNAL,
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static GObjectClass *parent_class = NULL;
+
+GType
+ephy_zoom_action_get_type (void)
+{
+        static GType type = 0;
+
+        if (G_UNLIKELY (type == 0))
+        {
+                static const GTypeInfo our_info =
+			{
+				sizeof (EphyZoomActionClass),
+				NULL, /* base_init */
+				NULL, /* base_finalize */
+				(GClassInitFunc) ephy_zoom_action_class_init,
+				NULL,
+				NULL, /* class_data */
+				sizeof (EphyZoomAction),
+				0, /* n_preallocs */
+				(GInstanceInitFunc) ephy_zoom_action_init,
+			};
+
+                type = g_type_register_static (GTK_TYPE_ACTION,
+					       "EphyZoomAction",
+					       &our_info, 0);
+        }
+
+        return type;
+}
+
+static void
+zoom_to_level_cb (EphyZoomControl *control,
+		  float zoom,
+		  EphyZoomAction *action)
+{
+	g_signal_emit (action, signals[ZOOM_TO_LEVEL_SIGNAL], 0, zoom);
+}
+
+static void
+sync_zoom_cb (GtkAction *action, GParamSpec *pspec, GtkWidget *proxy)
+{
+	EphyZoomAction *zoom_action = EPHY_ZOOM_ACTION (action);
+
+	g_object_set (G_OBJECT (proxy), "zoom", zoom_action->priv->zoom, NULL);
+}
+
+static void
+connect_proxy (GtkAction *action, GtkWidget *proxy)
+{
+	if (EPHY_IS_ZOOM_CONTROL (proxy))
+	{
+		g_signal_connect_object (action, "notify::zoom",
+					 G_CALLBACK (sync_zoom_cb), proxy, 0);
+	
+		g_signal_connect (proxy, "zoom_to_level",
+				  G_CALLBACK (zoom_to_level_cb), action);
+	}
+
+	GTK_ACTION_CLASS (parent_class)->connect_proxy (action, proxy);
+}
+
+static void
+proxy_menu_activate_cb (GtkMenuItem *menu_item, EphyZoomAction *action)
+{
+	gint index;
+	float zoom;
+
+	/* menu item was toggled OFF */
+	if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (menu_item))) return;
+
+	index = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menu_item), "zoom-level"));
+	zoom = zoom_levels[index].level;
+
+	if (zoom != action->priv->zoom)
+	{
+		g_signal_emit (action, signals[ZOOM_TO_LEVEL_SIGNAL], 0, zoom);
+	}
+}
+
+static GtkWidget *
+create_menu_item (GtkAction *action)
+{
+	EphyZoomActionPrivate *p = EPHY_ZOOM_ACTION (action)->priv;
+	GtkWidget *menu, *menu_item;
+	GSList *group = NULL;
+	int i;
+
+	menu = gtk_menu_new ();
+
+	for (i = 0; i < n_zoom_levels; i++)
+	{
+		menu_item = gtk_radio_menu_item_new_with_label (group, _(zoom_levels[i].name));
+		group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menu_item));
+
+		gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item),
+						p->zoom == zoom_levels[i].level);
+
+		gtk_widget_show (menu_item);
+		gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+
+		g_object_set_data (G_OBJECT (menu_item), "zoom-level", GINT_TO_POINTER (i));
+		g_signal_connect_object (G_OBJECT (menu_item), "activate",
+					 G_CALLBACK (proxy_menu_activate_cb), action, 0);
+	}
+
+	gtk_widget_show (menu);
+
+        menu_item = GTK_ACTION_CLASS (parent_class)->create_menu_item (action);
+
+	gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), menu);
+
+	gtk_widget_show (menu_item);
+
+	return menu_item;
+}
+
+static void
+ephy_zoom_action_set_property (GObject *object,
+			       guint prop_id,
+			       const GValue *value,
+			       GParamSpec *pspec)
+{
+	EphyZoomAction *action;
+
+	action = EPHY_ZOOM_ACTION (object);
+
+	switch (prop_id)
+	{
+		case PROP_ZOOM:
+			action->priv->zoom = g_value_get_float (value);
+			break;
+	}
+}
+
+static void
+ephy_zoom_action_get_property (GObject *object,
+			       guint prop_id,
+			       GValue *value,
+			       GParamSpec *pspec)
+{
+	EphyZoomAction *action;
+
+	action = EPHY_ZOOM_ACTION (object);
+
+	switch (prop_id)
+	{
+		case PROP_ZOOM:
+			g_value_set_float (value, action->priv->zoom);
+			break;
+	}
+}
+
+static void
+ephy_zoom_action_class_init (EphyZoomActionClass *class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (class);
+	GtkActionClass *action_class = GTK_ACTION_CLASS (class);
+
+	object_class->set_property = ephy_zoom_action_set_property;
+	object_class->get_property = ephy_zoom_action_get_property;
+
+	parent_class = g_type_class_peek_parent (class);
+
+	action_class->toolbar_item_type = EPHY_TYPE_ZOOM_CONTROL;
+	action_class->connect_proxy = connect_proxy;
+	action_class->create_menu_item = create_menu_item;
+
+	g_object_class_install_property (object_class,
+					 PROP_ZOOM,
+					 g_param_spec_float ("zoom",
+							     "Zoom",
+							     "Zoom",
+							     ZOOM_MINIMAL,
+							     ZOOM_MAXIMAL,
+							     1.0,
+							     G_PARAM_READWRITE));
+
+	signals[ZOOM_TO_LEVEL_SIGNAL] =
+		g_signal_new ("zoom_to_level",
+			      G_OBJECT_CLASS_TYPE (object_class),
+			      G_SIGNAL_RUN_FIRST,
+			      G_STRUCT_OFFSET (EphyZoomActionClass, zoom_to_level),
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__FLOAT,
+			      G_TYPE_NONE,
+			      1,
+			      G_TYPE_FLOAT);
+
+	g_type_class_add_private (object_class, sizeof (EphyZoomActionPrivate));
+}
+
+static void
+ephy_zoom_action_init (EphyZoomAction *action)
+{
+	action->priv = EPHY_ZOOM_ACTION_GET_PRIVATE (action);
+
+	action->priv->zoom = 1.0;
+}
+
+void
+ephy_zoom_action_set_zoom_level (EphyZoomAction *action, float zoom)
+{
+	g_return_if_fail (EPHY_IS_ZOOM_ACTION (action));
+	
+	if (zoom < ZOOM_MINIMAL || zoom > ZOOM_MAXIMAL) return;
+
+	action->priv->zoom = zoom;
+	g_object_notify (G_OBJECT (action), "zoom");
+}
+
+float
+ephy_zoom_action_get_zoom_level (EphyZoomAction *action)
+{
+	g_return_val_if_fail (EPHY_IS_ZOOM_ACTION (action), 1.0);
+	
+	return action->priv->zoom;
+}
--- /dev/null	2005-04-22 17:55:38.547441544 -0300
+++ cut-n-paste/zoom-control/ephy-zoom-control.h	2005-04-25 11:51:15.000000000 -0300
@@ -0,0 +1,63 @@
+/*
+ *  Copyright (C) 2003  Christian Persch
+ *
+ *  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.
+ *
+ *  $Id: ephy-zoom-control.h,v 1.4 2003/11/28 12:53:11 chpe Exp $
+ */
+
+#ifndef EPHY_ZOOM_CONTROL_H
+#define EPHY_ZOOM_CONTROL_H
+
+#include <gtk/gtktoolitem.h>
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_ZOOM_CONTROL			(ephy_zoom_control_get_type())
+#define EPHY_ZOOM_CONTROL(object)		(G_TYPE_CHECK_INSTANCE_CAST((object), EPHY_TYPE_ZOOM_CONTROL, EphyZoomControl))
+#define EPHY_ZOOM_CONTROL_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), EPHY_TYPE_ZOOM_CONTROL, EphyZoomControlClass))
+#define EPHY_IS_ZOOM_CONTROL(object)		(G_TYPE_CHECK_INSTANCE_TYPE((object), EPHY_TYPE_ZOOM_CONTROL))
+#define EPHY_IS_ZOOM_CONTROL_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((klass), EPHY_TYPE_ZOOM_CONTROL))
+#define EPHY_ZOOM_CONTROL_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), EPHY_TYPE_ZOOM_CONTROL, EphyZoomControlClass))
+
+typedef struct _EphyZoomControl		EphyZoomControl;
+typedef struct _EphyZoomControlClass	EphyZoomControlClass;
+typedef struct _EphyZoomControlPrivate	EphyZoomControlPrivate;
+
+struct _EphyZoomControlClass
+{
+	GtkToolItemClass parent_class;
+
+	/* signals */
+	void (*zoom_to_level) 	(EphyZoomControl *control, float level);
+};
+
+struct _EphyZoomControl
+{
+	GtkToolItem parent_object;
+
+	/*< private >*/
+	EphyZoomControlPrivate *priv;
+};
+
+GType	ephy_zoom_control_get_type	 (void);
+
+void	ephy_zoom_control_set_zoom_level (EphyZoomControl *control, float zoom);
+
+float	ephy_zoom_control_get_zoom_level (EphyZoomControl *control);
+
+G_END_DECLS
+
+#endif
--- /dev/null	2005-04-22 17:55:38.547441544 -0300
+++ cut-n-paste/zoom-control/ephy-zoom-control.c	2005-04-25 14:25:46.000000000 -0300
@@ -0,0 +1,320 @@
+/*
+ *  Copyright (C) 2003, 2004 Christian Persch
+ *
+ *  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.
+ *
+ *  $Id: ephy-zoom-control.c,v 1.15 2005/01/14 18:08:29 chpe Exp $
+ */
+
+#include "config.h"
+
+#include "ephy-zoom-control.h"
+#include "ephy-zoom.h"
+#include "ev-debug.h"
+
+#include <gtk/gtk.h>
+#include <gtk/gtkcombobox.h>
+#include <gtk/gtktooltips.h>
+#include <glib/gi18n.h>
+
+#define EPHY_ZOOM_CONTROL_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_ZOOM_CONTROL, EphyZoomControlPrivate))
+
+struct _EphyZoomControlPrivate
+{
+	GtkComboBox *combo;
+	float zoom;
+	guint handler_id;
+};
+
+enum
+{
+	PROP_0,
+	PROP_ZOOM
+};
+
+enum
+{
+	ZOOM_TO_LEVEL_SIGNAL,
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+static GObjectClass *parent_class = NULL;
+
+static void	ephy_zoom_control_class_init	(EphyZoomControlClass *klass);
+static void	ephy_zoom_control_init		(EphyZoomControl *control);
+static void	ephy_zoom_control_finalize	(GObject *o);
+
+GType
+ephy_zoom_control_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0))
+	{
+		static const GTypeInfo our_info =
+			{
+				sizeof (EphyZoomControlClass),
+				NULL, /* base_init */
+				NULL, /* base_finalize */
+				(GClassInitFunc) ephy_zoom_control_class_init,
+				NULL,
+				NULL, /* class_data */
+				sizeof (EphyZoomControl),
+				0, /* n_preallocs */
+				(GInstanceInitFunc) ephy_zoom_control_init,
+			};
+
+		type = g_type_register_static (GTK_TYPE_TOOL_ITEM,
+					       "EphyZoomControl",
+					       &our_info, 0);
+	}
+
+	return type;
+}
+
+static void
+combo_changed_cb (GtkComboBox *combo, EphyZoomControl *control)
+{
+	gint index;
+	float zoom;
+
+	index = gtk_combo_box_get_active (combo);
+	zoom = zoom_levels[index].level;
+
+	if (zoom != control->priv->zoom)
+	{
+		g_signal_emit (control, signals[ZOOM_TO_LEVEL_SIGNAL], 0, zoom);	
+	}
+}
+
+static void
+sync_zoom_cb (EphyZoomControl *control, GParamSpec *pspec, gpointer data)
+{
+	EphyZoomControlPrivate *p = control->priv;
+	guint index;
+
+	index = ephy_zoom_get_zoom_level_index (p->zoom);
+
+	g_signal_handler_block (p->combo, p->handler_id);
+	gtk_combo_box_set_active (p->combo, index);
+	g_signal_handler_unblock (p->combo, p->handler_id);	
+}
+
+static void
+ephy_zoom_control_init (EphyZoomControl *control)
+{
+	EphyZoomControlPrivate *p;
+	GtkComboBox *combo;
+	GtkWidget *vbox;
+	guint i;
+
+	p = EPHY_ZOOM_CONTROL_GET_PRIVATE (control);
+	control->priv = p;
+
+	p->zoom = 1.0;
+
+	combo = p->combo = GTK_COMBO_BOX (gtk_combo_box_new_text ());
+
+	for (i = 0; i < n_zoom_levels; i++)
+	{
+		gtk_combo_box_append_text (combo, _(zoom_levels[i].name));
+	}
+
+	p->combo = combo;
+	gtk_combo_box_set_focus_on_click (GTK_COMBO_BOX (p->combo), FALSE);
+	g_object_ref (combo);
+	gtk_object_sink (GTK_OBJECT (combo));
+	gtk_widget_show (GTK_WIDGET (combo));
+
+	i = ephy_zoom_get_zoom_level_index (p->zoom);
+	gtk_combo_box_set_active (combo, i);
+
+	vbox = gtk_vbox_new (TRUE, 0);
+	gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (combo), TRUE, FALSE, 0);
+	gtk_widget_show (vbox);
+
+	gtk_container_add (GTK_CONTAINER (control), vbox);
+
+	p->handler_id = g_signal_connect (combo, "changed",
+					  G_CALLBACK (combo_changed_cb), control);
+	
+	g_signal_connect_object (control, "notify::zoom",
+				 G_CALLBACK (sync_zoom_cb), NULL, 0);
+}
+
+static void
+ephy_zoom_control_set_property (GObject *object,
+				guint prop_id,
+				const GValue *value,
+				GParamSpec *pspec)
+{
+	EphyZoomControl *control;
+	EphyZoomControlPrivate *p;
+
+	control = EPHY_ZOOM_CONTROL (object);
+	p = control->priv;
+
+	switch (prop_id)
+	{
+		case PROP_ZOOM:
+			p->zoom = g_value_get_float (value);
+			break;
+	}
+}
+
+static void
+ephy_zoom_control_get_property (GObject *object,
+				guint prop_id,
+				GValue *value,
+				GParamSpec *pspec)
+{
+	EphyZoomControl *control;
+	EphyZoomControlPrivate *p;
+
+	control = EPHY_ZOOM_CONTROL (object);
+	p = control->priv;
+
+	switch (prop_id)
+	{
+		case PROP_ZOOM:
+			g_value_set_float (value, p->zoom);
+			break;
+	}
+}
+
+static void
+set_combo_tooltip (GtkWidget *widget, 
+		   GtkTooltipsData *data)
+{
+	if (GTK_IS_BUTTON (widget))
+	{
+		gtk_tooltips_set_tip (data->tooltips, widget,
+				      data->tip_text, data->tip_private);
+	}
+}
+
+static void
+combo_realized (GtkWidget *combo,
+		GtkWidget *control)
+{
+	GtkTooltipsData *data;
+
+	data = gtk_tooltips_data_get (control);
+	g_return_if_fail (data != NULL);
+
+	gtk_container_forall (GTK_CONTAINER (combo),
+			      (GtkCallback) set_combo_tooltip, data);
+}
+
+static gboolean
+ephy_zoom_control_set_tooltip (GtkToolItem *tool_item,
+			       GtkTooltips *tooltips,
+			       const char *tip_text,
+			       const char *tip_private)
+{
+	EphyZoomControl *control = EPHY_ZOOM_CONTROL (tool_item);
+	GtkWidget *widget = GTK_WIDGET (tool_item);
+
+	/* hack to make tooltips work also on Ctrl-F1 */
+	gtk_tooltips_set_tip (tooltips, widget, tip_text, tip_private);
+
+	g_signal_handlers_disconnect_by_func
+		(control->priv->combo, G_CALLBACK (combo_realized), widget);
+
+	if (GTK_WIDGET_REALIZED (tool_item))
+	{
+		combo_realized (GTK_WIDGET (control->priv->combo), widget);
+	}
+	else
+	{
+		g_signal_connect_after (control->priv->combo, "realize",
+					G_CALLBACK (combo_realized), widget);
+	}
+
+	return TRUE;
+}
+
+static void
+ephy_zoom_control_class_init (EphyZoomControlClass *klass)
+{
+	GObjectClass *object_class;
+	GtkToolItemClass *tool_item_class;
+
+	parent_class = g_type_class_peek_parent (klass);
+
+	object_class = (GObjectClass *)klass;
+	tool_item_class = (GtkToolItemClass *)klass;
+
+	object_class->set_property = ephy_zoom_control_set_property;
+	object_class->get_property = ephy_zoom_control_get_property;
+	object_class->finalize = ephy_zoom_control_finalize;
+
+	tool_item_class->set_tooltip = ephy_zoom_control_set_tooltip;
+
+	g_object_class_install_property (object_class,
+					 PROP_ZOOM,
+					 g_param_spec_float ("zoom",
+							     "Zoom",
+							     "Zoom level to display in the item.",
+							     ZOOM_MINIMAL,
+							     ZOOM_MAXIMAL,
+							     1.0,
+							     G_PARAM_READWRITE));
+
+	signals[ZOOM_TO_LEVEL_SIGNAL] =
+		g_signal_new ("zoom_to_level",
+			      G_TYPE_FROM_CLASS (klass),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (EphyZoomControlClass,
+					       zoom_to_level),
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__FLOAT,
+			      G_TYPE_NONE,
+			      1,
+			      G_TYPE_FLOAT);
+
+	g_type_class_add_private (object_class, sizeof (EphyZoomControlPrivate));
+}
+
+static void
+ephy_zoom_control_finalize (GObject *o)
+{
+	EphyZoomControl *control = EPHY_ZOOM_CONTROL (o);
+
+	g_object_unref (control->priv->combo);
+
+	G_OBJECT_CLASS (parent_class)->finalize (o);
+}
+
+void
+ephy_zoom_control_set_zoom_level (EphyZoomControl *control, float zoom)
+{
+	g_return_if_fail (EPHY_IS_ZOOM_CONTROL (control));
+	
+	if (zoom < ZOOM_MINIMAL || zoom > ZOOM_MAXIMAL) return;
+
+	control->priv->zoom = zoom;
+	g_object_notify (G_OBJECT (control), "zoom");
+}
+
+float
+ephy_zoom_control_get_zoom_level (EphyZoomControl *control)
+{
+	g_return_val_if_fail (EPHY_IS_ZOOM_CONTROL (control), 1.0);
+	
+	return control->priv->zoom;
+}
