[gthumb: 4/129] rotate tool: added ability to change the rotation center



commit 1d2294ccc8bd7c10dd0df1ba15e052a355204881
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Wed Apr 13 20:12:14 2011 +0200

    rotate tool: added ability to change the rotation center
    
    the user can define the rotation center double-clicking on the image or using the controls in the tool options.

 extensions/file_tools/data/ui/rotate-options.ui |  198 +++++++++++++---------
 extensions/file_tools/gth-file-tool-rotate.c    |  116 ++++++++++---
 extensions/file_tools/gth-image-rotator.c       |  116 ++++++++------
 extensions/file_tools/gth-image-rotator.h       |    6 +-
 gthumb/gth-image-viewer.c                       |    4 +-
 5 files changed, 280 insertions(+), 160 deletions(-)
---
diff --git a/extensions/file_tools/data/ui/rotate-options.ui b/extensions/file_tools/data/ui/rotate-options.ui
index 58735c7..fcb796b 100644
--- a/extensions/file_tools/data/ui/rotate-options.ui
+++ b/extensions/file_tools/data/ui/rotate-options.ui
@@ -81,7 +81,56 @@
               </packing>
             </child>
             <child>
+              <object class="GtkFrame" id="frame1">
+                <property name="visible">True</property>
+                <property name="label_xalign">0</property>
+                <property name="shadow_type">none</property>
+                <child>
+                  <object class="GtkAlignment" id="alignment1">
+                    <property name="visible">True</property>
+                    <property name="top_padding">6</property>
+                    <property name="left_padding">12</property>
+                    <child>
+                      <object class="GtkVBox" id="vbox6">
+                        <property name="visible">True</property>
+                        <property name="spacing">6</property>
+                        <child>
+                          <object class="GtkComboBox" id="size_combobox">
+                            <property name="visible">True</property>
+                            <property name="model">size_liststore</property>
+                            <child>
+                              <object class="GtkCellRendererText" id="cellrenderertext2"/>
+                              <attributes>
+                                <attribute name="text">0</attribute>
+                              </attributes>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child type="label">
+                  <object class="GtkLabel" id="label3">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">Size</property>
+                    <property name="use_markup">True</property>
+                    <attributes>
+                      <attribute name="weight" value="bold"/>
+                    </attributes>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
               <object class="GtkFrame" id="frame4">
+                <property name="visible">True</property>
                 <property name="label_xalign">0</property>
                 <property name="shadow_type">none</property>
                 <child>
@@ -90,15 +139,13 @@
                     <property name="top_padding">6</property>
                     <property name="left_padding">12</property>
                     <child>
-                      <object class="GtkTable" id="table3">
+                      <object class="GtkVBox" id="vbox5">
                         <property name="visible">True</property>
-                        <property name="n_rows">2</property>
-                        <property name="column_spacing">6</property>
-                        <property name="row_spacing">6</property>
+                        <property name="spacing">6</property>
                         <child>
-                          <object class="GtkHBox" id="hbox4">
+                          <object class="GtkHBox" id="hbox1">
                             <property name="visible">True</property>
-                            <property name="spacing">6</property>
+                            <property name="spacing">4</property>
                             <child>
                               <object class="GtkSpinButton" id="center_x_spinbutton">
                                 <property name="visible">True</property>
@@ -117,6 +164,33 @@
                               </packing>
                             </child>
                             <child>
+                              <object class="GtkLabel" id="label5">
+                                <property name="visible">True</property>
+                                <property name="label" translatable="yes">&#xD7;</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkSpinButton" id="center_y_spinbutton">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="invisible_char">&#x25CF;</property>
+                                <property name="width_chars">6</property>
+                                <property name="adjustment">center_y_adjustment</property>
+                                <property name="climb_rate">1</property>
+                                <property name="numeric">True</property>
+                                <property name="update_policy">if-valid</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                            <child>
                               <object class="GtkComboBox" id="unit_combobox">
                                 <property name="visible">True</property>
                                 <property name="model">unit_liststore</property>
@@ -131,28 +205,32 @@
                               <packing>
                                 <property name="expand">False</property>
                                 <property name="fill">False</property>
-                                <property name="position">1</property>
+                                <property name="position">3</property>
                               </packing>
                             </child>
                           </object>
                           <packing>
-                            <property name="x_options">GTK_FILL</property>
+                            <property name="position">0</property>
                           </packing>
                         </child>
                         <child>
-                          <object class="GtkHBox" id="hbox5">
+                          <object class="GtkHButtonBox" id="hbuttonbox2">
                             <property name="visible">True</property>
-                            <property name="spacing">6</property>
+                            <property name="layout_style">start</property>
                             <child>
-                              <object class="GtkSpinButton" id="center_y_spinbutton">
+                              <object class="GtkButton" id="center_button">
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
-                                <property name="invisible_char">&#x25CF;</property>
-                                <property name="width_chars">6</property>
-                                <property name="adjustment">center_y_adjustment</property>
-                                <property name="climb_rate">1</property>
-                                <property name="numeric">True</property>
-                                <property name="update_policy">if-valid</property>
+                                <property name="receives_default">True</property>
+                                <child>
+                                  <object class="GtkLabel" id="label8">
+                                    <property name="visible">True</property>
+                                    <property name="label" translatable="yes">Center</property>
+                                    <attributes>
+                                      <attribute name="size" value="8000"/>
+                                    </attributes>
+                                  </object>
+                                </child>
                               </object>
                               <packing>
                                 <property name="expand">False</property>
@@ -160,14 +238,9 @@
                                 <property name="position">0</property>
                               </packing>
                             </child>
-                            <child>
-                              <placeholder/>
-                            </child>
                           </object>
                           <packing>
-                            <property name="top_attach">1</property>
-                            <property name="bottom_attach">2</property>
-                            <property name="x_options">GTK_FILL</property>
+                            <property name="position">1</property>
                           </packing>
                         </child>
                       </object>
@@ -177,46 +250,7 @@
                 <child type="label">
                   <object class="GtkLabel" id="label7">
                     <property name="visible">True</property>
-                    <property name="label" translatable="yes">Center</property>
-                    <property name="use_markup">True</property>
-                    <attributes>
-                      <attribute name="weight" value="bold"/>
-                    </attributes>
-                  </object>
-                </child>
-              </object>
-              <packing>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkFrame" id="frame1">
-                <property name="visible">True</property>
-                <property name="label_xalign">0</property>
-                <property name="shadow_type">none</property>
-                <child>
-                  <object class="GtkAlignment" id="alignment1">
-                    <property name="visible">True</property>
-                    <property name="top_padding">6</property>
-                    <property name="left_padding">12</property>
-                    <child>
-                      <object class="GtkComboBox" id="size_combobox">
-                        <property name="visible">True</property>
-                        <property name="model">size_liststore</property>
-                        <child>
-                          <object class="GtkCellRendererText" id="cellrenderertext2"/>
-                          <attributes>
-                            <attribute name="text">0</attribute>
-                          </attributes>
-                        </child>
-                      </object>
-                    </child>
-                  </object>
-                </child>
-                <child type="label">
-                  <object class="GtkLabel" id="label3">
-                    <property name="visible">True</property>
-                    <property name="label" translatable="yes">Size</property>
+                    <property name="label" translatable="yes">Axis of rotation</property>
                     <property name="use_markup">True</property>
                     <attributes>
                       <attribute name="weight" value="bold"/>
@@ -250,19 +284,6 @@
                             <property name="column_spacing">6</property>
                             <property name="row_spacing">6</property>
                             <child>
-                              <object class="GtkLabel" id="label4">
-                                <property name="visible">True</property>
-                                <property name="xalign">0</property>
-                                <property name="label" translatable="yes">_Background:</property>
-                                <property name="use_underline">True</property>
-                              </object>
-                              <packing>
-                                <property name="top_attach">1</property>
-                                <property name="bottom_attach">2</property>
-                                <property name="x_options">GTK_FILL</property>
-                              </packing>
-                            </child>
-                            <child>
                               <object class="GtkHBox" id="grid_box">
                                 <property name="visible">True</property>
                                 <property name="spacing">6</property>
@@ -289,24 +310,39 @@
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkHBox" id="hbox3">
+                              <object class="GtkHBox" id="hbox2">
                                 <property name="visible">True</property>
+                                <property name="spacing">6</property>
+                                <child>
+                                  <object class="GtkLabel" id="label4">
+                                    <property name="visible">True</property>
+                                    <property name="xalign">0</property>
+                                    <property name="label" translatable="yes">_Background:</property>
+                                    <property name="use_underline">True</property>
+                                    <property name="mnemonic_widget">background_colorbutton</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
                                 <child>
                                   <object class="GtkColorButton" id="background_colorbutton">
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="receives_default">True</property>
+                                    <property name="relief">none</property>
                                     <property name="use_alpha">True</property>
+                                    <property name="title" translatable="yes"></property>
                                     <property name="color">#000000000000</property>
                                   </object>
                                   <packing>
                                     <property name="expand">False</property>
-                                    <property name="position">0</property>
+                                    <property name="position">1</property>
                                   </packing>
                                 </child>
                               </object>
                               <packing>
-                                <property name="left_attach">1</property>
                                 <property name="right_attach">2</property>
                                 <property name="top_attach">1</property>
                                 <property name="bottom_attach">2</property>
@@ -416,12 +452,12 @@
     </data>
   </object>
   <object class="GtkAdjustment" id="center_x_adjustment">
-    <property name="lower">1</property>
+    <property name="lower">-999999</property>
     <property name="upper">999999</property>
     <property name="step_increment">1</property>
   </object>
   <object class="GtkAdjustment" id="center_y_adjustment">
-    <property name="lower">1</property>
+    <property name="lower">-999999</property>
     <property name="upper">999999</property>
     <property name="step_increment">1</property>
   </object>
diff --git a/extensions/file_tools/gth-file-tool-rotate.c b/extensions/file_tools/gth-file-tool-rotate.c
index e923f73..49a3bc8 100644
--- a/extensions/file_tools/gth-file-tool-rotate.c
+++ b/extensions/file_tools/gth-file-tool-rotate.c
@@ -108,12 +108,51 @@ ok_button_clicked_cb (GtkButton *button,
 
 
 static void
+rotator_center_changed_cb (GObject  *gobject,
+			   gpointer  user_data)
+{
+	GthFileToolRotate *self = user_data;
+	int                x, y;
+	double             dx, dy;
+
+	g_signal_handlers_block_by_data (GET_WIDGET ("center_x_spinbutton"), self);
+	g_signal_handlers_block_by_data (GET_WIDGET ("center_y_spinbutton"), self);
+
+	gth_image_rotator_get_center (self->priv->rotator, &x, &y);
+	if (self->priv->unit == GTH_UNIT_PERCENTAGE) {
+		dx = ((double) x / self->priv->pixbuf_width) * 100.0;
+		dy = ((double) y / self->priv->pixbuf_height) * 100.0;
+	}
+	else {
+		dx = x;
+		dy = y;
+	}
+	gtk_spin_button_set_value (GTK_SPIN_BUTTON (GET_WIDGET ("center_x_spinbutton")), dx);
+	gtk_spin_button_set_value (GTK_SPIN_BUTTON (GET_WIDGET ("center_y_spinbutton")), dy);
+
+	g_signal_handlers_unblock_by_data (GET_WIDGET ("center_x_spinbutton"), self);
+	g_signal_handlers_unblock_by_data (GET_WIDGET ("center_y_spinbutton"), self);
+}
+
+
+static void
 center_position_changed_cb (GtkSpinButton *spinbutton,
 			    gpointer       user_data)
 {
-	/*GthFileToolRotate *self = user_data;
+	GthFileToolRotate *self = user_data;
+	double             x, y;
 
-	FIXME */
+	g_signal_handlers_block_by_data (self->priv->rotator, user_data);
+
+	x = gtk_spin_button_get_value (GTK_SPIN_BUTTON (GET_WIDGET ("center_x_spinbutton")));
+	y = gtk_spin_button_get_value (GTK_SPIN_BUTTON (GET_WIDGET ("center_y_spinbutton")));
+	if (self->priv->unit == GTH_UNIT_PERCENTAGE) {
+		x = round ((double) self->priv->pixbuf_width * (x / 100.0));
+		y = round ((double) self->priv->pixbuf_height * (y / 100.0));
+	}
+	gth_image_rotator_set_center (self->priv->rotator, x, y);
+
+	g_signal_handlers_unblock_by_data (self->priv->rotator, user_data);
 }
 
 
@@ -121,35 +160,41 @@ static void
 unit_combobox_changed_cb (GtkComboBox *combobox,
 			  gpointer     user_data)
 {
-	/* FIXME GthFileToolRotate *self = user_data;
+	GthFileToolRotate *self = user_data;
 
-	g_signal_handlers_block_by_data (GET_WIDGET ("resize_width_spinbutton"), self);
-	g_signal_handlers_block_by_data (GET_WIDGET ("resize_height_spinbutton"), self);
+	g_signal_handlers_block_by_data (GET_WIDGET ("center_x_spinbutton"), self);
+	g_signal_handlers_block_by_data (GET_WIDGET ("center_y_spinbutton"), self);
 
 	self->priv->unit = gtk_combo_box_get_active (combobox);
 	if (self->priv->unit == GTH_UNIT_PERCENTAGE) {
 		double p;
 
-		gtk_spin_button_set_digits (GTK_SPIN_BUTTON (GET_WIDGET ("resize_width_spinbutton")), 2);
-		gtk_spin_button_set_digits (GTK_SPIN_BUTTON (GET_WIDGET ("resize_height_spinbutton")), 2);
+		gtk_spin_button_set_digits (GTK_SPIN_BUTTON (GET_WIDGET ("center_x_spinbutton")), 2);
+		gtk_spin_button_set_digits (GTK_SPIN_BUTTON (GET_WIDGET ("center_y_spinbutton")), 2);
+
+		p = gtk_spin_button_get_value (GTK_SPIN_BUTTON (GET_WIDGET ("center_x_spinbutton"))) / self->priv->pixbuf_width * 100.0;
+		gtk_spin_button_set_value (GTK_SPIN_BUTTON (GET_WIDGET ("center_x_spinbutton")), p);
 
-		p = ((double) self->priv->new_width) / self->priv->pixbuf_width * 100.0;
-		gtk_spin_button_set_value (GTK_SPIN_BUTTON (GET_WIDGET ("resize_width_spinbutton")), p);
-		p = ((double) self->priv->new_height) / self->priv->pixbuf_height * 100.0;
-		gtk_spin_button_set_value (GTK_SPIN_BUTTON (GET_WIDGET ("resize_height_spinbutton")), p);
+		p = gtk_spin_button_get_value (GTK_SPIN_BUTTON (GET_WIDGET ("center_y_spinbutton"))) / self->priv->pixbuf_height * 100.0;
+		gtk_spin_button_set_value (GTK_SPIN_BUTTON (GET_WIDGET ("center_y_spinbutton")), p);
 	}
 	else if (self->priv->unit == GTH_UNIT_PIXELS) {
-		gtk_spin_button_set_digits (GTK_SPIN_BUTTON (GET_WIDGET ("resize_width_spinbutton")), 0);
-		gtk_spin_button_set_digits (GTK_SPIN_BUTTON (GET_WIDGET ("resize_height_spinbutton")), 0);
-		gtk_spin_button_set_value (GTK_SPIN_BUTTON (GET_WIDGET ("resize_width_spinbutton")), self->priv->new_width);
-		gtk_spin_button_set_value (GTK_SPIN_BUTTON (GET_WIDGET ("resize_height_spinbutton")), self->priv->new_height);
+		double p;
+
+		gtk_spin_button_set_digits (GTK_SPIN_BUTTON (GET_WIDGET ("center_x_spinbutton")), 0);
+		gtk_spin_button_set_digits (GTK_SPIN_BUTTON (GET_WIDGET ("center_y_spinbutton")), 0);
+
+		p = round (self->priv->pixbuf_width * (gtk_spin_button_get_value (GTK_SPIN_BUTTON (GET_WIDGET ("center_x_spinbutton"))) / 100.0));
+		gtk_spin_button_set_value (GTK_SPIN_BUTTON (GET_WIDGET ("center_x_spinbutton")), p);
+
+		p = round (self->priv->pixbuf_height * (gtk_spin_button_get_value (GTK_SPIN_BUTTON (GET_WIDGET ("center_y_spinbutton"))) / 100.0));
+		gtk_spin_button_set_value (GTK_SPIN_BUTTON (GET_WIDGET ("center_y_spinbutton")), p);
 	}
 
-	g_signal_handlers_unblock_by_data (GET_WIDGET ("resize_width_spinbutton"), self);
-	g_signal_handlers_unblock_by_data (GET_WIDGET ("resize_height_spinbutton"), self);
+	g_signal_handlers_unblock_by_data (GET_WIDGET ("center_x_spinbutton"), self);
+	g_signal_handlers_unblock_by_data (GET_WIDGET ("center_y_spinbutton"), self);
 
-	selection_width_value_changed_cb (GTK_SPIN_BUTTON (GET_WIDGET ("resize_width_spinbutton")), self);
-	*/
+	center_position_changed_cb (NULL, self);
 }
 
 
@@ -293,6 +338,18 @@ background_colorbutton_notify_color_cb (GObject    *gobject,
 }
 
 
+static void
+center_button_clicked_cb (GtkButton *button,
+			  gpointer    user_data)
+{
+	GthFileToolRotate *self = user_data;
+
+	gth_image_rotator_set_center (self->priv->rotator,
+				      self->priv->pixbuf_width * 0.5,
+				      self->priv->pixbuf_height * 0.5);
+}
+
+
 static GtkWidget *
 gth_file_tool_rotate_get_options (GthFileTool *base)
 {
@@ -355,13 +412,13 @@ gth_file_tool_rotate_get_options (GthFileTool *base)
 
 	self->priv->angle_adj = gimp_scale_entry_new (GET_WIDGET ("angle_box"),
 						      NULL,
-						      0.0, -180.0, 180.0, 5.0, 10.0, 0);
+						      0.0, -180.0, 180.0, 1.0, 10.0, 2);
 	self->priv->small_angle_adj = gimp_scale_entry_new (GET_WIDGET ("small_angle_box"),
 							    NULL,
 							    0.0, -5.0, 5.0, 0.01, 0.1, 2);
 	self->priv->grid_adj = gimp_scale_entry_new (GET_WIDGET ("grid_box"),
 						     NULL,
-						     DEFAULT_GRID, 1.0, 50.0, 1.0, 10.0, 0);
+						     DEFAULT_GRID, 2.0, 50.0, 1.0, 10.0, 0);
 
 	g_signal_connect (GET_WIDGET ("ok_button"),
 			  "clicked",
@@ -411,17 +468,22 @@ gth_file_tool_rotate_get_options (GthFileTool *base)
 			  "notify::color",
 			  G_CALLBACK (background_colorbutton_notify_color_cb),
 			  self);
-
+	g_signal_connect (GET_WIDGET ("center_button"),
+			  "clicked",
+			  G_CALLBACK (center_button_clicked_cb),
+			  self);
 
 	self->priv->rotator = (GthImageRotator *) gth_image_rotator_new (GTH_IMAGE_VIEWER (viewer));
 	gth_image_rotator_set_grid (self->priv->rotator, FALSE, DEFAULT_GRID);
 	_gth_file_tool_rotate (self, 0.0);
+	gth_image_rotator_set_center (self->priv->rotator,
+				      self->priv->pixbuf_width * 0.5,
+				      self->priv->pixbuf_height * 0.5);
 
-	/*g_signal_connect (self->priv->rotator,
-			  "changed",
-			  G_CALLBACK (rotator_changed_cb),
+	g_signal_connect (self->priv->rotator,
+			  "center-changed",
+			  G_CALLBACK (rotator_center_changed_cb),
 			  self);
-	 */
 
 	gth_image_viewer_set_tool (GTH_IMAGE_VIEWER (viewer), (GthImageViewerTool *) self->priv->rotator);
 
@@ -479,7 +541,7 @@ gth_file_tool_rotate_instance_init (GthFileToolRotate *self)
 {
 	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_FILE_TOOL_ROTATE, GthFileToolRotatePrivate);
 	self->priv->tmp_pixbuf = NULL;
-	self->priv->step = 5.0;
+	self->priv->step = 0.0; /* FIXME */
 	self->priv->use_grid = TRUE;
 	gth_file_tool_construct (GTH_FILE_TOOL (self), "tool-rotate", _("Rotate..."), _("Rotate"), TRUE);
 }
diff --git a/extensions/file_tools/gth-image-rotator.c b/extensions/file_tools/gth-image-rotator.c
index af1d66b..3e3fab1 100644
--- a/extensions/file_tools/gth-image-rotator.c
+++ b/extensions/file_tools/gth-image-rotator.c
@@ -27,6 +27,7 @@
 
 enum {
 	CHANGED,
+	CENTER_CHANGED,
 	LAST_SIGNAL
 };
 
@@ -51,10 +52,11 @@ struct _GthImageRotatorPrivate {
 
 	int                 original_width;
 	int                 original_height;
-	cairo_surface_t    *image;
-	GdkRectangle        image_area;
+	double              preview_zoom;
+	cairo_surface_t    *preview_image;
+	GdkRectangle        preview_image_area;
+	GdkPoint            preview_center;
 	GdkRectangle        clip_area;
-	gboolean            paint_image;
 	cairo_matrix_t      matrix;
 };
 
@@ -79,8 +81,11 @@ _gth_image_rotator_update_tranformation_matrix (GthImageRotator *self)
 	int    tx, ty;
 	double zoom;
 
-	tx = self->priv->image_area.x + self->priv->center.x;
-	ty = self->priv->image_area.y + self->priv->center.y;
+	self->priv->preview_center.x = self->priv->center.x * self->priv->preview_zoom;
+	self->priv->preview_center.y = self->priv->center.y * self->priv->preview_zoom;
+
+	tx = self->priv->preview_image_area.x + self->priv->preview_center.x;
+	ty = self->priv->preview_image_area.y + self->priv->preview_center.y;
 	zoom = gth_image_viewer_get_zoom (self->priv->viewer);
 
 	cairo_matrix_init_identity (&self->priv->matrix);
@@ -90,7 +95,7 @@ _gth_image_rotator_update_tranformation_matrix (GthImageRotator *self)
 
 	gth_transform_resize (&self->priv->matrix,
 			      self->priv->resize,
-			      &self->priv->image_area,
+			      &self->priv->preview_image_area,
 			      &self->priv->clip_area);
 }
 
@@ -103,20 +108,17 @@ update_image_surface (GthImageRotator *self)
 	int            max_size;
 	int            width;
 	int            height;
-	double         zoom;
 	GdkPixbuf     *tmp_pixbuf;
 
-	if (self->priv->image != NULL) {
-		cairo_surface_destroy (self->priv->image);
-		self->priv->image = NULL;
+	if (self->priv->preview_image != NULL) {
+		cairo_surface_destroy (self->priv->preview_image);
+		self->priv->preview_image = NULL;
 	}
 
 	src_pixbuf = gth_image_viewer_get_current_pixbuf (GTH_IMAGE_VIEWER (self->priv->viewer));
 	if (src_pixbuf == NULL)
 		return;
 
-	zoom = gth_image_viewer_get_zoom (self->priv->viewer);
-
 	self->priv->original_width = gdk_pixbuf_get_width (src_pixbuf);
 	self->priv->original_height = gdk_pixbuf_get_height (src_pixbuf);
 	width = self->priv->original_width;
@@ -127,14 +129,14 @@ update_image_surface (GthImageRotator *self)
 		tmp_pixbuf = _gdk_pixbuf_scale_simple_safe (src_pixbuf, width, height, GDK_INTERP_BILINEAR);
 	else
 		tmp_pixbuf = gdk_pixbuf_copy (src_pixbuf);
-	self->priv->image = _cairo_image_surface_create_from_pixbuf (tmp_pixbuf);
-	self->priv->image_area.width = width;
-	self->priv->image_area.height = height;
-	self->priv->image_area.x = MAX ((allocation.width - self->priv->image_area.width) / 2, 0);
-	self->priv->image_area.y = MAX ((allocation.height - self->priv->image_area.height) / 2, 0);
 
-	self->priv->center.x = self->priv->image_area.width * 0.5;
-	self->priv->center.y = self->priv->image_area.height * 0.5;
+	self->priv->preview_zoom = (double) width / self->priv->original_width;
+
+	self->priv->preview_image = _cairo_image_surface_create_from_pixbuf (tmp_pixbuf);
+	self->priv->preview_image_area.width = width;
+	self->priv->preview_image_area.height = height;
+	self->priv->preview_image_area.x = MAX ((allocation.width - self->priv->preview_image_area.width) / 2, 0);
+	self->priv->preview_image_area.y = MAX ((allocation.height - self->priv->preview_image_area.height) / 2, 0);
 
 	_gth_image_rotator_update_tranformation_matrix (self);
 
@@ -166,21 +168,21 @@ gth_image_rotator_unmap (GthImageViewerTool *base)
 
 static void
 paint_image (GthImageRotator *self,
-	     GdkEventExpose  *event,
 	     cairo_t         *cr)
 {
 	cairo_save (cr);
 
+	cairo_set_matrix (cr, &self->priv->matrix);
 	cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
-	cairo_set_source_surface (cr, self->priv->image,
-				  self->priv->image_area.x,
-				  self->priv->image_area.y);
+	cairo_set_source_surface (cr, self->priv->preview_image,
+				  self->priv->preview_image_area.x,
+				  self->priv->preview_image_area.y);
 	cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_FAST);
   	cairo_rectangle (cr,
-  			 self->priv->image_area.x,
-  			 self->priv->image_area.y,
-  			 self->priv->image_area.width,
-  			 self->priv->image_area.height);
+  			 self->priv->preview_image_area.x,
+  			 self->priv->preview_image_area.y,
+  			 self->priv->preview_image_area.width,
+  			 self->priv->preview_image_area.height);
   	cairo_fill (cr);
 
   	cairo_restore (cr);
@@ -256,8 +258,8 @@ paint_center (GthImageRotator *self,
   	/* rotation center */
 
 	cairo_translate (cr,
-			 self->priv->image_area.x + self->priv->center.x + 0.5,
-			 self->priv->image_area.y + self->priv->center.y + 0.5);
+			 self->priv->preview_image_area.x + self->priv->preview_center.x + 0.5,
+			 self->priv->preview_image_area.y + self->priv->preview_center.y + 0.5);
 	cairo_arc (cr, 0.0, 0.0, 10.0, 0.0, 2 * M_PI);
 
 	cairo_move_to (cr, 0.0, - 10.0);
@@ -278,9 +280,8 @@ gth_image_rotator_expose (GthImageViewerTool *base,
 	GthImageRotator *self = GTH_IMAGE_ROTATOR (base);
 	GtkStyle        *style;
 	GtkAllocation    allocation;
-	cairo_matrix_t   matrix;
 
-	if (self->priv->image == NULL)
+	if (self->priv->preview_image == NULL)
 		return;
 
 	cairo_save (cr);
@@ -317,21 +318,13 @@ gth_image_rotator_expose (GthImageViewerTool *base,
 
   	/* image */
 
-  	matrix = self->priv->matrix;
-	cairo_set_matrix (cr, &matrix);
-
-	if (self->priv->paint_image)
-		paint_image (self, event, cr);
+	paint_image (self, cr);
 
 	/* grid */
 
-	cairo_matrix_init_identity (&matrix);
-	cairo_set_matrix (cr, &matrix);
-
 	if (self->priv->paint_grid)
 		paint_grid (self, event, cr);
-
-	/* paint_center (self, event, cr); FIXME */
+	paint_center (self, event, cr);
 
 	cairo_restore (cr);
 }
@@ -351,7 +344,15 @@ static gboolean
 gth_image_rotator_button_press (GthImageViewerTool *base,
 				GdkEventButton     *event)
 {
-	/* FIXME */
+	GthImageRotator *self = GTH_IMAGE_ROTATOR (base);
+
+	if (event->type == GDK_2BUTTON_PRESS) {
+		double x, y;
+
+		x = (event->x - self->priv->preview_image_area.x) / self->priv->preview_zoom;
+		y = (event->y - self->priv->preview_image_area.y) / self->priv->preview_zoom;
+		gth_image_rotator_set_center (self, (int) x, (int) y);
+	}
 
 	return FALSE;
 }
@@ -385,8 +386,7 @@ static void
 gth_image_rotator_instance_init (GthImageRotator *self)
 {
 	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_IMAGE_ROTATOR, GthImageRotatorPrivate);
-	self->priv->image = NULL;
-	self->priv->paint_image = TRUE;
+	self->priv->preview_image = NULL;
 	self->priv->paint_grid = FALSE;
 	self->priv->grid_lines = 0;
 	self->priv->resize = GTH_TRANSFORM_RESIZE_CLIP;
@@ -406,8 +406,8 @@ gth_image_rotator_finalize (GObject *object)
 	g_return_if_fail (GTH_IS_IMAGE_ROTATOR (object));
 
 	self = (GthImageRotator *) object;
-	if (self->priv->image != NULL)
-		cairo_surface_destroy (self->priv->image);
+	if (self->priv->preview_image != NULL)
+		cairo_surface_destroy (self->priv->preview_image);
 
 	/* Chain up */
 	G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -433,6 +433,14 @@ gth_image_rotator_class_init (GthImageRotatorClass *class)
 					 g_cclosure_marshal_VOID__VOID,
 					 G_TYPE_NONE,
 					 0);
+	signals[CENTER_CHANGED] = g_signal_new ("center-changed",
+					 	G_TYPE_FROM_CLASS (class),
+					 	G_SIGNAL_RUN_LAST,
+					 	G_STRUCT_OFFSET (GthImageRotatorClass, center_changed),
+					 	NULL, NULL,
+					 	g_cclosure_marshal_VOID__VOID,
+					 	G_TYPE_NONE,
+					 	0);
 }
 
 
@@ -510,7 +518,17 @@ gth_image_rotator_set_center (GthImageRotator *self,
 	_gth_image_rotator_update_tranformation_matrix (self);
 	gtk_widget_queue_draw (GTK_WIDGET (self->priv->viewer));
 
-	g_signal_emit (self, signals[CHANGED], 0);
+	g_signal_emit (self, signals[CENTER_CHANGED], 0);
+}
+
+
+void
+gth_image_rotator_get_center (GthImageRotator *self,
+			      int             *x,
+			      int             *y)
+{
+	*x = self->priv->center.x;
+	*y = self->priv->center.y;
 }
 
 
@@ -583,8 +601,8 @@ gth_image_rotator_get_result (GthImageRotator *self)
 
 	/* compute the transformation matrix and the clip area */
 
-	tx = self->priv->original_width * 0.5;
-	ty = self->priv->original_height * 0.5;
+	tx = self->priv->center.x;
+	ty = self->priv->center.y;
 	cairo_matrix_init_identity (&matrix);
 	cairo_matrix_translate (&matrix, tx, ty);
 	cairo_matrix_rotate (&matrix, self->priv->angle);
diff --git a/extensions/file_tools/gth-image-rotator.h b/extensions/file_tools/gth-image-rotator.h
index 25c7a7e..223ba9a 100644
--- a/extensions/file_tools/gth-image-rotator.h
+++ b/extensions/file_tools/gth-image-rotator.h
@@ -52,7 +52,8 @@ struct _GthImageRotatorClass
 
 	/*< signals >*/
 
-	void (* changed) (GthImageRotator *rotator);
+	void (* changed)        (GthImageRotator *rotator);
+	void (* center_changed) (GthImageRotator *rotator);
 };
 
 GType                 gth_image_rotator_get_type        (void);
@@ -60,6 +61,9 @@ GthImageViewerTool *  gth_image_rotator_new             (GthImageViewer     *vie
 void                  gth_image_rotator_set_center      (GthImageRotator    *rotator,
 						         int                 x,
 						         int                 y);
+void                  gth_image_rotator_get_center      (GthImageRotator    *rotator,
+							 int                *x,
+							 int                *y);
 void                  gth_image_rotator_set_angle       (GthImageRotator    *rotator,
 						         double              angle);
 void                  gth_image_rotator_set_grid        (GthImageRotator    *self,
diff --git a/gthumb/gth-image-viewer.c b/gthumb/gth-image-viewer.c
index c4717c0..662d657 100644
--- a/gthumb/gth-image-viewer.c
+++ b/gthumb/gth-image-viewer.c
@@ -916,14 +916,14 @@ gth_image_viewer_button_press (GtkWidget      *widget,
 	    || (event->type == GDK_3BUTTON_PRESS))
 	{
 		self->priv->double_click = TRUE;
-		return FALSE;
+		/*return FALSE;*/
 	}
 	else
 		self->priv->double_click = FALSE;
 
 	retval = gth_image_viewer_tool_button_press (self->priv->tool, event);
 
-	if (self->pressed) {
+	if (self->pressed && ! self->priv->double_click) {
 		self->event_x_start = self->event_x_prev = event->x;
 		self->event_y_start = self->event_y_prev = event->y;
 		self->drag_x = self->drag_x_start = self->drag_x_prev = event->x + self->x_offset;



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