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 <glib-object.h>
21
22 #include "core-types.h"
23
24 #include "core/gimpsubprogress.h"
25 #include "core/gimpprogress.h"
26
27
28 enum
29 {
30 PROP_0,
31 PROP_PROGRESS
32 };
33
34
35 static void gimp_sub_progress_iface_init (GimpProgressInterface *iface);
36
37 static void gimp_sub_progress_finalize (GObject *object);
38 static void gimp_sub_progress_set_property (GObject *object,
39 guint property_id,
40 const GValue *value,
41 GParamSpec *pspec);
42 static void gimp_sub_progress_get_property (GObject *object,
43 guint property_id,
44 GValue *value,
45 GParamSpec *pspec);
46
47 static GimpProgress * gimp_sub_progress_start (GimpProgress *progress,
48 gboolean cancellable,
49 const gchar *message);
50 static void gimp_sub_progress_end (GimpProgress *progress);
51 static gboolean gimp_sub_progress_is_active (GimpProgress *progress);
52 static void gimp_sub_progress_set_text (GimpProgress *progress,
53 const gchar *message);
54 static void gimp_sub_progress_set_value (GimpProgress *progress,
55 gdouble percentage);
56 static gdouble gimp_sub_progress_get_value (GimpProgress *progress);
57 static void gimp_sub_progress_pulse (GimpProgress *progress);
58 static guint32 gimp_sub_progress_get_window_id (GimpProgress *progress);
59 static gboolean gimp_sub_progress_message (GimpProgress *progress,
60 Gimp *gimp,
61 GimpMessageSeverity severity,
62 const gchar *domain,
63 const gchar *message);
64
65
G_DEFINE_TYPE_WITH_CODE(GimpSubProgress,gimp_sub_progress,G_TYPE_OBJECT,G_IMPLEMENT_INTERFACE (GIMP_TYPE_PROGRESS,gimp_sub_progress_iface_init))66 G_DEFINE_TYPE_WITH_CODE (GimpSubProgress, gimp_sub_progress, G_TYPE_OBJECT,
67 G_IMPLEMENT_INTERFACE (GIMP_TYPE_PROGRESS,
68 gimp_sub_progress_iface_init))
69
70 #define parent_class gimp_sub_progress_parent_class
71
72
73 static void
74 gimp_sub_progress_class_init (GimpSubProgressClass *klass)
75 {
76 GObjectClass *object_class = G_OBJECT_CLASS (klass);
77
78 object_class->finalize = gimp_sub_progress_finalize;
79 object_class->set_property = gimp_sub_progress_set_property;
80 object_class->get_property = gimp_sub_progress_get_property;
81
82 g_object_class_install_property (object_class, PROP_PROGRESS,
83 g_param_spec_object ("progress",
84 NULL, NULL,
85 GIMP_TYPE_PROGRESS,
86 G_PARAM_READWRITE |
87 G_PARAM_CONSTRUCT_ONLY));
88 }
89
90 static void
gimp_sub_progress_init(GimpSubProgress * sub)91 gimp_sub_progress_init (GimpSubProgress *sub)
92 {
93 sub->progress = NULL;
94 sub->start = 0.0;
95 sub->end = 1.0;
96 }
97
98 static void
gimp_sub_progress_finalize(GObject * object)99 gimp_sub_progress_finalize (GObject *object)
100 {
101 GimpSubProgress *sub = GIMP_SUB_PROGRESS (object);
102
103 g_clear_object (&sub->progress);
104
105 G_OBJECT_CLASS (parent_class)->finalize (object);
106 }
107
108 static void
gimp_sub_progress_iface_init(GimpProgressInterface * iface)109 gimp_sub_progress_iface_init (GimpProgressInterface *iface)
110 {
111 iface->start = gimp_sub_progress_start;
112 iface->end = gimp_sub_progress_end;
113 iface->is_active = gimp_sub_progress_is_active;
114 iface->set_text = gimp_sub_progress_set_text;
115 iface->set_value = gimp_sub_progress_set_value;
116 iface->get_value = gimp_sub_progress_get_value;
117 iface->pulse = gimp_sub_progress_pulse;
118 iface->get_window_id = gimp_sub_progress_get_window_id;
119 iface->message = gimp_sub_progress_message;
120 }
121
122 static void
gimp_sub_progress_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)123 gimp_sub_progress_set_property (GObject *object,
124 guint property_id,
125 const GValue *value,
126 GParamSpec *pspec)
127 {
128 GimpSubProgress *sub = GIMP_SUB_PROGRESS (object);
129
130 switch (property_id)
131 {
132 case PROP_PROGRESS:
133 g_return_if_fail (sub->progress == NULL);
134 sub->progress = g_value_dup_object (value);
135 break;
136
137 default:
138 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
139 break;
140 }
141 }
142
143 static void
gimp_sub_progress_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)144 gimp_sub_progress_get_property (GObject *object,
145 guint property_id,
146 GValue *value,
147 GParamSpec *pspec)
148 {
149 GimpSubProgress *sub = GIMP_SUB_PROGRESS (object);
150
151 switch (property_id)
152 {
153 case PROP_PROGRESS:
154 g_value_set_object (value, sub->progress);
155 break;
156
157 default:
158 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
159 break;
160 }
161 }
162
163 static GimpProgress *
gimp_sub_progress_start(GimpProgress * progress,gboolean cancellable,const gchar * message)164 gimp_sub_progress_start (GimpProgress *progress,
165 gboolean cancellable,
166 const gchar *message)
167 {
168 /* does nothing */
169 return NULL;
170 }
171
172 static void
gimp_sub_progress_end(GimpProgress * progress)173 gimp_sub_progress_end (GimpProgress *progress)
174 {
175 /* does nothing */
176 }
177
178 static gboolean
gimp_sub_progress_is_active(GimpProgress * progress)179 gimp_sub_progress_is_active (GimpProgress *progress)
180 {
181 GimpSubProgress *sub = GIMP_SUB_PROGRESS (progress);
182
183 if (sub->progress)
184 return gimp_progress_is_active (sub->progress);
185
186 return FALSE;
187 }
188
189 static void
gimp_sub_progress_set_text(GimpProgress * progress,const gchar * message)190 gimp_sub_progress_set_text (GimpProgress *progress,
191 const gchar *message)
192 {
193 /* does nothing */
194 }
195
196 static void
gimp_sub_progress_set_value(GimpProgress * progress,gdouble percentage)197 gimp_sub_progress_set_value (GimpProgress *progress,
198 gdouble percentage)
199 {
200 GimpSubProgress *sub = GIMP_SUB_PROGRESS (progress);
201
202 if (sub->progress)
203 gimp_progress_set_value (sub->progress,
204 sub->start + percentage * (sub->end - sub->start));
205 }
206
207 static gdouble
gimp_sub_progress_get_value(GimpProgress * progress)208 gimp_sub_progress_get_value (GimpProgress *progress)
209 {
210 GimpSubProgress *sub = GIMP_SUB_PROGRESS (progress);
211
212 if (sub->progress)
213 return gimp_progress_get_value (sub->progress);
214
215 return 0.0;
216 }
217
218 static void
gimp_sub_progress_pulse(GimpProgress * progress)219 gimp_sub_progress_pulse (GimpProgress *progress)
220 {
221 GimpSubProgress *sub = GIMP_SUB_PROGRESS (progress);
222
223 if (sub->progress)
224 gimp_progress_pulse (sub->progress);
225 }
226
227 static guint32
gimp_sub_progress_get_window_id(GimpProgress * progress)228 gimp_sub_progress_get_window_id (GimpProgress *progress)
229 {
230 GimpSubProgress *sub = GIMP_SUB_PROGRESS (progress);
231
232 if (sub->progress)
233 return gimp_progress_get_window_id (sub->progress);
234
235 return 0;
236 }
237
238 static gboolean
gimp_sub_progress_message(GimpProgress * progress,Gimp * gimp,GimpMessageSeverity severity,const gchar * domain,const gchar * message)239 gimp_sub_progress_message (GimpProgress *progress,
240 Gimp *gimp,
241 GimpMessageSeverity severity,
242 const gchar *domain,
243 const gchar *message)
244 {
245 GimpSubProgress *sub = GIMP_SUB_PROGRESS (progress);
246
247 if (sub->progress)
248 return gimp_progress_message (sub->progress,
249 gimp, severity, domain, message);
250
251 return FALSE;
252 }
253
254 /**
255 * gimp_sub_progress_new:
256 * @progress: parent progress or %NULL
257 *
258 * GimpSubProgress implements the GimpProgress interface and can be
259 * used wherever a GimpProgress is needed. It maps progress
260 * information to a sub-range of its parent @progress. This is useful
261 * when an action breaks down into multiple sub-actions that itself
262 * need a #GimpProgress pointer. See gimp_image_scale() for an example.
263 *
264 * Return value: a new #GimpProgress object
265 */
266 GimpProgress *
gimp_sub_progress_new(GimpProgress * progress)267 gimp_sub_progress_new (GimpProgress *progress)
268 {
269 GimpSubProgress *sub;
270
271 g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL);
272
273 sub = g_object_new (GIMP_TYPE_SUB_PROGRESS,
274 "progress", progress,
275 NULL);
276
277 return GIMP_PROGRESS (sub);
278 }
279
280 /**
281 * gimp_sub_progress_set_range:
282 * @start: start value of range on the parent process
283 * @end: end value of range on the parent process
284 *
285 * Sets a range on the parent progress that this @progress should be
286 * mapped to.
287 */
288 void
gimp_sub_progress_set_range(GimpSubProgress * progress,gdouble start,gdouble end)289 gimp_sub_progress_set_range (GimpSubProgress *progress,
290 gdouble start,
291 gdouble end)
292 {
293 g_return_if_fail (GIMP_IS_SUB_PROGRESS (progress));
294 g_return_if_fail (start < end);
295
296 progress->start = start;
297 progress->end = end;
298 }
299
300 /**
301 * gimp_sub_progress_set_step:
302 * @index: step index
303 * @num_steps: number of steps
304 *
305 * A more convenient form of gimp_sub_progress_set_range().
306 */
307 void
gimp_sub_progress_set_step(GimpSubProgress * progress,gint index,gint num_steps)308 gimp_sub_progress_set_step (GimpSubProgress *progress,
309 gint index,
310 gint num_steps)
311 {
312 g_return_if_fail (GIMP_IS_SUB_PROGRESS (progress));
313 g_return_if_fail (index < num_steps && num_steps > 0);
314
315 progress->start = (gdouble) index / num_steps;
316 progress->end = (gdouble) (index + 1) / num_steps;
317 }
318