/* PIKA - Photo and Image Kooker Application * a rebranding of The GNU Image Manipulation Program (created with heckimp) * A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio * * Original copyright, applying to most contents (license remains unchanged): * Copyright (C) 1995 Spencer Kimball and Peter Mattis * * Measure tool * Copyright (C) 1999-2003 Sven Neumann * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "config.h" #include #include #include #include "libpikabase/pikabase.h" #include "libpikamath/pikamath.h" #include "libpikawidgets/pikawidgets.h" #include "tools-types.h" #include "core/pikaimage.h" #include "core/pikaimage-guides.h" #include "core/pikaimage-undo.h" #include "core/pikaimage-undo-push.h" #include "core/pikaprogress.h" #include "core/pika-transform-utils.h" #include "widgets/pikahelp-ids.h" #include "widgets/pikawidgets-utils.h" #include "display/pikadisplay.h" #include "display/pikadisplayshell.h" #include "display/pikadisplayshell-appearance.h" #include "display/pikatoolcompass.h" #include "display/pikatoolgui.h" #include "pikameasureoptions.h" #include "pikameasuretool.h" #include "pikatoolcontrol.h" #include "pika-intl.h" /* local function prototypes */ static void pika_measure_tool_control (PikaTool *tool, PikaToolAction action, PikaDisplay *display); static void pika_measure_tool_modifier_key (PikaTool *tool, GdkModifierType key, gboolean press, GdkModifierType state, PikaDisplay *display); static void pika_measure_tool_button_press (PikaTool *tool, const PikaCoords *coords, guint32 time, GdkModifierType state, PikaButtonPressType press_type, PikaDisplay *display); static void pika_measure_tool_button_release (PikaTool *tool, const PikaCoords *coords, guint32 time, GdkModifierType state, PikaButtonReleaseType release_type, PikaDisplay *display); static void pika_measure_tool_motion (PikaTool *tool, const PikaCoords *coords, guint32 time, GdkModifierType state, PikaDisplay *display); static void pika_measure_tool_recalc_matrix (PikaTransformTool *tr_tool); static gchar * pika_measure_tool_get_undo_desc (PikaTransformTool *tr_tool); static void pika_measure_tool_compass_changed (PikaToolWidget *widget, PikaMeasureTool *measure); static void pika_measure_tool_compass_response(PikaToolWidget *widget, gint response_id, PikaMeasureTool *measure); static void pika_measure_tool_compass_status (PikaToolWidget *widget, const gchar *status, PikaMeasureTool *measure); static void pika_measure_tool_compass_create_guides (PikaToolWidget *widget, gint x, gint y, gboolean horizontal, gboolean vertical, PikaMeasureTool *measure); static void pika_measure_tool_start (PikaMeasureTool *measure, PikaDisplay *display, const PikaCoords *coords); static void pika_measure_tool_halt (PikaMeasureTool *measure); static PikaToolGui * pika_measure_tool_dialog_new (PikaMeasureTool *measure); static void pika_measure_tool_dialog_update (PikaMeasureTool *measure, PikaDisplay *display); static void pika_measure_tool_straighten_button_clicked (GtkWidget *button, PikaMeasureTool *measure); G_DEFINE_TYPE (PikaMeasureTool, pika_measure_tool, PIKA_TYPE_TRANSFORM_TOOL) #define parent_class pika_measure_tool_parent_class void pika_measure_tool_register (PikaToolRegisterCallback callback, gpointer data) { (* callback) (PIKA_TYPE_MEASURE_TOOL, PIKA_TYPE_MEASURE_OPTIONS, pika_measure_options_gui, 0, "pika-measure-tool", _("Measure"), _("Measure Tool: Measure distances and angles"), N_("_Measure"), "M", NULL, PIKA_HELP_TOOL_MEASURE, PIKA_ICON_TOOL_MEASURE, data); } static void pika_measure_tool_class_init (PikaMeasureToolClass *klass) { PikaToolClass *tool_class = PIKA_TOOL_CLASS (klass); PikaTransformToolClass *tr_class = PIKA_TRANSFORM_TOOL_CLASS (klass); tool_class->control = pika_measure_tool_control; tool_class->modifier_key = pika_measure_tool_modifier_key; tool_class->button_press = pika_measure_tool_button_press; tool_class->button_release = pika_measure_tool_button_release; tool_class->motion = pika_measure_tool_motion; tr_class->recalc_matrix = pika_measure_tool_recalc_matrix; tr_class->get_undo_desc = pika_measure_tool_get_undo_desc; tr_class->undo_desc = C_("undo-type", "Straighten"); tr_class->progress_text = _("Straightening"); } static void pika_measure_tool_init (PikaMeasureTool *measure) { PikaTool *tool = PIKA_TOOL (measure); pika_tool_control_set_handle_empty_image (tool->control, TRUE); pika_tool_control_set_active_modifiers (tool->control, PIKA_TOOL_ACTIVE_MODIFIERS_SEPARATE); pika_tool_control_set_precision (tool->control, PIKA_CURSOR_PRECISION_PIXEL_BORDER); pika_tool_control_set_cursor (tool->control, PIKA_CURSOR_CROSSHAIR_SMALL); pika_tool_control_set_tool_cursor (tool->control, PIKA_TOOL_CURSOR_MEASURE); pika_draw_tool_set_default_status (PIKA_DRAW_TOOL (tool), _("Click-Drag to create a line")); } static void pika_measure_tool_control (PikaTool *tool, PikaToolAction action, PikaDisplay *display) { PikaMeasureTool *measure = PIKA_MEASURE_TOOL (tool); switch (action) { case PIKA_TOOL_ACTION_PAUSE: case PIKA_TOOL_ACTION_RESUME: break; case PIKA_TOOL_ACTION_HALT: pika_measure_tool_halt (measure); break; case PIKA_TOOL_ACTION_COMMIT: break; } PIKA_TOOL_CLASS (parent_class)->control (tool, action, display); } static void pika_measure_tool_modifier_key (PikaTool *tool, GdkModifierType key, gboolean press, GdkModifierType state, PikaDisplay *display) { PikaMeasureOptions *options = PIKA_MEASURE_TOOL_GET_OPTIONS (tool); if (key == pika_get_toggle_behavior_mask ()) { switch (options->orientation) { case PIKA_COMPASS_ORIENTATION_HORIZONTAL: g_object_set (options, "orientation", PIKA_COMPASS_ORIENTATION_VERTICAL, NULL); break; case PIKA_COMPASS_ORIENTATION_VERTICAL: g_object_set (options, "orientation", PIKA_COMPASS_ORIENTATION_HORIZONTAL, NULL); break; default: break; } } } static void pika_measure_tool_button_press (PikaTool *tool, const PikaCoords *coords, guint32 time, GdkModifierType state, PikaButtonPressType press_type, PikaDisplay *display) { PikaMeasureTool *measure = PIKA_MEASURE_TOOL (tool); PikaMeasureOptions *options = PIKA_MEASURE_TOOL_GET_OPTIONS (tool); PikaDisplayShell *shell = pika_display_get_shell (display); PikaImage *image = pika_display_get_image (display); if (tool->display && display != tool->display) pika_tool_control (tool, PIKA_TOOL_ACTION_HALT, tool->display); if (! measure->widget) { measure->supress_guides = TRUE; pika_measure_tool_start (measure, display, coords); pika_tool_widget_hover (measure->widget, coords, state, TRUE); } if (pika_tool_widget_button_press (measure->widget, coords, time, state, press_type)) { measure->grab_widget = measure->widget; } /* create the info window if necessary */ if (! measure->gui) { if (options->use_info_window || ! pika_display_shell_get_show_statusbar (shell)) { g_set_weak_pointer (&measure->gui, pika_measure_tool_dialog_new (measure)); } } if (measure->gui) { pika_tool_gui_set_shell (measure->gui, shell); pika_tool_gui_set_viewable (measure->gui, PIKA_VIEWABLE (image)); pika_measure_tool_dialog_update (measure, display); } pika_tool_control_activate (tool->control); } static void pika_measure_tool_button_release (PikaTool *tool, const PikaCoords *coords, guint32 time, GdkModifierType state, PikaButtonReleaseType release_type, PikaDisplay *display) { PikaMeasureTool *measure = PIKA_MEASURE_TOOL (tool); pika_tool_control_halt (tool->control); if (measure->grab_widget) { pika_tool_widget_button_release (measure->grab_widget, coords, time, state, release_type); measure->grab_widget = NULL; } measure->supress_guides = FALSE; } static void pika_measure_tool_motion (PikaTool *tool, const PikaCoords *coords, guint32 time, GdkModifierType state, PikaDisplay *display) { PikaMeasureTool *measure = PIKA_MEASURE_TOOL (tool); if (measure->grab_widget) { pika_tool_widget_motion (measure->grab_widget, coords, time, state); } } static void pika_measure_tool_recalc_matrix (PikaTransformTool *tr_tool) { PikaMeasureTool *measure = PIKA_MEASURE_TOOL (tr_tool); gdouble angle; if (measure->n_points < 2) { tr_tool->transform_valid = FALSE; return; } g_object_get (measure->widget, "pixel-angle", &angle, NULL); pika_matrix3_identity (&tr_tool->transform); pika_transform_matrix_rotate_center (&tr_tool->transform, measure->x[0], measure->y[0], angle); tr_tool->transform_valid = TRUE; } static gchar * pika_measure_tool_get_undo_desc (PikaTransformTool *tr_tool) { PikaMeasureTool *measure = PIKA_MEASURE_TOOL (tr_tool); PikaCompassOrientation orientation; gdouble angle; g_object_get (measure->widget, "effective-orientation", &orientation, "pixel-angle", &angle, NULL); angle = pika_rad_to_deg (fabs (angle)); switch (orientation) { case PIKA_COMPASS_ORIENTATION_AUTO: return g_strdup_printf (C_("undo-type", "Straighten by %-3.3g°"), angle); case PIKA_COMPASS_ORIENTATION_HORIZONTAL: return g_strdup_printf (C_("undo-type", "Straighten Horizontally by %-3.3g°"), angle); case PIKA_COMPASS_ORIENTATION_VERTICAL: return g_strdup_printf (C_("undo-type", "Straighten Vertically by %-3.3g°"), angle); } g_return_val_if_reached (NULL); } static void pika_measure_tool_compass_changed (PikaToolWidget *widget, PikaMeasureTool *measure) { PikaMeasureOptions *options = PIKA_MEASURE_TOOL_GET_OPTIONS (measure); g_object_get (widget, "n-points", &measure->n_points, "x1", &measure->x[0], "y1", &measure->y[0], "x2", &measure->x[1], "y2", &measure->y[1], "x3", &measure->x[2], "y3", &measure->y[2], NULL); gtk_widget_set_sensitive (options->straighten_button, measure->n_points >= 2); pika_measure_tool_dialog_update (measure, PIKA_TOOL (measure)->display); } static void pika_measure_tool_compass_response (PikaToolWidget *widget, gint response_id, PikaMeasureTool *measure) { PikaTool *tool = PIKA_TOOL (measure); if (response_id == PIKA_TOOL_WIDGET_RESPONSE_CANCEL) pika_tool_control (tool, PIKA_TOOL_ACTION_HALT, tool->display); } static void pika_measure_tool_compass_status (PikaToolWidget *widget, const gchar *status, PikaMeasureTool *measure) { PikaTool *tool = PIKA_TOOL (measure); if (! status) { /* replace status bar hint by distance and angle */ pika_measure_tool_dialog_update (measure, tool->display); } } static void pika_measure_tool_compass_create_guides (PikaToolWidget *widget, gint x, gint y, gboolean horizontal, gboolean vertical, PikaMeasureTool *measure) { PikaDisplay *display = PIKA_TOOL (measure)->display; PikaImage *image = pika_display_get_image (display); if (measure->supress_guides) return; if (x < 0 || x > pika_image_get_width (image)) vertical = FALSE; if (y < 0 || y > pika_image_get_height (image)) horizontal = FALSE; if (horizontal || vertical) { if (horizontal && vertical) pika_image_undo_group_start (image, PIKA_UNDO_GROUP_GUIDE, _("Add Guides")); if (horizontal) pika_image_add_hguide (image, y, TRUE); if (vertical) pika_image_add_vguide (image, x, TRUE); if (horizontal && vertical) pika_image_undo_group_end (image); pika_image_flush (image); } } static void pika_measure_tool_start (PikaMeasureTool *measure, PikaDisplay *display, const PikaCoords *coords) { PikaTool *tool = PIKA_TOOL (measure); PikaDisplayShell *shell = pika_display_get_shell (display); PikaMeasureOptions *options = PIKA_MEASURE_TOOL_GET_OPTIONS (tool); measure->n_points = 1; measure->x[0] = coords->x; measure->y[0] = coords->y; measure->x[1] = 0; measure->y[1] = 0; measure->x[2] = 0; measure->y[2] = 0; measure->widget = pika_tool_compass_new (shell, options->orientation, measure->n_points, measure->x[0], measure->y[0], measure->x[1], measure->y[1], measure->x[2], measure->y[2]); pika_draw_tool_set_widget (PIKA_DRAW_TOOL (tool), measure->widget); g_object_bind_property (options, "orientation", measure->widget, "orientation", G_BINDING_DEFAULT); g_signal_connect (measure->widget, "changed", G_CALLBACK (pika_measure_tool_compass_changed), measure); g_signal_connect (measure->widget, "response", G_CALLBACK (pika_measure_tool_compass_response), measure); g_signal_connect (measure->widget, "status", G_CALLBACK (pika_measure_tool_compass_status), measure); g_signal_connect (measure->widget, "create-guides", G_CALLBACK (pika_measure_tool_compass_create_guides), measure); g_signal_connect (options->straighten_button, "clicked", G_CALLBACK (pika_measure_tool_straighten_button_clicked), measure); tool->display = display; pika_draw_tool_start (PIKA_DRAW_TOOL (measure), display); } static void pika_measure_tool_halt (PikaMeasureTool *measure) { PikaMeasureOptions *options = PIKA_MEASURE_TOOL_GET_OPTIONS (measure); PikaTool *tool = PIKA_TOOL (measure); if (options->straighten_button) { gtk_widget_set_sensitive (options->straighten_button, FALSE); g_signal_handlers_disconnect_by_func ( options->straighten_button, G_CALLBACK (pika_measure_tool_straighten_button_clicked), measure); } if (tool->display) pika_tool_pop_status (tool, tool->display); if (pika_draw_tool_is_active (PIKA_DRAW_TOOL (measure))) pika_draw_tool_stop (PIKA_DRAW_TOOL (measure)); pika_draw_tool_set_widget (PIKA_DRAW_TOOL (tool), NULL); g_clear_object (&measure->widget); g_clear_object (&measure->gui); tool->display = NULL; } static void pika_measure_tool_dialog_update (PikaMeasureTool *measure, PikaDisplay *display) { PikaDisplayShell *shell = pika_display_get_shell (display); PikaImage *image = pika_display_get_image (display); gint ax, ay; gint bx, by; gint pixel_width; gint pixel_height; gdouble unit_width; gdouble unit_height; gdouble pixel_distance; gdouble unit_distance; gdouble inch_distance; gdouble pixel_angle; gdouble unit_angle; gdouble xres; gdouble yres; gchar format[128]; gint unit_distance_digits = 0; gint unit_width_digits; gint unit_height_digits; /* calculate distance and angle */ ax = measure->x[1] - measure->x[0]; ay = measure->y[1] - measure->y[0]; if (measure->n_points == 3) { bx = measure->x[2] - measure->x[0]; by = measure->y[2] - measure->y[0]; } else { bx = 0; by = 0; } pixel_width = ABS (ax - bx); pixel_height = ABS (ay - by); pika_image_get_resolution (image, &xres, &yres); unit_width = pika_pixels_to_units (pixel_width, shell->unit, xres); unit_height = pika_pixels_to_units (pixel_height, shell->unit, yres); pixel_distance = sqrt (SQR (ax - bx) + SQR (ay - by)); inch_distance = sqrt (SQR ((gdouble) (ax - bx) / xres) + SQR ((gdouble) (ay - by) / yres)); unit_distance = pika_unit_get_factor (shell->unit) * inch_distance; g_object_get (measure->widget, "pixel-angle", &pixel_angle, "unit-angle", &unit_angle, NULL); pixel_angle = fabs (pixel_angle * 180.0 / G_PI); unit_angle = fabs (unit_angle * 180.0 / G_PI); /* Compute minimum digits to display accurate values, so that * every pixel shows a different value in unit. */ if (inch_distance) unit_distance_digits = pika_unit_get_scaled_digits (shell->unit, pixel_distance / inch_distance); unit_width_digits = pika_unit_get_scaled_digits (shell->unit, xres); unit_height_digits = pika_unit_get_scaled_digits (shell->unit, yres); if (shell->unit == PIKA_UNIT_PIXEL) { pika_tool_replace_status (PIKA_TOOL (measure), display, "%.1f %s, %.2f\302\260 (%d × %d)", pixel_distance, _("pixels"), pixel_angle, pixel_width, pixel_height); } else { g_snprintf (format, sizeof (format), "%%.%df %s, %%.2f\302\260 (%%.%df × %%.%df)", unit_distance_digits, pika_unit_get_plural (shell->unit), unit_width_digits, unit_height_digits); pika_tool_replace_status (PIKA_TOOL (measure), display, format, unit_distance, unit_angle, unit_width, unit_height); } if (measure->gui) { gchar buf[128]; /* Distance */ g_snprintf (buf, sizeof (buf), "%.1f", pixel_distance); gtk_label_set_text (GTK_LABEL (measure->distance_label[0]), buf); if (shell->unit != PIKA_UNIT_PIXEL) { g_snprintf (format, sizeof (format), "%%.%df", unit_distance_digits); g_snprintf (buf, sizeof (buf), format, unit_distance); gtk_label_set_text (GTK_LABEL (measure->distance_label[1]), buf); gtk_label_set_text (GTK_LABEL (measure->unit_label[0]), pika_unit_get_plural (shell->unit)); } else { gtk_label_set_text (GTK_LABEL (measure->distance_label[1]), NULL); gtk_label_set_text (GTK_LABEL (measure->unit_label[0]), NULL); } /* Angle */ g_snprintf (buf, sizeof (buf), "%.2f", pixel_angle); gtk_label_set_text (GTK_LABEL (measure->angle_label[0]), buf); if (fabs (unit_angle - pixel_angle) > 0.01) { g_snprintf (buf, sizeof (buf), "%.2f", unit_angle); gtk_label_set_text (GTK_LABEL (measure->angle_label[1]), buf); gtk_label_set_text (GTK_LABEL (measure->unit_label[1]), "\302\260"); } else { gtk_label_set_text (GTK_LABEL (measure->angle_label[1]), NULL); gtk_label_set_text (GTK_LABEL (measure->unit_label[1]), NULL); } /* Width */ g_snprintf (buf, sizeof (buf), "%d", pixel_width); gtk_label_set_text (GTK_LABEL (measure->width_label[0]), buf); if (shell->unit != PIKA_UNIT_PIXEL) { g_snprintf (format, sizeof (format), "%%.%df", unit_width_digits); g_snprintf (buf, sizeof (buf), format, unit_width); gtk_label_set_text (GTK_LABEL (measure->width_label[1]), buf); gtk_label_set_text (GTK_LABEL (measure->unit_label[2]), pika_unit_get_plural (shell->unit)); } else { gtk_label_set_text (GTK_LABEL (measure->width_label[1]), NULL); gtk_label_set_text (GTK_LABEL (measure->unit_label[2]), NULL); } g_snprintf (buf, sizeof (buf), "%d", pixel_height); gtk_label_set_text (GTK_LABEL (measure->height_label[0]), buf); /* Height */ if (shell->unit != PIKA_UNIT_PIXEL) { g_snprintf (format, sizeof (format), "%%.%df", unit_height_digits); g_snprintf (buf, sizeof (buf), format, unit_height); gtk_label_set_text (GTK_LABEL (measure->height_label[1]), buf); gtk_label_set_text (GTK_LABEL (measure->unit_label[3]), pika_unit_get_plural (shell->unit)); } else { gtk_label_set_text (GTK_LABEL (measure->height_label[1]), NULL); gtk_label_set_text (GTK_LABEL (measure->unit_label[3]), NULL); } pika_tool_gui_show (measure->gui); } } static PikaToolGui * pika_measure_tool_dialog_new (PikaMeasureTool *measure) { PikaTool *tool = PIKA_TOOL (measure); PikaDisplayShell *shell; PikaToolGui *gui; GtkWidget *grid; GtkWidget *label; g_return_val_if_fail (tool->display != NULL, NULL); shell = pika_display_get_shell (tool->display); gui = pika_tool_gui_new (tool->tool_info, NULL, _("Measure Distances and Angles"), NULL, NULL, pika_widget_get_monitor (GTK_WIDGET (shell)), TRUE, _("_Close"), GTK_RESPONSE_CLOSE, NULL); pika_tool_gui_set_auto_overlay (gui, TRUE); pika_tool_gui_set_focus_on_map (gui, FALSE); g_signal_connect (gui, "response", G_CALLBACK (g_object_unref), NULL); grid = gtk_grid_new (); gtk_grid_set_column_spacing (GTK_GRID (grid), 6); gtk_grid_set_row_spacing (GTK_GRID (grid), 6); gtk_box_pack_start (GTK_BOX (pika_tool_gui_get_vbox (gui)), grid, FALSE, FALSE, 0); gtk_widget_show (grid); label = gtk_label_new (_("Distance:")); gtk_label_set_xalign (GTK_LABEL (label), 0.0); gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1); gtk_widget_show (label); measure->distance_label[0] = label = gtk_label_new ("0.0"); gtk_label_set_selectable (GTK_LABEL (label), TRUE); gtk_label_set_xalign (GTK_LABEL (label), 1.0); gtk_grid_attach (GTK_GRID (grid), label, 1, 0, 1, 1); gtk_widget_show (label); label = gtk_label_new (_("pixels")); gtk_label_set_xalign (GTK_LABEL (label), 0.0); gtk_grid_attach (GTK_GRID (grid), label, 2, 0, 1, 1); gtk_widget_show (label); measure->distance_label[1] = label = gtk_label_new ("0.0"); gtk_label_set_selectable (GTK_LABEL (label), TRUE); gtk_label_set_xalign (GTK_LABEL (label), 1.0); gtk_grid_attach (GTK_GRID (grid), label, 3, 0, 1, 1); gtk_widget_show (label); measure->unit_label[0] = label = gtk_label_new (NULL); gtk_label_set_xalign (GTK_LABEL (label), 0.0); gtk_grid_attach (GTK_GRID (grid), label, 4, 0, 1, 1); gtk_widget_show (label); label = gtk_label_new (_("Angle:")); gtk_label_set_xalign (GTK_LABEL (label), 0.0); gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1); gtk_widget_show (label); measure->angle_label[0] = label = gtk_label_new ("0.0"); gtk_label_set_selectable (GTK_LABEL (label), TRUE); gtk_label_set_xalign (GTK_LABEL (label), 1.0); gtk_grid_attach (GTK_GRID (grid), label, 1, 1, 1, 1); gtk_widget_show (label); label = gtk_label_new ("\302\260"); gtk_label_set_xalign (GTK_LABEL (label), 0.0); gtk_grid_attach (GTK_GRID (grid), label, 2, 1, 1, 1); gtk_widget_show (label); measure->angle_label[1] = label = gtk_label_new (NULL); gtk_label_set_selectable (GTK_LABEL (label), TRUE); gtk_label_set_xalign (GTK_LABEL (label), 1.0); gtk_grid_attach (GTK_GRID (grid), label, 3, 1, 1, 1); gtk_widget_show (label); measure->unit_label[1] = label = gtk_label_new (NULL); gtk_label_set_xalign (GTK_LABEL (label), 0.0); gtk_grid_attach (GTK_GRID (grid), label, 4, 1, 1, 1); gtk_widget_show (label); label = gtk_label_new (_("Width:")); gtk_label_set_xalign (GTK_LABEL (label), 0.0); gtk_grid_attach (GTK_GRID (grid), label, 0, 2, 1, 1); gtk_widget_show (label); measure->width_label[0] = label = gtk_label_new ("0.0"); gtk_label_set_selectable (GTK_LABEL (label), TRUE); gtk_label_set_xalign (GTK_LABEL (label), 1.0); gtk_grid_attach (GTK_GRID (grid), label, 1, 2, 1, 1); gtk_widget_show (label); label = gtk_label_new (_("pixels")); gtk_label_set_xalign (GTK_LABEL (label), 0.0); gtk_grid_attach (GTK_GRID (grid), label, 2, 2, 1, 1); gtk_widget_show (label); measure->width_label[1] = label = gtk_label_new ("0.0"); gtk_label_set_selectable (GTK_LABEL (label), TRUE); gtk_label_set_xalign (GTK_LABEL (label), 1.0); gtk_grid_attach (GTK_GRID (grid), label, 3, 2, 1, 1); gtk_widget_show (label); measure->unit_label[2] = label = gtk_label_new (NULL); gtk_label_set_xalign (GTK_LABEL (label), 0.0); gtk_grid_attach (GTK_GRID (grid), label, 4, 2, 1, 1); gtk_widget_show (label); label = gtk_label_new (_("Height:")); gtk_label_set_xalign (GTK_LABEL (label), 0.0); gtk_grid_attach (GTK_GRID (grid), label, 0, 3, 1, 1); gtk_widget_show (label); measure->height_label[0] = label = gtk_label_new ("0.0"); gtk_label_set_selectable (GTK_LABEL (label), TRUE); gtk_label_set_xalign (GTK_LABEL (label), 1.0); gtk_grid_attach (GTK_GRID (grid), label, 1, 3, 1, 1); gtk_widget_show (label); label = gtk_label_new (_("pixels")); gtk_label_set_xalign (GTK_LABEL (label), 0.0); gtk_grid_attach (GTK_GRID (grid), label, 2, 3, 1, 1); gtk_widget_show (label); measure->height_label[1] = label = gtk_label_new ("0.0"); gtk_label_set_selectable (GTK_LABEL (label), TRUE); gtk_label_set_xalign (GTK_LABEL (label), 1.0); gtk_grid_attach (GTK_GRID (grid), label, 3, 3, 1, 1); gtk_widget_show (label); measure->unit_label[3] = label = gtk_label_new (NULL); gtk_label_set_xalign (GTK_LABEL (label), 0.0); gtk_grid_attach (GTK_GRID (grid), label, 4, 3, 1, 1); gtk_widget_show (label); return gui; } static void pika_measure_tool_straighten_button_clicked (GtkWidget *button, PikaMeasureTool *measure) { PikaTool *tool = PIKA_TOOL (measure); PikaTransformTool *tr_tool = PIKA_TRANSFORM_TOOL (measure); if (pika_transform_tool_transform (tr_tool, tool->display)) pika_tool_control (tool, PIKA_TOOL_ACTION_HALT, tool->display); }