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 <math.h>
21
22 #include <gegl.h>
23 #include <gtk/gtk.h>
24
25 #include "display-types.h"
26
27 #include "core/gimpimage.h"
28
29 #include "gimpdisplay.h"
30 #include "gimpdisplayshell.h"
31 #include "gimpdisplayshell-scale.h"
32 #include "gimpdisplayshell-scrollbars.h"
33
34
35 #define MINIMUM_STEP_AMOUNT 1.0
36
37
38 /**
39 * gimp_display_shell_scrollbars_update:
40 * @shell:
41 *
42 **/
43 void
gimp_display_shell_scrollbars_update(GimpDisplayShell * shell)44 gimp_display_shell_scrollbars_update (GimpDisplayShell *shell)
45 {
46 g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
47
48 if (! shell->display)
49 return;
50
51 /* Horizontal scrollbar */
52
53 g_object_freeze_notify (G_OBJECT (shell->hsbdata));
54
55 /* Update upper and lower value before we set the new value */
56 gimp_display_shell_scrollbars_setup_horizontal (shell, shell->offset_x);
57
58 g_object_set (shell->hsbdata,
59 "value", (gdouble) shell->offset_x,
60 "page-size", (gdouble) shell->disp_width,
61 "page-increment", (gdouble) shell->disp_width / 2,
62 NULL);
63
64 g_object_thaw_notify (G_OBJECT (shell->hsbdata)); /* emits "changed" */
65
66
67 /* Vertcal scrollbar */
68
69 g_object_freeze_notify (G_OBJECT (shell->vsbdata));
70
71 /* Update upper and lower value before we set the new value */
72 gimp_display_shell_scrollbars_setup_vertical (shell, shell->offset_y);
73
74 g_object_set (shell->vsbdata,
75 "value", (gdouble) shell->offset_y,
76 "page-size", (gdouble) shell->disp_height,
77 "page-increment", (gdouble) shell->disp_height / 2,
78 NULL);
79
80 g_object_thaw_notify (G_OBJECT (shell->vsbdata)); /* emits "changed" */
81 }
82
83 /**
84 * gimp_display_shell_scrollbars_setup_horizontal:
85 * @shell:
86 * @value:
87 *
88 * Setup the limits of the horizontal scrollbar
89 **/
90 void
gimp_display_shell_scrollbars_setup_horizontal(GimpDisplayShell * shell,gdouble value)91 gimp_display_shell_scrollbars_setup_horizontal (GimpDisplayShell *shell,
92 gdouble value)
93 {
94 gint bounds_x;
95 gint bounds_width;
96 gint bounding_box_x;
97 gint bounding_box_width;
98 gint x1;
99 gint x2;
100 gdouble lower;
101 gdouble upper;
102 gdouble scale_x;
103
104 g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
105
106 if (! shell->display || ! gimp_display_get_image (shell->display))
107 return;
108
109 gimp_display_shell_scale_get_image_bounds (shell,
110 &bounds_x, NULL,
111 &bounds_width, NULL);
112
113 if (! gimp_display_shell_get_infinite_canvas (shell))
114 {
115 bounding_box_x = bounds_x;
116 bounding_box_width = bounds_width;
117 }
118 else
119 {
120 gimp_display_shell_scale_get_image_bounding_box (
121 shell,
122 &bounding_box_x, NULL,
123 &bounding_box_width, NULL);
124 }
125
126 x1 = bounding_box_x;
127 x2 = bounding_box_x + bounding_box_width;
128
129 x1 = MIN (x1, bounds_x + bounds_width / 2 - shell->disp_width / 2);
130 x2 = MAX (x2, bounds_x + bounds_width / 2 + (shell->disp_width + 1) / 2);
131
132 lower = MIN (value, x1);
133 upper = MAX (value + shell->disp_width, x2);
134
135 gimp_display_shell_get_rotated_scale (shell, &scale_x, NULL);
136
137 g_object_set (shell->hsbdata,
138 "lower", lower,
139 "upper", upper,
140 "step-increment", (gdouble) MAX (scale_x, MINIMUM_STEP_AMOUNT),
141 NULL);
142 }
143
144 /**
145 * gimp_display_shell_scrollbars_setup_vertical:
146 * @shell:
147 * @value:
148 *
149 * Setup the limits of the vertical scrollbar
150 **/
151 void
gimp_display_shell_scrollbars_setup_vertical(GimpDisplayShell * shell,gdouble value)152 gimp_display_shell_scrollbars_setup_vertical (GimpDisplayShell *shell,
153 gdouble value)
154 {
155 gint bounds_y;
156 gint bounds_height;
157 gint bounding_box_y;
158 gint bounding_box_height;
159 gint y1;
160 gint y2;
161 gdouble lower;
162 gdouble upper;
163 gdouble scale_y;
164
165 g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
166
167 if (! shell->display || ! gimp_display_get_image (shell->display))
168 return;
169
170 gimp_display_shell_scale_get_image_bounds (shell,
171 NULL, &bounds_y,
172 NULL, &bounds_height);
173
174 if (! gimp_display_shell_get_infinite_canvas (shell))
175 {
176 bounding_box_y = bounds_y;
177 bounding_box_height = bounds_height;
178 }
179 else
180 {
181 gimp_display_shell_scale_get_image_bounding_box (
182 shell,
183 NULL, &bounding_box_y,
184 NULL, &bounding_box_height);
185 }
186
187 y1 = bounding_box_y;
188 y2 = bounding_box_y + bounding_box_height;
189
190 y1 = MIN (y1, bounds_y + bounds_height / 2 - shell->disp_height / 2);
191 y2 = MAX (y2, bounds_y + bounds_height / 2 + (shell->disp_height + 1) / 2);
192
193 lower = MIN (value, y1);
194 upper = MAX (value + shell->disp_height, y2);
195
196 gimp_display_shell_get_rotated_scale (shell, NULL, &scale_y);
197
198 g_object_set (shell->vsbdata,
199 "lower", lower,
200 "upper", upper,
201 "step-increment", (gdouble) MAX (scale_y, MINIMUM_STEP_AMOUNT),
202 NULL);
203 }
204
205 /**
206 * gimp_display_shell_scrollbars_update_steppers:
207 * @shell:
208 * @min_offset_x:
209 * @max_offset_x:
210 * @min_offset_y:
211 * @max_offset_y:
212 *
213 * Sets the scrollbars' stepper sensitivity which is set differently
214 * from its adjustment limits because we support overscrolling.
215 **/
216 void
gimp_display_shell_scrollbars_update_steppers(GimpDisplayShell * shell,gint min_offset_x,gint max_offset_x,gint min_offset_y,gint max_offset_y)217 gimp_display_shell_scrollbars_update_steppers (GimpDisplayShell *shell,
218 gint min_offset_x,
219 gint max_offset_x,
220 gint min_offset_y,
221 gint max_offset_y)
222 {
223 g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
224
225 gtk_range_set_lower_stepper_sensitivity (GTK_RANGE (shell->hsb),
226 min_offset_x < shell->offset_x ?
227 GTK_SENSITIVITY_ON :
228 GTK_SENSITIVITY_OFF);
229
230 gtk_range_set_upper_stepper_sensitivity (GTK_RANGE (shell->hsb),
231 max_offset_x > shell->offset_x ?
232 GTK_SENSITIVITY_ON :
233 GTK_SENSITIVITY_OFF);
234
235 gtk_range_set_lower_stepper_sensitivity (GTK_RANGE (shell->vsb),
236 min_offset_y < shell->offset_y ?
237 GTK_SENSITIVITY_ON :
238 GTK_SENSITIVITY_OFF);
239
240 gtk_range_set_upper_stepper_sensitivity (GTK_RANGE (shell->vsb),
241 max_offset_y > shell->offset_y ?
242 GTK_SENSITIVITY_ON :
243 GTK_SENSITIVITY_OFF);
244 }
245