]> git.sur5r.net Git - glabels/commitdiff
Object dragging enhancement
authorMarek Černocký <marek@manet.cz>
Sat, 13 Feb 2016 22:51:22 +0000 (23:51 +0100)
committerJim Evins <evins@snaught.com>
Sun, 14 Feb 2016 17:52:54 +0000 (12:52 -0500)
src/view-box.c
src/view-box.h
src/view-ellipse.c
src/view-ellipse.h
src/view-line.c
src/view-line.h
src/view.c
src/view.h

index a69bfd1cb0a6620c00bb65ac550d66cbb2cbea14..408d68c907539e3dabcd243d14a17e3ccbb60623 100644 (file)
@@ -78,9 +78,9 @@ gl_view_box_get_create_cursor (void)
 /* Object creation handler: button press event.                              */
 /*****************************************************************************/
 void
-gl_view_box_create_button_press_event   (glView *view,
-                                         gdouble x,
-                                         gdouble y)
+gl_view_box_create_button_press_event (glView *view,
+                                       gdouble x,
+                                       gdouble y)
 {
        GObject             *object;
 
@@ -101,19 +101,28 @@ gl_view_box_create_button_press_event   (glView *view,
 /* Object creation handler: motion event.                                    */
 /*****************************************************************************/
 void
-gl_view_box_create_motion_event         (glView *view,
-                                         gdouble x,
-                                         gdouble y)
+gl_view_box_create_motion_event (glView  *view,
+                                 gdouble  x,
+                                 gdouble  y,
+                                 gboolean square)
 {
-        gdouble w, h;
-
-        gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object),
-                                      MIN (x, view->create_x0), MIN (y, view->create_y0),
-                                      FALSE);
-
-        w = MAX (x, view->create_x0) - MIN (x, view->create_x0);
-        h = MAX (y, view->create_y0) - MIN (y, view->create_y0);
-        gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h, FALSE);
+       gdouble w, h;
+
+       w = ABS (x - view->create_x0);
+       h = ABS (y - view->create_y0);
+       if (square)
+               if (w < h) {
+                       h = w;
+                       y = (y < view->create_y0 ? view->create_y0 - h : view->create_y0 + h);
+               } else {
+                       w = h;
+                       x = (x < view->create_x0 ? view->create_x0 - w : view->create_x0 + w);
+               }
+
+       gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object),
+                                     MIN (x, view->create_x0), MIN (y, view->create_y0),
+                                     FALSE);
+       gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h, FALSE);
 }
 
 
@@ -121,23 +130,17 @@ gl_view_box_create_motion_event         (glView *view,
 /* Object creation handler: button relesase event.                           */
 /*****************************************************************************/
 void
-gl_view_box_create_button_release_event (glView *view,
-                                         gdouble x,
-                                         gdouble y)
+gl_view_box_create_button_release_event (glView  *view,
+                                         gdouble  x,
+                                         gdouble  y,
+                                         gboolean square)
 {
-        gdouble              w, h;
-
-        if ((view->create_x0 == x) && (view->create_y0 == y)) {
-                x = view->create_x0 + 36.0;
-                y = view->create_y0 + 36.0;
-        }
-        gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object),
-                                      MIN (x, view->create_x0), MIN (y, view->create_y0),
-                                      FALSE);
-
-        w = MAX (x, view->create_x0) - MIN (x, view->create_x0);
-        h = MAX (y, view->create_y0) - MIN (y, view->create_y0);
-        gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h, FALSE);
+       if ((view->create_x0 == x) && (view->create_y0 == y)) {
+               x = view->create_x0 + 36.0;
+               y = view->create_y0 + 36.0;
+       }
+
+       gl_view_box_create_motion_event (view, x, y, square);
 }
 
 
index 81448b9dccd31a44a316f180328a5c91a101ce32..47782a40f0eb31b3862605df06b8c7524027a2da 100644 (file)
@@ -32,17 +32,19 @@ G_BEGIN_DECLS
 GdkCursor *gl_view_box_get_create_cursor           (void);
 
 /* Object creation handlers. */
-void       gl_view_box_create_button_press_event   (glView *view,
-                                                    gdouble x,
-                                                    gdouble y);
-
-void       gl_view_box_create_motion_event         (glView *view,
-                                                    gdouble x,
-                                                    gdouble y);
-
-void       gl_view_box_create_button_release_event (glView *view,
-                                                    gdouble x,
-                                                    gdouble y);
+void       gl_view_box_create_button_press_event   (glView  *view,
+                                                    gdouble  x,
+                                                    gdouble  y);
+
+void       gl_view_box_create_motion_event         (glView  *view,
+                                                    gdouble  x,
+                                                    gdouble  y,
+                                                    gboolean square);
+
+void       gl_view_box_create_button_release_event (glView  *view,
+                                                    gdouble  x,
+                                                    gdouble  y,
+                                                    gboolean square);
 
 
 G_END_DECLS
index 7de5cd76de61e71fd4a0326776d1509e492f00d4..66f55fe97d4db0f974f126025ff8292e33d6d468 100644 (file)
@@ -78,9 +78,9 @@ gl_view_ellipse_get_create_cursor (void)
 /* Object creation handler: button press event.                              */
 /*****************************************************************************/
 void
-gl_view_ellipse_create_button_press_event   (glView *view,
-                                             gdouble x,
-                                             gdouble y)
+gl_view_ellipse_create_button_press_event (glView *view,
+                                           gdouble x,
+                                           gdouble y)
 {
        GObject             *object;
 
@@ -101,19 +101,28 @@ gl_view_ellipse_create_button_press_event   (glView *view,
 /* Object creation handler: motion event.                                    */
 /*****************************************************************************/
 void
-gl_view_ellipse_create_motion_event     (glView *view,
-                                         gdouble x,
-                                         gdouble y)
+gl_view_ellipse_create_motion_event (glView  *view,
+                                     gdouble  x,
+                                     gdouble  y,
+                                     gboolean circle)
 {
-        gdouble w, h;
-
-        gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object),
-                                      MIN (x, view->create_x0), MIN (y, view->create_y0),
-                                      FALSE);
-
-        w = MAX (x, view->create_x0) - MIN (x, view->create_x0);
-        h = MAX (y, view->create_y0) - MIN (y, view->create_y0);
-        gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h, FALSE);
+       gdouble w, h;
+
+       w = ABS (x - view->create_x0);
+       h = ABS (y - view->create_y0);
+       if (circle)
+               if (w < h) {
+                       h = w;
+                       y = (y < view->create_y0 ? view->create_y0 - h : view->create_y0 + h);
+               } else {
+                       w = h;
+                       x = (x < view->create_x0 ? view->create_x0 - w : view->create_x0 + w);
+               }
+
+       gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object),
+                                     MIN (x, view->create_x0), MIN (y, view->create_y0),
+                                     FALSE);
+       gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h, FALSE);
 }
 
 
@@ -121,23 +130,17 @@ gl_view_ellipse_create_motion_event     (glView *view,
 /* Object creation handler: button relesase event.                           */
 /*****************************************************************************/
 void
-gl_view_ellipse_create_button_release_event (glView *view,
-                                             gdouble x,
-                                             gdouble y)
+gl_view_ellipse_create_button_release_event (glView  *view,
+                                             gdouble  x,
+                                             gdouble  y,
+                                             gboolean circle)
 {
-        gdouble              w, h;
-
-        if ((view->create_x0 == x) && (view->create_y0 == y)) {
-                x = view->create_x0 + 36.0;
-                y = view->create_y0 + 36.0;
-        }
-        gl_label_object_set_position (GL_LABEL_OBJECT(view->create_object),
-                                      MIN (x, view->create_x0), MIN (y, view->create_y0),
-                                      FALSE);
-
-        w = MAX (x, view->create_x0) - MIN (x, view->create_x0);
-        h = MAX (y, view->create_y0) - MIN (y, view->create_y0);
-        gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h, FALSE);
+       if ((view->create_x0 == x) && (view->create_y0 == y)) {
+               x = view->create_x0 + 36.0;
+               y = view->create_y0 + 36.0;
+       }
+
+       gl_view_ellipse_create_motion_event (view, x, y, circle);
 }
 
 
index a75afd63def413e3ed4d7ba1ee431db4dae5bf90..4c8ed7b0e6aa023f6e0404714705255515e0f76b 100644 (file)
@@ -31,17 +31,19 @@ G_BEGIN_DECLS
 GdkCursor *gl_view_ellipse_get_create_cursor           (void);
 
 /* Object creation handlers. */
-void       gl_view_ellipse_create_button_press_event   (glView *view,
-                                                        gdouble x,
-                                                        gdouble y);
-
-void       gl_view_ellipse_create_motion_event         (glView *view,
-                                                        gdouble x,
-                                                        gdouble y);
-
-void       gl_view_ellipse_create_button_release_event (glView *view,
-                                                        gdouble x,
-                                                        gdouble y);
+void       gl_view_ellipse_create_button_press_event   (glView  *view,
+                                                        gdouble  x,
+                                                        gdouble  y);
+
+void       gl_view_ellipse_create_motion_event         (glView  *view,
+                                                        gdouble  x,
+                                                        gdouble  y,
+                                                        gboolean circle);
+
+void       gl_view_ellipse_create_button_release_event (glView  *view,
+                                                        gdouble  x,
+                                                        gdouble  y,
+                                                        gboolean circle);
 
 
 G_END_DECLS
index 9da709e1ba99e3b4a64047b4c5c3be004b17c6a0..e616350abb62d40332a0fbf9eea3954667df4d8d 100644 (file)
@@ -78,9 +78,9 @@ gl_view_line_get_create_cursor (void)
 /* Object creation handler: button press event.                              */
 /*****************************************************************************/
 void
-gl_view_line_create_button_press_event   (glView *view,
-                                          gdouble x,
-                                          gdouble y)
+gl_view_line_create_button_press_event (glView  *view,
+                                        gdouble  x,
+                                        gdouble  y)
 {
        GObject             *object;
 
@@ -101,15 +101,30 @@ gl_view_line_create_button_press_event   (glView *view,
 /* Object creation handler: motion event.                                    */
 /*****************************************************************************/
 void
-gl_view_line_create_motion_event     (glView *view,
-                                      gdouble x,
-                                      gdouble y)
+gl_view_line_create_motion_event (glView  *view,
+                                  gdouble  x,
+                                  gdouble  y,
+                                  gboolean fixed_angle)
 {
-        gdouble w, h;
-
-        w = x - view->create_x0;
-        h = y - view->create_y0;
-        gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h, FALSE);
+       gdouble w, h;
+
+       w = x - view->create_x0;
+       h = y - view->create_y0;
+
+       if (fixed_angle &&                                /* step by 45 degree */
+           h != 0) {                                     /* avoid divide by 0 */
+               if (ABS (w) / ABS (h) < 0.414213562)      /* precalculated tangent of 22,5 degree */
+                       w = 0;                            /* horizontal line */
+               else if (ABS (w) / ABS (h) > 2.414213562) /* precalculated tangent of 67,5 degree */
+                       h = 0;                            /* vertical line */
+               else                                      /* diagonal line */
+                       if (w < h)
+                               h = SIGN_AND_VALUE(h, w);
+                       else
+                               w = SIGN_AND_VALUE(w, h);
+       }
+
+       gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h, FALSE);
 }
 
 
@@ -117,19 +132,17 @@ gl_view_line_create_motion_event     (glView *view,
 /* Object creation handler: button relesase event.                           */
 /*****************************************************************************/
 void
-gl_view_line_create_button_release_event (glView *view,
-                                          gdouble x,
-                                          gdouble y)
+gl_view_line_create_button_release_event (glView  *view,
+                                          gdouble  x,
+                                          gdouble  y,
+                                          gboolean fixed_angle)
 {
-        gdouble              w, h;
-
-        if ((view->create_x0 == x) && (view->create_y0 == y)) {
-                x = view->create_x0 + 36.0;
-                y = view->create_y0 + 36.0;
-        }
-        w = x - view->create_x0;
-        h = y - view->create_y0;
-        gl_label_object_set_size (GL_LABEL_OBJECT(view->create_object), w, h, FALSE);
+       if ((view->create_x0 == x) && (view->create_y0 == y)) {
+               x = view->create_x0 + 36.0;
+               y = view->create_y0 + 36.0;
+       }
+
+       gl_view_line_create_motion_event (view, x, y, fixed_angle);
 }
 
 
index 67bd71070375fa9f695d15bb71d2c8f082cbd771..38df400809731c9873344048e9a7c287c0fb0233 100644 (file)
 
 G_BEGIN_DECLS
 
+/* Macro for value with sign from first argument and absolute value from second argument */
+/* It is used in diagonal lines calculations */
+#define SIGN_AND_VALUE(var_for_sign, var_for_val) (var_for_sign > 0 ? (var_for_val < 0 ? -var_for_val : var_for_val) : (var_for_val < 0 ? var_for_val : -var_for_val))
 
 /* cursor for creating line objects */
 GdkCursor *gl_view_line_get_create_cursor           (void);
 
 /* Object creation handlers. */
-void       gl_view_line_create_button_press_event   (glView *view,
-                                                     gdouble x,
-                                                     gdouble y);
+void       gl_view_line_create_button_press_event   (glView  *view,
+                                                     gdouble  x,
+                                                     gdouble  y);
 
-void       gl_view_line_create_motion_event         (glView *view,
-                                                     gdouble x,
-                                                     gdouble y);
+void       gl_view_line_create_motion_event         (glView  *view,
+                                                     gdouble  x,
+                                                     gdouble  y,
+                                                     gboolean fixed_angle);
 
-void       gl_view_line_create_button_release_event (glView *view,
-                                                     gdouble x,
-                                                     gdouble y);
+void       gl_view_line_create_button_release_event (glView  *view,
+                                                     gdouble  x,
+                                                     gdouble  y,
+                                                     gboolean fixed_angle);
 
 
 G_END_DECLS
index 23eda5244e1dca0b7be03fa7de0d322f8305ac4f..b7eff714f190926ab26282d245a3ffab8de8e583 100644 (file)
@@ -185,10 +185,17 @@ static gboolean   button_release_event_cb         (glView            *view,
 static gboolean   key_press_event_cb              (glView            *view,
                                                    GdkEventKey       *event);
 
+static void       move_event                      (glView            *view,
+                                                   gdouble            x,
+                                                   gdouble            y,
+                                                   gboolean           keep_direction);
+
 static void       resize_event                    (glView            *view,
                                                    cairo_t           *cr,
                                                    gdouble            x,
-                                                   gdouble            y);
+                                                   gdouble            y,
+                                                   gboolean           keep_ratio,
+                                                   gboolean           keep_direction);
 
 /****************************************************************************/
 /* Boilerplate Object stuff.                                                */
@@ -1454,15 +1461,11 @@ motion_notify_event_cb (glView            *view,
                         break;
 
                 case GL_VIEW_ARROW_MOVE:
-                        gl_label_move_selection (view->label,
-                                                (x - view->move_last_x),
-                                                (y - view->move_last_y));
-                        view->move_last_x = x;
-                        view->move_last_y = y;
+                        move_event (view, x, y, event->state & GDK_SHIFT_MASK);
                         break;
 
                 case GL_VIEW_ARROW_RESIZE:
-                        resize_event (view, cr, event->x, event->y);
+                        resize_event (view, cr, event->x, event->y, event->state & GDK_CONTROL_MASK, event->state & GDK_SHIFT_MASK);
                         break;
 
                 default:
@@ -1478,13 +1481,13 @@ motion_notify_event_cb (glView            *view,
                         switch (view->create_type)
                         {
                         case GL_LABEL_OBJECT_BOX:
-                                gl_view_box_create_motion_event (view, x, y);
+                                gl_view_box_create_motion_event (view, x, y, event->state & GDK_CONTROL_MASK);
                                 break;
                         case GL_LABEL_OBJECT_ELLIPSE:
-                                gl_view_ellipse_create_motion_event (view, x, y);
+                                gl_view_ellipse_create_motion_event (view, x, y, event->state & GDK_CONTROL_MASK);
                                 break;
                         case GL_LABEL_OBJECT_LINE: 
-                                gl_view_line_create_motion_event (view, x, y);
+                                gl_view_line_create_motion_event (view, x, y, event->state & GDK_SHIFT_MASK);
                                 break;
                         case GL_LABEL_OBJECT_IMAGE:
                                 gl_view_image_create_motion_event (view, x, y);
@@ -1575,7 +1578,10 @@ button_press_event_cb (glView            *view,
                         {
                                 view->resize_object = object;
                                 view->resize_handle = handle;
-                                view->resize_honor_aspect = event->state & GDK_CONTROL_MASK;
+                                gl_label_object_get_size (object, &(view->saved_w), &(view->saved_h));
+                                view->saved_ratio = view->saved_h / view->saved_w;
+                                view->saved_x = x;
+                                view->saved_y = y;
 
                                 view->state = GL_VIEW_ARROW_RESIZE;
                         }
@@ -1604,6 +1610,8 @@ button_press_event_cb (glView            *view,
                                 }
                                 view->move_last_x = x;
                                 view->move_last_y = y;
+                                view->saved_x = x;
+                                view->saved_y = y;
 
                                 view->state = GL_VIEW_ARROW_MOVE;
                         }
@@ -1764,13 +1772,13 @@ button_release_event_cb (glView            *view,
                         switch (view->create_type)
                         {
                         case GL_LABEL_OBJECT_BOX:
-                                gl_view_box_create_button_release_event (view, x, y);
+                                gl_view_box_create_button_release_event (view, x, y, event->state & GDK_CONTROL_MASK);
                                 break;
                         case GL_LABEL_OBJECT_ELLIPSE:
-                                gl_view_ellipse_create_button_release_event (view, x, y);
+                                gl_view_ellipse_create_button_release_event (view, x, y, event->state & GDK_CONTROL_MASK);
                                 break;
                         case GL_LABEL_OBJECT_LINE:
-                                gl_view_line_create_button_release_event (view, x, y);
+                                gl_view_line_create_button_release_event (view, x, y, event->state & GDK_CONTROL_MASK);
                                 break;
                         case GL_LABEL_OBJECT_IMAGE:
                                 gl_view_image_create_button_release_event (view, x, y);
@@ -1850,21 +1858,85 @@ key_press_event_cb (glView            *view,
                         break;
                 default:
                         return FALSE;
+
                }
         }
         return TRUE;    /* We handled this or we were dragging. */
 }
 
 
+/*---------------------------------------------------------------------------*/
+/* PRIVATE.  Move object.                                                    */
+/*---------------------------------------------------------------------------*/
+static void
+move_event (glView   *view,
+            gdouble   x,
+            gdouble   y,
+            gboolean  keep_direction)
+{
+       gdouble delta_x, delta_y;
+
+       if (keep_direction)
+       {
+               /* Move only on one axis */
+               if (ABS (x - view->saved_x) > ABS (y - view->saved_y))
+               {
+                       /* Move only on x axis */
+                       delta_x = x - view->move_last_x;
+                       view->move_last_x = x;
+                       if (view->move_last_y == view->saved_y)
+                       {
+                               /* Already on origin y */
+                               delta_y = 0;
+                       }
+                       else
+                       {
+                               /* Move back to origin y */
+                               delta_y = view->saved_y - view->move_last_y;
+                               view->move_last_y = view->saved_y;
+                       }
+               }
+               else
+               {
+                       /* Move only on y axis */
+                       delta_y = y - view->move_last_y;
+                       view->move_last_y = y;
+                       if (view->move_last_x == view->saved_x)
+                       {
+                               /* Already on origin x */
+                               delta_x = 0;
+                       }
+                       else
+                       {
+                               /* Move back to origin x */
+                               delta_x = view->saved_x - view->move_last_x;
+                               view->move_last_x = view->saved_x;
+                       }
+               }
+       }
+       else
+       {
+               /* Normal move */
+               delta_x = x - view->move_last_x;
+               delta_y = y - view->move_last_y;
+               view->move_last_x = x;
+               view->move_last_y = y;
+       }
+
+       gl_label_move_selection (view->label, delta_x, delta_y);
+}
+
+
 /*---------------------------------------------------------------------------*/
 /* PRIVATE.  Resize object.                                                  */
 /*---------------------------------------------------------------------------*/
 static void
-resize_event (glView             *view,
-              cairo_t            *cr,
-              gdouble             x,
-              gdouble             y)
+resize_event (glView   *view,
+              cairo_t  *cr,
+              gdouble   x,
+              gdouble   y,
+              gboolean  keep_ratio,
+              gboolean  keep_direction)
 {
         cairo_matrix_t matrix;
         gdouble        x0, y0, x1, y1, x2, y2;
@@ -1910,60 +1982,165 @@ resize_event (glView             *view,
         switch (view->resize_handle)
         {
 
-        case GL_LABEL_OBJECT_HANDLE_NW:
-                w = MAX (x2 - x, 0);
-                h = MAX (y2 - y, 0);
-                break;
+       case GL_LABEL_OBJECT_HANDLE_NW:
+               w = MAX (x2 - x, 0);
+               h = MAX (y2 - y, 0);
+               if (keep_ratio)
+               {
+                       if (h/w > view->saved_ratio)
+                               w = h / view->saved_ratio;
+                       else
+                               h = w * view->saved_ratio;
+               }
+               break;
 
-        case GL_LABEL_OBJECT_HANDLE_N:
-                w = x2 - x1;
-                h = MAX (y2 - y, 0);
-                break;
+       case GL_LABEL_OBJECT_HANDLE_N:
+               h = MAX (y2 - y, 0);
+               if (keep_ratio)
+                       w = h / view->saved_ratio;
+               else
+                       w = view->saved_w;
+               x0 = ((x2 - x1) - w)/2;
+               break;
 
-        case GL_LABEL_OBJECT_HANDLE_NE:
-                w = MAX (x - x1, 0);
-                h = MAX (y2 - y, 0);
-                break;
+       case GL_LABEL_OBJECT_HANDLE_NE:
+               w = MAX (x - x1, 0);
+               h = MAX (y2 - y, 0);
+               if (keep_ratio)
+               {
+                       if (h/w > view->saved_ratio)
+                               w = h / view->saved_ratio;
+                       else
+                               h = w * view->saved_ratio;
+               }
+               break;
 
-        case GL_LABEL_OBJECT_HANDLE_E:
-                w = MAX (x - x1, 0);
-                h = y2 - y1;
-                break;
+       case GL_LABEL_OBJECT_HANDLE_E:
+               w = MAX (x - x1, 0);
+               if (keep_ratio)
+                       h = w * view->saved_ratio;
+               else
+                       h = view->saved_h;
+               y0 = ((y2 - y1) - h)/2;
+               break;
 
-        case GL_LABEL_OBJECT_HANDLE_SE:
-                w = MAX (x - x1, 0);
-                h = MAX (y - y1, 0);
-                break;
+       case GL_LABEL_OBJECT_HANDLE_SE:
+               w = MAX (x - x1, 0);
+               h = MAX (y - y1, 0);
+               if (keep_ratio)
+               {
+                       if (h/w > view->saved_ratio)
+                               w = h / view->saved_ratio;
+                       else
+                               h = w * view->saved_ratio;
+               }
+               break;
 
-        case GL_LABEL_OBJECT_HANDLE_S:
-                w = x2 - x1;
-                h = MAX (y - y1, 0);
-                break;
+       case GL_LABEL_OBJECT_HANDLE_S:
+               h = MAX (y - y1, 0);
+               if (keep_ratio)
+                       w = h / view->saved_ratio;
+               else
+                       w = view->saved_w;
+               x0 = ((x2 - x1) - w)/2;
+               break;
 
-        case GL_LABEL_OBJECT_HANDLE_SW:
-                w = MAX (x2 - x, 0);
-                h = MAX (y - y1, 0);
-                break;
+       case GL_LABEL_OBJECT_HANDLE_SW:
+               w = MAX (x2 - x, 0);
+               h = MAX (y - y1, 0);
+               if (keep_ratio)
+               {
+                       if (h/w > view->saved_ratio)
+                               w = h / view->saved_ratio;
+                       else
+                               h = w * view->saved_ratio;
+               }
+               break;
 
-        case GL_LABEL_OBJECT_HANDLE_W:
-                w = MAX (x2 - x, 0);
-                h = y2 - y1;
-                break;
-        case GL_LABEL_OBJECT_HANDLE_P1:
-                x1 = x;
-                y1 = y;
-                dx = (x2 - x);
-                dy = (y2 - y);
-                x0 = x0 + x1;
-                y0 = y0 + y1;
-                break;
+       case GL_LABEL_OBJECT_HANDLE_W:
+               w = MAX (x2 - x, 0);
+               if (keep_ratio && !keep_direction)
+                       h = w * view->saved_ratio;
+               else
+                       h = view->saved_h;
+               y0 = ((y2 - y1) - h)/2;
+               break;
 
-        case GL_LABEL_OBJECT_HANDLE_P2:
-                dx = x - x1;
-                dy = y - y1;
-                x0 = x0 + x1;
-                y0 = y0 + y1;
-                break;
+       case GL_LABEL_OBJECT_HANDLE_P1:
+               x1 = x;
+               y1 = y;
+               dx = (x2 - x);
+               dy = (y2 - y);
+               x0 = x0 + x1;
+               y0 = y0 + y1;
+               if (keep_ratio &&
+                   !keep_direction)                                /* Keep direction with Shift has priority to keep aspect ratio with Ctrl */
+               {
+                       if (dy/dx > view->saved_ratio)
+                       {
+                               dx = dy / view->saved_ratio;
+                               x0 = x0 - (dx - (x2 - x));
+                       }
+                       else
+                       {
+                               dy = dx * view->saved_ratio;
+                               y0 = y0 - (dy - (y2 - y));
+                       }
+               }
+               else if (keep_direction &&
+                        dy != 0)                                   /*avoid div by 0*/
+               {
+                       if (ABS (dx) / ABS (dy) < 0.414213562)      /* precalculated tangent of 22,5 degree */
+                       {
+                               dx = 0;                             /* horizontal line */
+                               x0 = x0 + (x2 - x);
+                       }
+                       else if (ABS (dx) / ABS (dy) > 2.414213562) /* precalculated tangent of 67,5 degree */
+                       {
+                               dy = 0;                             /* vertical line */
+                               y0 = y0 + (y2 - y);
+                       }
+                       else                                        /* diagonal line */
+                       {
+                               if (dx < dy)
+                               {
+                                       dy = SIGN_AND_VALUE(dy, dx);
+                                       y0 = y0 - (dy - (y2 - y));
+                               }
+                               else
+                               {
+                                       dx = SIGN_AND_VALUE(dx, dy);
+                                       x0 = x0 - (dx - (x2 - x));
+                               }
+                       }
+               }
+               break;
+
+       case GL_LABEL_OBJECT_HANDLE_P2:
+               dx = x - x1;
+               dy = y - y1;
+               if (keep_ratio && !keep_direction)
+               {
+                       if (dy/dx > view->saved_ratio)
+                               dx = dy / view->saved_ratio;
+                       else
+                               dy = dx * view->saved_ratio;
+               }
+               else if (keep_direction && dy != 0 /*avoid div by 0*/)
+               {
+                       if (ABS (dx) / ABS (dy) < 0.414213562)      /* precalculated tangent of 22,5 degree */
+                               dx = 0;                             /* horizontal line */
+                       else if (ABS (dx) / ABS (dy) > 2.414213562) /* precalculated tangent of 67,5 degree */
+                               dy = 0;                             /* vertical line */
+                       else                                        /* diagonal line */
+                               if (dx < dy)
+                                       dy = SIGN_AND_VALUE(dy, dx);//(dy < 0 ? -ABS (dx) : ABS (dx));
+                               else
+                                       dx = SIGN_AND_VALUE(dx, dy);//(dx < 0 ? -ABS (dy) : ABS (dy));
+               }
+               x0 = x0 + x1;
+               y0 = y0 + y1;
+               break;
 
         default:
                 g_print ("Invalid handle.\n");  /* Should not happen! */
@@ -1973,14 +2150,7 @@ resize_event (glView             *view,
         if ( (view->resize_handle != GL_LABEL_OBJECT_HANDLE_P1) &&
              (view->resize_handle != GL_LABEL_OBJECT_HANDLE_P2) )
         {
-                if ( view->resize_honor_aspect )
-                {
-                        gl_label_object_set_size_honor_aspect (view->resize_object, w, h, TRUE);
-                }
-                else
-                {
-                        gl_label_object_set_size (view->resize_object, w, h, TRUE);
-                }
+                gl_label_object_set_size (view->resize_object, w, h, TRUE);
 
                 /*
                  * Query the new size in case it was constrained.
index a23efa7bbe2bba0ec4e9f6f0bdaacd1bbde6189f..c0d9c150725bffaf6e5658265981db66a839ec92 100644 (file)
@@ -54,46 +54,49 @@ typedef struct _glViewClass glViewClass;
 
 
 struct _glView {
-       GtkVBox            parent_widget;
-
-       glLabel           *label;
-
-       GtkWidget         *canvas;
-       gdouble            zoom;
-       gboolean           zoom_to_fit_flag;
-       gdouble            home_scale;
-        gdouble            x0, y0;
-        gdouble            w, h;
-
-        gboolean           update_scheduled_flag;
-        gboolean           grid_visible;
-       gdouble            grid_spacing;
-
-        gboolean           markup_visible;
-
-       glViewMode         mode;
-       glLabelObjectType  create_type;
-        glViewState        state;
-        gboolean           grabbed_flag;
-
-        /* GL_VIEW_ARROW_MOVE state */
-        gdouble            move_last_x;
-        gdouble            move_last_y;
-
-        /* GL_VIEW_ARROW_SELECT_REGION state */
-        gboolean           select_region_visible;
-        glLabelRegion      select_region;
-
-        /* GL_VIEW_ARROW_RESIZE state */
-        glLabelObject      *resize_object;
-        glLabelObjectHandle resize_handle;
-        gboolean            resize_honor_aspect;
-
-        /* GL_VIEW_CREATE_DRAG state */
-        glLabelObject     *create_object;
-        gdouble            create_x0;
-        gdouble            create_y0;
-
+       GtkVBox             parent_widget;
+
+       glLabel            *label;
+
+       GtkWidget          *canvas;
+       gdouble             zoom;
+       gboolean            zoom_to_fit_flag;
+       gdouble             home_scale;
+       gdouble             x0, y0;
+       gdouble             w, h;
+
+       gboolean            update_scheduled_flag;
+       gboolean            grid_visible;
+       gdouble             grid_spacing;
+
+       gboolean            markup_visible;
+
+       glViewMode          mode;
+       glLabelObjectType   create_type;
+       glViewState         state;
+       gboolean            grabbed_flag;
+
+       /* GL_VIEW_ARROW_MOVE state */
+       gdouble             move_last_x;
+       gdouble             move_last_y;
+       gdouble             saved_x;
+       gdouble             saved_y;
+
+       /* GL_VIEW_ARROW_SELECT_REGION state */
+       gboolean            select_region_visible;
+       glLabelRegion       select_region;
+
+       /* GL_VIEW_ARROW_RESIZE state */
+       glLabelObject      *resize_object;
+       glLabelObjectHandle resize_handle;
+       gdouble             saved_ratio;
+       gdouble             saved_w;
+       gdouble             saved_h;
+
+       /* GL_VIEW_CREATE_DRAG state */
+       glLabelObject      *create_object;
+       gdouble             create_x0;
+       gdouble             create_y0;
 };
 
 struct _glViewClass {