[gnome-photos/wip/foo: 8/10] EogPrintImageSetup -> PhotosPrintSetup



commit 20d37bdc4a47e8e3a5a8936e20c932534af93810
Author: Debarshi Ray <debarshir gnome org>
Date:   Tue Mar 26 20:06:32 2013 +0100

    EogPrintImageSetup -> PhotosPrintSetup

 src/Makefile.am             |    4 +-
 src/eog-print-image-setup.c | 1139 -------------------------------------------
 src/eog-print-image-setup.h |   72 ---
 src/photos-print-setup.c    | 1057 +++++++++++++++++++++++++++++++++++++++
 src/photos-print-setup.h    |   85 ++++
 5 files changed, 1144 insertions(+), 1213 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 62fec69..298d262 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -43,8 +43,6 @@ gnome_photos_SOURCES = \
        eog-metadata-reader-png.h \
        eog-print.c \
        eog-print.h \
-       eog-print-image-setup.c \
-       eog-print-image-setup.h \
        eog-transform.c \
        eog-transform.h \
        eog-uri-converter.c \
@@ -106,6 +104,8 @@ gnome_photos_SOURCES = \
        photos-preview-view.h \
        photos-print-preview.c \
        photos-print-preview.h \
+       photos-print-setup.c \
+       photos-print-setup.h \
        photos-properties-dialog.c \
        photos-properties-dialog.h \
        photos-query.c \
diff --git a/src/photos-print-setup.c b/src/photos-print-setup.c
new file mode 100644
index 0000000..239285c
--- /dev/null
+++ b/src/photos-print-setup.c
@@ -0,0 +1,1057 @@
+/*
+ * Photos - access, organize and share your photos on GNOME
+ * Copyright © 2006, 2007 The Free Software Foundation
+ * Copyright © 2013 Red Hat, Inc.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/* Based on code from:
+ *   + Eye of GNOME
+ */
+
+#include "config.h"
+
+#ifdef HAVE__NL_MEASUREMENT_MEASUREMENT
+#include <langinfo.h>
+#endif
+
+#include <glib/gi18n.h>
+#include <glib/gprintf.h>
+#include <gtk/gtkunixprint.h>
+
+#include "photos-print-setup.h"
+#include "photos-print-preview.h"
+#include "photos-utils.h"
+
+
+struct _PhotosPrintSetupPrivate
+{
+  GeglNode *node;
+  GtkPageSetup *page_setup;
+  GtkWidget *left;
+  GtkWidget *right;
+  GtkWidget *top;
+  GtkWidget *bottom;
+  GtkWidget *center;
+  GtkWidget *width;
+  GtkWidget *height;
+  GtkWidget *scaling;
+  GtkWidget *preview;
+  GtkWidget *unit;
+  GtkUnit current_unit;
+};
+
+
+enum
+{
+  PROP_0,
+  PROP_NODE,
+  PROP_PAGE_SETUP
+};
+
+
+G_DEFINE_TYPE (PhotosPrintSetup, photos_print_setup, GTK_TYPE_GRID);
+
+
+enum
+{
+  CENTER_NONE,
+  CENTER_HORIZONTAL,
+  CENTER_VERTICAL,
+  CENTER_BOTH
+};
+
+enum
+{
+  CHANGE_HORIZ,
+  CHANGE_VERT
+};
+
+enum
+{
+  UNIT_INCH,
+  UNIT_MM
+};
+
+#define FACTOR_INCH_TO_MM 25.4
+#define FACTOR_INCH_TO_PIXEL 72.
+#define FACTOR_MM_TO_INCH 0.03937007874015748
+#define FACTOR_MM_TO_PIXEL 2.834645669
+
+static void photos_print_setup_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec 
*pspec);
+static void photos_print_setup_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec 
*pspec);
+
+static void on_left_value_changed   (GtkSpinButton *spinbutton, gpointer user_data);
+static void on_right_value_changed  (GtkSpinButton *spinbutton, gpointer user_data);
+static void on_top_value_changed    (GtkSpinButton *spinbutton, gpointer user_data);
+static void on_bottom_value_changed (GtkSpinButton *spinbutton, gpointer user_data);
+
+static void on_width_value_changed  (GtkSpinButton *spinbutton, gpointer user_data);
+static void on_height_value_changed (GtkSpinButton *spinbutton, gpointer user_data);
+
+
+static void
+photos_print_setup_block_handlers (PhotosPrintSetup *self)
+{
+  PhotosPrintSetupPrivate *priv = self->priv;
+
+  g_signal_handlers_block_by_func (priv->left, on_left_value_changed, self);
+  g_signal_handlers_block_by_func (priv->right, on_right_value_changed, self);
+  g_signal_handlers_block_by_func (priv->width, on_width_value_changed, self);
+  g_signal_handlers_block_by_func (priv->top, on_top_value_changed, self);
+  g_signal_handlers_block_by_func (priv->bottom, on_bottom_value_changed, self);
+  g_signal_handlers_block_by_func (priv->height, on_height_value_changed, self);
+}
+
+
+static void
+photos_print_setup_unblock_handlers (PhotosPrintSetup *self)
+{
+  PhotosPrintSetupPrivate *priv = self->priv;
+
+  g_signal_handlers_unblock_by_func (priv->left, on_left_value_changed, self);
+  g_signal_handlers_unblock_by_func (priv->right, on_right_value_changed, self);
+  g_signal_handlers_unblock_by_func (priv->width, on_width_value_changed, self);
+  g_signal_handlers_unblock_by_func (priv->top, on_top_value_changed, self);
+  g_signal_handlers_unblock_by_func (priv->bottom, on_bottom_value_changed, self);
+  g_signal_handlers_unblock_by_func (priv->height, on_height_value_changed, self);
+}
+
+
+static gdouble
+get_scale_to_px_factor (PhotosPrintSetup *self)
+{
+  gdouble factor = 0.;
+
+  switch (self->priv->current_unit)
+    {
+    case GTK_UNIT_MM:
+      factor = FACTOR_MM_TO_PIXEL;
+      break;
+    case GTK_UNIT_INCH:
+      factor = FACTOR_INCH_TO_PIXEL;
+      break;
+    default:
+      g_assert_not_reached ();
+    }
+
+  return factor;
+}
+
+
+static gdouble
+photos_print_setup_get_max_percentage (PhotosPrintSetup *self)
+{
+  PhotosPrintSetupPrivate *priv = self->priv;
+  GeglRectangle bbox;
+  gdouble height;
+  gdouble page_height;
+  gdouble page_width;
+  gdouble width;
+  gdouble perc;
+
+  page_width = gtk_page_setup_get_page_width (priv->page_setup, GTK_UNIT_INCH);
+  page_height = gtk_page_setup_get_page_height (priv->page_setup, GTK_UNIT_INCH);
+  bbox = gegl_node_get_bounding_box (priv->node);
+
+  width  = (gdouble) bbox.width / FACTOR_INCH_TO_PIXEL;
+  height = (gdouble) bbox.height / FACTOR_INCH_TO_PIXEL;
+
+  if (page_width > width && page_height > height)
+    perc = 1.0;
+  else
+    perc = MIN (page_width / width, page_height / height);
+
+  return perc;
+}
+
+
+static void
+photos_print_setup_center (gdouble page_width, gdouble width, GtkSpinButton *s_left, GtkSpinButton *s_right)
+{
+  gdouble left;
+  gdouble right;
+
+  left = (page_width - width) / 2;
+  right = page_width - left - width;
+  gtk_spin_button_set_value (s_left, left);
+  gtk_spin_button_set_value (s_right, right);
+}
+
+
+static void
+on_center_changed (GtkComboBox *combobox, gpointer user_data)
+{
+  PhotosPrintSetup *self = PHOTOS_PRINT_SETUP (user_data);
+  PhotosPrintSetupPrivate *priv = self->priv;
+  gint active;
+
+  active = gtk_combo_box_get_active (combobox);
+
+  switch (active)
+    {
+    case CENTER_HORIZONTAL:
+      photos_print_setup_center (gtk_page_setup_get_page_width (priv->page_setup,
+                                                                priv->current_unit),
+                                 gtk_spin_button_get_value (GTK_SPIN_BUTTON (priv->width)),
+                                 GTK_SPIN_BUTTON (priv->left),
+                                 GTK_SPIN_BUTTON (priv->right));
+      break;
+    case CENTER_VERTICAL:
+      photos_print_setup_center (gtk_page_setup_get_page_height (priv->page_setup,
+                                                                 priv->current_unit),
+                                 gtk_spin_button_get_value (GTK_SPIN_BUTTON (priv->height)),
+                                 GTK_SPIN_BUTTON (priv->top),
+                                 GTK_SPIN_BUTTON (priv->bottom));
+      break;
+    case CENTER_BOTH:
+      photos_print_setup_center (gtk_page_setup_get_page_width (priv->page_setup,
+                                                                priv->current_unit),
+                                 gtk_spin_button_get_value (GTK_SPIN_BUTTON (priv->width)),
+                                 GTK_SPIN_BUTTON (priv->left),
+                                 GTK_SPIN_BUTTON (priv->right));
+      photos_print_setup_center (gtk_page_setup_get_page_height (priv->page_setup,
+                                                                 priv->current_unit),
+                                 gtk_spin_button_get_value (GTK_SPIN_BUTTON (priv->height)),
+                                 GTK_SPIN_BUTTON (priv->top),
+                                 GTK_SPIN_BUTTON (priv->bottom));
+      break;
+    case CENTER_NONE:
+    default:
+      break;
+    }
+
+  gtk_combo_box_set_active (combobox, active);
+}
+
+
+static void
+update_image_pos_ranges (PhotosPrintSetup *setup,
+                        gdouble page_width,
+                        gdouble page_height,
+                        gdouble width,
+                        gdouble height)
+{
+       PhotosPrintSetupPrivate *priv;
+
+       priv = setup->priv;
+
+       gtk_spin_button_set_range (GTK_SPIN_BUTTON (priv->left),
+                                  0, page_width - width);
+       gtk_spin_button_set_range (GTK_SPIN_BUTTON (priv->right),
+                                  0, page_width - width);
+       gtk_spin_button_set_range (GTK_SPIN_BUTTON (priv->top),
+                                  0, page_height - height);
+       gtk_spin_button_set_range (GTK_SPIN_BUTTON (priv->bottom),
+                                  0, page_height - height);
+}
+
+
+static void
+on_scale_changed (GtkRange *range, gpointer user_data)
+{
+  PhotosPrintSetup *self = PHOTOS_PRINT_SETUP (user_data);
+  PhotosPrintSetupPrivate *priv = self->priv;
+  GeglRectangle bbox;
+  gdouble height;
+  gdouble scale;
+  gdouble width;
+  gdouble left, right, top, bottom;
+  gdouble page_width, page_height;
+  gdouble factor;
+
+  gtk_combo_box_set_active (GTK_COMBO_BOX (priv->center), CENTER_NONE);
+
+  bbox = gegl_node_get_bounding_box (priv->node);
+  factor = get_scale_to_px_factor (self);
+
+  width = (gdouble) bbox.width / factor;
+  height = (gdouble) bbox.height / factor;
+
+  left = gtk_spin_button_get_value (GTK_SPIN_BUTTON (priv->left));
+  top = gtk_spin_button_get_value (GTK_SPIN_BUTTON (priv->top));
+
+  scale = CLAMP (0.01 * gtk_range_get_value (range), 0, photos_print_setup_get_max_percentage (self));
+
+  photos_print_preview_set_scale (PHOTOS_PRINT_PREVIEW (priv->preview), scale);
+
+  width  *= scale;
+  height *= scale;
+
+  page_width = gtk_page_setup_get_page_width (priv->page_setup, priv->current_unit);
+  page_height = gtk_page_setup_get_page_height (priv->page_setup, priv->current_unit);
+
+  update_image_pos_ranges (self, page_width, page_height, width, height);
+
+  right = page_width - left - width;
+  bottom = page_height - top - height;
+
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->width), width);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->height), height);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->right), right);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->bottom), bottom);
+}
+
+
+static gchar *
+on_scale_format_value (GtkScale *scale, gdouble value)
+{
+  return g_strdup_printf ("%i%%", (gint) value);
+}
+
+
+static void
+photos_print_setup_position_values_changed (PhotosPrintSetup *self,
+                                            GtkWidget *w_changed,
+                                            GtkWidget *w_to_update,
+                                            GtkWidget *w_size,
+                                            gdouble total_size,
+                                            gint change)
+{
+  PhotosPrintSetupPrivate *priv = self->priv;
+  gdouble changed, to_update, size;
+  gdouble pos;
+
+  size = gtk_spin_button_get_value (GTK_SPIN_BUTTON (w_size));
+  changed = gtk_spin_button_get_value (GTK_SPIN_BUTTON (w_changed));
+
+  to_update = total_size - changed - size;
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (w_to_update), to_update);
+  gtk_combo_box_set_active (GTK_COMBO_BOX (priv->center), CENTER_NONE);
+
+  switch (change)
+    {
+    case CHANGE_HORIZ:
+      pos = gtk_spin_button_get_value (GTK_SPIN_BUTTON (priv->left));
+      if (priv->current_unit == GTK_UNIT_MM)
+        pos *= FACTOR_MM_TO_INCH;
+      photos_print_preview_set_image_position (PHOTOS_PRINT_PREVIEW (priv->preview), pos, -1);
+      break;
+    case CHANGE_VERT:
+      pos = gtk_spin_button_get_value (GTK_SPIN_BUTTON (priv->top));
+      if (priv->current_unit == GTK_UNIT_MM)
+        pos *= FACTOR_MM_TO_INCH;
+      photos_print_preview_set_image_position (PHOTOS_PRINT_PREVIEW (priv->preview), -1, pos);
+      break;
+    }
+}
+
+
+static void
+on_left_value_changed (GtkSpinButton *spinbutton, gpointer user_data)
+{
+  PhotosPrintSetup *self = PHOTOS_PRINT_SETUP (user_data);
+  PhotosPrintSetupPrivate *priv = self->priv;
+
+  photos_print_setup_position_values_changed (self,
+                                              priv->left,
+                                              priv->right,
+                                              priv->width,
+                                              gtk_page_setup_get_page_width (priv->page_setup,
+                                                                             priv->current_unit),
+                                              CHANGE_HORIZ);
+}
+
+
+static void
+on_right_value_changed (GtkSpinButton *spinbutton, gpointer user_data)
+{
+  PhotosPrintSetup *self = PHOTOS_PRINT_SETUP (user_data);
+  PhotosPrintSetupPrivate *priv = self->priv;
+
+  photos_print_setup_position_values_changed (self,
+                                              priv->right,
+                                              priv->left,
+                                              priv->width,
+                                              gtk_page_setup_get_page_width (priv->page_setup,
+                                                                             priv->current_unit),
+                                              CHANGE_HORIZ);
+}
+
+
+static void
+on_top_value_changed (GtkSpinButton *spinbutton,
+                     gpointer       user_data)
+{
+  PhotosPrintSetup *self = PHOTOS_PRINT_SETUP (user_data);
+  PhotosPrintSetupPrivate *priv = self->priv;
+
+  photos_print_setup_position_values_changed (self,
+                                              priv->top,
+                                              priv->bottom,
+                                              priv->height,
+                                              gtk_page_setup_get_page_height (priv->page_setup,
+                                                                              priv->current_unit),
+                                              CHANGE_VERT);
+}
+
+
+static void
+on_bottom_value_changed (GtkSpinButton *spinbutton, gpointer user_data)
+{
+  PhotosPrintSetup *self = PHOTOS_PRINT_SETUP (user_data);
+  PhotosPrintSetupPrivate *priv = self->priv;
+
+  photos_print_setup_position_values_changed (self,
+                                              priv->bottom,
+                                              priv->top,
+                                              priv->height,
+                                              gtk_page_setup_get_page_height (priv->page_setup,
+                                                                              priv->current_unit),
+                                              CHANGE_VERT);
+}
+
+
+static void
+photos_print_setup_size_changed (PhotosPrintSetup *self,
+                                 GtkWidget *w_size_x,
+                                 GtkWidget *w_size_y,
+                                 GtkWidget *w_margin_x_1,
+                                 GtkWidget *w_margin_x_2,
+                                 GtkWidget *w_margin_y_1,
+                                 GtkWidget *w_margin_y_2,
+                                 gdouble page_size_x,
+                                 gdouble page_size_y,
+                                 gint change)
+{
+  PhotosPrintSetupPrivate *priv = self->priv;
+  GeglRectangle bbox;
+  gdouble margin_x_1, margin_x_2;
+  gdouble margin_y_1, margin_y_2;
+  gdouble orig_size_x = -1, orig_size_y = -1, scale;
+  gdouble size_x, size_y;
+  gdouble factor;
+
+  size_x = gtk_spin_button_get_value (GTK_SPIN_BUTTON (w_size_x));
+  margin_x_1 = gtk_spin_button_get_value (GTK_SPIN_BUTTON (w_margin_x_1));
+  margin_y_1 = gtk_spin_button_get_value (GTK_SPIN_BUTTON (w_margin_y_1));
+
+  bbox = gegl_node_get_bounding_box (priv->node);
+  factor = get_scale_to_px_factor (self);
+
+  switch (change)
+    {
+    case CHANGE_HORIZ:
+      orig_size_x = (gdouble) bbox.width / factor;
+      orig_size_y = (gdouble) bbox.height / factor;
+      break;
+    case CHANGE_VERT:
+      orig_size_y = (gdouble) bbox.width / factor;
+      orig_size_x = (gdouble) bbox.height / factor;
+      break;
+    }
+
+  scale = CLAMP (size_x / orig_size_x, 0, 1);
+
+  size_y = scale * orig_size_y;
+
+  margin_x_2 = page_size_x - margin_x_1 - size_x;
+  margin_y_2 = page_size_y - margin_y_1 - size_y;
+
+  photos_print_preview_set_scale (PHOTOS_PRINT_PREVIEW (priv->preview), scale);
+
+  switch (change)
+    {
+    case CHANGE_HORIZ:
+      update_image_pos_ranges (self, page_size_x, page_size_y, size_x, size_y);
+      break;
+    case CHANGE_VERT:
+      update_image_pos_ranges (self, page_size_y, page_size_x, size_y, size_x);
+      break;
+    }
+
+  gtk_range_set_value (GTK_RANGE (priv->scaling), 100*scale);
+
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (w_margin_x_2), margin_x_2);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (w_size_y), size_y);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (w_margin_y_2), margin_y_2);
+
+  gtk_combo_box_set_active (GTK_COMBO_BOX (priv->center), CENTER_NONE);
+}
+
+static void
+on_width_value_changed (GtkSpinButton *spinbutton,
+                       gpointer       user_data)
+{
+       PhotosPrintSetupPrivate *priv = PHOTOS_PRINT_SETUP (user_data)->priv;
+
+       photos_print_setup_size_changed (PHOTOS_PRINT_SETUP (user_data),
+                                         priv->width, priv->height,
+                                         priv->left, priv->right,
+                                         priv->top, priv->bottom,
+                                         gtk_page_setup_get_page_width (priv->page_setup,
+                                                                        priv->current_unit),
+                                         gtk_page_setup_get_page_height (priv->page_setup,
+                                                                         priv->current_unit),
+                                         CHANGE_HORIZ);
+}
+
+
+static void
+on_height_value_changed (GtkSpinButton *spinbutton,
+                        gpointer       user_data)
+{
+       PhotosPrintSetupPrivate *priv = PHOTOS_PRINT_SETUP (user_data)->priv;
+
+       photos_print_setup_size_changed (PHOTOS_PRINT_SETUP (user_data),
+                                         priv->height, priv->width,
+                                         priv->top, priv->bottom,
+                                         priv->left, priv->right,
+                                         gtk_page_setup_get_page_height (priv->page_setup,
+                                                                         priv->current_unit),
+                                         gtk_page_setup_get_page_width (priv->page_setup,
+                                                                        priv->current_unit),
+                                         CHANGE_VERT);
+}
+
+
+static void
+change_unit (GtkSpinButton *spinbutton,
+            gdouble factor,
+            gint digits,
+            gdouble step,
+            gdouble page)
+{
+       gdouble value;
+       gdouble range;
+
+       gtk_spin_button_get_range (spinbutton, NULL, &range);
+       range *= factor;
+
+       value = gtk_spin_button_get_value (spinbutton);
+       value *= factor;
+
+       gtk_spin_button_set_range (spinbutton, 0, range);
+       gtk_spin_button_set_value (spinbutton, value);
+       gtk_spin_button_set_digits (spinbutton, digits);
+       gtk_spin_button_set_increments  (spinbutton, step, page);
+}
+
+
+static void
+photos_print_setup_set_scale_unit (PhotosPrintSetup *setup, GtkUnit unit)
+{
+  PhotosPrintSetupPrivate *priv = setup->priv;
+  gdouble factor;
+  gdouble step, page;
+  gint digits;
+
+  if (G_UNLIKELY (priv->current_unit == unit))
+    return;
+
+  switch (unit)
+    {
+    case GTK_UNIT_MM:
+      factor = FACTOR_INCH_TO_MM;
+      digits = 0;
+      step = 1;
+      page = 10;
+      break;
+    case GTK_UNIT_INCH:
+      factor = FACTOR_MM_TO_INCH;
+      digits = 2;
+      step = 0.01;
+      page = 0.1;
+      break;
+    default:
+      g_assert_not_reached ();
+    }
+
+  photos_print_setup_block_handlers (setup);
+
+  change_unit (GTK_SPIN_BUTTON (priv->width), factor, digits, step, page);
+  change_unit (GTK_SPIN_BUTTON (priv->height), factor, digits, step, page);
+  change_unit (GTK_SPIN_BUTTON (priv->left), factor, digits, step, page);
+  change_unit (GTK_SPIN_BUTTON (priv->right), factor, digits, step, page);
+  change_unit (GTK_SPIN_BUTTON (priv->top), factor, digits, step, page);
+  change_unit (GTK_SPIN_BUTTON (priv->bottom), factor, digits, step, page);
+
+  photos_print_setup_unblock_handlers (setup);
+
+  priv->current_unit = unit;
+}
+
+
+static void
+on_unit_changed (GtkComboBox *combobox, gpointer user_data)
+{
+  GtkUnit unit = GTK_UNIT_INCH;
+
+  switch (gtk_combo_box_get_active (combobox))
+    {
+    case UNIT_INCH:
+      unit = GTK_UNIT_INCH;
+      break;
+    case UNIT_MM:
+      unit = GTK_UNIT_MM;
+      break;
+    default:
+      g_assert_not_reached ();
+    }
+
+  photos_print_setup_set_scale_unit (PHOTOS_PRINT_SETUP (user_data), unit);
+}
+
+
+static void
+on_preview_pixbuf_moved (PhotosPrintPreview *preview, gpointer user_data)
+{
+  PhotosPrintSetup *self = PHOTOS_PRINT_SETUP (user_data);
+  PhotosPrintSetupPrivate *priv = self->priv;
+  gdouble x;
+  gdouble y;
+
+  photos_print_preview_get_image_position (preview, &x, &y);
+
+  if (priv->current_unit == GTK_UNIT_MM)
+    {
+      x *= FACTOR_INCH_TO_MM;
+      y *= FACTOR_INCH_TO_MM;
+    }
+
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->left), x);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->top), y);
+}
+
+
+static gboolean
+on_preview_image_scrolled (GtkWidget *widget,
+                          GdkEventScroll *event,
+                          gpointer user_data)
+{
+       PhotosPrintSetupPrivate *priv = PHOTOS_PRINT_SETUP (user_data)->priv;
+       PhotosPrintPreview *preview = PHOTOS_PRINT_PREVIEW (widget);
+       gfloat scale;
+
+       scale = photos_print_preview_get_scale (preview);
+
+       if (!photos_print_preview_point_in_image_area (preview,
+                                                   event->x, event->y))
+       {
+               return FALSE;
+       }
+
+       switch (event->direction) {
+       case GDK_SCROLL_UP:
+               /* scale up */
+               scale *= 1.1;
+               break;
+       case GDK_SCROLL_DOWN:
+               /* scale down */
+               scale *= 0.9;
+               break;
+       default:
+               return FALSE;
+               break;
+       }
+
+       gtk_range_set_value (GTK_RANGE (priv->scaling), 100*scale);
+
+       return TRUE;
+}
+
+
+static gboolean
+on_preview_image_key_pressed (GtkWidget *widget, GdkEventKey *event, gpointer user_data)
+{
+  PhotosPrintSetupPrivate *priv = PHOTOS_PRINT_SETUP (user_data)->priv;
+  PhotosPrintPreview *preview = PHOTOS_PRINT_PREVIEW (widget);
+  gfloat scale;
+
+  scale = photos_print_preview_get_scale (preview);
+
+  switch (event->keyval)
+    {
+    case GDK_KEY_KP_Add:
+    case GDK_KEY_plus:
+      /* scale up */
+      scale *= 1.1;
+      break;
+    case GDK_KEY_KP_Subtract:
+    case GDK_KEY_minus:
+      /* scale down */
+      scale *= 0.9;
+      break;
+    default:
+      return FALSE;
+      break;
+    }
+
+  gtk_range_set_value (GTK_RANGE (priv->scaling), 100*scale);
+
+  return TRUE;
+}
+
+
+/* Function taken from gtkprintunixdialog.c */
+static GtkWidget *
+photos_print_setup_wrap_in_frame (const gchar *label, GtkWidget *child)
+{
+  GtkWidget *alignment;
+  GtkWidget *frame;
+  GtkWidget *label_widget;
+  gchar *bold_text;
+
+  label_widget = gtk_label_new ("");
+  gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
+  gtk_widget_show (label_widget);
+
+  bold_text = g_markup_printf_escaped ("<b>%s</b>", label);
+  gtk_label_set_markup (GTK_LABEL (label_widget), bold_text);
+  g_free (bold_text);
+
+  frame = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+  gtk_box_pack_start (GTK_BOX (frame), label_widget, FALSE, FALSE, 0);
+
+  alignment = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
+  gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 12, 0);
+  gtk_box_pack_start (GTK_BOX (frame), alignment, FALSE, FALSE, 0);
+
+  gtk_container_add (GTK_CONTAINER (alignment), child);
+
+  gtk_widget_show (frame);
+  gtk_widget_show (alignment);
+
+  return frame;
+}
+
+
+static GtkWidget *
+grid_attach_spin_button_with_label (GtkWidget *grid,
+                                   const gchar* text_label,
+                                   gint left, gint top)
+{
+       GtkWidget *label, *spin_button;
+
+       label = gtk_label_new_with_mnemonic (text_label);
+       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+       spin_button = gtk_spin_button_new_with_range (0, 100, 0.01);
+       gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spin_button), 2);
+       gtk_entry_set_width_chars (GTK_ENTRY (spin_button), 6);
+       gtk_grid_attach (GTK_GRID (grid), label, left, top, 1, 1);
+       gtk_grid_attach_next_to (GTK_GRID (grid), spin_button, label,
+                                GTK_POS_RIGHT, 1, 1);
+       gtk_label_set_mnemonic_widget (GTK_LABEL (label), spin_button);
+
+       return spin_button;
+}
+
+
+static void
+photos_print_setup_set_initial_values (PhotosPrintSetup *self)
+{
+  PhotosPrintSetupPrivate *priv = self->priv;
+  GeglRectangle bbox;
+  gdouble page_height;
+  gdouble page_width;
+  gdouble factor;
+  gdouble height;
+  gdouble max_perc;
+  gdouble width;
+
+  factor = get_scale_to_px_factor (self);
+
+  bbox = gegl_node_get_bounding_box (priv->node);
+  width = (gdouble) bbox.width/factor;
+  height = (gdouble) bbox.height/factor;
+
+  max_perc = photos_print_setup_get_max_percentage (self);
+
+  width *= max_perc;
+  height *= max_perc;
+
+  gtk_range_set_range (GTK_RANGE (priv->scaling), 1, 100 * max_perc);
+  gtk_range_set_increments (GTK_RANGE (priv->scaling), max_perc, 10 * max_perc);
+  gtk_range_set_value (GTK_RANGE (priv->scaling), 100 * max_perc);
+
+  photos_print_preview_set_scale (PHOTOS_PRINT_PREVIEW (priv->preview), max_perc);
+  gtk_spin_button_set_range (GTK_SPIN_BUTTON (priv->width), 0, width);
+  gtk_spin_button_set_range (GTK_SPIN_BUTTON (priv->height), 0, height);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->width), width);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (priv->height), height);
+
+  gtk_combo_box_set_active (GTK_COMBO_BOX (priv->center), CENTER_BOTH);
+
+  photos_print_setup_center (gtk_page_setup_get_page_width (priv->page_setup, priv->current_unit),
+                             gtk_spin_button_get_value (GTK_SPIN_BUTTON (priv->width)),
+                             GTK_SPIN_BUTTON (priv->left), GTK_SPIN_BUTTON (priv->right));
+  photos_print_setup_center (gtk_page_setup_get_page_height (priv->page_setup, priv->current_unit),
+                             gtk_spin_button_get_value (GTK_SPIN_BUTTON (priv->height)),
+                             GTK_SPIN_BUTTON (priv->top), GTK_SPIN_BUTTON (priv->bottom));
+
+  page_width = gtk_page_setup_get_page_width (priv->page_setup, priv->current_unit);
+  page_height = gtk_page_setup_get_page_height (priv->page_setup, priv->current_unit);
+
+  update_image_pos_ranges (self, page_width, page_height, width, height);
+}
+
+
+static void
+photos_print_setup_constructed (GObject *object)
+{
+  PhotosPrintSetup *self = PHOTOS_PRINT_SETUP (object);
+  PhotosPrintSetupPrivate *priv = self->priv;
+
+  G_OBJECT_CLASS (photos_print_setup_parent_class)->constructed (object);
+
+  photos_print_setup_set_initial_values (self);
+  photos_print_preview_set_from_page_setup (PHOTOS_PRINT_PREVIEW (priv->preview), priv->page_setup);
+
+  g_signal_connect (priv->left, "value-changed", G_CALLBACK (on_left_value_changed), self);
+  g_signal_connect (priv->right, "value-changed", G_CALLBACK (on_right_value_changed), self);
+  g_signal_connect (priv->top, "value-changed", G_CALLBACK (on_top_value_changed), self);
+  g_signal_connect (priv->bottom, "value-changed", G_CALLBACK (on_bottom_value_changed), self);
+  g_signal_connect (priv->width, "value-changed", G_CALLBACK (on_width_value_changed), self);
+  g_signal_connect (priv->height, "value-changed", G_CALLBACK (on_height_value_changed), self);
+  g_signal_connect (priv->scaling, "value-changed", G_CALLBACK (on_scale_changed), self);
+  g_signal_connect (priv->scaling, "format-value", G_CALLBACK (on_scale_format_value), NULL);
+  g_signal_connect (priv->preview, "pixbuf-moved", G_CALLBACK (on_preview_pixbuf_moved), self);
+  g_signal_connect (priv->preview, "scroll-event", G_CALLBACK (on_preview_image_scrolled), self);
+  g_signal_connect (priv->preview, "key-press-event", G_CALLBACK (on_preview_image_key_pressed), self);
+}
+
+
+static void
+photos_print_setup_dispose (GObject *object)
+{
+  PhotosPrintSetup *self = PHOTOS_PRINT_SETUP (object);
+  PhotosPrintSetupPrivate *priv = self->priv;
+
+  g_clear_object (&priv->node);
+  g_clear_object (&priv->page_setup);
+
+  G_OBJECT_CLASS (photos_print_setup_parent_class)->dispose (object);
+}
+
+
+static void
+photos_print_setup_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+  PhotosPrintSetup *self = PHOTOS_PRINT_SETUP (object);
+  PhotosPrintSetupPrivate *priv = self->priv;
+
+  switch (prop_id)
+    {
+    case PROP_NODE:
+      {
+        GdkPixbuf *pixbuf;
+
+        priv->node = GEGL_NODE (g_value_dup_object (value));
+        pixbuf = photos_utils_create_pixbuf_from_node (priv->node);
+        if (pixbuf != NULL)
+          {
+            g_object_set (priv->preview, "pixbuf", pixbuf, NULL);
+            g_object_unref (pixbuf);
+          }
+      }
+      break;
+    case PROP_PAGE_SETUP:
+      priv->page_setup = GTK_PAGE_SETUP (g_value_get_object (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+
+static void
+photos_print_setup_init (PhotosPrintSetup *self)
+{
+  GtkWidget *frame;
+  GtkWidget *grid;
+  GtkWidget *label;
+  GtkWidget *hscale;
+  GtkWidget *combobox;
+  PhotosPrintSetupPrivate *priv;
+
+#ifdef HAVE__NL_MEASUREMENT_MEASUREMENT
+  gchar *locale_scale = NULL;
+#endif
+
+  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+                                            PHOTOS_TYPE_PRINT_SETUP,
+                                            PhotosPrintSetupPrivate);
+  priv = self->priv;
+
+  gtk_container_set_border_width (GTK_CONTAINER (self), 12);
+  gtk_orientable_set_orientation (GTK_ORIENTABLE (self), GTK_ORIENTATION_VERTICAL);
+  gtk_grid_set_column_spacing (GTK_GRID (self), 18);
+  gtk_grid_set_row_spacing (GTK_GRID (self), 18);
+
+  grid = gtk_grid_new ();
+  gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
+  gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
+  frame = photos_print_setup_wrap_in_frame (_("Position"), grid);
+  gtk_grid_attach (GTK_GRID (self), frame, 0, 0, 1, 1);
+
+  priv->left = grid_attach_spin_button_with_label (grid, _("_Left:"), 0, 0);
+  priv->right = grid_attach_spin_button_with_label (grid,_("_Right:"), 0, 1);
+  priv->top = grid_attach_spin_button_with_label (grid, _("_Top:"), 2, 0);
+  priv->bottom = grid_attach_spin_button_with_label (grid, _("_Bottom:"), 2, 1);
+
+  label = gtk_label_new_with_mnemonic (_("C_enter:"));
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+
+  combobox = gtk_combo_box_text_new ();
+  gtk_combo_box_text_insert_text (GTK_COMBO_BOX_TEXT (combobox), CENTER_NONE, _("None"));
+  gtk_combo_box_text_insert_text (GTK_COMBO_BOX_TEXT (combobox), CENTER_HORIZONTAL, _("Horizontal"));
+  gtk_combo_box_text_insert_text (GTK_COMBO_BOX_TEXT (combobox), CENTER_VERTICAL, _("Vertical"));
+  gtk_combo_box_text_insert_text (GTK_COMBO_BOX_TEXT (combobox), CENTER_BOTH, _("Both"));
+  gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), CENTER_NONE);
+  /* Attach combobox below right margin spinbutton and span until end */
+  gtk_grid_attach_next_to (GTK_GRID (grid), combobox, priv->right, GTK_POS_BOTTOM, 3, 1);
+  /* Attach the label to the left of the combobox */
+  gtk_grid_attach_next_to (GTK_GRID (grid), label, combobox, GTK_POS_LEFT, 1, 1);
+  gtk_label_set_mnemonic_widget (GTK_LABEL (label), combobox);
+  priv->center = combobox;
+  g_signal_connect (G_OBJECT (combobox), "changed", G_CALLBACK (on_center_changed), self);
+
+  grid = gtk_grid_new ();
+  gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
+  gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
+  frame = photos_print_setup_wrap_in_frame (_("Size"), grid);
+  gtk_grid_attach (GTK_GRID (self), frame, 0, 1, 1, 1);
+
+  priv->width = grid_attach_spin_button_with_label (grid, _("_Width:"), 0, 0);
+  priv->height = grid_attach_spin_button_with_label (grid, _("_Height:"), 2, 0);
+
+  label = gtk_label_new_with_mnemonic (_("_Scaling:"));
+  hscale = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 1, 100, 1);
+  gtk_scale_set_value_pos (GTK_SCALE (hscale), GTK_POS_RIGHT);
+  gtk_range_set_value (GTK_RANGE (hscale), 100);
+  gtk_grid_attach_next_to (GTK_GRID (grid), hscale, priv->width, GTK_POS_BOTTOM, 3, 1);
+  gtk_grid_attach_next_to (GTK_GRID (grid), label, hscale, GTK_POS_LEFT, 1, 1);
+  gtk_label_set_mnemonic_widget (GTK_LABEL (label), hscale);
+  priv->scaling = hscale;
+
+  label = gtk_label_new_with_mnemonic (_("_Unit:"));
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+
+  combobox = gtk_combo_box_text_new ();
+  gtk_combo_box_text_insert_text (GTK_COMBO_BOX_TEXT (combobox), UNIT_MM, _("Millimeters"));
+  gtk_combo_box_text_insert_text (GTK_COMBO_BOX_TEXT (combobox), UNIT_INCH, _("Inches"));
+
+#ifdef HAVE__NL_MEASUREMENT_MEASUREMENT
+  locale_scale = nl_langinfo (_NL_MEASUREMENT_MEASUREMENT);
+  if (locale_scale && locale_scale[0] == 2)
+    {
+      gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), UNIT_INCH);
+      photos_print_setup_set_scale_unit (self, GTK_UNIT_INCH);
+    }
+  else
+#endif
+    {
+      gtk_combo_box_set_active (GTK_COMBO_BOX (combobox), UNIT_MM);
+      photos_print_setup_set_scale_unit (self, GTK_UNIT_MM);
+    }
+
+  gtk_grid_attach_next_to (GTK_GRID (grid), combobox, hscale, GTK_POS_BOTTOM, 3, 1);
+  gtk_grid_attach_next_to (GTK_GRID (grid), label, combobox, GTK_POS_LEFT, 1, 1);
+
+  gtk_label_set_mnemonic_widget (GTK_LABEL (label), combobox);
+  priv->unit = combobox;
+  g_signal_connect (G_OBJECT (combobox), "changed", G_CALLBACK (on_unit_changed), self);
+
+  priv->preview = photos_print_preview_new ();
+
+  /* FIXME: This shouldn't be set by hand */
+  gtk_widget_set_size_request (priv->preview, 250, 250);
+
+  frame = photos_print_setup_wrap_in_frame (_("Preview"), priv->preview);
+  /* The preview widget needs to span the whole grid height */
+  gtk_grid_attach (GTK_GRID (self), frame, 1, 0, 1, 2);
+
+  gtk_widget_show_all (GTK_WIDGET (self));
+}
+
+
+static void
+photos_print_setup_class_init (PhotosPrintSetupClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+  object_class->constructed = photos_print_setup_constructed;
+  object_class->dispose = photos_print_setup_dispose;
+  object_class->set_property = photos_print_setup_set_property;
+
+  g_object_class_install_property (object_class,
+                                   PROP_NODE,
+                                   g_param_spec_object ("node",
+                                                        "GeglNode object",
+                                                        "The node corresponding to the item whose printing "
+                                                        "properties will be set up",
+                                                        GEGL_TYPE_NODE,
+                                                        G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
+
+  g_object_class_install_property (object_class,
+                                   PROP_PAGE_SETUP,
+                                   g_param_spec_object ("page-setup",
+                                                        "GtkPageSetup object",
+                                                        "The information for the page where the item will be 
"
+                                                        "printed",
+                                                        GTK_TYPE_PAGE_SETUP,
+                                                        G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
+
+  g_type_class_add_private (class, sizeof (PhotosPrintSetupPrivate));
+}
+
+
+GtkWidget *
+photos_print_setup_new (GeglNode *node, GtkPageSetup *page_setup)
+{
+  return g_object_new (PHOTOS_TYPE_PRINT_SETUP, "node", node, "page-setup", page_setup, NULL);
+}
+
+
+void
+photos_print_setup_get_options (PhotosPrintSetup *self,
+                                gdouble *left,
+                                gdouble *top,
+                                gdouble *scale,
+                                GtkUnit *unit)
+{
+  PhotosPrintSetupPrivate *priv = self->priv;
+
+  *left = gtk_spin_button_get_value (GTK_SPIN_BUTTON (priv->left));
+  *top = gtk_spin_button_get_value (GTK_SPIN_BUTTON (priv->top));
+  *scale = gtk_range_get_value (GTK_RANGE (priv->scaling));
+  *unit = priv->current_unit;
+}
+
+
+void
+photos_print_setup_update (PhotosPrintSetup *self, GtkPageSetup *page_setup)
+{
+  PhotosPrintSetupPrivate *priv = self->priv;
+  gdouble pos_x;
+  gdouble pos_y;
+
+  priv->page_setup = gtk_page_setup_copy (page_setup);
+
+  photos_print_setup_set_initial_values (PHOTOS_PRINT_SETUP (self));
+
+  photos_print_preview_set_from_page_setup (PHOTOS_PRINT_PREVIEW (priv->preview), priv->page_setup);
+
+  pos_x = gtk_spin_button_get_value (GTK_SPIN_BUTTON (priv->left));
+  pos_y = gtk_spin_button_get_value (GTK_SPIN_BUTTON (priv->top));
+  if (priv->current_unit == GTK_UNIT_MM)
+    {
+      pos_x *= FACTOR_MM_TO_INCH;
+      pos_y *= FACTOR_MM_TO_INCH;
+    }
+  photos_print_preview_set_image_position (PHOTOS_PRINT_PREVIEW (priv->preview), pos_x, pos_y);
+}
diff --git a/src/photos-print-setup.h b/src/photos-print-setup.h
new file mode 100644
index 0000000..0b604df
--- /dev/null
+++ b/src/photos-print-setup.h
@@ -0,0 +1,85 @@
+/*
+ * Photos - access, organize and share your photos on GNOME
+ * Copyright © 2006, 2007 The Free Software Foundation
+ * Copyright © 2013 Red Hat, Inc.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/* Based on code from:
+ *   + Eye of GNOME
+ */
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#ifndef PHOTOS_PRINT_SETUP_H
+#define PHOTOS_PRINT_SETUP_H
+
+G_BEGIN_DECLS
+
+#define PHOTOS_TYPE_PRINT_SETUP (photos_print_setup_get_type ())
+
+#define PHOTOS_PRINT_SETUP(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+   PHOTOS_TYPE_PRINT_SETUP, PhotosPrintSetup))
+
+#define PHOTOS_PRINT_SETUP_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), \
+   PHOTOS_TYPE_PRINT_SETUP, PhotosPrintSetupClass))
+
+#define PHOTOS_IS_PRINT_SETUP(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+   PHOTOS_TYPE_PRINT_SETUP))
+
+#define PHOTOS_IS_PRINT_SETUP_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+   PHOTOS_TYPE_PRINT_SETUP))
+
+#define PHOTOS_PRINT_SETUP_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+   PHOTOS_TYPE_PRINT_SETUP, PhotosPrintSetupClass))
+
+typedef struct _PhotosPrintSetup         PhotosPrintSetup;
+typedef struct _PhotosPrintSetupClass    PhotosPrintSetupClass;
+typedef struct _PhotosPrintSetupPrivate  PhotosPrintSetupPrivate;
+
+struct _PhotosPrintSetup
+{
+  GtkGrid parent_instance;
+  PhotosPrintSetupPrivate *priv;
+};
+
+struct _PhotosPrintSetupClass
+{
+  GtkGridClass parent_class;
+};
+
+GType            photos_print_setup_get_type    (void) G_GNUC_CONST;
+
+GtkWidget        *photos_print_setup_new         (GeglNode *node, GtkPageSetup *page_setup);
+
+void              photos_print_setup_get_options (PhotosPrintSetup *self,
+                                                 gdouble *left,
+                                                 gdouble *top,
+                                                 gdouble *scale,
+                                                 GtkUnit *unit);
+
+void              photos_print_setup_update      (PhotosPrintSetup *self, GtkPageSetup *page_setup);
+
+G_END_DECLS
+
+#endif /* PHOTOS_PRINT_SETUP_H */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]