1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
16  */
17 
18 #include "config.h"
19 
20 #include <gegl.h>
21 #include <gtk/gtk.h>
22 
23 #include "libgimpmath/gimpmath.h"
24 #include "libgimpbase/gimpbase.h"
25 #include "libgimpwidgets/gimpwidgets.h"
26 
27 #include "resolution-calibrate-dialog.h"
28 
29 #include "gimp-intl.h"
30 
31 
32 static GtkWidget *calibrate_entry = NULL;
33 static gdouble    calibrate_xres  = 1.0;
34 static gdouble    calibrate_yres  = 1.0;
35 static gint       ruler_width     = 1;
36 static gint       ruler_height    = 1;
37 
38 
39 /**
40  * resolution_calibrate_dialog:
41  * @resolution_entry: a #GimpSizeEntry to connect the dialog to
42  * @icon_name:        an optional icon-name for the upper left corner
43  *
44  * Displays a dialog that allows the user to interactively determine
45  * her monitor resolution. This dialog runs it's own GTK main loop and
46  * is connected to a #GimpSizeEntry handling the resolution to be set.
47  **/
48 void
resolution_calibrate_dialog(GtkWidget * resolution_entry,const gchar * icon_name)49 resolution_calibrate_dialog (GtkWidget   *resolution_entry,
50                              const gchar *icon_name)
51 {
52   GtkWidget    *dialog;
53   GtkWidget    *table;
54   GtkWidget    *vbox;
55   GtkWidget    *hbox;
56   GtkWidget    *ruler;
57   GtkWidget    *label;
58   GdkScreen    *screen;
59   GdkRectangle  rect;
60   gint          monitor;
61 
62   g_return_if_fail (GIMP_IS_SIZE_ENTRY (resolution_entry));
63   g_return_if_fail (gtk_widget_get_realized (resolution_entry));
64 
65   /*  this dialog can only exist once  */
66   if (calibrate_entry)
67     return;
68 
69   dialog = gimp_dialog_new (_("Calibrate Monitor Resolution"),
70                             "gimp-resolution-calibration",
71                             gtk_widget_get_toplevel (resolution_entry),
72                             GTK_DIALOG_DESTROY_WITH_PARENT,
73                             NULL, NULL,
74 
75                             _("_Cancel"), GTK_RESPONSE_CANCEL,
76                             _("_OK"),     GTK_RESPONSE_OK,
77 
78                             NULL);
79 
80   gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
81                                            GTK_RESPONSE_OK,
82                                            GTK_RESPONSE_CANCEL,
83                                            -1);
84 
85   screen = gtk_widget_get_screen (dialog);
86   monitor = gdk_screen_get_monitor_at_window (screen,
87                                               gtk_widget_get_window (resolution_entry));
88   gdk_screen_get_monitor_workarea (screen, monitor, &rect);
89 
90   ruler_width  = rect.width  - 300 - (rect.width  % 100);
91   ruler_height = rect.height - 300 - (rect.height % 100);
92 
93   table = gtk_table_new (4, 4, FALSE);
94   gtk_container_set_border_width (GTK_CONTAINER (table), 12);
95   gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
96                       table, TRUE, TRUE, 0);
97   gtk_widget_show (table);
98 
99   if (icon_name)
100     {
101       GtkWidget *image = gtk_image_new_from_icon_name (icon_name,
102                                                        GTK_ICON_SIZE_DIALOG);
103 
104       gtk_table_attach (GTK_TABLE (table), image, 0, 1, 0, 1,
105                         GTK_SHRINK, GTK_SHRINK, 4, 4);
106       gtk_widget_show (image);
107     }
108 
109   ruler = gimp_ruler_new (GTK_ORIENTATION_HORIZONTAL);
110   gtk_widget_set_size_request (ruler, ruler_width, 32);
111   gimp_ruler_set_range (GIMP_RULER (ruler), 0, ruler_width, ruler_width);
112   gtk_table_attach (GTK_TABLE (table), ruler, 1, 3, 0, 1,
113                     GTK_SHRINK, GTK_SHRINK, 0, 0);
114   gtk_widget_show (ruler);
115 
116   ruler = gimp_ruler_new (GTK_ORIENTATION_VERTICAL);
117   gtk_widget_set_size_request (ruler, 32, ruler_height);
118   gimp_ruler_set_range (GIMP_RULER (ruler), 0, ruler_height, ruler_height);
119   gtk_table_attach (GTK_TABLE (table), ruler, 0, 1, 1, 3,
120                     GTK_SHRINK, GTK_SHRINK, 0, 0);
121   gtk_widget_show (ruler);
122 
123   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
124   gtk_table_attach (GTK_TABLE (table), vbox, 1, 2, 1, 2,
125                     GTK_SHRINK, GTK_SHRINK, 0, 0);
126   gtk_widget_show (vbox);
127 
128   label =
129     gtk_label_new (_("Measure the rulers and enter their lengths:"));
130   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
131   gtk_label_set_xalign (GTK_LABEL (label), 0.0);
132   gimp_label_set_attributes (GTK_LABEL (label),
133                              PANGO_ATTR_SCALE,  PANGO_SCALE_LARGE,
134                              PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD,
135                              -1);
136   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
137   gtk_widget_show (label);
138 
139   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
140   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
141   gtk_widget_show (hbox);
142 
143   calibrate_xres =
144     gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (resolution_entry), 0);
145   calibrate_yres =
146     gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (resolution_entry), 1);
147 
148   calibrate_entry =
149     gimp_coordinates_new  (GIMP_UNIT_INCH, "%p",
150                            FALSE, FALSE, 10,
151                            GIMP_SIZE_ENTRY_UPDATE_SIZE,
152                            FALSE,
153                            FALSE,
154                            _("_Horizontal:"),
155                            ruler_width,
156                            calibrate_xres,
157                            1, GIMP_MAX_IMAGE_SIZE,
158                            0, 0,
159                            _("_Vertical:"),
160                            ruler_height,
161                            calibrate_yres,
162                            1, GIMP_MAX_IMAGE_SIZE,
163                            0, 0);
164   gtk_widget_hide (GTK_WIDGET (GIMP_COORDINATES_CHAINBUTTON (calibrate_entry)));
165   g_signal_connect (dialog, "destroy",
166                     G_CALLBACK (gtk_widget_destroyed),
167                     &calibrate_entry);
168 
169   gtk_box_pack_end (GTK_BOX (hbox), calibrate_entry, FALSE, FALSE, 0);
170   gtk_widget_show (calibrate_entry);
171 
172   gtk_widget_show (dialog);
173 
174   switch (gimp_dialog_run (GIMP_DIALOG (dialog)))
175     {
176     case GTK_RESPONSE_OK:
177       {
178         GtkWidget *chain_button;
179         gdouble    x, y;
180 
181         x = gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (calibrate_entry), 0);
182         y = gimp_size_entry_get_refval (GIMP_SIZE_ENTRY (calibrate_entry), 1);
183 
184         calibrate_xres = (gdouble) ruler_width  * calibrate_xres / x;
185         calibrate_yres = (gdouble) ruler_height * calibrate_yres / y;
186 
187         chain_button = GIMP_COORDINATES_CHAINBUTTON (resolution_entry);
188 
189         if (ABS (x - y) > GIMP_MIN_RESOLUTION)
190           gimp_chain_button_set_active (GIMP_CHAIN_BUTTON (chain_button),
191                                         FALSE);
192 
193         gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (resolution_entry),
194                                     0, calibrate_xres);
195         gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (resolution_entry),
196                                     1, calibrate_yres);
197       }
198 
199     default:
200       break;
201     }
202 
203   gtk_widget_destroy (dialog);
204 }
205