From: Marek Černocký Date: Sat, 13 Feb 2016 22:51:22 +0000 (+0100) Subject: Object dragging enhancement X-Git-Tag: glabels-3_4_0~49 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=cb06227147d7c6eda9074530baabe75307773883;p=glabels Object dragging enhancement --- diff --git a/src/view-box.c b/src/view-box.c index a69bfd1c..408d68c9 100644 --- a/src/view-box.c +++ b/src/view-box.c @@ -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); } diff --git a/src/view-box.h b/src/view-box.h index 81448b9d..47782a40 100644 --- a/src/view-box.h +++ b/src/view-box.h @@ -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 diff --git a/src/view-ellipse.c b/src/view-ellipse.c index 7de5cd76..66f55fe9 100644 --- a/src/view-ellipse.c +++ b/src/view-ellipse.c @@ -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); } diff --git a/src/view-ellipse.h b/src/view-ellipse.h index a75afd63..4c8ed7b0 100644 --- a/src/view-ellipse.h +++ b/src/view-ellipse.h @@ -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 diff --git a/src/view-line.c b/src/view-line.c index 9da709e1..e616350a 100644 --- a/src/view-line.c +++ b/src/view-line.c @@ -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); } diff --git a/src/view-line.h b/src/view-line.h index 67bd7107..38df4008 100644 --- a/src/view-line.h +++ b/src/view-line.h @@ -26,22 +26,27 @@ 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 diff --git a/src/view.c b/src/view.c index 23eda524..b7eff714 100644 --- a/src/view.c +++ b/src/view.c @@ -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. diff --git a/src/view.h b/src/view.h index a23efa7b..c0d9c150 100644 --- a/src/view.h +++ b/src/view.h @@ -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 {