1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * gimpcontext.c
5  * Copyright (C) 1999-2010 Michael Natterer
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  */
20 
21 #include "config.h"
22 
23 #include <cairo.h>
24 #include <gegl.h>
25 #include <gdk-pixbuf/gdk-pixbuf.h>
26 
27 #include "libgimpbase/gimpbase.h"
28 #include "libgimpcolor/gimpcolor.h"
29 #include "libgimpconfig/gimpconfig.h"
30 
31 #include "core-types.h"
32 
33 #include "config/gimpcoreconfig.h"
34 
35 #include "gimp.h"
36 #include "gimp-memsize.h"
37 #include "gimpbrush.h"
38 #include "gimpbuffer.h"
39 #include "gimpcontainer.h"
40 #include "gimpcontext.h"
41 #include "gimpdatafactory.h"
42 #include "gimpdynamics.h"
43 #include "gimpimagefile.h"
44 #include "gimpgradient.h"
45 #include "gimpimage.h"
46 #include "gimpmarshal.h"
47 #include "gimpmybrush.h"
48 #include "gimppaintinfo.h"
49 #include "gimppalette.h"
50 #include "gimppattern.h"
51 #include "gimptemplate.h"
52 #include "gimptoolinfo.h"
53 #include "gimptoolpreset.h"
54 
55 #include "text/gimpfont.h"
56 
57 #include "gimp-intl.h"
58 
59 
60 #define RGBA_EPSILON 1e-10
61 
62 typedef void (* GimpContextCopyPropFunc) (GimpContext *src,
63                                           GimpContext *dest);
64 
65 #define context_find_defined(context, prop)                              \
66   while (!(((context)->defined_props) & (1 << (prop))) && (context)->parent) \
67     (context) = (context)->parent
68 
69 #define COPY_NAME(src, dest, member)            \
70   g_free (dest->member);                        \
71   dest->member = g_strdup (src->member)
72 
73 
74 /*  local function prototypes  */
75 
76 static void    gimp_context_config_iface_init (GimpConfigInterface   *iface);
77 
78 static void       gimp_context_constructed    (GObject               *object);
79 static void       gimp_context_dispose        (GObject               *object);
80 static void       gimp_context_finalize       (GObject               *object);
81 static void       gimp_context_set_property   (GObject               *object,
82                                                guint                  property_id,
83                                                const GValue          *value,
84                                                GParamSpec            *pspec);
85 static void       gimp_context_get_property   (GObject               *object,
86                                                guint                  property_id,
87                                                GValue                *value,
88                                                GParamSpec            *pspec);
89 static gint64     gimp_context_get_memsize    (GimpObject            *object,
90                                                gint64                *gui_size);
91 
92 static gboolean   gimp_context_serialize            (GimpConfig       *config,
93                                                      GimpConfigWriter *writer,
94                                                      gpointer          data);
95 static gboolean   gimp_context_deserialize          (GimpConfig       *config,
96                                                      GScanner         *scanner,
97                                                      gint              nest_level,
98                                                      gpointer          data);
99 static gboolean   gimp_context_serialize_property   (GimpConfig       *config,
100                                                      guint             property_id,
101                                                      const GValue     *value,
102                                                      GParamSpec       *pspec,
103                                                      GimpConfigWriter *writer);
104 static gboolean   gimp_context_deserialize_property (GimpConfig       *config,
105                                                      guint             property_id,
106                                                      GValue           *value,
107                                                      GParamSpec       *pspec,
108                                                      GScanner         *scanner,
109                                                      GTokenType       *expected);
110 static GimpConfig * gimp_context_duplicate          (GimpConfig       *config);
111 static gboolean     gimp_context_copy               (GimpConfig       *src,
112                                                      GimpConfig       *dest,
113                                                      GParamFlags       flags);
114 
115 /*  image  */
116 static void gimp_context_image_removed       (GimpContainer    *container,
117                                               GimpImage        *image,
118                                               GimpContext      *context);
119 static void gimp_context_real_set_image      (GimpContext      *context,
120                                               GimpImage        *image);
121 
122 /*  display  */
123 static void gimp_context_display_removed     (GimpContainer    *container,
124                                               gpointer          display,
125                                               GimpContext      *context);
126 static void gimp_context_real_set_display    (GimpContext      *context,
127                                               gpointer          display);
128 
129 /*  tool  */
130 static void gimp_context_tool_dirty          (GimpToolInfo     *tool_info,
131                                               GimpContext      *context);
132 static void gimp_context_tool_removed        (GimpContainer    *container,
133                                               GimpToolInfo     *tool_info,
134                                               GimpContext      *context);
135 static void gimp_context_tool_list_thaw      (GimpContainer    *container,
136                                               GimpContext      *context);
137 static void gimp_context_real_set_tool       (GimpContext      *context,
138                                               GimpToolInfo     *tool_info);
139 
140 /*  paint info  */
141 static void gimp_context_paint_info_dirty    (GimpPaintInfo    *paint_info,
142                                               GimpContext      *context);
143 static void gimp_context_paint_info_removed  (GimpContainer    *container,
144                                               GimpPaintInfo    *paint_info,
145                                               GimpContext      *context);
146 static void gimp_context_paint_info_list_thaw(GimpContainer    *container,
147                                               GimpContext      *context);
148 static void gimp_context_real_set_paint_info (GimpContext      *context,
149                                               GimpPaintInfo    *paint_info);
150 
151 /*  foreground  */
152 static void gimp_context_real_set_foreground (GimpContext      *context,
153                                               const GimpRGB    *color);
154 
155 /*  background  */
156 static void gimp_context_real_set_background (GimpContext      *context,
157                                               const GimpRGB    *color);
158 
159 /*  opacity  */
160 static void gimp_context_real_set_opacity    (GimpContext      *context,
161                                               gdouble           opacity);
162 
163 /*  paint mode  */
164 static void gimp_context_real_set_paint_mode (GimpContext      *context,
165                                               GimpLayerMode     paint_mode);
166 
167 /*  brush  */
168 static void gimp_context_brush_dirty         (GimpBrush        *brush,
169                                               GimpContext      *context);
170 static void gimp_context_brush_removed       (GimpContainer    *brush_list,
171                                               GimpBrush        *brush,
172                                               GimpContext      *context);
173 static void gimp_context_brush_list_thaw     (GimpContainer    *container,
174                                               GimpContext      *context);
175 static void gimp_context_real_set_brush      (GimpContext      *context,
176                                               GimpBrush        *brush);
177 
178 /*  dynamics  */
179 
180 static void gimp_context_dynamics_dirty      (GimpDynamics     *dynamics,
181                                               GimpContext      *context);
182 static void gimp_context_dynamics_removed    (GimpContainer    *container,
183                                               GimpDynamics     *dynamics,
184                                               GimpContext      *context);
185 static void gimp_context_dynamics_list_thaw  (GimpContainer    *container,
186                                               GimpContext      *context);
187 static void gimp_context_real_set_dynamics   (GimpContext      *context,
188                                               GimpDynamics     *dynamics);
189 
190 /*  mybrush  */
191 static void gimp_context_mybrush_dirty       (GimpMybrush      *brush,
192                                               GimpContext      *context);
193 static void gimp_context_mybrush_removed     (GimpContainer    *brush_list,
194                                               GimpMybrush      *brush,
195                                               GimpContext      *context);
196 static void gimp_context_mybrush_list_thaw   (GimpContainer    *container,
197                                               GimpContext      *context);
198 static void gimp_context_real_set_mybrush    (GimpContext      *context,
199                                               GimpMybrush      *brush);
200 
201 /*  pattern  */
202 static void gimp_context_pattern_dirty       (GimpPattern      *pattern,
203                                               GimpContext      *context);
204 static void gimp_context_pattern_removed     (GimpContainer    *container,
205                                               GimpPattern      *pattern,
206                                               GimpContext      *context);
207 static void gimp_context_pattern_list_thaw   (GimpContainer    *container,
208                                               GimpContext      *context);
209 static void gimp_context_real_set_pattern    (GimpContext      *context,
210                                               GimpPattern      *pattern);
211 
212 /*  gradient  */
213 static void gimp_context_gradient_dirty      (GimpGradient     *gradient,
214                                               GimpContext      *context);
215 static void gimp_context_gradient_removed    (GimpContainer    *container,
216                                               GimpGradient     *gradient,
217                                               GimpContext      *context);
218 static void gimp_context_gradient_list_thaw  (GimpContainer    *container,
219                                               GimpContext      *context);
220 static void gimp_context_real_set_gradient   (GimpContext      *context,
221                                               GimpGradient     *gradient);
222 
223 /*  palette  */
224 static void gimp_context_palette_dirty       (GimpPalette      *palette,
225                                               GimpContext      *context);
226 static void gimp_context_palette_removed     (GimpContainer    *container,
227                                               GimpPalette      *palette,
228                                               GimpContext      *context);
229 static void gimp_context_palette_list_thaw   (GimpContainer    *container,
230                                               GimpContext      *context);
231 static void gimp_context_real_set_palette    (GimpContext      *context,
232                                               GimpPalette      *palette);
233 
234 /*  font  */
235 static void gimp_context_font_dirty          (GimpFont         *font,
236                                               GimpContext      *context);
237 static void gimp_context_font_removed        (GimpContainer    *container,
238                                               GimpFont         *font,
239                                               GimpContext      *context);
240 static void gimp_context_font_list_thaw      (GimpContainer    *container,
241                                               GimpContext      *context);
242 static void gimp_context_real_set_font       (GimpContext      *context,
243                                               GimpFont         *font);
244 
245 /*  tool preset  */
246 static void gimp_context_tool_preset_dirty     (GimpToolPreset   *tool_preset,
247                                                 GimpContext      *context);
248 static void gimp_context_tool_preset_removed   (GimpContainer    *container,
249                                                 GimpToolPreset   *tool_preset,
250                                                 GimpContext      *context);
251 static void gimp_context_tool_preset_list_thaw (GimpContainer    *container,
252                                                 GimpContext      *context);
253 static void gimp_context_real_set_tool_preset  (GimpContext      *context,
254                                                 GimpToolPreset   *tool_preset);
255 
256 /*  buffer  */
257 static void gimp_context_buffer_dirty        (GimpBuffer       *buffer,
258                                               GimpContext      *context);
259 static void gimp_context_buffer_removed      (GimpContainer    *container,
260                                               GimpBuffer       *buffer,
261                                               GimpContext      *context);
262 static void gimp_context_buffer_list_thaw    (GimpContainer    *container,
263                                               GimpContext      *context);
264 static void gimp_context_real_set_buffer     (GimpContext      *context,
265                                               GimpBuffer       *buffer);
266 
267 /*  imagefile  */
268 static void gimp_context_imagefile_dirty     (GimpImagefile    *imagefile,
269                                               GimpContext      *context);
270 static void gimp_context_imagefile_removed   (GimpContainer    *container,
271                                               GimpImagefile    *imagefile,
272                                               GimpContext      *context);
273 static void gimp_context_imagefile_list_thaw (GimpContainer    *container,
274                                               GimpContext      *context);
275 static void gimp_context_real_set_imagefile  (GimpContext      *context,
276                                               GimpImagefile    *imagefile);
277 
278 /*  template  */
279 static void gimp_context_template_dirty      (GimpTemplate     *template,
280                                               GimpContext      *context);
281 static void gimp_context_template_removed    (GimpContainer    *container,
282                                               GimpTemplate     *template,
283                                               GimpContext      *context);
284 static void gimp_context_template_list_thaw  (GimpContainer    *container,
285                                               GimpContext      *context);
286 static void gimp_context_real_set_template   (GimpContext      *context,
287                                               GimpTemplate     *template);
288 
289 
290 /*  utilities  */
291 static gpointer gimp_context_find_object     (GimpContext      *context,
292                                               GimpContainer    *container,
293                                               const gchar      *object_name,
294                                               gpointer          standard_object);
295 
296 
297 /*  properties & signals  */
298 
299 enum
300 {
301   GIMP_CONTEXT_PROP_0,
302   GIMP_CONTEXT_PROP_GIMP
303 
304   /*  remaining values are in core-enums.h  (GimpContextPropType)  */
305 };
306 
307 enum
308 {
309   DUMMY_0,
310   DUMMY_1,
311   IMAGE_CHANGED,
312   DISPLAY_CHANGED,
313   TOOL_CHANGED,
314   PAINT_INFO_CHANGED,
315   FOREGROUND_CHANGED,
316   BACKGROUND_CHANGED,
317   OPACITY_CHANGED,
318   PAINT_MODE_CHANGED,
319   BRUSH_CHANGED,
320   DYNAMICS_CHANGED,
321   MYBRUSH_CHANGED,
322   PATTERN_CHANGED,
323   GRADIENT_CHANGED,
324   PALETTE_CHANGED,
325   FONT_CHANGED,
326   TOOL_PRESET_CHANGED,
327   BUFFER_CHANGED,
328   IMAGEFILE_CHANGED,
329   TEMPLATE_CHANGED,
330   PROP_NAME_CHANGED,
331   LAST_SIGNAL
332 };
333 
334 static const gchar * const gimp_context_prop_names[] =
335 {
336   NULL, /* PROP_0 */
337   "gimp",
338   "image",
339   "display",
340   "tool",
341   "paint-info",
342   "foreground",
343   "background",
344   "opacity",
345   "paint-mode",
346   "brush",
347   "dynamics",
348   "mybrush",
349   "pattern",
350   "gradient",
351   "palette",
352   "font",
353   "tool-preset",
354   "buffer",
355   "imagefile",
356   "template"
357 };
358 
359 static GType gimp_context_prop_types[] =
360 {
361   G_TYPE_NONE, /* PROP_0    */
362   G_TYPE_NONE, /* PROP_GIMP */
363   0,
364   G_TYPE_NONE,
365   0,
366   0,
367   G_TYPE_NONE,
368   G_TYPE_NONE,
369   G_TYPE_NONE,
370   G_TYPE_NONE,
371   0,
372   0,
373   0,
374   0,
375   0,
376   0,
377   0,
378   0,
379   0,
380   0,
381   0
382 };
383 
384 
385 G_DEFINE_TYPE_WITH_CODE (GimpContext, gimp_context, GIMP_TYPE_VIEWABLE,
386                          G_IMPLEMENT_INTERFACE (GIMP_TYPE_CONFIG,
387                                                 gimp_context_config_iface_init))
388 
389 #define parent_class gimp_context_parent_class
390 
391 static GimpConfigInterface *parent_config_iface = NULL;
392 
393 static guint gimp_context_signals[LAST_SIGNAL] = { 0 };
394 
395 
396 static void
gimp_context_class_init(GimpContextClass * klass)397 gimp_context_class_init (GimpContextClass *klass)
398 {
399   GObjectClass    *object_class      = G_OBJECT_CLASS (klass);
400   GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
401   GimpRGB          black;
402   GimpRGB          white;
403 
404   gimp_rgba_set (&black, 0.0, 0.0, 0.0, GIMP_OPACITY_OPAQUE);
405   gimp_rgba_set (&white, 1.0, 1.0, 1.0, GIMP_OPACITY_OPAQUE);
406 
407   gimp_context_signals[IMAGE_CHANGED] =
408     g_signal_new ("image-changed",
409                   G_TYPE_FROM_CLASS (klass),
410                   G_SIGNAL_RUN_FIRST,
411                   G_STRUCT_OFFSET (GimpContextClass, image_changed),
412                   NULL, NULL,
413                   gimp_marshal_VOID__OBJECT,
414                   G_TYPE_NONE, 1,
415                   GIMP_TYPE_IMAGE);
416 
417   gimp_context_signals[DISPLAY_CHANGED] =
418     g_signal_new ("display-changed",
419                   G_TYPE_FROM_CLASS (klass),
420                   G_SIGNAL_RUN_FIRST,
421                   G_STRUCT_OFFSET (GimpContextClass, display_changed),
422                   NULL, NULL,
423                   gimp_marshal_VOID__OBJECT,
424                   G_TYPE_NONE, 1,
425                   GIMP_TYPE_OBJECT);
426 
427   gimp_context_signals[TOOL_CHANGED] =
428     g_signal_new ("tool-changed",
429                   G_TYPE_FROM_CLASS (klass),
430                   G_SIGNAL_RUN_FIRST,
431                   G_STRUCT_OFFSET (GimpContextClass, tool_changed),
432                   NULL, NULL,
433                   gimp_marshal_VOID__OBJECT,
434                   G_TYPE_NONE, 1,
435                   GIMP_TYPE_TOOL_INFO);
436 
437   gimp_context_signals[PAINT_INFO_CHANGED] =
438     g_signal_new ("paint-info-changed",
439                   G_TYPE_FROM_CLASS (klass),
440                   G_SIGNAL_RUN_FIRST,
441                   G_STRUCT_OFFSET (GimpContextClass, paint_info_changed),
442                   NULL, NULL,
443                   gimp_marshal_VOID__OBJECT,
444                   G_TYPE_NONE, 1,
445                   GIMP_TYPE_PAINT_INFO);
446 
447   gimp_context_signals[FOREGROUND_CHANGED] =
448     g_signal_new ("foreground-changed",
449                   G_TYPE_FROM_CLASS (klass),
450                   G_SIGNAL_RUN_FIRST,
451                   G_STRUCT_OFFSET (GimpContextClass, foreground_changed),
452                   NULL, NULL,
453                   gimp_marshal_VOID__BOXED,
454                   G_TYPE_NONE, 1,
455                   GIMP_TYPE_RGB | G_SIGNAL_TYPE_STATIC_SCOPE);
456 
457   gimp_context_signals[BACKGROUND_CHANGED] =
458     g_signal_new ("background-changed",
459                   G_TYPE_FROM_CLASS (klass),
460                   G_SIGNAL_RUN_FIRST,
461                   G_STRUCT_OFFSET (GimpContextClass, background_changed),
462                   NULL, NULL,
463                   gimp_marshal_VOID__BOXED,
464                   G_TYPE_NONE, 1,
465                   GIMP_TYPE_RGB | G_SIGNAL_TYPE_STATIC_SCOPE);
466 
467   gimp_context_signals[OPACITY_CHANGED] =
468     g_signal_new ("opacity-changed",
469                   G_TYPE_FROM_CLASS (klass),
470                   G_SIGNAL_RUN_FIRST,
471                   G_STRUCT_OFFSET (GimpContextClass, opacity_changed),
472                   NULL, NULL,
473                   gimp_marshal_VOID__DOUBLE,
474                   G_TYPE_NONE, 1,
475                   G_TYPE_DOUBLE);
476 
477   gimp_context_signals[PAINT_MODE_CHANGED] =
478     g_signal_new ("paint-mode-changed",
479                   G_TYPE_FROM_CLASS (klass),
480                   G_SIGNAL_RUN_FIRST,
481                   G_STRUCT_OFFSET (GimpContextClass, paint_mode_changed),
482                   NULL, NULL,
483                   gimp_marshal_VOID__ENUM,
484                   G_TYPE_NONE, 1,
485                   GIMP_TYPE_LAYER_MODE);
486 
487   gimp_context_signals[BRUSH_CHANGED] =
488     g_signal_new ("brush-changed",
489                   G_TYPE_FROM_CLASS (klass),
490                   G_SIGNAL_RUN_FIRST,
491                   G_STRUCT_OFFSET (GimpContextClass, brush_changed),
492                   NULL, NULL,
493                   gimp_marshal_VOID__OBJECT,
494                   G_TYPE_NONE, 1,
495                   GIMP_TYPE_BRUSH);
496 
497   gimp_context_signals[DYNAMICS_CHANGED] =
498     g_signal_new ("dynamics-changed",
499                   G_TYPE_FROM_CLASS (klass),
500                   G_SIGNAL_RUN_FIRST,
501                   G_STRUCT_OFFSET (GimpContextClass, dynamics_changed),
502                   NULL, NULL,
503                   gimp_marshal_VOID__OBJECT,
504                   G_TYPE_NONE, 1,
505                   GIMP_TYPE_DYNAMICS);
506 
507   gimp_context_signals[MYBRUSH_CHANGED] =
508     g_signal_new ("mybrush-changed",
509                   G_TYPE_FROM_CLASS (klass),
510                   G_SIGNAL_RUN_FIRST,
511                   G_STRUCT_OFFSET (GimpContextClass, mybrush_changed),
512                   NULL, NULL,
513                   gimp_marshal_VOID__OBJECT,
514                   G_TYPE_NONE, 1,
515                   GIMP_TYPE_MYBRUSH);
516 
517   gimp_context_signals[PATTERN_CHANGED] =
518     g_signal_new ("pattern-changed",
519                   G_TYPE_FROM_CLASS (klass),
520                   G_SIGNAL_RUN_FIRST,
521                   G_STRUCT_OFFSET (GimpContextClass, pattern_changed),
522                   NULL, NULL,
523                   gimp_marshal_VOID__OBJECT,
524                   G_TYPE_NONE, 1,
525                   GIMP_TYPE_PATTERN);
526 
527   gimp_context_signals[GRADIENT_CHANGED] =
528     g_signal_new ("gradient-changed",
529                   G_TYPE_FROM_CLASS (klass),
530                   G_SIGNAL_RUN_FIRST,
531                   G_STRUCT_OFFSET (GimpContextClass, gradient_changed),
532                   NULL, NULL,
533                   gimp_marshal_VOID__OBJECT,
534                   G_TYPE_NONE, 1,
535                   GIMP_TYPE_GRADIENT);
536 
537   gimp_context_signals[PALETTE_CHANGED] =
538     g_signal_new ("palette-changed",
539                   G_TYPE_FROM_CLASS (klass),
540                   G_SIGNAL_RUN_FIRST,
541                   G_STRUCT_OFFSET (GimpContextClass, palette_changed),
542                   NULL, NULL,
543                   gimp_marshal_VOID__OBJECT,
544                   G_TYPE_NONE, 1,
545                   GIMP_TYPE_PALETTE);
546 
547   gimp_context_signals[FONT_CHANGED] =
548     g_signal_new ("font-changed",
549                   G_TYPE_FROM_CLASS (klass),
550                   G_SIGNAL_RUN_FIRST,
551                   G_STRUCT_OFFSET (GimpContextClass, font_changed),
552                   NULL, NULL,
553                   gimp_marshal_VOID__OBJECT,
554                   G_TYPE_NONE, 1,
555                   GIMP_TYPE_FONT);
556 
557   gimp_context_signals[TOOL_PRESET_CHANGED] =
558     g_signal_new ("tool-preset-changed",
559                   G_TYPE_FROM_CLASS (klass),
560                   G_SIGNAL_RUN_FIRST,
561                   G_STRUCT_OFFSET (GimpContextClass, tool_preset_changed),
562                   NULL, NULL,
563                   gimp_marshal_VOID__OBJECT,
564                   G_TYPE_NONE, 1,
565                   GIMP_TYPE_TOOL_PRESET);
566 
567   gimp_context_signals[BUFFER_CHANGED] =
568     g_signal_new ("buffer-changed",
569                   G_TYPE_FROM_CLASS (klass),
570                   G_SIGNAL_RUN_FIRST,
571                   G_STRUCT_OFFSET (GimpContextClass, buffer_changed),
572                   NULL, NULL,
573                   gimp_marshal_VOID__OBJECT,
574                   G_TYPE_NONE, 1,
575                   GIMP_TYPE_BUFFER);
576 
577   gimp_context_signals[IMAGEFILE_CHANGED] =
578     g_signal_new ("imagefile-changed",
579                   G_TYPE_FROM_CLASS (klass),
580                   G_SIGNAL_RUN_FIRST,
581                   G_STRUCT_OFFSET (GimpContextClass, imagefile_changed),
582                   NULL, NULL,
583                   gimp_marshal_VOID__OBJECT,
584                   G_TYPE_NONE, 1,
585                   GIMP_TYPE_IMAGEFILE);
586 
587   gimp_context_signals[TEMPLATE_CHANGED] =
588     g_signal_new ("template-changed",
589                   G_TYPE_FROM_CLASS (klass),
590                   G_SIGNAL_RUN_FIRST,
591                   G_STRUCT_OFFSET (GimpContextClass, template_changed),
592                   NULL, NULL,
593                   gimp_marshal_VOID__OBJECT,
594                   G_TYPE_NONE, 1,
595                   GIMP_TYPE_TEMPLATE);
596 
597   gimp_context_signals[PROP_NAME_CHANGED] =
598     g_signal_new ("prop-name-changed",
599                   G_TYPE_FROM_CLASS (klass),
600                   G_SIGNAL_RUN_FIRST,
601                   G_STRUCT_OFFSET (GimpContextClass, prop_name_changed),
602                   NULL, NULL,
603                   gimp_marshal_VOID__INT,
604                   G_TYPE_NONE, 1,
605                   G_TYPE_INT);
606 
607   object_class->constructed      = gimp_context_constructed;
608   object_class->set_property     = gimp_context_set_property;
609   object_class->get_property     = gimp_context_get_property;
610   object_class->dispose          = gimp_context_dispose;
611   object_class->finalize         = gimp_context_finalize;
612 
613   gimp_object_class->get_memsize = gimp_context_get_memsize;
614 
615   klass->image_changed           = NULL;
616   klass->display_changed         = NULL;
617   klass->tool_changed            = NULL;
618   klass->paint_info_changed      = NULL;
619   klass->foreground_changed      = NULL;
620   klass->background_changed      = NULL;
621   klass->opacity_changed         = NULL;
622   klass->paint_mode_changed      = NULL;
623   klass->brush_changed           = NULL;
624   klass->dynamics_changed        = NULL;
625   klass->mybrush_changed         = NULL;
626   klass->pattern_changed         = NULL;
627   klass->gradient_changed        = NULL;
628   klass->palette_changed         = NULL;
629   klass->font_changed            = NULL;
630   klass->tool_preset_changed     = NULL;
631   klass->buffer_changed          = NULL;
632   klass->imagefile_changed       = NULL;
633   klass->template_changed        = NULL;
634   klass->prop_name_changed       = NULL;
635 
636   gimp_context_prop_types[GIMP_CONTEXT_PROP_IMAGE]       = GIMP_TYPE_IMAGE;
637   gimp_context_prop_types[GIMP_CONTEXT_PROP_TOOL]        = GIMP_TYPE_TOOL_INFO;
638   gimp_context_prop_types[GIMP_CONTEXT_PROP_PAINT_INFO]  = GIMP_TYPE_PAINT_INFO;
639   gimp_context_prop_types[GIMP_CONTEXT_PROP_BRUSH]       = GIMP_TYPE_BRUSH;
640   gimp_context_prop_types[GIMP_CONTEXT_PROP_DYNAMICS]    = GIMP_TYPE_DYNAMICS;
641   gimp_context_prop_types[GIMP_CONTEXT_PROP_MYBRUSH]     = GIMP_TYPE_MYBRUSH;
642   gimp_context_prop_types[GIMP_CONTEXT_PROP_PATTERN]     = GIMP_TYPE_PATTERN;
643   gimp_context_prop_types[GIMP_CONTEXT_PROP_GRADIENT]    = GIMP_TYPE_GRADIENT;
644   gimp_context_prop_types[GIMP_CONTEXT_PROP_PALETTE]     = GIMP_TYPE_PALETTE;
645   gimp_context_prop_types[GIMP_CONTEXT_PROP_FONT]        = GIMP_TYPE_FONT;
646   gimp_context_prop_types[GIMP_CONTEXT_PROP_TOOL_PRESET] = GIMP_TYPE_TOOL_PRESET;
647   gimp_context_prop_types[GIMP_CONTEXT_PROP_BUFFER]      = GIMP_TYPE_BUFFER;
648   gimp_context_prop_types[GIMP_CONTEXT_PROP_IMAGEFILE]   = GIMP_TYPE_IMAGEFILE;
649   gimp_context_prop_types[GIMP_CONTEXT_PROP_TEMPLATE]    = GIMP_TYPE_TEMPLATE;
650 
651   g_object_class_install_property (object_class, GIMP_CONTEXT_PROP_GIMP,
652                                    g_param_spec_object ("gimp",
653                                                         NULL, NULL,
654                                                         GIMP_TYPE_GIMP,
655                                                         GIMP_PARAM_READWRITE |
656                                                         G_PARAM_CONSTRUCT_ONLY));
657 
658   g_object_class_install_property (object_class, GIMP_CONTEXT_PROP_IMAGE,
659                                    g_param_spec_object (gimp_context_prop_names[GIMP_CONTEXT_PROP_IMAGE],
660                                                         NULL, NULL,
661                                                         GIMP_TYPE_IMAGE,
662                                                         GIMP_PARAM_READWRITE));
663 
664   g_object_class_install_property (object_class, GIMP_CONTEXT_PROP_DISPLAY,
665                                    g_param_spec_object (gimp_context_prop_names[GIMP_CONTEXT_PROP_DISPLAY],
666                                                         NULL, NULL,
667                                                         GIMP_TYPE_OBJECT,
668                                                         GIMP_PARAM_READWRITE));
669 
670   GIMP_CONFIG_PROP_OBJECT (object_class, GIMP_CONTEXT_PROP_TOOL,
671                            gimp_context_prop_names[GIMP_CONTEXT_PROP_TOOL],
672                            NULL, NULL,
673                            GIMP_TYPE_TOOL_INFO,
674                            GIMP_PARAM_STATIC_STRINGS);
675 
676   GIMP_CONFIG_PROP_OBJECT (object_class, GIMP_CONTEXT_PROP_PAINT_INFO,
677                            gimp_context_prop_names[GIMP_CONTEXT_PROP_PAINT_INFO],
678                            NULL, NULL,
679                            GIMP_TYPE_PAINT_INFO,
680                            GIMP_PARAM_STATIC_STRINGS);
681 
682   GIMP_CONFIG_PROP_RGB (object_class, GIMP_CONTEXT_PROP_FOREGROUND,
683                         gimp_context_prop_names[GIMP_CONTEXT_PROP_FOREGROUND],
684                         _("Foreground"),
685                         _("Foreground color"),
686                          FALSE, &black,
687                         GIMP_PARAM_STATIC_STRINGS);
688 
689   GIMP_CONFIG_PROP_RGB (object_class, GIMP_CONTEXT_PROP_BACKGROUND,
690                         gimp_context_prop_names[GIMP_CONTEXT_PROP_BACKGROUND],
691                         _("Background"),
692                         _("Background color"),
693                         FALSE, &white,
694                         GIMP_PARAM_STATIC_STRINGS);
695 
696   GIMP_CONFIG_PROP_DOUBLE (object_class, GIMP_CONTEXT_PROP_OPACITY,
697                            gimp_context_prop_names[GIMP_CONTEXT_PROP_OPACITY],
698                            _("Opacity"),
699                            _("Opacity"),
700                            GIMP_OPACITY_TRANSPARENT,
701                            GIMP_OPACITY_OPAQUE,
702                            GIMP_OPACITY_OPAQUE,
703                            GIMP_PARAM_STATIC_STRINGS);
704 
705   GIMP_CONFIG_PROP_ENUM (object_class, GIMP_CONTEXT_PROP_PAINT_MODE,
706                          gimp_context_prop_names[GIMP_CONTEXT_PROP_PAINT_MODE],
707                          _("Paint Mode"),
708                          _("Paint Mode"),
709                          GIMP_TYPE_LAYER_MODE,
710                          GIMP_LAYER_MODE_NORMAL,
711                          GIMP_PARAM_STATIC_STRINGS);
712 
713   GIMP_CONFIG_PROP_OBJECT (object_class, GIMP_CONTEXT_PROP_BRUSH,
714                            gimp_context_prop_names[GIMP_CONTEXT_PROP_BRUSH],
715                            _("Brush"),
716                            _("Brush"),
717                            GIMP_TYPE_BRUSH,
718                            GIMP_PARAM_STATIC_STRINGS);
719 
720   GIMP_CONFIG_PROP_OBJECT (object_class, GIMP_CONTEXT_PROP_DYNAMICS,
721                            gimp_context_prop_names[GIMP_CONTEXT_PROP_DYNAMICS],
722                            _("Dynamics"),
723                            _("Paint dynamics"),
724                            GIMP_TYPE_DYNAMICS,
725                            GIMP_PARAM_STATIC_STRINGS);
726 
727   GIMP_CONFIG_PROP_OBJECT (object_class, GIMP_CONTEXT_PROP_MYBRUSH,
728                            gimp_context_prop_names[GIMP_CONTEXT_PROP_MYBRUSH],
729                            _("MyPaint Brush"),
730                            _("MyPaint Brush"),
731                            GIMP_TYPE_MYBRUSH,
732                            GIMP_PARAM_STATIC_STRINGS);
733 
734   GIMP_CONFIG_PROP_OBJECT (object_class, GIMP_CONTEXT_PROP_PATTERN,
735                            gimp_context_prop_names[GIMP_CONTEXT_PROP_PATTERN],
736                            _("Pattern"),
737                            _("Pattern"),
738                            GIMP_TYPE_PATTERN,
739                            GIMP_PARAM_STATIC_STRINGS);
740 
741   GIMP_CONFIG_PROP_OBJECT (object_class, GIMP_CONTEXT_PROP_GRADIENT,
742                            gimp_context_prop_names[GIMP_CONTEXT_PROP_GRADIENT],
743                            _("Gradient"),
744                            _("Gradient"),
745                            GIMP_TYPE_GRADIENT,
746                            GIMP_PARAM_STATIC_STRINGS);
747 
748   GIMP_CONFIG_PROP_OBJECT (object_class, GIMP_CONTEXT_PROP_PALETTE,
749                            gimp_context_prop_names[GIMP_CONTEXT_PROP_PALETTE],
750                            _("Palette"),
751                            _("Palette"),
752                            GIMP_TYPE_PALETTE,
753                            GIMP_PARAM_STATIC_STRINGS);
754 
755   GIMP_CONFIG_PROP_OBJECT (object_class, GIMP_CONTEXT_PROP_FONT,
756                            gimp_context_prop_names[GIMP_CONTEXT_PROP_FONT],
757                            _("Font"),
758                            _("Font"),
759                            GIMP_TYPE_FONT,
760                            GIMP_PARAM_STATIC_STRINGS);
761 
762   GIMP_CONFIG_PROP_OBJECT (object_class, GIMP_CONTEXT_PROP_TOOL_PRESET,
763                            gimp_context_prop_names[GIMP_CONTEXT_PROP_TOOL_PRESET],
764                            _("Tool Preset"),
765                            _("Tool Preset"),
766                            GIMP_TYPE_TOOL_PRESET,
767                            GIMP_PARAM_STATIC_STRINGS);
768 
769   g_object_class_install_property (object_class, GIMP_CONTEXT_PROP_BUFFER,
770                                    g_param_spec_object (gimp_context_prop_names[GIMP_CONTEXT_PROP_BUFFER],
771                                                         NULL, NULL,
772                                                         GIMP_TYPE_BUFFER,
773                                                         GIMP_PARAM_READWRITE));
774 
775   g_object_class_install_property (object_class, GIMP_CONTEXT_PROP_IMAGEFILE,
776                                    g_param_spec_object (gimp_context_prop_names[GIMP_CONTEXT_PROP_IMAGEFILE],
777                                                         NULL, NULL,
778                                                         GIMP_TYPE_IMAGEFILE,
779                                                         GIMP_PARAM_READWRITE));
780 
781   g_object_class_install_property (object_class, GIMP_CONTEXT_PROP_TEMPLATE,
782                                    g_param_spec_object (gimp_context_prop_names[GIMP_CONTEXT_PROP_TEMPLATE],
783                                                         NULL, NULL,
784                                                         GIMP_TYPE_TEMPLATE,
785                                                         GIMP_PARAM_READWRITE));
786 }
787 
788 static void
gimp_context_init(GimpContext * context)789 gimp_context_init (GimpContext *context)
790 {
791   context->gimp            = NULL;
792 
793   context->parent          = NULL;
794 
795   context->defined_props   = GIMP_CONTEXT_PROP_MASK_ALL;
796   context->serialize_props = GIMP_CONTEXT_PROP_MASK_ALL;
797 
798   context->image           = NULL;
799   context->display         = NULL;
800 
801   context->tool_info       = NULL;
802   context->tool_name       = NULL;
803 
804   context->paint_info      = NULL;
805   context->paint_name      = NULL;
806 
807   context->brush           = NULL;
808   context->brush_name      = NULL;
809 
810   context->dynamics        = NULL;
811   context->dynamics_name   = NULL;
812 
813   context->mybrush         = NULL;
814   context->mybrush_name    = NULL;
815 
816   context->pattern         = NULL;
817   context->pattern_name    = NULL;
818 
819   context->gradient        = NULL;
820   context->gradient_name   = NULL;
821 
822   context->palette         = NULL;
823   context->palette_name    = NULL;
824 
825   context->font            = NULL;
826   context->font_name       = NULL;
827 
828   context->tool_preset      = NULL;
829   context->tool_preset_name = NULL;
830 
831   context->buffer          = NULL;
832   context->buffer_name     = NULL;
833 
834   context->imagefile       = NULL;
835   context->imagefile_name  = NULL;
836 
837   context->template        = NULL;
838   context->template_name   = NULL;
839 }
840 
841 static void
gimp_context_config_iface_init(GimpConfigInterface * iface)842 gimp_context_config_iface_init (GimpConfigInterface *iface)
843 {
844   parent_config_iface = g_type_interface_peek_parent (iface);
845 
846   if (! parent_config_iface)
847     parent_config_iface = g_type_default_interface_peek (GIMP_TYPE_CONFIG);
848 
849   iface->serialize            = gimp_context_serialize;
850   iface->deserialize          = gimp_context_deserialize;
851   iface->serialize_property   = gimp_context_serialize_property;
852   iface->deserialize_property = gimp_context_deserialize_property;
853   iface->duplicate            = gimp_context_duplicate;
854   iface->copy                 = gimp_context_copy;
855 }
856 
857 static void
gimp_context_constructed(GObject * object)858 gimp_context_constructed (GObject *object)
859 {
860   Gimp          *gimp;
861   GimpContainer *container;
862 
863   G_OBJECT_CLASS (parent_class)->constructed (object);
864 
865   gimp = GIMP_CONTEXT (object)->gimp;
866 
867   gimp_assert (GIMP_IS_GIMP (gimp));
868 
869   gimp->context_list = g_list_prepend (gimp->context_list, object);
870 
871   g_signal_connect_object (gimp->images, "remove",
872                            G_CALLBACK (gimp_context_image_removed),
873                            object, 0);
874   g_signal_connect_object (gimp->displays, "remove",
875                            G_CALLBACK (gimp_context_display_removed),
876                            object, 0);
877 
878   g_signal_connect_object (gimp->tool_info_list, "remove",
879                            G_CALLBACK (gimp_context_tool_removed),
880                            object, 0);
881   g_signal_connect_object (gimp->tool_info_list, "thaw",
882                            G_CALLBACK (gimp_context_tool_list_thaw),
883                            object, 0);
884 
885   g_signal_connect_object (gimp->paint_info_list, "remove",
886                            G_CALLBACK (gimp_context_paint_info_removed),
887                            object, 0);
888   g_signal_connect_object (gimp->paint_info_list, "thaw",
889                            G_CALLBACK (gimp_context_paint_info_list_thaw),
890                            object, 0);
891 
892   container = gimp_data_factory_get_container (gimp->brush_factory);
893   g_signal_connect_object (container, "remove",
894                            G_CALLBACK (gimp_context_brush_removed),
895                            object, 0);
896   g_signal_connect_object (container, "thaw",
897                            G_CALLBACK (gimp_context_brush_list_thaw),
898                            object, 0);
899 
900   container = gimp_data_factory_get_container (gimp->dynamics_factory);
901   g_signal_connect_object (container, "remove",
902                            G_CALLBACK (gimp_context_dynamics_removed),
903                            object, 0);
904   g_signal_connect_object (container, "thaw",
905                            G_CALLBACK (gimp_context_dynamics_list_thaw),
906                            object, 0);
907 
908   container = gimp_data_factory_get_container (gimp->mybrush_factory);
909   g_signal_connect_object (container, "remove",
910                            G_CALLBACK (gimp_context_mybrush_removed),
911                            object, 0);
912   g_signal_connect_object (container, "thaw",
913                            G_CALLBACK (gimp_context_mybrush_list_thaw),
914                            object, 0);
915 
916   container = gimp_data_factory_get_container (gimp->pattern_factory);
917   g_signal_connect_object (container, "remove",
918                            G_CALLBACK (gimp_context_pattern_removed),
919                            object, 0);
920   g_signal_connect_object (container, "thaw",
921                            G_CALLBACK (gimp_context_pattern_list_thaw),
922                            object, 0);
923 
924   container = gimp_data_factory_get_container (gimp->gradient_factory);
925   g_signal_connect_object (container, "remove",
926                            G_CALLBACK (gimp_context_gradient_removed),
927                            object, 0);
928   g_signal_connect_object (container, "thaw",
929                            G_CALLBACK (gimp_context_gradient_list_thaw),
930                            object, 0);
931 
932   container = gimp_data_factory_get_container (gimp->palette_factory);
933   g_signal_connect_object (container, "remove",
934                            G_CALLBACK (gimp_context_palette_removed),
935                            object, 0);
936   g_signal_connect_object (container, "thaw",
937                            G_CALLBACK (gimp_context_palette_list_thaw),
938                            object, 0);
939 
940   container = gimp_data_factory_get_container (gimp->font_factory);
941   g_signal_connect_object (container, "remove",
942                            G_CALLBACK (gimp_context_font_removed),
943                            object, 0);
944   g_signal_connect_object (container, "thaw",
945                            G_CALLBACK (gimp_context_font_list_thaw),
946                            object, 0);
947 
948   container = gimp_data_factory_get_container (gimp->tool_preset_factory);
949   g_signal_connect_object (container, "remove",
950                            G_CALLBACK (gimp_context_tool_preset_removed),
951                            object, 0);
952   g_signal_connect_object (container, "thaw",
953                            G_CALLBACK (gimp_context_tool_preset_list_thaw),
954                            object, 0);
955 
956   g_signal_connect_object (gimp->named_buffers, "remove",
957                            G_CALLBACK (gimp_context_buffer_removed),
958                            object, 0);
959   g_signal_connect_object (gimp->named_buffers, "thaw",
960                            G_CALLBACK (gimp_context_buffer_list_thaw),
961                            object, 0);
962 
963   g_signal_connect_object (gimp->documents, "remove",
964                            G_CALLBACK (gimp_context_imagefile_removed),
965                            object, 0);
966   g_signal_connect_object (gimp->documents, "thaw",
967                            G_CALLBACK (gimp_context_imagefile_list_thaw),
968                            object, 0);
969 
970   g_signal_connect_object (gimp->templates, "remove",
971                            G_CALLBACK (gimp_context_template_removed),
972                            object, 0);
973   g_signal_connect_object (gimp->templates, "thaw",
974                            G_CALLBACK (gimp_context_template_list_thaw),
975                            object, 0);
976 
977   gimp_context_set_paint_info (GIMP_CONTEXT (object),
978                                gimp_paint_info_get_standard (gimp));
979 }
980 
981 static void
gimp_context_dispose(GObject * object)982 gimp_context_dispose (GObject *object)
983 {
984   GimpContext *context = GIMP_CONTEXT (object);
985 
986   gimp_context_set_parent (context, NULL);
987 
988   if (context->gimp)
989     {
990       context->gimp->context_list = g_list_remove (context->gimp->context_list,
991                                                    context);
992       context->gimp = NULL;
993     }
994 
995   g_clear_object (&context->tool_info);
996   g_clear_object (&context->paint_info);
997   g_clear_object (&context->brush);
998   g_clear_object (&context->dynamics);
999   g_clear_object (&context->mybrush);
1000   g_clear_object (&context->pattern);
1001   g_clear_object (&context->gradient);
1002   g_clear_object (&context->palette);
1003   g_clear_object (&context->font);
1004   g_clear_object (&context->tool_preset);
1005   g_clear_object (&context->buffer);
1006   g_clear_object (&context->imagefile);
1007   g_clear_object (&context->template);
1008 
1009   G_OBJECT_CLASS (parent_class)->dispose (object);
1010 }
1011 
1012 static void
gimp_context_finalize(GObject * object)1013 gimp_context_finalize (GObject *object)
1014 {
1015   GimpContext *context = GIMP_CONTEXT (object);
1016 
1017   context->parent  = NULL;
1018   context->image   = NULL;
1019   context->display = NULL;
1020 
1021   g_clear_pointer (&context->tool_name,        g_free);
1022   g_clear_pointer (&context->paint_name,       g_free);
1023   g_clear_pointer (&context->brush_name,       g_free);
1024   g_clear_pointer (&context->dynamics_name,    g_free);
1025   g_clear_pointer (&context->mybrush_name,     g_free);
1026   g_clear_pointer (&context->pattern_name,     g_free);
1027   g_clear_pointer (&context->gradient_name,    g_free);
1028   g_clear_pointer (&context->palette_name,     g_free);
1029   g_clear_pointer (&context->font_name,        g_free);
1030   g_clear_pointer (&context->tool_preset_name, g_free);
1031   g_clear_pointer (&context->buffer_name,      g_free);
1032   g_clear_pointer (&context->imagefile_name,   g_free);
1033   g_clear_pointer (&context->template_name,    g_free);
1034 
1035   G_OBJECT_CLASS (parent_class)->finalize (object);
1036 }
1037 
1038 static void
gimp_context_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)1039 gimp_context_set_property (GObject      *object,
1040                            guint         property_id,
1041                            const GValue *value,
1042                            GParamSpec   *pspec)
1043 {
1044   GimpContext *context = GIMP_CONTEXT (object);
1045 
1046   switch (property_id)
1047     {
1048     case GIMP_CONTEXT_PROP_GIMP:
1049       context->gimp = g_value_get_object (value);
1050       break;
1051     case GIMP_CONTEXT_PROP_IMAGE:
1052       gimp_context_set_image (context, g_value_get_object (value));
1053       break;
1054     case GIMP_CONTEXT_PROP_DISPLAY:
1055       gimp_context_set_display (context, g_value_get_object (value));
1056       break;
1057     case GIMP_CONTEXT_PROP_TOOL:
1058       gimp_context_set_tool (context, g_value_get_object (value));
1059       break;
1060     case GIMP_CONTEXT_PROP_PAINT_INFO:
1061       gimp_context_set_paint_info (context, g_value_get_object (value));
1062       break;
1063     case GIMP_CONTEXT_PROP_FOREGROUND:
1064       gimp_context_set_foreground (context, g_value_get_boxed (value));
1065       break;
1066     case GIMP_CONTEXT_PROP_BACKGROUND:
1067       gimp_context_set_background (context, g_value_get_boxed (value));
1068       break;
1069     case GIMP_CONTEXT_PROP_OPACITY:
1070       gimp_context_set_opacity (context, g_value_get_double (value));
1071       break;
1072     case GIMP_CONTEXT_PROP_PAINT_MODE:
1073       gimp_context_set_paint_mode (context, g_value_get_enum (value));
1074       break;
1075     case GIMP_CONTEXT_PROP_BRUSH:
1076       gimp_context_set_brush (context, g_value_get_object (value));
1077       break;
1078     case GIMP_CONTEXT_PROP_DYNAMICS:
1079       gimp_context_set_dynamics (context, g_value_get_object (value));
1080       break;
1081     case GIMP_CONTEXT_PROP_MYBRUSH:
1082       gimp_context_set_mybrush (context, g_value_get_object (value));
1083       break;
1084     case GIMP_CONTEXT_PROP_PATTERN:
1085       gimp_context_set_pattern (context, g_value_get_object (value));
1086       break;
1087     case GIMP_CONTEXT_PROP_GRADIENT:
1088       gimp_context_set_gradient (context, g_value_get_object (value));
1089       break;
1090     case GIMP_CONTEXT_PROP_PALETTE:
1091       gimp_context_set_palette (context, g_value_get_object (value));
1092       break;
1093     case GIMP_CONTEXT_PROP_FONT:
1094       gimp_context_set_font (context, g_value_get_object (value));
1095       break;
1096     case GIMP_CONTEXT_PROP_TOOL_PRESET:
1097       gimp_context_set_tool_preset (context, g_value_get_object (value));
1098       break;
1099     case GIMP_CONTEXT_PROP_BUFFER:
1100       gimp_context_set_buffer (context, g_value_get_object (value));
1101       break;
1102     case GIMP_CONTEXT_PROP_IMAGEFILE:
1103       gimp_context_set_imagefile (context, g_value_get_object (value));
1104       break;
1105     case GIMP_CONTEXT_PROP_TEMPLATE:
1106       gimp_context_set_template (context, g_value_get_object (value));
1107       break;
1108     default:
1109       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1110       break;
1111     }
1112 }
1113 
1114 static void
gimp_context_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)1115 gimp_context_get_property (GObject    *object,
1116                            guint       property_id,
1117                            GValue     *value,
1118                            GParamSpec *pspec)
1119 {
1120   GimpContext *context = GIMP_CONTEXT (object);
1121 
1122   switch (property_id)
1123     {
1124     case GIMP_CONTEXT_PROP_GIMP:
1125       g_value_set_object (value, context->gimp);
1126       break;
1127     case GIMP_CONTEXT_PROP_IMAGE:
1128       g_value_set_object (value, gimp_context_get_image (context));
1129       break;
1130     case GIMP_CONTEXT_PROP_DISPLAY:
1131       g_value_set_object (value, gimp_context_get_display (context));
1132       break;
1133     case GIMP_CONTEXT_PROP_TOOL:
1134       g_value_set_object (value, gimp_context_get_tool (context));
1135       break;
1136     case GIMP_CONTEXT_PROP_PAINT_INFO:
1137       g_value_set_object (value, gimp_context_get_paint_info (context));
1138       break;
1139     case GIMP_CONTEXT_PROP_FOREGROUND:
1140       {
1141         GimpRGB color;
1142 
1143         gimp_context_get_foreground (context, &color);
1144         g_value_set_boxed (value, &color);
1145       }
1146       break;
1147     case GIMP_CONTEXT_PROP_BACKGROUND:
1148       {
1149         GimpRGB color;
1150 
1151         gimp_context_get_background (context, &color);
1152         g_value_set_boxed (value, &color);
1153       }
1154       break;
1155     case GIMP_CONTEXT_PROP_OPACITY:
1156       g_value_set_double (value, gimp_context_get_opacity (context));
1157       break;
1158     case GIMP_CONTEXT_PROP_PAINT_MODE:
1159       g_value_set_enum (value, gimp_context_get_paint_mode (context));
1160       break;
1161     case GIMP_CONTEXT_PROP_BRUSH:
1162       g_value_set_object (value, gimp_context_get_brush (context));
1163       break;
1164     case GIMP_CONTEXT_PROP_DYNAMICS:
1165       g_value_set_object (value, gimp_context_get_dynamics (context));
1166       break;
1167     case GIMP_CONTEXT_PROP_MYBRUSH:
1168       g_value_set_object (value, gimp_context_get_mybrush (context));
1169       break;
1170     case GIMP_CONTEXT_PROP_PATTERN:
1171       g_value_set_object (value, gimp_context_get_pattern (context));
1172       break;
1173     case GIMP_CONTEXT_PROP_GRADIENT:
1174       g_value_set_object (value, gimp_context_get_gradient (context));
1175       break;
1176     case GIMP_CONTEXT_PROP_PALETTE:
1177       g_value_set_object (value, gimp_context_get_palette (context));
1178       break;
1179     case GIMP_CONTEXT_PROP_FONT:
1180       g_value_set_object (value, gimp_context_get_font (context));
1181       break;
1182     case GIMP_CONTEXT_PROP_TOOL_PRESET:
1183       g_value_set_object (value, gimp_context_get_tool_preset (context));
1184       break;
1185     case GIMP_CONTEXT_PROP_BUFFER:
1186       g_value_set_object (value, gimp_context_get_buffer (context));
1187       break;
1188     case GIMP_CONTEXT_PROP_IMAGEFILE:
1189       g_value_set_object (value, gimp_context_get_imagefile (context));
1190       break;
1191     case GIMP_CONTEXT_PROP_TEMPLATE:
1192       g_value_set_object (value, gimp_context_get_template (context));
1193       break;
1194     default:
1195       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1196       break;
1197     }
1198 }
1199 
1200 static gint64
gimp_context_get_memsize(GimpObject * object,gint64 * gui_size)1201 gimp_context_get_memsize (GimpObject *object,
1202                           gint64     *gui_size)
1203 {
1204   GimpContext *context = GIMP_CONTEXT (object);
1205   gint64       memsize = 0;
1206 
1207   memsize += gimp_string_get_memsize (context->tool_name);
1208   memsize += gimp_string_get_memsize (context->paint_name);
1209   memsize += gimp_string_get_memsize (context->brush_name);
1210   memsize += gimp_string_get_memsize (context->dynamics_name);
1211   memsize += gimp_string_get_memsize (context->mybrush_name);
1212   memsize += gimp_string_get_memsize (context->pattern_name);
1213   memsize += gimp_string_get_memsize (context->palette_name);
1214   memsize += gimp_string_get_memsize (context->font_name);
1215   memsize += gimp_string_get_memsize (context->tool_preset_name);
1216   memsize += gimp_string_get_memsize (context->buffer_name);
1217   memsize += gimp_string_get_memsize (context->imagefile_name);
1218   memsize += gimp_string_get_memsize (context->template_name);
1219 
1220   return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
1221                                                                   gui_size);
1222 }
1223 
1224 static gboolean
gimp_context_serialize(GimpConfig * config,GimpConfigWriter * writer,gpointer data)1225 gimp_context_serialize (GimpConfig       *config,
1226                         GimpConfigWriter *writer,
1227                         gpointer          data)
1228 {
1229   return gimp_config_serialize_changed_properties (config, writer);
1230 }
1231 
1232 static gboolean
gimp_context_deserialize(GimpConfig * config,GScanner * scanner,gint nest_level,gpointer data)1233 gimp_context_deserialize (GimpConfig *config,
1234                           GScanner   *scanner,
1235                           gint        nest_level,
1236                           gpointer    data)
1237 {
1238   GimpContext   *context        = GIMP_CONTEXT (config);
1239   GimpLayerMode  old_paint_mode = context->paint_mode;
1240   gboolean       success;
1241 
1242   success = gimp_config_deserialize_properties (config, scanner, nest_level);
1243 
1244   if (context->paint_mode != old_paint_mode)
1245     {
1246       if (context->paint_mode == GIMP_LAYER_MODE_OVERLAY_LEGACY)
1247         g_object_set (context,
1248                       "paint-mode", GIMP_LAYER_MODE_SOFTLIGHT_LEGACY,
1249                       NULL);
1250     }
1251 
1252   return success;
1253 }
1254 
1255 static gboolean
gimp_context_serialize_property(GimpConfig * config,guint property_id,const GValue * value,GParamSpec * pspec,GimpConfigWriter * writer)1256 gimp_context_serialize_property (GimpConfig       *config,
1257                                  guint             property_id,
1258                                  const GValue     *value,
1259                                  GParamSpec       *pspec,
1260                                  GimpConfigWriter *writer)
1261 {
1262   GimpContext *context = GIMP_CONTEXT (config);
1263   GimpObject  *serialize_obj;
1264 
1265   /*  serialize nothing if the property is not in serialize_props  */
1266   if (! ((1 << property_id) & context->serialize_props))
1267     return TRUE;
1268 
1269   switch (property_id)
1270     {
1271     case GIMP_CONTEXT_PROP_TOOL:
1272     case GIMP_CONTEXT_PROP_PAINT_INFO:
1273     case GIMP_CONTEXT_PROP_BRUSH:
1274     case GIMP_CONTEXT_PROP_DYNAMICS:
1275     case GIMP_CONTEXT_PROP_MYBRUSH:
1276     case GIMP_CONTEXT_PROP_PATTERN:
1277     case GIMP_CONTEXT_PROP_GRADIENT:
1278     case GIMP_CONTEXT_PROP_PALETTE:
1279     case GIMP_CONTEXT_PROP_FONT:
1280     case GIMP_CONTEXT_PROP_TOOL_PRESET:
1281       serialize_obj = g_value_get_object (value);
1282       break;
1283 
1284     default:
1285       return FALSE;
1286     }
1287 
1288   gimp_config_writer_open (writer, pspec->name);
1289 
1290   if (serialize_obj)
1291     gimp_config_writer_string (writer, gimp_object_get_name (serialize_obj));
1292   else
1293     gimp_config_writer_print (writer, "NULL", 4);
1294 
1295   gimp_config_writer_close (writer);
1296 
1297   return TRUE;
1298 }
1299 
1300 static gboolean
gimp_context_deserialize_property(GimpConfig * object,guint property_id,GValue * value,GParamSpec * pspec,GScanner * scanner,GTokenType * expected)1301 gimp_context_deserialize_property (GimpConfig *object,
1302                                    guint       property_id,
1303                                    GValue     *value,
1304                                    GParamSpec *pspec,
1305                                    GScanner   *scanner,
1306                                    GTokenType *expected)
1307 {
1308   GimpContext   *context = GIMP_CONTEXT (object);
1309   GimpContainer *container;
1310   gpointer       standard;
1311   gchar        **name_loc;
1312   gchar         *object_name;
1313 
1314   switch (property_id)
1315     {
1316     case GIMP_CONTEXT_PROP_TOOL:
1317       container = context->gimp->tool_info_list;
1318       standard  = gimp_tool_info_get_standard (context->gimp);
1319       name_loc  = &context->tool_name;
1320       break;
1321 
1322     case GIMP_CONTEXT_PROP_PAINT_INFO:
1323       container = context->gimp->paint_info_list;
1324       standard  = gimp_paint_info_get_standard (context->gimp);
1325       name_loc  = &context->paint_name;
1326       break;
1327 
1328     case GIMP_CONTEXT_PROP_BRUSH:
1329       container = gimp_data_factory_get_container (context->gimp->brush_factory);
1330       standard  = gimp_brush_get_standard (context);
1331       name_loc  = &context->brush_name;
1332       break;
1333 
1334     case GIMP_CONTEXT_PROP_DYNAMICS:
1335       container = gimp_data_factory_get_container (context->gimp->dynamics_factory);
1336       standard  = gimp_dynamics_get_standard (context);
1337       name_loc  = &context->dynamics_name;
1338       break;
1339 
1340     case GIMP_CONTEXT_PROP_MYBRUSH:
1341       container = gimp_data_factory_get_container (context->gimp->mybrush_factory);
1342       standard  = gimp_mybrush_get_standard (context);
1343       name_loc  = &context->mybrush_name;
1344       break;
1345 
1346     case GIMP_CONTEXT_PROP_PATTERN:
1347       container = gimp_data_factory_get_container (context->gimp->pattern_factory);
1348       standard  = gimp_pattern_get_standard (context);
1349       name_loc  = &context->pattern_name;
1350       break;
1351 
1352     case GIMP_CONTEXT_PROP_GRADIENT:
1353       container = gimp_data_factory_get_container (context->gimp->gradient_factory);
1354       standard  = gimp_gradient_get_standard (context);
1355       name_loc  = &context->gradient_name;
1356       break;
1357 
1358     case GIMP_CONTEXT_PROP_PALETTE:
1359       container = gimp_data_factory_get_container (context->gimp->palette_factory);
1360       standard  = gimp_palette_get_standard (context);
1361       name_loc  = &context->palette_name;
1362       break;
1363 
1364     case GIMP_CONTEXT_PROP_FONT:
1365       container = gimp_data_factory_get_container (context->gimp->font_factory);
1366       standard  = gimp_font_get_standard ();
1367       name_loc  = &context->font_name;
1368       break;
1369 
1370     case GIMP_CONTEXT_PROP_TOOL_PRESET:
1371       container = gimp_data_factory_get_container (context->gimp->tool_preset_factory);
1372       standard  = NULL;
1373       name_loc  = &context->tool_preset_name;
1374       break;
1375 
1376     default:
1377       return FALSE;
1378     }
1379 
1380   if (gimp_scanner_parse_identifier (scanner, "NULL"))
1381     {
1382       g_value_set_object (value, NULL);
1383     }
1384   else if (gimp_scanner_parse_string (scanner, &object_name))
1385     {
1386       GimpObject *deserialize_obj;
1387 
1388       if (! object_name)
1389         object_name = g_strdup ("");
1390 
1391       deserialize_obj = gimp_container_get_child_by_name (container,
1392                                                           object_name);
1393 
1394       if (! deserialize_obj)
1395         {
1396           g_value_set_object (value, standard);
1397 
1398           g_free (*name_loc);
1399           *name_loc = g_strdup (object_name);
1400         }
1401       else
1402         {
1403           g_value_set_object (value, deserialize_obj);
1404         }
1405 
1406       g_free (object_name);
1407     }
1408   else
1409     {
1410       *expected = G_TOKEN_STRING;
1411     }
1412 
1413   return TRUE;
1414 }
1415 
1416 static GimpConfig *
gimp_context_duplicate(GimpConfig * config)1417 gimp_context_duplicate (GimpConfig *config)
1418 {
1419   GimpContext *context = GIMP_CONTEXT (config);
1420   GimpContext *new;
1421 
1422   new = GIMP_CONTEXT (parent_config_iface->duplicate (config));
1423 
1424   COPY_NAME (context, new, tool_name);
1425   COPY_NAME (context, new, paint_name);
1426   COPY_NAME (context, new, brush_name);
1427   COPY_NAME (context, new, dynamics_name);
1428   COPY_NAME (context, new, mybrush_name);
1429   COPY_NAME (context, new, pattern_name);
1430   COPY_NAME (context, new, gradient_name);
1431   COPY_NAME (context, new, palette_name);
1432   COPY_NAME (context, new, font_name);
1433   COPY_NAME (context, new, tool_preset_name);
1434   COPY_NAME (context, new, buffer_name);
1435   COPY_NAME (context, new, imagefile_name);
1436   COPY_NAME (context, new, template_name);
1437 
1438   return GIMP_CONFIG (new);
1439 }
1440 
1441 static gboolean
gimp_context_copy(GimpConfig * src,GimpConfig * dest,GParamFlags flags)1442 gimp_context_copy (GimpConfig  *src,
1443                    GimpConfig  *dest,
1444                    GParamFlags  flags)
1445 {
1446   GimpContext *src_context  = GIMP_CONTEXT (src);
1447   GimpContext *dest_context = GIMP_CONTEXT (dest);
1448   gboolean     success      = parent_config_iface->copy (src, dest, flags);
1449 
1450   COPY_NAME (src_context, dest_context, tool_name);
1451   COPY_NAME (src_context, dest_context, paint_name);
1452   COPY_NAME (src_context, dest_context, brush_name);
1453   COPY_NAME (src_context, dest_context, dynamics_name);
1454   COPY_NAME (src_context, dest_context, mybrush_name);
1455   COPY_NAME (src_context, dest_context, pattern_name);
1456   COPY_NAME (src_context, dest_context, gradient_name);
1457   COPY_NAME (src_context, dest_context, palette_name);
1458   COPY_NAME (src_context, dest_context, font_name);
1459   COPY_NAME (src_context, dest_context, tool_preset_name);
1460   COPY_NAME (src_context, dest_context, buffer_name);
1461   COPY_NAME (src_context, dest_context, imagefile_name);
1462   COPY_NAME (src_context, dest_context, template_name);
1463 
1464   return success;
1465 }
1466 
1467 
1468 /*****************************************************************************/
1469 /*  public functions  ********************************************************/
1470 
1471 GimpContext *
gimp_context_new(Gimp * gimp,const gchar * name,GimpContext * template)1472 gimp_context_new (Gimp        *gimp,
1473                   const gchar *name,
1474                   GimpContext *template)
1475 {
1476   GimpContext *context;
1477 
1478   g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
1479   g_return_val_if_fail (name != NULL, NULL);
1480   g_return_val_if_fail (template == NULL || GIMP_IS_CONTEXT (template), NULL);
1481 
1482   context = g_object_new (GIMP_TYPE_CONTEXT,
1483                           "name", name,
1484                           "gimp", gimp,
1485                           NULL);
1486 
1487   if (template)
1488     {
1489       context->defined_props = template->defined_props;
1490 
1491       gimp_context_copy_properties (template, context,
1492                                     GIMP_CONTEXT_PROP_MASK_ALL);
1493     }
1494 
1495   return context;
1496 }
1497 
1498 GimpContext *
gimp_context_get_parent(GimpContext * context)1499 gimp_context_get_parent (GimpContext *context)
1500 {
1501   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
1502 
1503   return context->parent;
1504 }
1505 
1506 static void
gimp_context_parent_notify(GimpContext * parent,GParamSpec * pspec,GimpContext * context)1507 gimp_context_parent_notify (GimpContext *parent,
1508                             GParamSpec  *pspec,
1509                             GimpContext *context)
1510 {
1511   if (pspec->owner_type == GIMP_TYPE_CONTEXT)
1512     {
1513       GimpContextPropType prop = pspec->param_id;
1514 
1515       /*  copy from parent if the changed property is undefined;
1516        *  ignore properties that are not context properties, for
1517        *  example notifications on the context's "gimp" property
1518        */
1519       if ((prop >= GIMP_CONTEXT_PROP_FIRST) &&
1520           (prop <= GIMP_CONTEXT_PROP_LAST)  &&
1521           ! ((1 << prop) & context->defined_props))
1522         {
1523           gimp_context_copy_property (parent, context, prop);
1524         }
1525     }
1526 }
1527 
1528 void
gimp_context_set_parent(GimpContext * context,GimpContext * parent)1529 gimp_context_set_parent (GimpContext *context,
1530                          GimpContext *parent)
1531 {
1532   g_return_if_fail (GIMP_IS_CONTEXT (context));
1533   g_return_if_fail (parent == NULL || GIMP_IS_CONTEXT (parent));
1534   g_return_if_fail (parent == NULL || parent->parent != context);
1535   g_return_if_fail (context != parent);
1536 
1537   if (context->parent == parent)
1538     return;
1539 
1540   if (context->parent)
1541     {
1542       g_signal_handlers_disconnect_by_func (context->parent,
1543                                             gimp_context_parent_notify,
1544                                             context);
1545 
1546       g_object_remove_weak_pointer (G_OBJECT (context->parent),
1547                                     (gpointer) &context->parent);
1548     }
1549 
1550   context->parent = parent;
1551 
1552   if (parent)
1553     {
1554       g_object_add_weak_pointer (G_OBJECT (context->parent),
1555                                  (gpointer) &context->parent);
1556 
1557       /*  copy all undefined properties from the new parent  */
1558       gimp_context_copy_properties (parent, context,
1559                                     ~context->defined_props &
1560                                     GIMP_CONTEXT_PROP_MASK_ALL);
1561 
1562       g_signal_connect_object (parent, "notify",
1563                                G_CALLBACK (gimp_context_parent_notify),
1564                                context,
1565                                0);
1566     }
1567 }
1568 
1569 
1570 /*  define / undefinine context properties  */
1571 
1572 void
gimp_context_define_property(GimpContext * context,GimpContextPropType prop,gboolean defined)1573 gimp_context_define_property (GimpContext         *context,
1574                               GimpContextPropType  prop,
1575                               gboolean             defined)
1576 {
1577   GimpContextPropMask mask;
1578 
1579   g_return_if_fail (GIMP_IS_CONTEXT (context));
1580   g_return_if_fail ((prop >= GIMP_CONTEXT_PROP_FIRST) &&
1581                     (prop <= GIMP_CONTEXT_PROP_LAST));
1582 
1583   mask = (1 << prop);
1584 
1585   if (defined)
1586     {
1587       if (! (context->defined_props & mask))
1588         {
1589           context->defined_props |= mask;
1590         }
1591     }
1592   else
1593     {
1594       if (context->defined_props & mask)
1595         {
1596           context->defined_props &= ~mask;
1597 
1598           if (context->parent)
1599             gimp_context_copy_property (context->parent, context, prop);
1600         }
1601     }
1602 }
1603 
1604 gboolean
gimp_context_property_defined(GimpContext * context,GimpContextPropType prop)1605 gimp_context_property_defined (GimpContext         *context,
1606                                GimpContextPropType  prop)
1607 {
1608   g_return_val_if_fail (GIMP_IS_CONTEXT (context), FALSE);
1609 
1610   return (context->defined_props & (1 << prop)) ? TRUE : FALSE;
1611 }
1612 
1613 void
gimp_context_define_properties(GimpContext * context,GimpContextPropMask prop_mask,gboolean defined)1614 gimp_context_define_properties (GimpContext         *context,
1615                                 GimpContextPropMask  prop_mask,
1616                                 gboolean             defined)
1617 {
1618   GimpContextPropType prop;
1619 
1620   g_return_if_fail (GIMP_IS_CONTEXT (context));
1621 
1622   for (prop = GIMP_CONTEXT_PROP_FIRST; prop <= GIMP_CONTEXT_PROP_LAST; prop++)
1623     if ((1 << prop) & prop_mask)
1624       gimp_context_define_property (context, prop, defined);
1625 }
1626 
1627 
1628 /*  specify which context properties will be serialized  */
1629 
1630 void
gimp_context_set_serialize_properties(GimpContext * context,GimpContextPropMask props_mask)1631 gimp_context_set_serialize_properties (GimpContext         *context,
1632                                        GimpContextPropMask  props_mask)
1633 {
1634   g_return_if_fail (GIMP_IS_CONTEXT (context));
1635 
1636   context->serialize_props = props_mask;
1637 }
1638 
1639 GimpContextPropMask
gimp_context_get_serialize_properties(GimpContext * context)1640 gimp_context_get_serialize_properties (GimpContext *context)
1641 {
1642   g_return_val_if_fail (GIMP_IS_CONTEXT (context), 0);
1643 
1644   return context->serialize_props;
1645 }
1646 
1647 
1648 /*  copying context properties  */
1649 
1650 void
gimp_context_copy_property(GimpContext * src,GimpContext * dest,GimpContextPropType prop)1651 gimp_context_copy_property (GimpContext         *src,
1652                             GimpContext         *dest,
1653                             GimpContextPropType  prop)
1654 {
1655   g_return_if_fail (GIMP_IS_CONTEXT (src));
1656   g_return_if_fail (GIMP_IS_CONTEXT (dest));
1657   g_return_if_fail ((prop >= GIMP_CONTEXT_PROP_FIRST) &&
1658                     (prop <= GIMP_CONTEXT_PROP_LAST));
1659 
1660   switch (prop)
1661     {
1662     case GIMP_CONTEXT_PROP_IMAGE:
1663       gimp_context_real_set_image (dest, src->image);
1664       break;
1665 
1666     case GIMP_CONTEXT_PROP_DISPLAY:
1667       gimp_context_real_set_display (dest, src->display);
1668       break;
1669 
1670     case GIMP_CONTEXT_PROP_TOOL:
1671       gimp_context_real_set_tool (dest, src->tool_info);
1672       COPY_NAME (src, dest, tool_name);
1673       break;
1674 
1675     case GIMP_CONTEXT_PROP_PAINT_INFO:
1676       gimp_context_real_set_paint_info (dest, src->paint_info);
1677       COPY_NAME (src, dest, paint_name);
1678       break;
1679 
1680     case GIMP_CONTEXT_PROP_FOREGROUND:
1681       gimp_context_real_set_foreground (dest, &src->foreground);
1682       break;
1683 
1684     case GIMP_CONTEXT_PROP_BACKGROUND:
1685       gimp_context_real_set_background (dest, &src->background);
1686       break;
1687 
1688     case GIMP_CONTEXT_PROP_OPACITY:
1689       gimp_context_real_set_opacity (dest, src->opacity);
1690       break;
1691 
1692     case GIMP_CONTEXT_PROP_PAINT_MODE:
1693       gimp_context_real_set_paint_mode (dest, src->paint_mode);
1694       break;
1695 
1696     case GIMP_CONTEXT_PROP_BRUSH:
1697       gimp_context_real_set_brush (dest, src->brush);
1698       COPY_NAME (src, dest, brush_name);
1699       break;
1700 
1701     case GIMP_CONTEXT_PROP_DYNAMICS:
1702       gimp_context_real_set_dynamics (dest, src->dynamics);
1703       COPY_NAME (src, dest, dynamics_name);
1704       break;
1705 
1706     case GIMP_CONTEXT_PROP_MYBRUSH:
1707       gimp_context_real_set_mybrush (dest, src->mybrush);
1708       COPY_NAME (src, dest, mybrush_name);
1709       break;
1710 
1711     case GIMP_CONTEXT_PROP_PATTERN:
1712       gimp_context_real_set_pattern (dest, src->pattern);
1713       COPY_NAME (src, dest, pattern_name);
1714       break;
1715 
1716     case GIMP_CONTEXT_PROP_GRADIENT:
1717       gimp_context_real_set_gradient (dest, src->gradient);
1718       COPY_NAME (src, dest, gradient_name);
1719       break;
1720 
1721     case GIMP_CONTEXT_PROP_PALETTE:
1722       gimp_context_real_set_palette (dest, src->palette);
1723       COPY_NAME (src, dest, palette_name);
1724       break;
1725 
1726     case GIMP_CONTEXT_PROP_FONT:
1727       gimp_context_real_set_font (dest, src->font);
1728       COPY_NAME (src, dest, font_name);
1729       break;
1730 
1731     case GIMP_CONTEXT_PROP_TOOL_PRESET:
1732       gimp_context_real_set_tool_preset (dest, src->tool_preset);
1733       COPY_NAME (src, dest, tool_preset_name);
1734       break;
1735 
1736     case GIMP_CONTEXT_PROP_BUFFER:
1737       gimp_context_real_set_buffer (dest, src->buffer);
1738       COPY_NAME (src, dest, buffer_name);
1739       break;
1740 
1741     case GIMP_CONTEXT_PROP_IMAGEFILE:
1742       gimp_context_real_set_imagefile (dest, src->imagefile);
1743       COPY_NAME (src, dest, imagefile_name);
1744       break;
1745 
1746     case GIMP_CONTEXT_PROP_TEMPLATE:
1747       gimp_context_real_set_template (dest, src->template);
1748       COPY_NAME (src, dest, template_name);
1749       break;
1750 
1751     default:
1752       break;
1753     }
1754 }
1755 
1756 void
gimp_context_copy_properties(GimpContext * src,GimpContext * dest,GimpContextPropMask prop_mask)1757 gimp_context_copy_properties (GimpContext         *src,
1758                               GimpContext         *dest,
1759                               GimpContextPropMask  prop_mask)
1760 {
1761   GimpContextPropType prop;
1762 
1763   g_return_if_fail (GIMP_IS_CONTEXT (src));
1764   g_return_if_fail (GIMP_IS_CONTEXT (dest));
1765 
1766   for (prop = GIMP_CONTEXT_PROP_FIRST; prop <= GIMP_CONTEXT_PROP_LAST; prop++)
1767     if ((1 << prop) & prop_mask)
1768       gimp_context_copy_property (src, dest, prop);
1769 }
1770 
1771 
1772 /*  attribute access functions  */
1773 
1774 /*****************************************************************************/
1775 /*  manipulate by GType  *****************************************************/
1776 
1777 GimpContextPropType
gimp_context_type_to_property(GType type)1778 gimp_context_type_to_property (GType type)
1779 {
1780   GimpContextPropType prop;
1781 
1782   for (prop = GIMP_CONTEXT_PROP_FIRST; prop <= GIMP_CONTEXT_PROP_LAST; prop++)
1783     {
1784       if (g_type_is_a (type, gimp_context_prop_types[prop]))
1785         return prop;
1786     }
1787 
1788   return -1;
1789 }
1790 
1791 const gchar *
gimp_context_type_to_prop_name(GType type)1792 gimp_context_type_to_prop_name (GType type)
1793 {
1794   GimpContextPropType prop;
1795 
1796   for (prop = GIMP_CONTEXT_PROP_FIRST; prop <= GIMP_CONTEXT_PROP_LAST; prop++)
1797     {
1798       if (g_type_is_a (type, gimp_context_prop_types[prop]))
1799         return gimp_context_prop_names[prop];
1800     }
1801 
1802   return NULL;
1803 }
1804 
1805 const gchar *
gimp_context_type_to_signal_name(GType type)1806 gimp_context_type_to_signal_name (GType type)
1807 {
1808   GimpContextPropType prop;
1809 
1810   for (prop = GIMP_CONTEXT_PROP_FIRST; prop <= GIMP_CONTEXT_PROP_LAST; prop++)
1811     {
1812       if (g_type_is_a (type, gimp_context_prop_types[prop]))
1813         return g_signal_name (gimp_context_signals[prop]);
1814     }
1815 
1816   return NULL;
1817 }
1818 
1819 GimpObject *
gimp_context_get_by_type(GimpContext * context,GType type)1820 gimp_context_get_by_type (GimpContext *context,
1821                           GType        type)
1822 {
1823   GimpContextPropType  prop;
1824   GimpObject          *object = NULL;
1825 
1826   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
1827 
1828   prop = gimp_context_type_to_property (type);
1829 
1830   g_return_val_if_fail (prop != -1, NULL);
1831 
1832   g_object_get (context,
1833                 gimp_context_prop_names[prop], &object,
1834                 NULL);
1835 
1836   /*  g_object_get() refs the object, this function however is a getter,
1837    *  which usually doesn't ref it's return value
1838    */
1839   if (object)
1840     g_object_unref (object);
1841 
1842   return object;
1843 }
1844 
1845 void
gimp_context_set_by_type(GimpContext * context,GType type,GimpObject * object)1846 gimp_context_set_by_type (GimpContext *context,
1847                           GType        type,
1848                           GimpObject  *object)
1849 {
1850   GimpContextPropType  prop;
1851   GParamSpec          *pspec;
1852   GValue               value = G_VALUE_INIT;
1853 
1854   g_return_if_fail (GIMP_IS_CONTEXT (context));
1855   g_return_if_fail (object == NULL || G_IS_OBJECT (object));
1856 
1857   prop = gimp_context_type_to_property (type);
1858 
1859   g_return_if_fail (prop != -1);
1860 
1861   pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (context),
1862                                         gimp_context_prop_names[prop]);
1863 
1864   g_return_if_fail (pspec != NULL);
1865 
1866   g_value_init (&value, pspec->value_type);
1867   g_value_set_object (&value, object);
1868 
1869   /*  we use gimp_context_set_property() (which in turn only calls
1870    *  gimp_context_set_foo() functions) instead of the much more obvious
1871    *  g_object_set(); this avoids g_object_freeze_notify()/thaw_notify()
1872    *  around the g_object_set() and makes GimpContext callbacks being
1873    *  called in a much more predictable order. See bug #731279.
1874    */
1875   gimp_context_set_property (G_OBJECT (context),
1876                              pspec->param_id,
1877                              (const GValue *) &value,
1878                              pspec);
1879 
1880   g_value_unset (&value);
1881 }
1882 
1883 void
gimp_context_changed_by_type(GimpContext * context,GType type)1884 gimp_context_changed_by_type (GimpContext *context,
1885                               GType        type)
1886 {
1887   GimpContextPropType  prop;
1888   GimpObject          *object;
1889 
1890   g_return_if_fail (GIMP_IS_CONTEXT (context));
1891 
1892   prop = gimp_context_type_to_property (type);
1893 
1894   g_return_if_fail (prop != -1);
1895 
1896   object = gimp_context_get_by_type (context, type);
1897 
1898   g_signal_emit (context,
1899                  gimp_context_signals[prop], 0,
1900                  object);
1901 }
1902 
1903 
1904 /*****************************************************************************/
1905 /*  image  *******************************************************************/
1906 
1907 GimpImage *
gimp_context_get_image(GimpContext * context)1908 gimp_context_get_image (GimpContext *context)
1909 {
1910   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
1911 
1912   return context->image;
1913 }
1914 
1915 void
gimp_context_set_image(GimpContext * context,GimpImage * image)1916 gimp_context_set_image (GimpContext *context,
1917                         GimpImage   *image)
1918 {
1919   g_return_if_fail (GIMP_IS_CONTEXT (context));
1920   g_return_if_fail (image == NULL || GIMP_IS_IMAGE (image));
1921 
1922   context_find_defined (context, GIMP_CONTEXT_PROP_IMAGE);
1923 
1924   gimp_context_real_set_image (context, image);
1925 }
1926 
1927 void
gimp_context_image_changed(GimpContext * context)1928 gimp_context_image_changed (GimpContext *context)
1929 {
1930   g_return_if_fail (GIMP_IS_CONTEXT (context));
1931 
1932   g_signal_emit (context,
1933                  gimp_context_signals[IMAGE_CHANGED], 0,
1934                  context->image);
1935 }
1936 
1937 static void
gimp_context_image_removed(GimpContainer * container,GimpImage * image,GimpContext * context)1938 gimp_context_image_removed (GimpContainer *container,
1939                             GimpImage     *image,
1940                             GimpContext   *context)
1941 {
1942   if (context->image == image)
1943     gimp_context_real_set_image (context, NULL);
1944 }
1945 
1946 static void
gimp_context_real_set_image(GimpContext * context,GimpImage * image)1947 gimp_context_real_set_image (GimpContext *context,
1948                              GimpImage   *image)
1949 {
1950   if (context->image == image)
1951     return;
1952 
1953   context->image = image;
1954 
1955   g_object_notify (G_OBJECT (context), "image");
1956   gimp_context_image_changed (context);
1957 }
1958 
1959 
1960 /*****************************************************************************/
1961 /*  display  *****************************************************************/
1962 
1963 gpointer
gimp_context_get_display(GimpContext * context)1964 gimp_context_get_display (GimpContext *context)
1965 {
1966   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
1967 
1968   return context->display;
1969 }
1970 
1971 void
gimp_context_set_display(GimpContext * context,gpointer display)1972 gimp_context_set_display (GimpContext *context,
1973                           gpointer     display)
1974 {
1975   g_return_if_fail (GIMP_IS_CONTEXT (context));
1976   g_return_if_fail (display == NULL || GIMP_IS_OBJECT (display));
1977 
1978   context_find_defined (context, GIMP_CONTEXT_PROP_DISPLAY);
1979 
1980   gimp_context_real_set_display (context, display);
1981 }
1982 
1983 void
gimp_context_display_changed(GimpContext * context)1984 gimp_context_display_changed (GimpContext *context)
1985 {
1986   g_return_if_fail (GIMP_IS_CONTEXT (context));
1987 
1988   g_signal_emit (context,
1989                  gimp_context_signals[DISPLAY_CHANGED], 0,
1990                  context->display);
1991 }
1992 
1993 static void
gimp_context_display_removed(GimpContainer * container,gpointer display,GimpContext * context)1994 gimp_context_display_removed (GimpContainer *container,
1995                               gpointer       display,
1996                               GimpContext   *context)
1997 {
1998   if (context->display == display)
1999     gimp_context_real_set_display (context, NULL);
2000 }
2001 
2002 static void
gimp_context_real_set_display(GimpContext * context,gpointer display)2003 gimp_context_real_set_display (GimpContext *context,
2004                                gpointer     display)
2005 {
2006   GimpObject *old_display;
2007 
2008   if (context->display == display)
2009     {
2010       /*  make sure that setting a display *always* sets the image
2011        *  to that display's image, even if the display already
2012        *  matches
2013        */
2014       if (display)
2015         {
2016           GimpImage *image;
2017 
2018           g_object_get (display, "image", &image, NULL);
2019 
2020           gimp_context_real_set_image (context, image);
2021 
2022           if (image)
2023             g_object_unref (image);
2024         }
2025 
2026       return;
2027     }
2028 
2029   old_display = context->display;
2030 
2031   context->display = display;
2032 
2033   if (context->display)
2034     {
2035       GimpImage *image;
2036 
2037       g_object_get (display, "image", &image, NULL);
2038 
2039       gimp_context_real_set_image (context, image);
2040 
2041       if (image)
2042         g_object_unref (image);
2043     }
2044   else if (old_display)
2045     {
2046       gimp_context_real_set_image (context, NULL);
2047     }
2048 
2049   g_object_notify (G_OBJECT (context), "display");
2050   gimp_context_display_changed (context);
2051 }
2052 
2053 
2054 /*****************************************************************************/
2055 /*  tool  ********************************************************************/
2056 
2057 GimpToolInfo *
gimp_context_get_tool(GimpContext * context)2058 gimp_context_get_tool (GimpContext *context)
2059 {
2060   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
2061 
2062   return context->tool_info;
2063 }
2064 
2065 void
gimp_context_set_tool(GimpContext * context,GimpToolInfo * tool_info)2066 gimp_context_set_tool (GimpContext  *context,
2067                        GimpToolInfo *tool_info)
2068 {
2069   g_return_if_fail (GIMP_IS_CONTEXT (context));
2070   g_return_if_fail (tool_info == NULL || GIMP_IS_TOOL_INFO (tool_info));
2071 
2072   context_find_defined (context, GIMP_CONTEXT_PROP_TOOL);
2073 
2074   gimp_context_real_set_tool (context, tool_info);
2075 }
2076 
2077 void
gimp_context_tool_changed(GimpContext * context)2078 gimp_context_tool_changed (GimpContext *context)
2079 {
2080   g_return_if_fail (GIMP_IS_CONTEXT (context));
2081 
2082   g_signal_emit (context,
2083                  gimp_context_signals[TOOL_CHANGED], 0,
2084                  context->tool_info);
2085 }
2086 
2087 static void
gimp_context_tool_dirty(GimpToolInfo * tool_info,GimpContext * context)2088 gimp_context_tool_dirty (GimpToolInfo *tool_info,
2089                          GimpContext  *context)
2090 {
2091   g_free (context->tool_name);
2092   context->tool_name = g_strdup (gimp_object_get_name (tool_info));
2093 
2094   g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
2095                  GIMP_CONTEXT_PROP_TOOL);
2096 }
2097 
2098 static void
gimp_context_tool_list_thaw(GimpContainer * container,GimpContext * context)2099 gimp_context_tool_list_thaw (GimpContainer *container,
2100                              GimpContext   *context)
2101 {
2102   GimpToolInfo *tool_info;
2103 
2104   if (! context->tool_name)
2105     context->tool_name = g_strdup ("gimp-paintbrush-tool");
2106 
2107   tool_info = gimp_context_find_object (context, container,
2108                                         context->tool_name,
2109                                         gimp_tool_info_get_standard (context->gimp));
2110 
2111   gimp_context_real_set_tool (context, tool_info);
2112 }
2113 
2114 static void
gimp_context_tool_removed(GimpContainer * container,GimpToolInfo * tool_info,GimpContext * context)2115 gimp_context_tool_removed (GimpContainer *container,
2116                            GimpToolInfo  *tool_info,
2117                            GimpContext   *context)
2118 {
2119   if (tool_info == context->tool_info)
2120     {
2121       g_signal_handlers_disconnect_by_func (context->tool_info,
2122                                             gimp_context_tool_dirty,
2123                                             context);
2124       g_clear_object (&context->tool_info);
2125 
2126       if (! gimp_container_frozen (container))
2127         gimp_context_tool_list_thaw (container, context);
2128     }
2129 }
2130 
2131 static void
gimp_context_real_set_tool(GimpContext * context,GimpToolInfo * tool_info)2132 gimp_context_real_set_tool (GimpContext  *context,
2133                             GimpToolInfo *tool_info)
2134 {
2135   if (context->tool_info == tool_info)
2136     return;
2137 
2138   if (context->tool_name &&
2139       tool_info != gimp_tool_info_get_standard (context->gimp))
2140     {
2141       g_clear_pointer (&context->tool_name, g_free);
2142     }
2143 
2144   if (context->tool_info)
2145     g_signal_handlers_disconnect_by_func (context->tool_info,
2146                                           gimp_context_tool_dirty,
2147                                           context);
2148 
2149   g_set_object (&context->tool_info, tool_info);
2150 
2151   if (tool_info)
2152     {
2153       g_signal_connect_object (tool_info, "name-changed",
2154                                G_CALLBACK (gimp_context_tool_dirty),
2155                                context,
2156                                0);
2157 
2158       if (tool_info != gimp_tool_info_get_standard (context->gimp))
2159         context->tool_name = g_strdup (gimp_object_get_name (tool_info));
2160 
2161       if (tool_info->paint_info)
2162         gimp_context_real_set_paint_info (context, tool_info->paint_info);
2163     }
2164 
2165   g_object_notify (G_OBJECT (context), "tool");
2166   gimp_context_tool_changed (context);
2167 }
2168 
2169 
2170 /*****************************************************************************/
2171 /*  paint info  **************************************************************/
2172 
2173 GimpPaintInfo *
gimp_context_get_paint_info(GimpContext * context)2174 gimp_context_get_paint_info (GimpContext *context)
2175 {
2176   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
2177 
2178   return context->paint_info;
2179 }
2180 
2181 void
gimp_context_set_paint_info(GimpContext * context,GimpPaintInfo * paint_info)2182 gimp_context_set_paint_info (GimpContext   *context,
2183                              GimpPaintInfo *paint_info)
2184 {
2185   g_return_if_fail (GIMP_IS_CONTEXT (context));
2186   g_return_if_fail (paint_info == NULL || GIMP_IS_PAINT_INFO (paint_info));
2187 
2188   context_find_defined (context, GIMP_CONTEXT_PROP_PAINT_INFO);
2189 
2190   gimp_context_real_set_paint_info (context, paint_info);
2191 }
2192 
2193 void
gimp_context_paint_info_changed(GimpContext * context)2194 gimp_context_paint_info_changed (GimpContext *context)
2195 {
2196   g_return_if_fail (GIMP_IS_CONTEXT (context));
2197 
2198   g_signal_emit (context,
2199                  gimp_context_signals[PAINT_INFO_CHANGED], 0,
2200                  context->paint_info);
2201 }
2202 
2203 static void
gimp_context_paint_info_dirty(GimpPaintInfo * paint_info,GimpContext * context)2204 gimp_context_paint_info_dirty (GimpPaintInfo *paint_info,
2205                                GimpContext   *context)
2206 {
2207   g_free (context->paint_name);
2208   context->paint_name = g_strdup (gimp_object_get_name (paint_info));
2209 
2210   g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
2211                  GIMP_CONTEXT_PROP_PAINT_INFO);
2212 }
2213 
2214 /*  the global paint info list is there again after refresh  */
2215 static void
gimp_context_paint_info_list_thaw(GimpContainer * container,GimpContext * context)2216 gimp_context_paint_info_list_thaw (GimpContainer *container,
2217                                    GimpContext   *context)
2218 {
2219   GimpPaintInfo *paint_info;
2220 
2221   if (! context->paint_name)
2222     context->paint_name = g_strdup ("gimp-paintbrush");
2223 
2224   paint_info = gimp_context_find_object (context, container,
2225                                          context->paint_name,
2226                                          gimp_paint_info_get_standard (context->gimp));
2227 
2228   gimp_context_real_set_paint_info (context, paint_info);
2229 }
2230 
2231 static void
gimp_context_paint_info_removed(GimpContainer * container,GimpPaintInfo * paint_info,GimpContext * context)2232 gimp_context_paint_info_removed (GimpContainer *container,
2233                                  GimpPaintInfo *paint_info,
2234                                  GimpContext   *context)
2235 {
2236   if (paint_info == context->paint_info)
2237     {
2238       g_signal_handlers_disconnect_by_func (context->paint_info,
2239                                             gimp_context_paint_info_dirty,
2240                                             context);
2241       g_clear_object (&context->paint_info);
2242 
2243       if (! gimp_container_frozen (container))
2244         gimp_context_paint_info_list_thaw (container, context);
2245     }
2246 }
2247 
2248 static void
gimp_context_real_set_paint_info(GimpContext * context,GimpPaintInfo * paint_info)2249 gimp_context_real_set_paint_info (GimpContext   *context,
2250                                   GimpPaintInfo *paint_info)
2251 {
2252   if (context->paint_info == paint_info)
2253     return;
2254 
2255   if (context->paint_name &&
2256       paint_info != gimp_paint_info_get_standard (context->gimp))
2257     {
2258       g_clear_pointer (&context->paint_name, g_free);
2259     }
2260 
2261   if (context->paint_info)
2262     g_signal_handlers_disconnect_by_func (context->paint_info,
2263                                           gimp_context_paint_info_dirty,
2264                                           context);
2265 
2266   g_set_object (&context->paint_info, paint_info);
2267 
2268   if (paint_info)
2269     {
2270       g_signal_connect_object (paint_info, "name-changed",
2271                                G_CALLBACK (gimp_context_paint_info_dirty),
2272                                context,
2273                                0);
2274 
2275       if (paint_info != gimp_paint_info_get_standard (context->gimp))
2276         context->paint_name = g_strdup (gimp_object_get_name (paint_info));
2277     }
2278 
2279   g_object_notify (G_OBJECT (context), "paint-info");
2280   gimp_context_paint_info_changed (context);
2281 }
2282 
2283 
2284 /*****************************************************************************/
2285 /*  foreground color  ********************************************************/
2286 
2287 void
gimp_context_get_foreground(GimpContext * context,GimpRGB * color)2288 gimp_context_get_foreground (GimpContext *context,
2289                              GimpRGB     *color)
2290 {
2291   g_return_if_fail (GIMP_IS_CONTEXT (context));
2292   g_return_if_fail (color != NULL);
2293 
2294   *color = context->foreground;
2295 }
2296 
2297 void
gimp_context_set_foreground(GimpContext * context,const GimpRGB * color)2298 gimp_context_set_foreground (GimpContext   *context,
2299                              const GimpRGB *color)
2300 {
2301   g_return_if_fail (GIMP_IS_CONTEXT (context));
2302   g_return_if_fail (color != NULL);
2303 
2304   context_find_defined (context, GIMP_CONTEXT_PROP_FOREGROUND);
2305 
2306   gimp_context_real_set_foreground (context, color);
2307 }
2308 
2309 void
gimp_context_foreground_changed(GimpContext * context)2310 gimp_context_foreground_changed (GimpContext *context)
2311 {
2312   g_return_if_fail (GIMP_IS_CONTEXT (context));
2313 
2314   g_signal_emit (context,
2315                  gimp_context_signals[FOREGROUND_CHANGED], 0,
2316                  &context->foreground);
2317 }
2318 
2319 static void
gimp_context_real_set_foreground(GimpContext * context,const GimpRGB * color)2320 gimp_context_real_set_foreground (GimpContext   *context,
2321                                   const GimpRGB *color)
2322 {
2323   if (gimp_rgba_distance (&context->foreground, color) < RGBA_EPSILON)
2324     return;
2325 
2326   context->foreground = *color;
2327   gimp_rgb_set_alpha (&context->foreground, GIMP_OPACITY_OPAQUE);
2328 
2329   g_object_notify (G_OBJECT (context), "foreground");
2330   gimp_context_foreground_changed (context);
2331 }
2332 
2333 
2334 /*****************************************************************************/
2335 /*  background color  ********************************************************/
2336 
2337 void
gimp_context_get_background(GimpContext * context,GimpRGB * color)2338 gimp_context_get_background (GimpContext *context,
2339                              GimpRGB     *color)
2340 {
2341   g_return_if_fail (GIMP_IS_CONTEXT (context));
2342 
2343   g_return_if_fail (color != NULL);
2344 
2345   *color = context->background;
2346 }
2347 
2348 void
gimp_context_set_background(GimpContext * context,const GimpRGB * color)2349 gimp_context_set_background (GimpContext   *context,
2350                              const GimpRGB *color)
2351 {
2352   g_return_if_fail (GIMP_IS_CONTEXT (context));
2353   g_return_if_fail (color != NULL);
2354 
2355   context_find_defined (context, GIMP_CONTEXT_PROP_BACKGROUND);
2356 
2357   gimp_context_real_set_background (context, color);
2358 }
2359 
2360 void
gimp_context_background_changed(GimpContext * context)2361 gimp_context_background_changed (GimpContext *context)
2362 {
2363   g_return_if_fail (GIMP_IS_CONTEXT (context));
2364 
2365   g_signal_emit (context,
2366                  gimp_context_signals[BACKGROUND_CHANGED], 0,
2367                  &context->background);
2368 }
2369 
2370 static void
gimp_context_real_set_background(GimpContext * context,const GimpRGB * color)2371 gimp_context_real_set_background (GimpContext   *context,
2372                                   const GimpRGB *color)
2373 {
2374   if (gimp_rgba_distance (&context->background, color) < RGBA_EPSILON)
2375     return;
2376 
2377   context->background = *color;
2378   gimp_rgb_set_alpha (&context->background, GIMP_OPACITY_OPAQUE);
2379 
2380   g_object_notify (G_OBJECT (context), "background");
2381   gimp_context_background_changed (context);
2382 }
2383 
2384 
2385 /*****************************************************************************/
2386 /*  color utility functions  *************************************************/
2387 
2388 void
gimp_context_set_default_colors(GimpContext * context)2389 gimp_context_set_default_colors (GimpContext *context)
2390 {
2391   GimpContext *bg_context;
2392   GimpRGB      fg;
2393   GimpRGB      bg;
2394 
2395   g_return_if_fail (GIMP_IS_CONTEXT (context));
2396 
2397   bg_context = context;
2398 
2399   context_find_defined (context, GIMP_CONTEXT_PROP_FOREGROUND);
2400   context_find_defined (bg_context, GIMP_CONTEXT_PROP_BACKGROUND);
2401 
2402   gimp_rgba_set (&fg, 0.0, 0.0, 0.0, GIMP_OPACITY_OPAQUE);
2403   gimp_rgba_set (&bg, 1.0, 1.0, 1.0, GIMP_OPACITY_OPAQUE);
2404 
2405   gimp_context_real_set_foreground (context, &fg);
2406   gimp_context_real_set_background (bg_context, &bg);
2407 }
2408 
2409 void
gimp_context_swap_colors(GimpContext * context)2410 gimp_context_swap_colors (GimpContext *context)
2411 {
2412   GimpContext *bg_context;
2413   GimpRGB      fg;
2414   GimpRGB      bg;
2415 
2416   g_return_if_fail (GIMP_IS_CONTEXT (context));
2417 
2418   bg_context = context;
2419 
2420   context_find_defined (context, GIMP_CONTEXT_PROP_FOREGROUND);
2421   context_find_defined (bg_context, GIMP_CONTEXT_PROP_BACKGROUND);
2422 
2423   gimp_context_get_foreground (context, &fg);
2424   gimp_context_get_background (bg_context, &bg);
2425 
2426   gimp_context_real_set_foreground (context, &bg);
2427   gimp_context_real_set_background (bg_context, &fg);
2428 }
2429 
2430 
2431 /*****************************************************************************/
2432 /*  opacity  *****************************************************************/
2433 
2434 gdouble
gimp_context_get_opacity(GimpContext * context)2435 gimp_context_get_opacity (GimpContext *context)
2436 {
2437   g_return_val_if_fail (GIMP_IS_CONTEXT (context), GIMP_OPACITY_OPAQUE);
2438 
2439   return context->opacity;
2440 }
2441 
2442 void
gimp_context_set_opacity(GimpContext * context,gdouble opacity)2443 gimp_context_set_opacity (GimpContext *context,
2444                           gdouble      opacity)
2445 {
2446   g_return_if_fail (GIMP_IS_CONTEXT (context));
2447 
2448   context_find_defined (context, GIMP_CONTEXT_PROP_OPACITY);
2449 
2450   gimp_context_real_set_opacity (context, opacity);
2451 }
2452 
2453 void
gimp_context_opacity_changed(GimpContext * context)2454 gimp_context_opacity_changed (GimpContext *context)
2455 {
2456   g_return_if_fail (GIMP_IS_CONTEXT (context));
2457 
2458   g_signal_emit (context,
2459                  gimp_context_signals[OPACITY_CHANGED], 0,
2460                  context->opacity);
2461 }
2462 
2463 static void
gimp_context_real_set_opacity(GimpContext * context,gdouble opacity)2464 gimp_context_real_set_opacity (GimpContext *context,
2465                                gdouble      opacity)
2466 {
2467   if (context->opacity == opacity)
2468     return;
2469 
2470   context->opacity = opacity;
2471 
2472   g_object_notify (G_OBJECT (context), "opacity");
2473   gimp_context_opacity_changed (context);
2474 }
2475 
2476 
2477 /*****************************************************************************/
2478 /*  paint mode  **************************************************************/
2479 
2480 GimpLayerMode
gimp_context_get_paint_mode(GimpContext * context)2481 gimp_context_get_paint_mode (GimpContext *context)
2482 {
2483   g_return_val_if_fail (GIMP_IS_CONTEXT (context), GIMP_LAYER_MODE_NORMAL);
2484 
2485   return context->paint_mode;
2486 }
2487 
2488 void
gimp_context_set_paint_mode(GimpContext * context,GimpLayerMode paint_mode)2489 gimp_context_set_paint_mode (GimpContext   *context,
2490                              GimpLayerMode  paint_mode)
2491 {
2492   g_return_if_fail (GIMP_IS_CONTEXT (context));
2493 
2494   context_find_defined (context, GIMP_CONTEXT_PROP_PAINT_MODE);
2495 
2496   gimp_context_real_set_paint_mode (context, paint_mode);
2497 }
2498 
2499 void
gimp_context_paint_mode_changed(GimpContext * context)2500 gimp_context_paint_mode_changed (GimpContext *context)
2501 {
2502   g_return_if_fail (GIMP_IS_CONTEXT (context));
2503 
2504   g_signal_emit (context,
2505                  gimp_context_signals[PAINT_MODE_CHANGED], 0,
2506                  context->paint_mode);
2507 }
2508 
2509 static void
gimp_context_real_set_paint_mode(GimpContext * context,GimpLayerMode paint_mode)2510 gimp_context_real_set_paint_mode (GimpContext   *context,
2511                                   GimpLayerMode  paint_mode)
2512 {
2513   if (context->paint_mode == paint_mode)
2514     return;
2515 
2516   context->paint_mode = paint_mode;
2517 
2518   g_object_notify (G_OBJECT (context), "paint-mode");
2519   gimp_context_paint_mode_changed (context);
2520 }
2521 
2522 
2523 /*****************************************************************************/
2524 /*  brush  *******************************************************************/
2525 
2526 GimpBrush *
gimp_context_get_brush(GimpContext * context)2527 gimp_context_get_brush (GimpContext *context)
2528 {
2529   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
2530 
2531   return context->brush;
2532 }
2533 
2534 void
gimp_context_set_brush(GimpContext * context,GimpBrush * brush)2535 gimp_context_set_brush (GimpContext *context,
2536                         GimpBrush   *brush)
2537 {
2538   g_return_if_fail (GIMP_IS_CONTEXT (context));
2539   g_return_if_fail (brush == NULL || GIMP_IS_BRUSH (brush));
2540 
2541   context_find_defined (context, GIMP_CONTEXT_PROP_BRUSH);
2542 
2543   gimp_context_real_set_brush (context, brush);
2544 }
2545 
2546 void
gimp_context_brush_changed(GimpContext * context)2547 gimp_context_brush_changed (GimpContext *context)
2548 {
2549   g_return_if_fail (GIMP_IS_CONTEXT (context));
2550 
2551   g_signal_emit (context,
2552                  gimp_context_signals[BRUSH_CHANGED], 0,
2553                  context->brush);
2554 }
2555 
2556 static void
gimp_context_brush_dirty(GimpBrush * brush,GimpContext * context)2557 gimp_context_brush_dirty (GimpBrush   *brush,
2558                           GimpContext *context)
2559 {
2560   g_free (context->brush_name);
2561   context->brush_name = g_strdup (gimp_object_get_name (brush));
2562 
2563   g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
2564                  GIMP_CONTEXT_PROP_BRUSH);
2565 }
2566 
2567 static void
gimp_context_brush_list_thaw(GimpContainer * container,GimpContext * context)2568 gimp_context_brush_list_thaw (GimpContainer *container,
2569                               GimpContext   *context)
2570 {
2571   GimpBrush *brush;
2572 
2573   if (! context->brush_name)
2574     context->brush_name = g_strdup (context->gimp->config->default_brush);
2575 
2576   brush = gimp_context_find_object (context, container,
2577                                     context->brush_name,
2578                                     gimp_brush_get_standard (context));
2579 
2580   gimp_context_real_set_brush (context, brush);
2581 }
2582 
2583 /*  the active brush disappeared  */
2584 static void
gimp_context_brush_removed(GimpContainer * container,GimpBrush * brush,GimpContext * context)2585 gimp_context_brush_removed (GimpContainer *container,
2586                             GimpBrush     *brush,
2587                             GimpContext   *context)
2588 {
2589   if (brush == context->brush)
2590     {
2591       g_signal_handlers_disconnect_by_func (context->brush,
2592                                             gimp_context_brush_dirty,
2593                                             context);
2594       g_clear_object (&context->brush);
2595 
2596       if (! gimp_container_frozen (container))
2597         gimp_context_brush_list_thaw (container, context);
2598     }
2599 }
2600 
2601 static void
gimp_context_real_set_brush(GimpContext * context,GimpBrush * brush)2602 gimp_context_real_set_brush (GimpContext *context,
2603                              GimpBrush   *brush)
2604 {
2605   if (context->brush == brush)
2606     return;
2607 
2608   if (context->brush_name &&
2609       brush != GIMP_BRUSH (gimp_brush_get_standard (context)))
2610     {
2611       g_clear_pointer (&context->brush_name, g_free);
2612     }
2613 
2614   if (context->brush)
2615     g_signal_handlers_disconnect_by_func (context->brush,
2616                                           gimp_context_brush_dirty,
2617                                           context);
2618 
2619   g_set_object (&context->brush, brush);
2620 
2621   if (brush)
2622     {
2623       g_signal_connect_object (brush, "name-changed",
2624                                G_CALLBACK (gimp_context_brush_dirty),
2625                                context,
2626                                0);
2627 
2628       if (brush != GIMP_BRUSH (gimp_brush_get_standard (context)))
2629         context->brush_name = g_strdup (gimp_object_get_name (brush));
2630     }
2631 
2632   g_object_notify (G_OBJECT (context), "brush");
2633   gimp_context_brush_changed (context);
2634 }
2635 
2636 
2637 /*****************************************************************************/
2638 /*  dynamics *****************************************************************/
2639 
2640 GimpDynamics *
gimp_context_get_dynamics(GimpContext * context)2641 gimp_context_get_dynamics (GimpContext *context)
2642 {
2643   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
2644 
2645   return context->dynamics;
2646 }
2647 
2648 void
gimp_context_set_dynamics(GimpContext * context,GimpDynamics * dynamics)2649 gimp_context_set_dynamics (GimpContext  *context,
2650                            GimpDynamics *dynamics)
2651 {
2652   g_return_if_fail (GIMP_IS_CONTEXT (context));
2653   g_return_if_fail (dynamics == NULL || GIMP_IS_DYNAMICS (dynamics));
2654 
2655   context_find_defined (context, GIMP_CONTEXT_PROP_DYNAMICS);
2656 
2657   gimp_context_real_set_dynamics (context, dynamics);
2658 }
2659 
2660 void
gimp_context_dynamics_changed(GimpContext * context)2661 gimp_context_dynamics_changed (GimpContext *context)
2662 {
2663   g_return_if_fail (GIMP_IS_CONTEXT (context));
2664 
2665   g_signal_emit (context,
2666                  gimp_context_signals[DYNAMICS_CHANGED], 0,
2667                  context->dynamics);
2668 }
2669 
2670 static void
gimp_context_dynamics_dirty(GimpDynamics * dynamics,GimpContext * context)2671 gimp_context_dynamics_dirty (GimpDynamics *dynamics,
2672                              GimpContext  *context)
2673 {
2674   g_free (context->dynamics_name);
2675   context->dynamics_name = g_strdup (gimp_object_get_name (dynamics));
2676 
2677   g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
2678                  GIMP_CONTEXT_PROP_DYNAMICS);
2679 }
2680 
2681 static void
gimp_context_dynamics_removed(GimpContainer * container,GimpDynamics * dynamics,GimpContext * context)2682 gimp_context_dynamics_removed (GimpContainer *container,
2683                                GimpDynamics  *dynamics,
2684                                GimpContext   *context)
2685 {
2686   if (dynamics == context->dynamics)
2687     {
2688       g_signal_handlers_disconnect_by_func (context->dynamics,
2689                                             gimp_context_dynamics_dirty,
2690                                             context);
2691       g_clear_object (&context->dynamics);
2692 
2693       if (! gimp_container_frozen (container))
2694         gimp_context_dynamics_list_thaw (container, context);
2695     }
2696 }
2697 
2698 static void
gimp_context_dynamics_list_thaw(GimpContainer * container,GimpContext * context)2699 gimp_context_dynamics_list_thaw (GimpContainer *container,
2700                                  GimpContext   *context)
2701 {
2702   GimpDynamics *dynamics;
2703 
2704   if (! context->dynamics_name)
2705     context->dynamics_name = g_strdup (context->gimp->config->default_dynamics);
2706 
2707   dynamics = gimp_context_find_object (context, container,
2708                                        context->dynamics_name,
2709                                        gimp_dynamics_get_standard (context));
2710 
2711   gimp_context_real_set_dynamics (context, dynamics);
2712 }
2713 
2714 static void
gimp_context_real_set_dynamics(GimpContext * context,GimpDynamics * dynamics)2715 gimp_context_real_set_dynamics (GimpContext  *context,
2716                                 GimpDynamics *dynamics)
2717 {
2718   if (context->dynamics == dynamics)
2719     return;
2720 
2721   if (context->dynamics_name &&
2722       dynamics != GIMP_DYNAMICS (gimp_dynamics_get_standard (context)))
2723     {
2724       g_clear_pointer (&context->dynamics_name, g_free);
2725     }
2726 
2727   if (context->dynamics)
2728     g_signal_handlers_disconnect_by_func (context->dynamics,
2729                                           gimp_context_dynamics_dirty,
2730                                           context);
2731 
2732   g_set_object (&context->dynamics, dynamics);
2733 
2734   if (dynamics)
2735     {
2736       g_signal_connect_object (dynamics, "name-changed",
2737                                G_CALLBACK (gimp_context_dynamics_dirty),
2738                                context,
2739                                0);
2740 
2741       if (dynamics != GIMP_DYNAMICS (gimp_dynamics_get_standard (context)))
2742         context->dynamics_name = g_strdup (gimp_object_get_name (dynamics));
2743     }
2744 
2745   g_object_notify (G_OBJECT (context), "dynamics");
2746   gimp_context_dynamics_changed (context);
2747 }
2748 
2749 
2750 /*****************************************************************************/
2751 /*  mybrush  *****************************************************************/
2752 
2753 GimpMybrush *
gimp_context_get_mybrush(GimpContext * context)2754 gimp_context_get_mybrush (GimpContext *context)
2755 {
2756   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
2757 
2758   return context->mybrush;
2759 }
2760 
2761 void
gimp_context_set_mybrush(GimpContext * context,GimpMybrush * brush)2762 gimp_context_set_mybrush (GimpContext *context,
2763                           GimpMybrush *brush)
2764 {
2765   g_return_if_fail (GIMP_IS_CONTEXT (context));
2766   g_return_if_fail (brush == NULL || GIMP_IS_MYBRUSH (brush));
2767 
2768   context_find_defined (context, GIMP_CONTEXT_PROP_MYBRUSH);
2769 
2770   gimp_context_real_set_mybrush (context, brush);
2771 }
2772 
2773 void
gimp_context_mybrush_changed(GimpContext * context)2774 gimp_context_mybrush_changed (GimpContext *context)
2775 {
2776   g_return_if_fail (GIMP_IS_CONTEXT (context));
2777 
2778   g_signal_emit (context,
2779                  gimp_context_signals[MYBRUSH_CHANGED], 0,
2780                  context->mybrush);
2781 }
2782 
2783 static void
gimp_context_mybrush_dirty(GimpMybrush * brush,GimpContext * context)2784 gimp_context_mybrush_dirty (GimpMybrush *brush,
2785                             GimpContext *context)
2786 {
2787   g_free (context->mybrush_name);
2788   context->mybrush_name = g_strdup (gimp_object_get_name (brush));
2789 
2790   g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
2791                  GIMP_CONTEXT_PROP_MYBRUSH);
2792 }
2793 
2794 static void
gimp_context_mybrush_list_thaw(GimpContainer * container,GimpContext * context)2795 gimp_context_mybrush_list_thaw (GimpContainer *container,
2796                                 GimpContext   *context)
2797 {
2798   GimpMybrush *brush;
2799 
2800   if (! context->mybrush_name)
2801     context->mybrush_name = g_strdup (context->gimp->config->default_mypaint_brush);
2802 
2803   brush = gimp_context_find_object (context, container,
2804                                     context->mybrush_name,
2805                                     gimp_mybrush_get_standard (context));
2806 
2807   gimp_context_real_set_mybrush (context, brush);
2808 }
2809 
2810 static void
gimp_context_mybrush_removed(GimpContainer * container,GimpMybrush * brush,GimpContext * context)2811 gimp_context_mybrush_removed (GimpContainer *container,
2812                               GimpMybrush   *brush,
2813                               GimpContext   *context)
2814 {
2815   if (brush == context->mybrush)
2816     {
2817       g_signal_handlers_disconnect_by_func (context->mybrush,
2818                                             gimp_context_mybrush_dirty,
2819                                             context);
2820       g_clear_object (&context->mybrush);
2821 
2822       if (! gimp_container_frozen (container))
2823         gimp_context_mybrush_list_thaw (container, context);
2824     }
2825 }
2826 
2827 static void
gimp_context_real_set_mybrush(GimpContext * context,GimpMybrush * brush)2828 gimp_context_real_set_mybrush (GimpContext *context,
2829                                GimpMybrush *brush)
2830 {
2831   if (context->mybrush == brush)
2832     return;
2833 
2834   if (context->mybrush_name &&
2835       brush != GIMP_MYBRUSH (gimp_mybrush_get_standard (context)))
2836     {
2837       g_clear_pointer (&context->mybrush_name, g_free);
2838     }
2839 
2840   if (context->mybrush)
2841     g_signal_handlers_disconnect_by_func (context->mybrush,
2842                                           gimp_context_mybrush_dirty,
2843                                           context);
2844 
2845   g_set_object (&context->mybrush, brush);
2846 
2847   if (brush)
2848     {
2849       g_signal_connect_object (brush, "name-changed",
2850                                G_CALLBACK (gimp_context_mybrush_dirty),
2851                                context,
2852                                0);
2853 
2854       if (brush != GIMP_MYBRUSH (gimp_mybrush_get_standard (context)))
2855         context->mybrush_name = g_strdup (gimp_object_get_name (brush));
2856     }
2857 
2858   g_object_notify (G_OBJECT (context), "mybrush");
2859   gimp_context_mybrush_changed (context);
2860 }
2861 
2862 
2863 /*****************************************************************************/
2864 /*  pattern  *****************************************************************/
2865 
2866 GimpPattern *
gimp_context_get_pattern(GimpContext * context)2867 gimp_context_get_pattern (GimpContext *context)
2868 {
2869   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
2870 
2871   return context->pattern;
2872 }
2873 
2874 void
gimp_context_set_pattern(GimpContext * context,GimpPattern * pattern)2875 gimp_context_set_pattern (GimpContext *context,
2876                           GimpPattern *pattern)
2877 {
2878   g_return_if_fail (GIMP_IS_CONTEXT (context));
2879   g_return_if_fail (pattern == NULL || GIMP_IS_PATTERN (pattern));
2880 
2881   context_find_defined (context, GIMP_CONTEXT_PROP_PATTERN);
2882 
2883   gimp_context_real_set_pattern (context, pattern);
2884 }
2885 
2886 void
gimp_context_pattern_changed(GimpContext * context)2887 gimp_context_pattern_changed (GimpContext *context)
2888 {
2889   g_return_if_fail (GIMP_IS_CONTEXT (context));
2890 
2891   g_signal_emit (context,
2892                  gimp_context_signals[PATTERN_CHANGED], 0,
2893                  context->pattern);
2894 }
2895 
2896 static void
gimp_context_pattern_dirty(GimpPattern * pattern,GimpContext * context)2897 gimp_context_pattern_dirty (GimpPattern *pattern,
2898                             GimpContext *context)
2899 {
2900   g_free (context->pattern_name);
2901   context->pattern_name = g_strdup (gimp_object_get_name (pattern));
2902 
2903   g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
2904                  GIMP_CONTEXT_PROP_PATTERN);
2905 }
2906 
2907 static void
gimp_context_pattern_list_thaw(GimpContainer * container,GimpContext * context)2908 gimp_context_pattern_list_thaw (GimpContainer *container,
2909                                 GimpContext   *context)
2910 {
2911   GimpPattern *pattern;
2912 
2913   if (! context->pattern_name)
2914     context->pattern_name = g_strdup (context->gimp->config->default_pattern);
2915 
2916   pattern = gimp_context_find_object (context, container,
2917                                       context->pattern_name,
2918                                       gimp_pattern_get_standard (context));
2919 
2920   gimp_context_real_set_pattern (context, pattern);
2921 }
2922 
2923 static void
gimp_context_pattern_removed(GimpContainer * container,GimpPattern * pattern,GimpContext * context)2924 gimp_context_pattern_removed (GimpContainer *container,
2925                               GimpPattern   *pattern,
2926                               GimpContext   *context)
2927 {
2928   if (pattern == context->pattern)
2929     {
2930       g_signal_handlers_disconnect_by_func (context->pattern,
2931                                             gimp_context_pattern_dirty,
2932                                             context);
2933       g_clear_object (&context->pattern);
2934 
2935       if (! gimp_container_frozen (container))
2936         gimp_context_pattern_list_thaw (container, context);
2937     }
2938 }
2939 
2940 static void
gimp_context_real_set_pattern(GimpContext * context,GimpPattern * pattern)2941 gimp_context_real_set_pattern (GimpContext *context,
2942                                GimpPattern *pattern)
2943 {
2944   if (context->pattern == pattern)
2945     return;
2946 
2947   if (context->pattern_name &&
2948       pattern != GIMP_PATTERN (gimp_pattern_get_standard (context)))
2949     {
2950       g_clear_pointer (&context->pattern_name, g_free);
2951     }
2952 
2953   if (context->pattern)
2954     g_signal_handlers_disconnect_by_func (context->pattern,
2955                                           gimp_context_pattern_dirty,
2956                                           context);
2957 
2958   g_set_object (&context->pattern, pattern);
2959 
2960   if (pattern)
2961     {
2962       g_signal_connect_object (pattern, "name-changed",
2963                                G_CALLBACK (gimp_context_pattern_dirty),
2964                                context,
2965                                0);
2966 
2967       if (pattern != GIMP_PATTERN (gimp_pattern_get_standard (context)))
2968         context->pattern_name = g_strdup (gimp_object_get_name (pattern));
2969     }
2970 
2971   g_object_notify (G_OBJECT (context), "pattern");
2972   gimp_context_pattern_changed (context);
2973 }
2974 
2975 
2976 /*****************************************************************************/
2977 /*  gradient  ****************************************************************/
2978 
2979 GimpGradient *
gimp_context_get_gradient(GimpContext * context)2980 gimp_context_get_gradient (GimpContext *context)
2981 {
2982   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
2983 
2984   return context->gradient;
2985 }
2986 
2987 void
gimp_context_set_gradient(GimpContext * context,GimpGradient * gradient)2988 gimp_context_set_gradient (GimpContext  *context,
2989                            GimpGradient *gradient)
2990 {
2991   g_return_if_fail (GIMP_IS_CONTEXT (context));
2992   g_return_if_fail (gradient == NULL || GIMP_IS_GRADIENT (gradient));
2993 
2994   context_find_defined (context, GIMP_CONTEXT_PROP_GRADIENT);
2995 
2996   gimp_context_real_set_gradient (context, gradient);
2997 }
2998 
2999 void
gimp_context_gradient_changed(GimpContext * context)3000 gimp_context_gradient_changed (GimpContext *context)
3001 {
3002   g_return_if_fail (GIMP_IS_CONTEXT (context));
3003 
3004   g_signal_emit (context,
3005                  gimp_context_signals[GRADIENT_CHANGED], 0,
3006                  context->gradient);
3007 }
3008 
3009 static void
gimp_context_gradient_dirty(GimpGradient * gradient,GimpContext * context)3010 gimp_context_gradient_dirty (GimpGradient *gradient,
3011                              GimpContext  *context)
3012 {
3013   g_free (context->gradient_name);
3014   context->gradient_name = g_strdup (gimp_object_get_name (gradient));
3015 
3016   g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
3017                  GIMP_CONTEXT_PROP_GRADIENT);
3018 }
3019 
3020 static void
gimp_context_gradient_list_thaw(GimpContainer * container,GimpContext * context)3021 gimp_context_gradient_list_thaw (GimpContainer *container,
3022                                  GimpContext   *context)
3023 {
3024   GimpGradient *gradient;
3025 
3026   if (! context->gradient_name)
3027     context->gradient_name = g_strdup (context->gimp->config->default_gradient);
3028 
3029   gradient = gimp_context_find_object (context, container,
3030                                        context->gradient_name,
3031                                        gimp_gradient_get_standard (context));
3032 
3033   gimp_context_real_set_gradient (context, gradient);
3034 }
3035 
3036 static void
gimp_context_gradient_removed(GimpContainer * container,GimpGradient * gradient,GimpContext * context)3037 gimp_context_gradient_removed (GimpContainer *container,
3038                                GimpGradient  *gradient,
3039                                GimpContext   *context)
3040 {
3041   if (gradient == context->gradient)
3042     {
3043       g_signal_handlers_disconnect_by_func (context->gradient,
3044                                             gimp_context_gradient_dirty,
3045                                             context);
3046       g_clear_object (&context->gradient);
3047 
3048       if (! gimp_container_frozen (container))
3049         gimp_context_gradient_list_thaw (container, context);
3050     }
3051 }
3052 
3053 static void
gimp_context_real_set_gradient(GimpContext * context,GimpGradient * gradient)3054 gimp_context_real_set_gradient (GimpContext  *context,
3055                                 GimpGradient *gradient)
3056 {
3057   if (context->gradient == gradient)
3058     return;
3059 
3060   if (context->gradient_name &&
3061       gradient != GIMP_GRADIENT (gimp_gradient_get_standard (context)))
3062     {
3063       g_clear_pointer (&context->gradient_name, g_free);
3064     }
3065 
3066   if (context->gradient)
3067     g_signal_handlers_disconnect_by_func (context->gradient,
3068                                           gimp_context_gradient_dirty,
3069                                           context);
3070 
3071   g_set_object (&context->gradient, gradient);
3072 
3073   if (gradient)
3074     {
3075       g_signal_connect_object (gradient, "name-changed",
3076                                G_CALLBACK (gimp_context_gradient_dirty),
3077                                context,
3078                                0);
3079 
3080       if (gradient != GIMP_GRADIENT (gimp_gradient_get_standard (context)))
3081         context->gradient_name = g_strdup (gimp_object_get_name (gradient));
3082     }
3083 
3084   g_object_notify (G_OBJECT (context), "gradient");
3085   gimp_context_gradient_changed (context);
3086 }
3087 
3088 
3089 /*****************************************************************************/
3090 /*  palette  *****************************************************************/
3091 
3092 GimpPalette *
gimp_context_get_palette(GimpContext * context)3093 gimp_context_get_palette (GimpContext *context)
3094 {
3095   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
3096 
3097   return context->palette;
3098 }
3099 
3100 void
gimp_context_set_palette(GimpContext * context,GimpPalette * palette)3101 gimp_context_set_palette (GimpContext *context,
3102                           GimpPalette *palette)
3103 {
3104   g_return_if_fail (GIMP_IS_CONTEXT (context));
3105   g_return_if_fail (palette == NULL || GIMP_IS_PALETTE (palette));
3106 
3107   context_find_defined (context, GIMP_CONTEXT_PROP_PALETTE);
3108 
3109   gimp_context_real_set_palette (context, palette);
3110 }
3111 
3112 void
gimp_context_palette_changed(GimpContext * context)3113 gimp_context_palette_changed (GimpContext *context)
3114 {
3115   g_return_if_fail (GIMP_IS_CONTEXT (context));
3116 
3117   g_signal_emit (context,
3118                  gimp_context_signals[PALETTE_CHANGED], 0,
3119                  context->palette);
3120 }
3121 
3122 static void
gimp_context_palette_dirty(GimpPalette * palette,GimpContext * context)3123 gimp_context_palette_dirty (GimpPalette *palette,
3124                             GimpContext *context)
3125 {
3126   g_free (context->palette_name);
3127   context->palette_name = g_strdup (gimp_object_get_name (palette));
3128 
3129   g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
3130                  GIMP_CONTEXT_PROP_PALETTE);
3131 }
3132 
3133 static void
gimp_context_palette_list_thaw(GimpContainer * container,GimpContext * context)3134 gimp_context_palette_list_thaw (GimpContainer *container,
3135                                 GimpContext   *context)
3136 {
3137   GimpPalette *palette;
3138 
3139   if (! context->palette_name)
3140     context->palette_name = g_strdup (context->gimp->config->default_palette);
3141 
3142   palette = gimp_context_find_object (context, container,
3143                                       context->palette_name,
3144                                       gimp_palette_get_standard (context));
3145 
3146   gimp_context_real_set_palette (context, palette);
3147 }
3148 
3149 static void
gimp_context_palette_removed(GimpContainer * container,GimpPalette * palette,GimpContext * context)3150 gimp_context_palette_removed (GimpContainer *container,
3151                               GimpPalette   *palette,
3152                               GimpContext   *context)
3153 {
3154   if (palette == context->palette)
3155     {
3156       g_signal_handlers_disconnect_by_func (context->palette,
3157                                             gimp_context_palette_dirty,
3158                                             context);
3159       g_clear_object (&context->palette);
3160 
3161       if (! gimp_container_frozen (container))
3162         gimp_context_palette_list_thaw (container, context);
3163     }
3164 }
3165 
3166 static void
gimp_context_real_set_palette(GimpContext * context,GimpPalette * palette)3167 gimp_context_real_set_palette (GimpContext *context,
3168                                GimpPalette *palette)
3169 {
3170   if (context->palette == palette)
3171     return;
3172 
3173   if (context->palette_name &&
3174       palette != GIMP_PALETTE (gimp_palette_get_standard (context)))
3175     {
3176       g_clear_pointer (&context->palette_name, g_free);
3177     }
3178 
3179   if (context->palette)
3180     g_signal_handlers_disconnect_by_func (context->palette,
3181                                           gimp_context_palette_dirty,
3182                                           context);
3183 
3184   g_set_object (&context->palette, palette);
3185 
3186   if (palette)
3187     {
3188       g_signal_connect_object (palette, "name-changed",
3189                                G_CALLBACK (gimp_context_palette_dirty),
3190                                context,
3191                                0);
3192 
3193       if (palette != GIMP_PALETTE (gimp_palette_get_standard (context)))
3194         context->palette_name = g_strdup (gimp_object_get_name (palette));
3195     }
3196 
3197   g_object_notify (G_OBJECT (context), "palette");
3198   gimp_context_palette_changed (context);
3199 }
3200 
3201 
3202 /*****************************************************************************/
3203 /*  font     *****************************************************************/
3204 
3205 GimpFont *
gimp_context_get_font(GimpContext * context)3206 gimp_context_get_font (GimpContext *context)
3207 {
3208   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
3209 
3210   return context->font;
3211 }
3212 
3213 void
gimp_context_set_font(GimpContext * context,GimpFont * font)3214 gimp_context_set_font (GimpContext *context,
3215                        GimpFont    *font)
3216 {
3217   g_return_if_fail (GIMP_IS_CONTEXT (context));
3218   g_return_if_fail (font == NULL || GIMP_IS_FONT (font));
3219 
3220   context_find_defined (context, GIMP_CONTEXT_PROP_FONT);
3221 
3222   gimp_context_real_set_font (context, font);
3223 }
3224 
3225 const gchar *
gimp_context_get_font_name(GimpContext * context)3226 gimp_context_get_font_name (GimpContext *context)
3227 {
3228   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
3229 
3230   return context->font_name;
3231 }
3232 
3233 void
gimp_context_set_font_name(GimpContext * context,const gchar * name)3234 gimp_context_set_font_name (GimpContext *context,
3235                             const gchar *name)
3236 {
3237   GimpContainer *container;
3238   GimpObject    *font;
3239 
3240   g_return_if_fail (GIMP_IS_CONTEXT (context));
3241 
3242   container = gimp_data_factory_get_container (context->gimp->font_factory);
3243   font      = gimp_container_get_child_by_name (container, name);
3244 
3245   if (font)
3246     {
3247       gimp_context_set_font (context, GIMP_FONT (font));
3248     }
3249   else
3250     {
3251       /* No font with this name exists, use the standard font, but
3252        * keep the intended name around
3253        */
3254       gimp_context_set_font (context, GIMP_FONT (gimp_font_get_standard ()));
3255 
3256       g_free (context->font_name);
3257       context->font_name = g_strdup (name);
3258     }
3259 }
3260 
3261 void
gimp_context_font_changed(GimpContext * context)3262 gimp_context_font_changed (GimpContext *context)
3263 {
3264   g_return_if_fail (GIMP_IS_CONTEXT (context));
3265 
3266   g_signal_emit (context,
3267                  gimp_context_signals[FONT_CHANGED], 0,
3268                  context->font);
3269 }
3270 
3271 static void
gimp_context_font_dirty(GimpFont * font,GimpContext * context)3272 gimp_context_font_dirty (GimpFont    *font,
3273                          GimpContext *context)
3274 {
3275   g_free (context->font_name);
3276   context->font_name = g_strdup (gimp_object_get_name (font));
3277 
3278   g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
3279                  GIMP_CONTEXT_PROP_FONT);
3280 }
3281 
3282 static void
gimp_context_font_list_thaw(GimpContainer * container,GimpContext * context)3283 gimp_context_font_list_thaw (GimpContainer *container,
3284                              GimpContext   *context)
3285 {
3286   GimpFont *font;
3287 
3288   if (! context->font_name)
3289     context->font_name = g_strdup (context->gimp->config->default_font);
3290 
3291   font = gimp_context_find_object (context, container,
3292                                    context->font_name,
3293                                    gimp_font_get_standard ());
3294 
3295   gimp_context_real_set_font (context, font);
3296 }
3297 
3298 static void
gimp_context_font_removed(GimpContainer * container,GimpFont * font,GimpContext * context)3299 gimp_context_font_removed (GimpContainer *container,
3300                            GimpFont      *font,
3301                            GimpContext   *context)
3302 {
3303   if (font == context->font)
3304     {
3305       g_signal_handlers_disconnect_by_func (context->font,
3306                                             gimp_context_font_dirty,
3307                                             context);
3308       g_clear_object (&context->font);
3309 
3310       if (! gimp_container_frozen (container))
3311         gimp_context_font_list_thaw (container, context);
3312     }
3313 }
3314 
3315 static void
gimp_context_real_set_font(GimpContext * context,GimpFont * font)3316 gimp_context_real_set_font (GimpContext *context,
3317                             GimpFont    *font)
3318 {
3319   if (context->font == font)
3320     return;
3321 
3322   if (context->font_name &&
3323       font != GIMP_FONT (gimp_font_get_standard ()))
3324     {
3325       g_clear_pointer (&context->font_name, g_free);
3326     }
3327 
3328   if (context->font)
3329     g_signal_handlers_disconnect_by_func (context->font,
3330                                           gimp_context_font_dirty,
3331                                           context);
3332 
3333   g_set_object (&context->font, font);
3334 
3335   if (font)
3336     {
3337       g_signal_connect_object (font, "name-changed",
3338                                G_CALLBACK (gimp_context_font_dirty),
3339                                context,
3340                                0);
3341 
3342       if (font != GIMP_FONT (gimp_font_get_standard ()))
3343         context->font_name = g_strdup (gimp_object_get_name (font));
3344     }
3345 
3346   g_object_notify (G_OBJECT (context), "font");
3347   gimp_context_font_changed (context);
3348 }
3349 
3350 
3351 /********************************************************************************/
3352 /*  tool preset *****************************************************************/
3353 
3354 GimpToolPreset *
gimp_context_get_tool_preset(GimpContext * context)3355 gimp_context_get_tool_preset (GimpContext *context)
3356 {
3357   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
3358 
3359   return context->tool_preset;
3360 }
3361 
3362 void
gimp_context_set_tool_preset(GimpContext * context,GimpToolPreset * tool_preset)3363 gimp_context_set_tool_preset (GimpContext    *context,
3364                               GimpToolPreset *tool_preset)
3365 {
3366   g_return_if_fail (GIMP_IS_CONTEXT (context));
3367   g_return_if_fail (tool_preset == NULL || GIMP_IS_TOOL_PRESET (tool_preset));
3368 
3369   context_find_defined (context, GIMP_CONTEXT_PROP_TOOL_PRESET);
3370 
3371   gimp_context_real_set_tool_preset (context, tool_preset);
3372 }
3373 
3374 void
gimp_context_tool_preset_changed(GimpContext * context)3375 gimp_context_tool_preset_changed (GimpContext *context)
3376 {
3377   g_return_if_fail (GIMP_IS_CONTEXT (context));
3378 
3379   g_signal_emit (context,
3380                  gimp_context_signals[TOOL_PRESET_CHANGED], 0,
3381                  context->tool_preset);
3382 }
3383 
3384 static void
gimp_context_tool_preset_dirty(GimpToolPreset * tool_preset,GimpContext * context)3385 gimp_context_tool_preset_dirty (GimpToolPreset *tool_preset,
3386                                 GimpContext    *context)
3387 {
3388   g_free (context->tool_preset_name);
3389   context->tool_preset_name = g_strdup (gimp_object_get_name (tool_preset));
3390 
3391   g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
3392                  GIMP_CONTEXT_PROP_TOOL_PRESET);
3393 }
3394 
3395 static void
gimp_context_tool_preset_removed(GimpContainer * container,GimpToolPreset * tool_preset,GimpContext * context)3396 gimp_context_tool_preset_removed (GimpContainer  *container,
3397                                   GimpToolPreset *tool_preset,
3398                                   GimpContext    *context)
3399 {
3400   if (tool_preset == context->tool_preset)
3401     {
3402       g_signal_handlers_disconnect_by_func (context->tool_preset,
3403                                             gimp_context_tool_preset_dirty,
3404                                             context);
3405       g_clear_object (&context->tool_preset);
3406 
3407       if (! gimp_container_frozen (container))
3408         gimp_context_tool_preset_list_thaw (container, context);
3409     }
3410 }
3411 
3412 static void
gimp_context_tool_preset_list_thaw(GimpContainer * container,GimpContext * context)3413 gimp_context_tool_preset_list_thaw (GimpContainer *container,
3414                                     GimpContext   *context)
3415 {
3416   GimpToolPreset *tool_preset;
3417 
3418   tool_preset = gimp_context_find_object (context, container,
3419                                           context->tool_preset_name,
3420                                           NULL);
3421 
3422   gimp_context_real_set_tool_preset (context, tool_preset);
3423 }
3424 
3425 static void
gimp_context_real_set_tool_preset(GimpContext * context,GimpToolPreset * tool_preset)3426 gimp_context_real_set_tool_preset (GimpContext    *context,
3427                                    GimpToolPreset *tool_preset)
3428 {
3429   if (context->tool_preset == tool_preset)
3430     return;
3431 
3432   if (context->tool_preset_name)
3433     {
3434       g_clear_pointer (&context->tool_preset_name, g_free);
3435     }
3436 
3437   if (context->tool_preset)
3438     g_signal_handlers_disconnect_by_func (context->tool_preset,
3439                                           gimp_context_tool_preset_dirty,
3440                                           context);
3441 
3442   g_set_object (&context->tool_preset, tool_preset);
3443 
3444   if (tool_preset)
3445     {
3446       g_signal_connect_object (tool_preset, "name-changed",
3447                                G_CALLBACK (gimp_context_tool_preset_dirty),
3448                                context,
3449                                0);
3450 
3451       context->tool_preset_name = g_strdup (gimp_object_get_name (tool_preset));
3452     }
3453 
3454   g_object_notify (G_OBJECT (context), "tool-preset");
3455   gimp_context_tool_preset_changed (context);
3456 }
3457 
3458 
3459 /*****************************************************************************/
3460 /*  buffer  ******************************************************************/
3461 
3462 GimpBuffer *
gimp_context_get_buffer(GimpContext * context)3463 gimp_context_get_buffer (GimpContext *context)
3464 {
3465   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
3466 
3467   return context->buffer;
3468 }
3469 
3470 void
gimp_context_set_buffer(GimpContext * context,GimpBuffer * buffer)3471 gimp_context_set_buffer (GimpContext *context,
3472                          GimpBuffer *buffer)
3473 {
3474   g_return_if_fail (GIMP_IS_CONTEXT (context));
3475   g_return_if_fail (buffer == NULL || GIMP_IS_BUFFER (buffer));
3476 
3477   context_find_defined (context, GIMP_CONTEXT_PROP_BUFFER);
3478 
3479   gimp_context_real_set_buffer (context, buffer);
3480 }
3481 
3482 void
gimp_context_buffer_changed(GimpContext * context)3483 gimp_context_buffer_changed (GimpContext *context)
3484 {
3485   g_return_if_fail (GIMP_IS_CONTEXT (context));
3486 
3487   g_signal_emit (context,
3488                  gimp_context_signals[BUFFER_CHANGED], 0,
3489                  context->buffer);
3490 }
3491 
3492 static void
gimp_context_buffer_dirty(GimpBuffer * buffer,GimpContext * context)3493 gimp_context_buffer_dirty (GimpBuffer  *buffer,
3494                            GimpContext *context)
3495 {
3496   g_free (context->buffer_name);
3497   context->buffer_name = g_strdup (gimp_object_get_name (buffer));
3498 
3499   g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
3500                  GIMP_CONTEXT_PROP_BUFFER);
3501 }
3502 
3503 static void
gimp_context_buffer_list_thaw(GimpContainer * container,GimpContext * context)3504 gimp_context_buffer_list_thaw (GimpContainer *container,
3505                                GimpContext   *context)
3506 {
3507   GimpBuffer *buffer;
3508 
3509   buffer = gimp_context_find_object (context, container,
3510                                      context->buffer_name,
3511                                      NULL);
3512 
3513   if (buffer)
3514     {
3515       gimp_context_real_set_buffer (context, buffer);
3516     }
3517   else
3518     {
3519       g_object_notify (G_OBJECT (context), "buffer");
3520       gimp_context_buffer_changed (context);
3521     }
3522 }
3523 
3524 static void
gimp_context_buffer_removed(GimpContainer * container,GimpBuffer * buffer,GimpContext * context)3525 gimp_context_buffer_removed (GimpContainer *container,
3526                              GimpBuffer    *buffer,
3527                              GimpContext   *context)
3528 {
3529   if (buffer == context->buffer)
3530     {
3531       g_signal_handlers_disconnect_by_func (context->buffer,
3532                                             gimp_context_buffer_dirty,
3533                                             context);
3534       g_clear_object (&context->buffer);
3535 
3536       if (! gimp_container_frozen (container))
3537         gimp_context_buffer_list_thaw (container, context);
3538     }
3539 }
3540 
3541 static void
gimp_context_real_set_buffer(GimpContext * context,GimpBuffer * buffer)3542 gimp_context_real_set_buffer (GimpContext *context,
3543                               GimpBuffer  *buffer)
3544 {
3545   if (context->buffer == buffer)
3546     return;
3547 
3548   if (context->buffer_name)
3549     {
3550       g_clear_pointer (&context->buffer_name, g_free);
3551     }
3552 
3553   if (context->buffer)
3554     g_signal_handlers_disconnect_by_func (context->buffer,
3555                                           gimp_context_buffer_dirty,
3556                                           context);
3557 
3558   g_set_object (&context->buffer, buffer);
3559 
3560   if (buffer)
3561     {
3562       g_signal_connect_object (buffer, "name-changed",
3563                                G_CALLBACK (gimp_context_buffer_dirty),
3564                                context,
3565                                0);
3566 
3567       context->buffer_name = g_strdup (gimp_object_get_name (buffer));
3568     }
3569 
3570   g_object_notify (G_OBJECT (context), "buffer");
3571   gimp_context_buffer_changed (context);
3572 }
3573 
3574 
3575 /*****************************************************************************/
3576 /*  imagefile  ***************************************************************/
3577 
3578 GimpImagefile *
gimp_context_get_imagefile(GimpContext * context)3579 gimp_context_get_imagefile (GimpContext *context)
3580 {
3581   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
3582 
3583   return context->imagefile;
3584 }
3585 
3586 void
gimp_context_set_imagefile(GimpContext * context,GimpImagefile * imagefile)3587 gimp_context_set_imagefile (GimpContext   *context,
3588                             GimpImagefile *imagefile)
3589 {
3590   g_return_if_fail (GIMP_IS_CONTEXT (context));
3591   g_return_if_fail (imagefile == NULL || GIMP_IS_IMAGEFILE (imagefile));
3592 
3593   context_find_defined (context, GIMP_CONTEXT_PROP_IMAGEFILE);
3594 
3595   gimp_context_real_set_imagefile (context, imagefile);
3596 }
3597 
3598 void
gimp_context_imagefile_changed(GimpContext * context)3599 gimp_context_imagefile_changed (GimpContext *context)
3600 {
3601   g_return_if_fail (GIMP_IS_CONTEXT (context));
3602 
3603   g_signal_emit (context,
3604                  gimp_context_signals[IMAGEFILE_CHANGED], 0,
3605                  context->imagefile);
3606 }
3607 
3608 static void
gimp_context_imagefile_dirty(GimpImagefile * imagefile,GimpContext * context)3609 gimp_context_imagefile_dirty (GimpImagefile *imagefile,
3610                               GimpContext   *context)
3611 {
3612   g_free (context->imagefile_name);
3613   context->imagefile_name = g_strdup (gimp_object_get_name (imagefile));
3614 
3615   g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
3616                  GIMP_CONTEXT_PROP_IMAGEFILE);
3617 }
3618 
3619 static void
gimp_context_imagefile_list_thaw(GimpContainer * container,GimpContext * context)3620 gimp_context_imagefile_list_thaw (GimpContainer *container,
3621                                   GimpContext   *context)
3622 {
3623   GimpImagefile *imagefile;
3624 
3625   imagefile = gimp_context_find_object (context, container,
3626                                         context->imagefile_name,
3627                                         NULL);
3628 
3629   if (imagefile)
3630     {
3631       gimp_context_real_set_imagefile (context, imagefile);
3632     }
3633   else
3634     {
3635       g_object_notify (G_OBJECT (context), "imagefile");
3636       gimp_context_imagefile_changed (context);
3637     }
3638 }
3639 
3640 static void
gimp_context_imagefile_removed(GimpContainer * container,GimpImagefile * imagefile,GimpContext * context)3641 gimp_context_imagefile_removed (GimpContainer *container,
3642                                 GimpImagefile *imagefile,
3643                                 GimpContext   *context)
3644 {
3645   if (imagefile == context->imagefile)
3646     {
3647       g_signal_handlers_disconnect_by_func (context->imagefile,
3648                                             gimp_context_imagefile_dirty,
3649                                             context);
3650       g_clear_object (&context->imagefile);
3651 
3652       if (! gimp_container_frozen (container))
3653         gimp_context_imagefile_list_thaw (container, context);
3654     }
3655 }
3656 
3657 static void
gimp_context_real_set_imagefile(GimpContext * context,GimpImagefile * imagefile)3658 gimp_context_real_set_imagefile (GimpContext   *context,
3659                                  GimpImagefile *imagefile)
3660 {
3661   if (context->imagefile == imagefile)
3662     return;
3663 
3664   if (context->imagefile_name)
3665     {
3666       g_clear_pointer (&context->imagefile_name, g_free);
3667     }
3668 
3669   if (context->imagefile)
3670     g_signal_handlers_disconnect_by_func (context->imagefile,
3671                                           gimp_context_imagefile_dirty,
3672                                           context);
3673 
3674   g_set_object (&context->imagefile, imagefile);
3675 
3676   if (imagefile)
3677     {
3678       g_signal_connect_object (imagefile, "name-changed",
3679                                G_CALLBACK (gimp_context_imagefile_dirty),
3680                                context,
3681                                0);
3682 
3683       context->imagefile_name = g_strdup (gimp_object_get_name (imagefile));
3684     }
3685 
3686   g_object_notify (G_OBJECT (context), "imagefile");
3687   gimp_context_imagefile_changed (context);
3688 }
3689 
3690 
3691 /*****************************************************************************/
3692 /*  template  ***************************************************************/
3693 
3694 GimpTemplate *
gimp_context_get_template(GimpContext * context)3695 gimp_context_get_template (GimpContext *context)
3696 {
3697   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
3698 
3699   return context->template;
3700 }
3701 
3702 void
gimp_context_set_template(GimpContext * context,GimpTemplate * template)3703 gimp_context_set_template (GimpContext  *context,
3704                            GimpTemplate *template)
3705 {
3706   g_return_if_fail (GIMP_IS_CONTEXT (context));
3707   g_return_if_fail (template == NULL || GIMP_IS_TEMPLATE (template));
3708 
3709   context_find_defined (context, GIMP_CONTEXT_PROP_TEMPLATE);
3710 
3711   gimp_context_real_set_template (context, template);
3712 }
3713 
3714 void
gimp_context_template_changed(GimpContext * context)3715 gimp_context_template_changed (GimpContext *context)
3716 {
3717   g_return_if_fail (GIMP_IS_CONTEXT (context));
3718 
3719   g_signal_emit (context,
3720                  gimp_context_signals[TEMPLATE_CHANGED], 0,
3721                  context->template);
3722 }
3723 
3724 static void
gimp_context_template_dirty(GimpTemplate * template,GimpContext * context)3725 gimp_context_template_dirty (GimpTemplate *template,
3726                              GimpContext  *context)
3727 {
3728   g_free (context->template_name);
3729   context->template_name = g_strdup (gimp_object_get_name (template));
3730 
3731   g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
3732                  GIMP_CONTEXT_PROP_TEMPLATE);
3733 }
3734 
3735 static void
gimp_context_template_list_thaw(GimpContainer * container,GimpContext * context)3736 gimp_context_template_list_thaw (GimpContainer *container,
3737                                  GimpContext   *context)
3738 {
3739   GimpTemplate *template;
3740 
3741   template = gimp_context_find_object (context, container,
3742                                        context->template_name,
3743                                        NULL);
3744 
3745   if (template)
3746     {
3747       gimp_context_real_set_template (context, template);
3748     }
3749   else
3750     {
3751       g_object_notify (G_OBJECT (context), "template");
3752       gimp_context_template_changed (context);
3753     }
3754 }
3755 
3756 static void
gimp_context_template_removed(GimpContainer * container,GimpTemplate * template,GimpContext * context)3757 gimp_context_template_removed (GimpContainer *container,
3758                                GimpTemplate  *template,
3759                                GimpContext   *context)
3760 {
3761   if (template == context->template)
3762     {
3763       g_signal_handlers_disconnect_by_func (context->template,
3764                                             gimp_context_template_dirty,
3765                                             context);
3766       g_clear_object (&context->template);
3767 
3768       if (! gimp_container_frozen (container))
3769         gimp_context_template_list_thaw (container, context);
3770     }
3771 }
3772 
3773 static void
gimp_context_real_set_template(GimpContext * context,GimpTemplate * template)3774 gimp_context_real_set_template (GimpContext  *context,
3775                                 GimpTemplate *template)
3776 {
3777   if (context->template == template)
3778     return;
3779 
3780   if (context->template_name)
3781     {
3782       g_clear_pointer (&context->template_name, g_free);
3783     }
3784 
3785   if (context->template)
3786     g_signal_handlers_disconnect_by_func (context->template,
3787                                           gimp_context_template_dirty,
3788                                           context);
3789 
3790   g_set_object (&context->template, template);
3791 
3792   if (template)
3793     {
3794       g_signal_connect_object (template, "name-changed",
3795                                G_CALLBACK (gimp_context_template_dirty),
3796                                context,
3797                                0);
3798 
3799       context->template_name = g_strdup (gimp_object_get_name (template));
3800     }
3801 
3802   g_object_notify (G_OBJECT (context), "template");
3803   gimp_context_template_changed (context);
3804 }
3805 
3806 
3807 /*****************************************************************************/
3808 /*  utility functions  *******************************************************/
3809 
3810 static gpointer
gimp_context_find_object(GimpContext * context,GimpContainer * container,const gchar * object_name,gpointer standard_object)3811 gimp_context_find_object (GimpContext   *context,
3812                           GimpContainer *container,
3813                           const gchar   *object_name,
3814                           gpointer       standard_object)
3815 {
3816   GimpObject *object = NULL;
3817 
3818   if (object_name)
3819     object = gimp_container_get_child_by_name (container, object_name);
3820 
3821   if (! object && ! gimp_container_is_empty (container))
3822     object = gimp_container_get_child_by_index (container, 0);
3823 
3824   if (! object)
3825     object = standard_object;
3826 
3827   return object;
3828 }
3829