Code

tpdfv-ctl: Added controller module used to manage multiple GtkTPDFV widgets.
[tpdfview.git] / src / tpdfv-ctl.c
diff --git a/src/tpdfv-ctl.c b/src/tpdfv-ctl.c
new file mode 100644 (file)
index 0000000..6ac9598
--- /dev/null
@@ -0,0 +1,420 @@
+/*
+ * tpdfview - src/tpdfvctl.c
+ * Copyright (C) 2011 Sebastian 'tokkee' Harl <sh@tokkee.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This module provides a controller use to manage multiple GtkTPDFV widgets.
+ */
+
+#include "tpdfv-ctl.h"
+
+#include <assert.h>
+#include <errno.h>
+
+#include <stdlib.h>
+
+typedef struct {
+       GtkWidget *widget;
+       gint factor;
+       gint offset;
+} slave_t;
+
+typedef struct {
+       GtkWidget *main;
+       slave_t   *slaves;
+       gint slaves_num;
+} tpdfv_ctl_t;
+
+GType tpdfv_ctl_get_type(void);
+G_DEFINE_TYPE(TPDFVCtl, tpdfv_ctl, G_TYPE_OBJECT);
+
+#define TPDFV_CTL_GET_PRIVATE(obj) \
+       (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TPDFV_TYPE_CTL, tpdfv_ctl_t))
+
+/*
+ * Private helper functions.
+ */
+
+static void
+update_slave_page(tpdfv_ctl_t *ctl)
+{
+       gint current_page;
+       gint i;
+
+       current_page = gtk_tpdfv_get_current_page(ctl->main);
+
+       for (i = 0; i < ctl->slaves_num; ++i) {
+               slave_t *slave = ctl->slaves + i;
+
+               gtk_tpdfv_goto_page(slave->widget,
+                               current_page * slave->factor + slave->offset);
+       }
+} /* update_slave_page */
+
+/*
+ * GObject definition.
+ */
+
+static void
+tpdfv_ctl_dispose(GObject *obj)
+{
+       G_OBJECT_CLASS(tpdfv_ctl_parent_class)->dispose(obj);
+} /* tpdfv_ctl_dispose */
+
+static void
+tpdfv_ctl_finalize(GObject *obj)
+{
+       tpdfv_ctl_t *ctl = TPDFV_CTL_GET_PRIVATE(obj);
+
+       if (ctl->slaves)
+               free(ctl->slaves);
+       ctl->slaves = NULL;
+       ctl->slaves_num = 0;
+
+       G_OBJECT_CLASS(tpdfv_ctl_parent_class)->finalize(obj);
+} /* tpdfv_ctl_finalize */
+
+static void
+tpdfv_ctl_class_init(TPDFVCtlClass *class)
+{
+       GObjectClass *goclass;
+
+       goclass = G_OBJECT_CLASS(class);
+       g_type_class_add_private(goclass, sizeof(tpdfv_ctl_t));
+
+       goclass->dispose  = tpdfv_ctl_dispose;
+       goclass->finalize = tpdfv_ctl_finalize;
+} /* tpdfv_ctl_class_init */
+
+static void
+tpdfv_ctl_init(TPDFVCtl __attribute__((unused)) *ctl)
+{
+       /* nothing to do for now */
+} /* tpdfv_ctl_init */
+
+/*
+ * Public API.
+ */
+
+GObject *
+tpdfv_ctl_new(GtkTPDFV *main)
+{
+       TPDFVCtl *g_ctl;
+       tpdfv_ctl_t *ctl;
+
+       g_ctl = g_object_new(TPDFV_TYPE_CTL, NULL);
+       ctl   = TPDFV_CTL_GET_PRIVATE(g_ctl);
+
+       ctl->main = GTK_WIDGET(main);
+       ctl->slaves = NULL;
+       ctl->slaves_num = 0;
+       return G_OBJECT(g_ctl);
+} /* tpdfv_ctl_new */
+
+gboolean
+tpdfv_ctl_add_slave(GObject *obj, GtkTPDFV *slave,
+               gint factor, gint offset)
+{
+       tpdfv_ctl_t *ctl;
+       slave_t *s;
+
+       ctl = TPDFV_CTL_GET_PRIVATE(obj);
+       s = (slave_t *)realloc(ctl->slaves,
+                       (size_t)(ctl->slaves_num + 1) * sizeof(*s));
+       if (! s)
+               return FALSE;
+
+       ctl->slaves = s;
+       s = ctl->slaves + ctl->slaves_num;
+       ++ctl->slaves_num;
+
+       s->widget = GTK_WIDGET(slave);
+       s->factor = factor;
+       s->offset = offset;
+
+       update_slave_page(ctl);
+       return TRUE;
+} /* tpdfv_ctl_add_slave */
+
+void
+tpdfv_ctl_reload(GObject *obj)
+{
+       tpdfv_ctl_t *ctl;
+
+       gint i;
+
+       if (GTK_IS_TPDFV(obj))
+               return gtk_tpdfv_reload(GTK_WIDGET(obj));
+
+       ctl = TPDFV_CTL_GET_PRIVATE(obj);
+
+       gtk_tpdfv_reload(ctl->main);
+       for (i = 0; i < ctl->slaves_num; ++i)
+               gtk_tpdfv_reload(ctl->slaves[i].widget);
+} /* tpdfv_ctl_reload */
+
+void
+tpdfv_ctl_page_up(GObject *obj)
+{
+       tpdfv_ctl_t *ctl;
+
+       if (GTK_IS_TPDFV(obj))
+               return gtk_tpdfv_page_up(GTK_WIDGET(obj));
+
+       ctl = TPDFV_CTL_GET_PRIVATE(obj);
+
+       gtk_tpdfv_page_up(ctl->main);
+       update_slave_page(ctl);
+} /* tpdfv_ctl_page_up */
+
+void
+tpdfv_ctl_page_down(GObject *obj)
+{
+       tpdfv_ctl_t *ctl;
+
+       if (GTK_IS_TPDFV(obj))
+               return gtk_tpdfv_page_down(GTK_WIDGET(obj));
+
+       ctl = TPDFV_CTL_GET_PRIVATE(obj);
+
+       gtk_tpdfv_page_down(ctl->main);
+       update_slave_page(ctl);
+} /* tpdfv_ctl_page_down */
+
+void
+tpdfv_ctl_first_page(GObject *obj)
+{
+       tpdfv_ctl_t *ctl;
+
+       if (GTK_IS_TPDFV(obj))
+               return gtk_tpdfv_first_page(GTK_WIDGET(obj));
+
+       ctl = TPDFV_CTL_GET_PRIVATE(obj);
+
+       gtk_tpdfv_first_page(ctl->main);
+       update_slave_page(ctl);
+} /* tpdfv_ctl_first_page */
+
+void
+tpdfv_ctl_last_page(GObject *obj)
+{
+       tpdfv_ctl_t *ctl;
+
+       if (GTK_IS_TPDFV(obj))
+               return gtk_tpdfv_last_page(GTK_WIDGET(obj));
+
+       ctl = TPDFV_CTL_GET_PRIVATE(obj);
+
+       gtk_tpdfv_last_page(ctl->main);
+       update_slave_page(ctl);
+} /* tpdfv_ctl_last_page */
+
+void
+tpdfv_ctl_goto_page(GObject *obj, gint page)
+{
+       tpdfv_ctl_t *ctl;
+
+       if (GTK_IS_TPDFV(obj))
+               return gtk_tpdfv_goto_page(GTK_WIDGET(obj), page);
+
+       ctl = TPDFV_CTL_GET_PRIVATE(obj);
+
+       gtk_tpdfv_goto_page(ctl->main, page);
+       update_slave_page(ctl);
+} /* tpdfv_ctl_goto_page */
+
+void
+tpdfv_ctl_zoom_in(GObject *obj)
+{
+       tpdfv_ctl_t *ctl;
+
+       gint i;
+
+       if (GTK_IS_TPDFV(obj))
+               return gtk_tpdfv_zoom_in(GTK_WIDGET(obj));
+
+       ctl = TPDFV_CTL_GET_PRIVATE(obj);
+
+       gtk_tpdfv_zoom_in(ctl->main);
+       for (i = 0; i < ctl->slaves_num; ++i)
+               gtk_tpdfv_zoom_in(ctl->slaves[i].widget);
+} /* tpdfv_ctl_zoom_in */
+
+void
+tpdfv_ctl_zoom_out(GObject *obj)
+{
+       tpdfv_ctl_t *ctl;
+
+       gint i;
+
+       if (GTK_IS_TPDFV(obj))
+               return gtk_tpdfv_zoom_out(GTK_WIDGET(obj));
+
+       ctl = TPDFV_CTL_GET_PRIVATE(obj);
+
+       gtk_tpdfv_zoom_out(ctl->main);
+       for (i = 0; i < ctl->slaves_num; ++i)
+               gtk_tpdfv_zoom_out(ctl->slaves[i].widget);
+} /* tpdfv_ctl_zoom_out */
+
+void
+tpdfv_ctl_zoom_1(GObject *obj)
+{
+       tpdfv_ctl_t *ctl;
+
+       gint i;
+
+       if (GTK_IS_TPDFV(obj))
+               return gtk_tpdfv_zoom_1(GTK_WIDGET(obj));
+
+       ctl = TPDFV_CTL_GET_PRIVATE(obj);
+
+       gtk_tpdfv_zoom_1(ctl->main);
+       for (i = 0; i < ctl->slaves_num; ++i)
+               gtk_tpdfv_zoom_1(ctl->slaves[i].widget);
+} /* tpdfv_ctl_zoom_1 */
+
+void
+tpdfv_ctl_zoom_width(GObject *obj)
+{
+       tpdfv_ctl_t *ctl;
+
+       gint i;
+
+       if (GTK_IS_TPDFV(obj))
+               return gtk_tpdfv_zoom_width(GTK_WIDGET(obj));
+
+       ctl = TPDFV_CTL_GET_PRIVATE(obj);
+
+       gtk_tpdfv_zoom_width(ctl->main);
+       for (i = 0; i < ctl->slaves_num; ++i)
+               gtk_tpdfv_zoom_width(ctl->slaves[i].widget);
+} /* tpdfv_ctl_zoom_width */
+
+void
+tpdfv_ctl_zoom_height(GObject *obj)
+{
+       tpdfv_ctl_t *ctl;
+
+       gint i;
+
+       if (GTK_IS_TPDFV(obj))
+               return gtk_tpdfv_zoom_height(GTK_WIDGET(obj));
+
+       ctl = TPDFV_CTL_GET_PRIVATE(obj);
+
+       gtk_tpdfv_zoom_height(ctl->main);
+       for (i = 0; i < ctl->slaves_num; ++i)
+               gtk_tpdfv_zoom_height(ctl->slaves[i].widget);
+} /* tpdfv_ctl_zoom_height */
+
+void
+tpdfv_ctl_zoom_fit(GObject *obj)
+{
+       tpdfv_ctl_t *ctl;
+
+       gint i;
+
+       if (GTK_IS_TPDFV(obj))
+               return gtk_tpdfv_zoom_fit(GTK_WIDGET(obj));
+
+       ctl = TPDFV_CTL_GET_PRIVATE(obj);
+
+       gtk_tpdfv_zoom_fit(ctl->main);
+       for (i = 0; i < ctl->slaves_num; ++i)
+               gtk_tpdfv_zoom_fit(ctl->slaves[i].widget);
+} /* tpdfv_ctl_zoom_fit */
+
+void
+tpdfv_ctl_scroll_up(GObject *obj)
+{
+       tpdfv_ctl_t *ctl;
+
+       gint i;
+
+       if (GTK_IS_TPDFV(obj))
+               return gtk_tpdfv_scroll_up(GTK_WIDGET(obj));
+
+       ctl = TPDFV_CTL_GET_PRIVATE(obj);
+
+       gtk_tpdfv_scroll_up(ctl->main);
+       for (i = 0; i < ctl->slaves_num; ++i)
+               gtk_tpdfv_scroll_up(ctl->slaves[i].widget);
+} /* tpdfv_ctl_scroll_up */
+
+void
+tpdfv_ctl_scroll_down(GObject *obj)
+{
+       tpdfv_ctl_t *ctl;
+
+       gint i;
+
+       if (GTK_IS_TPDFV(obj))
+               return gtk_tpdfv_scroll_down(GTK_WIDGET(obj));
+
+       ctl = TPDFV_CTL_GET_PRIVATE(obj);
+
+       gtk_tpdfv_scroll_down(ctl->main);
+       for (i = 0; i < ctl->slaves_num; ++i)
+               gtk_tpdfv_scroll_down(ctl->slaves[i].widget);
+} /* tpdfv_ctl_scroll_down */
+
+void
+tpdfv_ctl_scroll_left(GObject *obj)
+{
+       tpdfv_ctl_t *ctl;
+
+       gint i;
+
+       if (GTK_IS_TPDFV(obj))
+               return gtk_tpdfv_scroll_left(GTK_WIDGET(obj));
+
+       ctl = TPDFV_CTL_GET_PRIVATE(obj);
+
+       gtk_tpdfv_scroll_left(ctl->main);
+       for (i = 0; i < ctl->slaves_num; ++i)
+               gtk_tpdfv_scroll_left(ctl->slaves[i].widget);
+} /* tpdfv_ctl_scroll_left */
+
+void
+tpdfv_ctl_scroll_right(GObject *obj)
+{
+       tpdfv_ctl_t *ctl;
+
+       gint i;
+
+       if (GTK_IS_TPDFV(obj))
+               return gtk_tpdfv_scroll_right(GTK_WIDGET(obj));
+
+       ctl = TPDFV_CTL_GET_PRIVATE(obj);
+
+       gtk_tpdfv_scroll_right(ctl->main);
+       for (i = 0; i < ctl->slaves_num; ++i)
+               gtk_tpdfv_scroll_right(ctl->slaves[i].widget);
+} /* tpdfv_ctl_scroll_right */
+
+/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
+