Code

tpdfv-ctl: Added controller module used to manage multiple GtkTPDFV widgets.
authorSebastian Harl <sh@tokkee.org>
Fri, 23 Dec 2011 18:36:42 +0000 (19:36 +0100)
committerSebastian Harl <sh@tokkee.org>
Fri, 23 Dec 2011 18:36:42 +0000 (19:36 +0100)
The controller includes one "main" and an arbitrary number of "slave" widgets.
Each slave widget has a factor and an offset assigned to it. Those numbers
define how the current page of the slave relates to that of the master. Thus,
it might be used, for example, to specify a slave widget used to display a
preview of the next page.

The controller provides a subset of the functions provided by the GtkTPDFV
widget and forwards the calls to the "main" and "slave" widgets according to
the slave settings.

To ease integration, those functions either accept a controller object or a
GtkTPDFV widget as an argument and, in the latter case, directly forward the
call to the specified widget only.

src/Makefile.am
src/gtk-tpdfv.h
src/tpdfv-ctl.c [new file with mode: 0644]
src/tpdfv-ctl.h [new file with mode: 0644]

index 5700b905229360535984795301b7e627a350ecac..4e3a166d0d9a1f746f5a12adcdda83aed6a07e65 100644 (file)
@@ -6,7 +6,8 @@ lib_LTLIBRARIES = libtpdfv.la
 BUILT_SOURCES = tpdfv_features.h
 
 libtpdfv_la_SOURCES = tpdfv.c tpdfv.h tpdfv_features.h \
-               gtk-tpdfv.c gtk-tpdfv-screen.c gtk-tpdfv.h
+               gtk-tpdfv.c gtk-tpdfv-screen.c gtk-tpdfv.h \
+               tpdfv-ctl.c tpdfv-ctl.h
 libtpdfv_la_CFLAGS = $(AM_CFLAGS) \
                @CAIRO_CFLAGS@ \
                @GTK2_CFLAGS@ \
index dc54e4c60cdd7a244e4f277fa499395fed254f01..36b15c7832f222f0840664614caae942ed3c17ad 100644 (file)
@@ -50,6 +50,9 @@ extern "C" {
 #define GTK_TPDFV_GET_CLASS(obj) \
        (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_TPDFV, GtkTPDFVClass))
 
+GType
+gtk_tpdfv_get_type(void);
+
 typedef struct {
        GtkDrawingArea graph;
 } GtkTPDFV;
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 : */
+
diff --git a/src/tpdfv-ctl.h b/src/tpdfv-ctl.h
new file mode 100644 (file)
index 0000000..afc71e0
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * tpdfview - src/tpdfvctl.h
+ * 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.
+ */
+
+#ifndef TPDFVCTL_H
+#define TPDFVCTL_H 1
+
+#include <glib-object.h>
+
+#include "gtk-tpdfv.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TPDFV_TYPE_CTL (tpdfv_ctl_get_type())
+#define TPDFV_CTL(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST((obj), TPDFV_TYPE_CTL, TPDFVCtl))
+#define TPDFV_CTL_CLASS(obj) \
+       (G_TYPE_CHECK_CLASS_CAST((obj), TPDFV_TYPE_CTL, TPDFVCtlClass))
+#define TPDFV_IS_CTL(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE((obj), TPDFV_TYPE_CTL))
+#define TPDFV_IS_CTL_CLASS(obj) \
+       (G_TYPE_CHECK_CLASS_TYPE((obj), TPDFV_TYPE_CTL))
+#define TPDFV_CTL_GET_CLASS(obj) \
+       (G_TYPE_INSTANCE_GET_CLASS((obj), TPDFV_TYPE_CTL, TPDFVCtlClass))
+
+GType
+tpdfv_ctl_get_type(void);
+
+typedef struct {
+       GObject parent_instance;
+} TPDFVCtl;
+
+typedef struct {
+       GObjectClass parent_class;
+} TPDFVCtlClass;
+
+/*
+ * tpdfv_ctl_new:
+ * Creates a new TPDFVCtl object using the specified main GtkTPDFV widget.
+ */
+GObject *
+tpdfv_ctl_new(GtkTPDFV *main);
+
+/*
+ * tpdfv_ctl_add_slave:
+ * Add a new slave to the controller.
+ *
+ * 'factor' and 'offset' determine how the current page of the slave relate to
+ * the master.
+ *
+ * Returns FALSE if adding the slave failed.
+ */
+gboolean
+tpdfv_ctl_add_slave(GObject *obj, GtkTPDFV *slave,
+               gint factor, gint offset);
+
+/*
+ * tpdfv_ctl_reload:
+ * Reload all PDF files.
+ */
+void
+tpdfv_ctl_reload(GObject *obj);
+
+/*
+ * tpdfv_ctl_page_up, tpdfv_ctl_page_down,
+ * tpdfv_ctl_first_page, tpdfv_ctl_last_page,
+ * tpdfv_ctl_goto_page:
+ * Navigation.
+ */
+void
+tpdfv_ctl_page_up(GObject *obj);
+void
+tpdfv_ctl_page_down(GObject *obj);
+void
+tpdfv_ctl_first_page(GObject *obj);
+void
+tpdfv_ctl_last_page(GObject *obj);
+void
+tpdfv_ctl_goto_page(GObject *obj, gint page);
+
+/*
+ * tpdfv_ctl_zoom_in, tpdfv_ctl_zoom_out,
+ * tpdfv_ctl_zoom_1:
+ * Zooming.
+ */
+void
+tpdfv_ctl_zoom_in(GObject *obj);
+void
+tpdfv_ctl_zoom_out(GObject *obj);
+void
+tpdfv_ctl_zoom_1(GObject *obj);
+void
+tpdfv_ctl_zoom_width(GObject *obj);
+void
+tpdfv_ctl_zoom_height(GObject *obj);
+void
+tpdfv_ctl_zoom_fit(GObject *obj);
+
+/*
+ * tpdfv_ctl_scroll_up, tpdfv_ctl_scroll_down,
+ * tpdfv_ctl_scroll_left, tpdfv_ctl_scroll_right:
+ * Scrolling.
+ */
+void
+tpdfv_ctl_scroll_up(GObject *obj);
+void
+tpdfv_ctl_scroll_down(GObject *obj);
+void
+tpdfv_ctl_scroll_left(GObject *obj);
+void
+tpdfv_ctl_scroll_right(GObject *obj);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ! TPDFVCTL_H */
+
+/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
+