[gimp] app: make image-coords overlay widgets work fine at any zoom factor



commit 84d33e4316d0b38cb5e9fe90871538dfd4d5fb43
Author: Michael Natterer <mitch gimp org>
Date:   Sun Feb 28 14:48:47 2010 +0100

    app: make image-coords overlay widgets work fine at any zoom factor
    
    Add anchor and spacing parameters to the shell overlay API, so
    overlays can be positioned on each side of a point in image space,
    with configurable spacing in display space.

 app/display/gimpdisplayshell.c  |  149 ++++++++++++++++++++++++++++++---------
 app/display/gimpdisplayshell.h  |   10 ++-
 app/tools/gimptexttool-editor.c |   10 ++-
 3 files changed, 128 insertions(+), 41 deletions(-)
---
diff --git a/app/display/gimpdisplayshell.c b/app/display/gimpdisplayshell.c
index e84c4e5..cca9567 100644
--- a/app/display/gimpdisplayshell.c
+++ b/app/display/gimpdisplayshell.c
@@ -98,6 +98,18 @@ enum
 };
 
 
+typedef struct _GimpDisplayShellOverlay GimpDisplayShellOverlay;
+
+struct _GimpDisplayShellOverlay
+{
+  gdouble       image_x;
+  gdouble       image_y;
+  GtkAnchorType anchor;
+  gint          spacing_x;
+  gint          spacing_y;
+};
+
+
 /*  local function prototypes  */
 
 static void      gimp_color_managed_iface_init     (GimpColorManagedInterface *iface);
@@ -141,6 +153,10 @@ static void      gimp_display_shell_sync_config    (GimpDisplayShell  *shell,
 static void      gimp_display_shell_remove_overlay (GtkWidget        *canvas,
                                                     GtkWidget        *child,
                                                     GimpDisplayShell *shell);
+static void   gimp_display_shell_transform_overlay (GimpDisplayShell *shell,
+                                                    GtkWidget        *child,
+                                                    gdouble          *x,
+                                                    gdouble          *y);
 
 
 G_DEFINE_TYPE_WITH_CODE (GimpDisplayShell, gimp_display_shell,
@@ -1064,6 +1080,74 @@ gimp_display_shell_remove_overlay (GtkWidget        *canvas,
   shell->children = g_list_remove (shell->children, child);
 }
 
+static void
+gimp_display_shell_transform_overlay (GimpDisplayShell *shell,
+                                      GtkWidget        *child,
+                                      gdouble          *x,
+                                      gdouble          *y)
+{
+  GimpDisplayShellOverlay *overlay;
+  GtkRequisition           requisition;
+
+  overlay = g_object_get_data (G_OBJECT (child), "image-coords-overlay");
+
+  gimp_display_shell_transform_xy_f (shell,
+                                     overlay->image_x,
+                                     overlay->image_y,
+                                     x, y,
+                                     FALSE);
+
+  gtk_widget_size_request (child, &requisition);
+
+  switch (overlay->anchor)
+    {
+    case GTK_ANCHOR_CENTER:
+      *x -= requisition.width  / 2;
+      *y -= requisition.height / 2;
+      break;
+
+    case GTK_ANCHOR_NORTH:
+      *x -= requisition.width / 2;
+      *y += overlay->spacing_y;
+      break;
+
+    case GTK_ANCHOR_NORTH_WEST:
+      *x += overlay->spacing_x;
+      *y += overlay->spacing_y;
+      break;
+
+    case GTK_ANCHOR_NORTH_EAST:
+      *x -= requisition.width + overlay->spacing_x;
+      *y += overlay->spacing_y;
+      break;
+
+    case GTK_ANCHOR_SOUTH:
+      *x -= requisition.width / 2;
+      *y -= requisition.height + overlay->spacing_y;
+      break;
+
+    case GTK_ANCHOR_SOUTH_WEST:
+      *x += overlay->spacing_x;
+      *y -= requisition.height + overlay->spacing_y;
+      break;
+
+    case GTK_ANCHOR_SOUTH_EAST:
+      *x -= requisition.width + overlay->spacing_x;
+      *y -= requisition.height + overlay->spacing_y;
+      break;
+
+    case GTK_ANCHOR_WEST:
+      *x += overlay->spacing_x;
+      *y -= requisition.height / 2;
+      break;
+
+    case GTK_ANCHOR_EAST:
+      *x -= requisition.width + overlay->spacing_x;
+      *y -= requisition.height / 2;
+      break;
+    }
+}
+
 
 /*  public functions  */
 
@@ -1087,29 +1171,31 @@ void
 gimp_display_shell_add_overlay (GimpDisplayShell *shell,
                                 GtkWidget        *child,
                                 gdouble           image_x,
-                                gdouble           image_y)
+                                gdouble           image_y,
+                                GtkAnchorType     anchor,
+                                gint              spacing_x,
+                                gint              spacing_y)
 {
-  gdouble *x_data;
-  gdouble *y_data;
-  gdouble  x, y;
+  GimpDisplayShellOverlay *overlay;
+  gdouble                  x, y;
 
   g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
   g_return_if_fail (GTK_IS_WIDGET (shell));
 
-  x_data = g_new (gdouble, 1);
-  y_data = g_new (gdouble, 1);
+  overlay = g_new0 (GimpDisplayShellOverlay, 1);
 
-  *x_data = image_x;
-  *y_data = image_y;
+  overlay->image_x   = image_x;
+  overlay->image_y   = image_y;
+  overlay->anchor    = anchor;
+  overlay->spacing_x = spacing_x;
+  overlay->spacing_y = spacing_y;
 
-  g_object_set_data_full (G_OBJECT (child), "image-x", x_data,
-                          (GDestroyNotify) g_free);
-  g_object_set_data_full (G_OBJECT (child), "image-y", y_data,
+  g_object_set_data_full (G_OBJECT (child), "image-coords-overlay", overlay,
                           (GDestroyNotify) g_free);
 
   shell->children = g_list_prepend (shell->children, child);
 
-  gimp_display_shell_transform_xy_f (shell, image_x, image_y, &x, &y, FALSE);
+  gimp_display_shell_transform_overlay (shell, child, &x, &y);
 
   gimp_overlay_box_add_child (GIMP_OVERLAY_BOX (shell->canvas), child, 0.0, 0.0);
   gimp_overlay_box_set_child_position (GIMP_OVERLAY_BOX (shell->canvas),
@@ -1120,25 +1206,28 @@ void
 gimp_display_shell_move_overlay (GimpDisplayShell *shell,
                                  GtkWidget        *child,
                                  gdouble           image_x,
-                                 gdouble           image_y)
+                                 gdouble           image_y,
+                                 GtkAnchorType     anchor,
+                                 gint              spacing_x,
+                                 gint              spacing_y)
 {
-  gdouble *x_data;
-  gdouble *y_data;
-  gdouble  x, y;
+  GimpDisplayShellOverlay *overlay;
+  gdouble                  x, y;
 
   g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
   g_return_if_fail (GTK_IS_WIDGET (shell));
 
-  x_data = g_object_get_data (G_OBJECT (child), "image-x");
-  y_data = g_object_get_data (G_OBJECT (child), "image-y");
+  overlay = g_object_get_data (G_OBJECT (child), "image-coords-overlay");
 
-  if (! x_data || ! y_data)
-    return;
+  g_return_if_fail (overlay != NULL);
 
-  *x_data = image_x;
-  *y_data = image_y;
+  overlay->image_x   = image_x;
+  overlay->image_y   = image_y;
+  overlay->anchor    = anchor;
+  overlay->spacing_x = spacing_x;
+  overlay->spacing_y = spacing_y;
 
-  gimp_display_shell_transform_xy_f (shell, *x_data, *y_data, &x, &y, FALSE);
+  gimp_display_shell_transform_overlay (shell, child, &x, &y);
 
   gimp_overlay_box_set_child_position (GIMP_OVERLAY_BOX (shell->canvas),
                                        child, x, y);
@@ -1341,14 +1430,9 @@ gimp_display_shell_scaled (GimpDisplayShell *shell)
   for (list = shell->children; list; list = g_list_next (list))
     {
       GtkWidget *child = list->data;
-      gdouble   *x_data;
-      gdouble   *y_data;
       gdouble    x, y;
 
-      x_data = g_object_get_data (G_OBJECT (child), "image-x");
-      y_data = g_object_get_data (G_OBJECT (child), "image-y");
-
-      gimp_display_shell_transform_xy_f (shell, *x_data, *y_data, &x, &y, FALSE);
+      gimp_display_shell_transform_overlay (shell, child, &x, &y);
 
       gimp_overlay_box_set_child_position (GIMP_OVERLAY_BOX (shell->canvas),
                                            child, x, y);
@@ -1367,14 +1451,9 @@ gimp_display_shell_scrolled (GimpDisplayShell *shell)
   for (list = shell->children; list; list = g_list_next (list))
     {
       GtkWidget *child = list->data;
-      gdouble   *x_data;
-      gdouble   *y_data;
       gdouble    x, y;
 
-      x_data = g_object_get_data (G_OBJECT (child), "image-x");
-      y_data = g_object_get_data (G_OBJECT (child), "image-y");
-
-      gimp_display_shell_transform_xy_f (shell, *x_data, *y_data, &x, &y, FALSE);
+      gimp_display_shell_transform_overlay (shell, child, &x, &y);
 
       gimp_overlay_box_set_child_position (GIMP_OVERLAY_BOX (shell->canvas),
                                            child, x, y);
diff --git a/app/display/gimpdisplayshell.h b/app/display/gimpdisplayshell.h
index 017f365..46f4251 100644
--- a/app/display/gimpdisplayshell.h
+++ b/app/display/gimpdisplayshell.h
@@ -222,11 +222,17 @@ GtkWidget       * gimp_display_shell_new           (GimpDisplay        *display,
 void              gimp_display_shell_add_overlay   (GimpDisplayShell   *shell,
                                                     GtkWidget          *child,
                                                     gdouble             image_x,
-                                                    gdouble             image_y);
+                                                    gdouble             image_y,
+                                                    GtkAnchorType       anchor,
+                                                    gint                spacing_x,
+                                                    gint                spacing_y);
 void              gimp_display_shell_move_overlay  (GimpDisplayShell   *shell,
                                                     GtkWidget          *child,
                                                     gdouble             image_x,
-                                                    gdouble             image_y);
+                                                    gdouble             image_y,
+                                                    GtkAnchorType       anchor,
+                                                    gint                spacing_x,
+                                                    gint                spacing_y);
 
 GimpImageWindow * gimp_display_shell_get_window    (GimpDisplayShell   *shell);
 GimpStatusbar   * gimp_display_shell_get_statusbar (GimpDisplayShell   *shell);
diff --git a/app/tools/gimptexttool-editor.c b/app/tools/gimptexttool-editor.c
index 3751218..11d7631 100644
--- a/app/tools/gimptexttool-editor.c
+++ b/app/tools/gimptexttool-editor.c
@@ -167,7 +167,8 @@ gimp_text_tool_editor_start (GimpTextTool *text_tool)
                                  GTK_SHADOW_OUT);
       gimp_display_shell_add_overlay (shell,
                                       text_tool->style_overlay,
-                                      0, 0);
+                                      0, 0,
+                                      GTK_ANCHOR_CENTER, 0, 0);
       gimp_overlay_box_set_child_opacity (GIMP_OVERLAY_BOX (shell->canvas),
                                           text_tool->style_overlay, 0.7);
 
@@ -204,8 +205,8 @@ gimp_text_tool_editor_position (GimpTextTool *text_tool)
 
       gimp_display_shell_move_overlay (shell,
                                        text_tool->style_overlay,
-                                       x + 2,
-                                       y - requisition.height - 6);
+                                       x, y,
+                                       GTK_ANCHOR_SOUTH_WEST, 4, 12);
 
       if (text_tool->image)
         {
@@ -1277,7 +1278,8 @@ gimp_text_tool_im_preedit_start (GtkIMContext *context,
   gimp_display_shell_add_overlay (shell,
                                   text_tool->preedit_overlay,
                                   cursor_rect.x + off_x,
-                                  cursor_rect.y + off_y);
+                                  cursor_rect.y + off_y,
+                                  GTK_ANCHOR_NORTH_WEST, 0, 0);
   gimp_overlay_box_set_child_opacity (GIMP_OVERLAY_BOX (shell->canvas),
                                       text_tool->preedit_overlay, 0.7);
   gtk_widget_show (text_tool->preedit_overlay);



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