summaryrefslogtreecommitdiffstats
path: root/app/core/gimpcontext.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/core/gimpcontext.c')
-rw-r--r--app/core/gimpcontext.c3828
1 files changed, 3828 insertions, 0 deletions
diff --git a/app/core/gimpcontext.c b/app/core/gimpcontext.c
new file mode 100644
index 0000000..3788583
--- /dev/null
+++ b/app/core/gimpcontext.c
@@ -0,0 +1,3828 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpcontext.c
+ * Copyright (C) 1999-2010 Michael Natterer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <cairo.h>
+#include <gegl.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpcolor/gimpcolor.h"
+#include "libgimpconfig/gimpconfig.h"
+
+#include "core-types.h"
+
+#include "config/gimpcoreconfig.h"
+
+#include "gimp.h"
+#include "gimp-memsize.h"
+#include "gimpbrush.h"
+#include "gimpbuffer.h"
+#include "gimpcontainer.h"
+#include "gimpcontext.h"
+#include "gimpdatafactory.h"
+#include "gimpdynamics.h"
+#include "gimpimagefile.h"
+#include "gimpgradient.h"
+#include "gimpimage.h"
+#include "gimpmarshal.h"
+#include "gimpmybrush.h"
+#include "gimppaintinfo.h"
+#include "gimppalette.h"
+#include "gimppattern.h"
+#include "gimptemplate.h"
+#include "gimptoolinfo.h"
+#include "gimptoolpreset.h"
+
+#include "text/gimpfont.h"
+
+#include "gimp-intl.h"
+
+
+#define RGBA_EPSILON 1e-10
+
+typedef void (* GimpContextCopyPropFunc) (GimpContext *src,
+ GimpContext *dest);
+
+#define context_find_defined(context, prop) \
+ while (!(((context)->defined_props) & (1 << (prop))) && (context)->parent) \
+ (context) = (context)->parent
+
+#define COPY_NAME(src, dest, member) \
+ g_free (dest->member); \
+ dest->member = g_strdup (src->member)
+
+
+/* local function prototypes */
+
+static void gimp_context_config_iface_init (GimpConfigInterface *iface);
+
+static void gimp_context_constructed (GObject *object);
+static void gimp_context_dispose (GObject *object);
+static void gimp_context_finalize (GObject *object);
+static void gimp_context_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gimp_context_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec);
+static gint64 gimp_context_get_memsize (GimpObject *object,
+ gint64 *gui_size);
+
+static gboolean gimp_context_serialize (GimpConfig *config,
+ GimpConfigWriter *writer,
+ gpointer data);
+static gboolean gimp_context_deserialize (GimpConfig *config,
+ GScanner *scanner,
+ gint nest_level,
+ gpointer data);
+static gboolean gimp_context_serialize_property (GimpConfig *config,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec,
+ GimpConfigWriter *writer);
+static gboolean gimp_context_deserialize_property (GimpConfig *config,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec,
+ GScanner *scanner,
+ GTokenType *expected);
+static GimpConfig * gimp_context_duplicate (GimpConfig *config);
+static gboolean gimp_context_copy (GimpConfig *src,
+ GimpConfig *dest,
+ GParamFlags flags);
+
+/* image */
+static void gimp_context_image_removed (GimpContainer *container,
+ GimpImage *image,
+ GimpContext *context);
+static void gimp_context_real_set_image (GimpContext *context,
+ GimpImage *image);
+
+/* display */
+static void gimp_context_display_removed (GimpContainer *container,
+ gpointer display,
+ GimpContext *context);
+static void gimp_context_real_set_display (GimpContext *context,
+ gpointer display);
+
+/* tool */
+static void gimp_context_tool_dirty (GimpToolInfo *tool_info,
+ GimpContext *context);
+static void gimp_context_tool_removed (GimpContainer *container,
+ GimpToolInfo *tool_info,
+ GimpContext *context);
+static void gimp_context_tool_list_thaw (GimpContainer *container,
+ GimpContext *context);
+static void gimp_context_real_set_tool (GimpContext *context,
+ GimpToolInfo *tool_info);
+
+/* paint info */
+static void gimp_context_paint_info_dirty (GimpPaintInfo *paint_info,
+ GimpContext *context);
+static void gimp_context_paint_info_removed (GimpContainer *container,
+ GimpPaintInfo *paint_info,
+ GimpContext *context);
+static void gimp_context_paint_info_list_thaw(GimpContainer *container,
+ GimpContext *context);
+static void gimp_context_real_set_paint_info (GimpContext *context,
+ GimpPaintInfo *paint_info);
+
+/* foreground */
+static void gimp_context_real_set_foreground (GimpContext *context,
+ const GimpRGB *color);
+
+/* background */
+static void gimp_context_real_set_background (GimpContext *context,
+ const GimpRGB *color);
+
+/* opacity */
+static void gimp_context_real_set_opacity (GimpContext *context,
+ gdouble opacity);
+
+/* paint mode */
+static void gimp_context_real_set_paint_mode (GimpContext *context,
+ GimpLayerMode paint_mode);
+
+/* brush */
+static void gimp_context_brush_dirty (GimpBrush *brush,
+ GimpContext *context);
+static void gimp_context_brush_removed (GimpContainer *brush_list,
+ GimpBrush *brush,
+ GimpContext *context);
+static void gimp_context_brush_list_thaw (GimpContainer *container,
+ GimpContext *context);
+static void gimp_context_real_set_brush (GimpContext *context,
+ GimpBrush *brush);
+
+/* dynamics */
+
+static void gimp_context_dynamics_dirty (GimpDynamics *dynamics,
+ GimpContext *context);
+static void gimp_context_dynamics_removed (GimpContainer *container,
+ GimpDynamics *dynamics,
+ GimpContext *context);
+static void gimp_context_dynamics_list_thaw (GimpContainer *container,
+ GimpContext *context);
+static void gimp_context_real_set_dynamics (GimpContext *context,
+ GimpDynamics *dynamics);
+
+/* mybrush */
+static void gimp_context_mybrush_dirty (GimpMybrush *brush,
+ GimpContext *context);
+static void gimp_context_mybrush_removed (GimpContainer *brush_list,
+ GimpMybrush *brush,
+ GimpContext *context);
+static void gimp_context_mybrush_list_thaw (GimpContainer *container,
+ GimpContext *context);
+static void gimp_context_real_set_mybrush (GimpContext *context,
+ GimpMybrush *brush);
+
+/* pattern */
+static void gimp_context_pattern_dirty (GimpPattern *pattern,
+ GimpContext *context);
+static void gimp_context_pattern_removed (GimpContainer *container,
+ GimpPattern *pattern,
+ GimpContext *context);
+static void gimp_context_pattern_list_thaw (GimpContainer *container,
+ GimpContext *context);
+static void gimp_context_real_set_pattern (GimpContext *context,
+ GimpPattern *pattern);
+
+/* gradient */
+static void gimp_context_gradient_dirty (GimpGradient *gradient,
+ GimpContext *context);
+static void gimp_context_gradient_removed (GimpContainer *container,
+ GimpGradient *gradient,
+ GimpContext *context);
+static void gimp_context_gradient_list_thaw (GimpContainer *container,
+ GimpContext *context);
+static void gimp_context_real_set_gradient (GimpContext *context,
+ GimpGradient *gradient);
+
+/* palette */
+static void gimp_context_palette_dirty (GimpPalette *palette,
+ GimpContext *context);
+static void gimp_context_palette_removed (GimpContainer *container,
+ GimpPalette *palette,
+ GimpContext *context);
+static void gimp_context_palette_list_thaw (GimpContainer *container,
+ GimpContext *context);
+static void gimp_context_real_set_palette (GimpContext *context,
+ GimpPalette *palette);
+
+/* font */
+static void gimp_context_font_dirty (GimpFont *font,
+ GimpContext *context);
+static void gimp_context_font_removed (GimpContainer *container,
+ GimpFont *font,
+ GimpContext *context);
+static void gimp_context_font_list_thaw (GimpContainer *container,
+ GimpContext *context);
+static void gimp_context_real_set_font (GimpContext *context,
+ GimpFont *font);
+
+/* tool preset */
+static void gimp_context_tool_preset_dirty (GimpToolPreset *tool_preset,
+ GimpContext *context);
+static void gimp_context_tool_preset_removed (GimpContainer *container,
+ GimpToolPreset *tool_preset,
+ GimpContext *context);
+static void gimp_context_tool_preset_list_thaw (GimpContainer *container,
+ GimpContext *context);
+static void gimp_context_real_set_tool_preset (GimpContext *context,
+ GimpToolPreset *tool_preset);
+
+/* buffer */
+static void gimp_context_buffer_dirty (GimpBuffer *buffer,
+ GimpContext *context);
+static void gimp_context_buffer_removed (GimpContainer *container,
+ GimpBuffer *buffer,
+ GimpContext *context);
+static void gimp_context_buffer_list_thaw (GimpContainer *container,
+ GimpContext *context);
+static void gimp_context_real_set_buffer (GimpContext *context,
+ GimpBuffer *buffer);
+
+/* imagefile */
+static void gimp_context_imagefile_dirty (GimpImagefile *imagefile,
+ GimpContext *context);
+static void gimp_context_imagefile_removed (GimpContainer *container,
+ GimpImagefile *imagefile,
+ GimpContext *context);
+static void gimp_context_imagefile_list_thaw (GimpContainer *container,
+ GimpContext *context);
+static void gimp_context_real_set_imagefile (GimpContext *context,
+ GimpImagefile *imagefile);
+
+/* template */
+static void gimp_context_template_dirty (GimpTemplate *template,
+ GimpContext *context);
+static void gimp_context_template_removed (GimpContainer *container,
+ GimpTemplate *template,
+ GimpContext *context);
+static void gimp_context_template_list_thaw (GimpContainer *container,
+ GimpContext *context);
+static void gimp_context_real_set_template (GimpContext *context,
+ GimpTemplate *template);
+
+
+/* utilities */
+static gpointer gimp_context_find_object (GimpContext *context,
+ GimpContainer *container,
+ const gchar *object_name,
+ gpointer standard_object);
+
+
+/* properties & signals */
+
+enum
+{
+ GIMP_CONTEXT_PROP_0,
+ GIMP_CONTEXT_PROP_GIMP
+
+ /* remaining values are in core-enums.h (GimpContextPropType) */
+};
+
+enum
+{
+ DUMMY_0,
+ DUMMY_1,
+ IMAGE_CHANGED,
+ DISPLAY_CHANGED,
+ TOOL_CHANGED,
+ PAINT_INFO_CHANGED,
+ FOREGROUND_CHANGED,
+ BACKGROUND_CHANGED,
+ OPACITY_CHANGED,
+ PAINT_MODE_CHANGED,
+ BRUSH_CHANGED,
+ DYNAMICS_CHANGED,
+ MYBRUSH_CHANGED,
+ PATTERN_CHANGED,
+ GRADIENT_CHANGED,
+ PALETTE_CHANGED,
+ FONT_CHANGED,
+ TOOL_PRESET_CHANGED,
+ BUFFER_CHANGED,
+ IMAGEFILE_CHANGED,
+ TEMPLATE_CHANGED,
+ PROP_NAME_CHANGED,
+ LAST_SIGNAL
+};
+
+static const gchar * const gimp_context_prop_names[] =
+{
+ NULL, /* PROP_0 */
+ "gimp",
+ "image",
+ "display",
+ "tool",
+ "paint-info",
+ "foreground",
+ "background",
+ "opacity",
+ "paint-mode",
+ "brush",
+ "dynamics",
+ "mybrush",
+ "pattern",
+ "gradient",
+ "palette",
+ "font",
+ "tool-preset",
+ "buffer",
+ "imagefile",
+ "template"
+};
+
+static GType gimp_context_prop_types[] =
+{
+ G_TYPE_NONE, /* PROP_0 */
+ G_TYPE_NONE, /* PROP_GIMP */
+ 0,
+ G_TYPE_NONE,
+ 0,
+ 0,
+ G_TYPE_NONE,
+ G_TYPE_NONE,
+ G_TYPE_NONE,
+ G_TYPE_NONE,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+
+G_DEFINE_TYPE_WITH_CODE (GimpContext, gimp_context, GIMP_TYPE_VIEWABLE,
+ G_IMPLEMENT_INTERFACE (GIMP_TYPE_CONFIG,
+ gimp_context_config_iface_init))
+
+#define parent_class gimp_context_parent_class
+
+static GimpConfigInterface *parent_config_iface = NULL;
+
+static guint gimp_context_signals[LAST_SIGNAL] = { 0 };
+
+
+static void
+gimp_context_class_init (GimpContextClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
+ GimpRGB black;
+ GimpRGB white;
+
+ gimp_rgba_set (&black, 0.0, 0.0, 0.0, GIMP_OPACITY_OPAQUE);
+ gimp_rgba_set (&white, 1.0, 1.0, 1.0, GIMP_OPACITY_OPAQUE);
+
+ gimp_context_signals[IMAGE_CHANGED] =
+ g_signal_new ("image-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpContextClass, image_changed),
+ NULL, NULL,
+ gimp_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ GIMP_TYPE_IMAGE);
+
+ gimp_context_signals[DISPLAY_CHANGED] =
+ g_signal_new ("display-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpContextClass, display_changed),
+ NULL, NULL,
+ gimp_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ GIMP_TYPE_OBJECT);
+
+ gimp_context_signals[TOOL_CHANGED] =
+ g_signal_new ("tool-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpContextClass, tool_changed),
+ NULL, NULL,
+ gimp_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ GIMP_TYPE_TOOL_INFO);
+
+ gimp_context_signals[PAINT_INFO_CHANGED] =
+ g_signal_new ("paint-info-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpContextClass, paint_info_changed),
+ NULL, NULL,
+ gimp_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ GIMP_TYPE_PAINT_INFO);
+
+ gimp_context_signals[FOREGROUND_CHANGED] =
+ g_signal_new ("foreground-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpContextClass, foreground_changed),
+ NULL, NULL,
+ gimp_marshal_VOID__BOXED,
+ G_TYPE_NONE, 1,
+ GIMP_TYPE_RGB | G_SIGNAL_TYPE_STATIC_SCOPE);
+
+ gimp_context_signals[BACKGROUND_CHANGED] =
+ g_signal_new ("background-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpContextClass, background_changed),
+ NULL, NULL,
+ gimp_marshal_VOID__BOXED,
+ G_TYPE_NONE, 1,
+ GIMP_TYPE_RGB | G_SIGNAL_TYPE_STATIC_SCOPE);
+
+ gimp_context_signals[OPACITY_CHANGED] =
+ g_signal_new ("opacity-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpContextClass, opacity_changed),
+ NULL, NULL,
+ gimp_marshal_VOID__DOUBLE,
+ G_TYPE_NONE, 1,
+ G_TYPE_DOUBLE);
+
+ gimp_context_signals[PAINT_MODE_CHANGED] =
+ g_signal_new ("paint-mode-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpContextClass, paint_mode_changed),
+ NULL, NULL,
+ gimp_marshal_VOID__ENUM,
+ G_TYPE_NONE, 1,
+ GIMP_TYPE_LAYER_MODE);
+
+ gimp_context_signals[BRUSH_CHANGED] =
+ g_signal_new ("brush-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpContextClass, brush_changed),
+ NULL, NULL,
+ gimp_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ GIMP_TYPE_BRUSH);
+
+ gimp_context_signals[DYNAMICS_CHANGED] =
+ g_signal_new ("dynamics-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpContextClass, dynamics_changed),
+ NULL, NULL,
+ gimp_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ GIMP_TYPE_DYNAMICS);
+
+ gimp_context_signals[MYBRUSH_CHANGED] =
+ g_signal_new ("mybrush-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpContextClass, mybrush_changed),
+ NULL, NULL,
+ gimp_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ GIMP_TYPE_MYBRUSH);
+
+ gimp_context_signals[PATTERN_CHANGED] =
+ g_signal_new ("pattern-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpContextClass, pattern_changed),
+ NULL, NULL,
+ gimp_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ GIMP_TYPE_PATTERN);
+
+ gimp_context_signals[GRADIENT_CHANGED] =
+ g_signal_new ("gradient-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpContextClass, gradient_changed),
+ NULL, NULL,
+ gimp_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ GIMP_TYPE_GRADIENT);
+
+ gimp_context_signals[PALETTE_CHANGED] =
+ g_signal_new ("palette-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpContextClass, palette_changed),
+ NULL, NULL,
+ gimp_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ GIMP_TYPE_PALETTE);
+
+ gimp_context_signals[FONT_CHANGED] =
+ g_signal_new ("font-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpContextClass, font_changed),
+ NULL, NULL,
+ gimp_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ GIMP_TYPE_FONT);
+
+ gimp_context_signals[TOOL_PRESET_CHANGED] =
+ g_signal_new ("tool-preset-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpContextClass, tool_preset_changed),
+ NULL, NULL,
+ gimp_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ GIMP_TYPE_TOOL_PRESET);
+
+ gimp_context_signals[BUFFER_CHANGED] =
+ g_signal_new ("buffer-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpContextClass, buffer_changed),
+ NULL, NULL,
+ gimp_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ GIMP_TYPE_BUFFER);
+
+ gimp_context_signals[IMAGEFILE_CHANGED] =
+ g_signal_new ("imagefile-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpContextClass, imagefile_changed),
+ NULL, NULL,
+ gimp_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ GIMP_TYPE_IMAGEFILE);
+
+ gimp_context_signals[TEMPLATE_CHANGED] =
+ g_signal_new ("template-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpContextClass, template_changed),
+ NULL, NULL,
+ gimp_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ GIMP_TYPE_TEMPLATE);
+
+ gimp_context_signals[PROP_NAME_CHANGED] =
+ g_signal_new ("prop-name-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GimpContextClass, prop_name_changed),
+ NULL, NULL,
+ gimp_marshal_VOID__INT,
+ G_TYPE_NONE, 1,
+ G_TYPE_INT);
+
+ object_class->constructed = gimp_context_constructed;
+ object_class->set_property = gimp_context_set_property;
+ object_class->get_property = gimp_context_get_property;
+ object_class->dispose = gimp_context_dispose;
+ object_class->finalize = gimp_context_finalize;
+
+ gimp_object_class->get_memsize = gimp_context_get_memsize;
+
+ klass->image_changed = NULL;
+ klass->display_changed = NULL;
+ klass->tool_changed = NULL;
+ klass->paint_info_changed = NULL;
+ klass->foreground_changed = NULL;
+ klass->background_changed = NULL;
+ klass->opacity_changed = NULL;
+ klass->paint_mode_changed = NULL;
+ klass->brush_changed = NULL;
+ klass->dynamics_changed = NULL;
+ klass->mybrush_changed = NULL;
+ klass->pattern_changed = NULL;
+ klass->gradient_changed = NULL;
+ klass->palette_changed = NULL;
+ klass->font_changed = NULL;
+ klass->tool_preset_changed = NULL;
+ klass->buffer_changed = NULL;
+ klass->imagefile_changed = NULL;
+ klass->template_changed = NULL;
+ klass->prop_name_changed = NULL;
+
+ gimp_context_prop_types[GIMP_CONTEXT_PROP_IMAGE] = GIMP_TYPE_IMAGE;
+ gimp_context_prop_types[GIMP_CONTEXT_PROP_TOOL] = GIMP_TYPE_TOOL_INFO;
+ gimp_context_prop_types[GIMP_CONTEXT_PROP_PAINT_INFO] = GIMP_TYPE_PAINT_INFO;
+ gimp_context_prop_types[GIMP_CONTEXT_PROP_BRUSH] = GIMP_TYPE_BRUSH;
+ gimp_context_prop_types[GIMP_CONTEXT_PROP_DYNAMICS] = GIMP_TYPE_DYNAMICS;
+ gimp_context_prop_types[GIMP_CONTEXT_PROP_MYBRUSH] = GIMP_TYPE_MYBRUSH;
+ gimp_context_prop_types[GIMP_CONTEXT_PROP_PATTERN] = GIMP_TYPE_PATTERN;
+ gimp_context_prop_types[GIMP_CONTEXT_PROP_GRADIENT] = GIMP_TYPE_GRADIENT;
+ gimp_context_prop_types[GIMP_CONTEXT_PROP_PALETTE] = GIMP_TYPE_PALETTE;
+ gimp_context_prop_types[GIMP_CONTEXT_PROP_FONT] = GIMP_TYPE_FONT;
+ gimp_context_prop_types[GIMP_CONTEXT_PROP_TOOL_PRESET] = GIMP_TYPE_TOOL_PRESET;
+ gimp_context_prop_types[GIMP_CONTEXT_PROP_BUFFER] = GIMP_TYPE_BUFFER;
+ gimp_context_prop_types[GIMP_CONTEXT_PROP_IMAGEFILE] = GIMP_TYPE_IMAGEFILE;
+ gimp_context_prop_types[GIMP_CONTEXT_PROP_TEMPLATE] = GIMP_TYPE_TEMPLATE;
+
+ g_object_class_install_property (object_class, GIMP_CONTEXT_PROP_GIMP,
+ g_param_spec_object ("gimp",
+ NULL, NULL,
+ GIMP_TYPE_GIMP,
+ GIMP_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class, GIMP_CONTEXT_PROP_IMAGE,
+ g_param_spec_object (gimp_context_prop_names[GIMP_CONTEXT_PROP_IMAGE],
+ NULL, NULL,
+ GIMP_TYPE_IMAGE,
+ GIMP_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class, GIMP_CONTEXT_PROP_DISPLAY,
+ g_param_spec_object (gimp_context_prop_names[GIMP_CONTEXT_PROP_DISPLAY],
+ NULL, NULL,
+ GIMP_TYPE_OBJECT,
+ GIMP_PARAM_READWRITE));
+
+ GIMP_CONFIG_PROP_OBJECT (object_class, GIMP_CONTEXT_PROP_TOOL,
+ gimp_context_prop_names[GIMP_CONTEXT_PROP_TOOL],
+ NULL, NULL,
+ GIMP_TYPE_TOOL_INFO,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_OBJECT (object_class, GIMP_CONTEXT_PROP_PAINT_INFO,
+ gimp_context_prop_names[GIMP_CONTEXT_PROP_PAINT_INFO],
+ NULL, NULL,
+ GIMP_TYPE_PAINT_INFO,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_RGB (object_class, GIMP_CONTEXT_PROP_FOREGROUND,
+ gimp_context_prop_names[GIMP_CONTEXT_PROP_FOREGROUND],
+ _("Foreground"),
+ _("Foreground color"),
+ FALSE, &black,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_RGB (object_class, GIMP_CONTEXT_PROP_BACKGROUND,
+ gimp_context_prop_names[GIMP_CONTEXT_PROP_BACKGROUND],
+ _("Background"),
+ _("Background color"),
+ FALSE, &white,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_DOUBLE (object_class, GIMP_CONTEXT_PROP_OPACITY,
+ gimp_context_prop_names[GIMP_CONTEXT_PROP_OPACITY],
+ _("Opacity"),
+ _("Opacity"),
+ GIMP_OPACITY_TRANSPARENT,
+ GIMP_OPACITY_OPAQUE,
+ GIMP_OPACITY_OPAQUE,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_ENUM (object_class, GIMP_CONTEXT_PROP_PAINT_MODE,
+ gimp_context_prop_names[GIMP_CONTEXT_PROP_PAINT_MODE],
+ _("Paint Mode"),
+ _("Paint Mode"),
+ GIMP_TYPE_LAYER_MODE,
+ GIMP_LAYER_MODE_NORMAL,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_OBJECT (object_class, GIMP_CONTEXT_PROP_BRUSH,
+ gimp_context_prop_names[GIMP_CONTEXT_PROP_BRUSH],
+ _("Brush"),
+ _("Brush"),
+ GIMP_TYPE_BRUSH,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_OBJECT (object_class, GIMP_CONTEXT_PROP_DYNAMICS,
+ gimp_context_prop_names[GIMP_CONTEXT_PROP_DYNAMICS],
+ _("Dynamics"),
+ _("Paint dynamics"),
+ GIMP_TYPE_DYNAMICS,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_OBJECT (object_class, GIMP_CONTEXT_PROP_MYBRUSH,
+ gimp_context_prop_names[GIMP_CONTEXT_PROP_MYBRUSH],
+ _("MyPaint Brush"),
+ _("MyPaint Brush"),
+ GIMP_TYPE_MYBRUSH,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_OBJECT (object_class, GIMP_CONTEXT_PROP_PATTERN,
+ gimp_context_prop_names[GIMP_CONTEXT_PROP_PATTERN],
+ _("Pattern"),
+ _("Pattern"),
+ GIMP_TYPE_PATTERN,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_OBJECT (object_class, GIMP_CONTEXT_PROP_GRADIENT,
+ gimp_context_prop_names[GIMP_CONTEXT_PROP_GRADIENT],
+ _("Gradient"),
+ _("Gradient"),
+ GIMP_TYPE_GRADIENT,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_OBJECT (object_class, GIMP_CONTEXT_PROP_PALETTE,
+ gimp_context_prop_names[GIMP_CONTEXT_PROP_PALETTE],
+ _("Palette"),
+ _("Palette"),
+ GIMP_TYPE_PALETTE,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_OBJECT (object_class, GIMP_CONTEXT_PROP_FONT,
+ gimp_context_prop_names[GIMP_CONTEXT_PROP_FONT],
+ _("Font"),
+ _("Font"),
+ GIMP_TYPE_FONT,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_OBJECT (object_class, GIMP_CONTEXT_PROP_TOOL_PRESET,
+ gimp_context_prop_names[GIMP_CONTEXT_PROP_TOOL_PRESET],
+ _("Tool Preset"),
+ _("Tool Preset"),
+ GIMP_TYPE_TOOL_PRESET,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_property (object_class, GIMP_CONTEXT_PROP_BUFFER,
+ g_param_spec_object (gimp_context_prop_names[GIMP_CONTEXT_PROP_BUFFER],
+ NULL, NULL,
+ GIMP_TYPE_BUFFER,
+ GIMP_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class, GIMP_CONTEXT_PROP_IMAGEFILE,
+ g_param_spec_object (gimp_context_prop_names[GIMP_CONTEXT_PROP_IMAGEFILE],
+ NULL, NULL,
+ GIMP_TYPE_IMAGEFILE,
+ GIMP_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class, GIMP_CONTEXT_PROP_TEMPLATE,
+ g_param_spec_object (gimp_context_prop_names[GIMP_CONTEXT_PROP_TEMPLATE],
+ NULL, NULL,
+ GIMP_TYPE_TEMPLATE,
+ GIMP_PARAM_READWRITE));
+}
+
+static void
+gimp_context_init (GimpContext *context)
+{
+ context->gimp = NULL;
+
+ context->parent = NULL;
+
+ context->defined_props = GIMP_CONTEXT_PROP_MASK_ALL;
+ context->serialize_props = GIMP_CONTEXT_PROP_MASK_ALL;
+
+ context->image = NULL;
+ context->display = NULL;
+
+ context->tool_info = NULL;
+ context->tool_name = NULL;
+
+ context->paint_info = NULL;
+ context->paint_name = NULL;
+
+ context->brush = NULL;
+ context->brush_name = NULL;
+
+ context->dynamics = NULL;
+ context->dynamics_name = NULL;
+
+ context->mybrush = NULL;
+ context->mybrush_name = NULL;
+
+ context->pattern = NULL;
+ context->pattern_name = NULL;
+
+ context->gradient = NULL;
+ context->gradient_name = NULL;
+
+ context->palette = NULL;
+ context->palette_name = NULL;
+
+ context->font = NULL;
+ context->font_name = NULL;
+
+ context->tool_preset = NULL;
+ context->tool_preset_name = NULL;
+
+ context->buffer = NULL;
+ context->buffer_name = NULL;
+
+ context->imagefile = NULL;
+ context->imagefile_name = NULL;
+
+ context->template = NULL;
+ context->template_name = NULL;
+}
+
+static void
+gimp_context_config_iface_init (GimpConfigInterface *iface)
+{
+ parent_config_iface = g_type_interface_peek_parent (iface);
+
+ if (! parent_config_iface)
+ parent_config_iface = g_type_default_interface_peek (GIMP_TYPE_CONFIG);
+
+ iface->serialize = gimp_context_serialize;
+ iface->deserialize = gimp_context_deserialize;
+ iface->serialize_property = gimp_context_serialize_property;
+ iface->deserialize_property = gimp_context_deserialize_property;
+ iface->duplicate = gimp_context_duplicate;
+ iface->copy = gimp_context_copy;
+}
+
+static void
+gimp_context_constructed (GObject *object)
+{
+ Gimp *gimp;
+ GimpContainer *container;
+
+ G_OBJECT_CLASS (parent_class)->constructed (object);
+
+ gimp = GIMP_CONTEXT (object)->gimp;
+
+ gimp_assert (GIMP_IS_GIMP (gimp));
+
+ gimp->context_list = g_list_prepend (gimp->context_list, object);
+
+ g_signal_connect_object (gimp->images, "remove",
+ G_CALLBACK (gimp_context_image_removed),
+ object, 0);
+ g_signal_connect_object (gimp->displays, "remove",
+ G_CALLBACK (gimp_context_display_removed),
+ object, 0);
+
+ g_signal_connect_object (gimp->tool_info_list, "remove",
+ G_CALLBACK (gimp_context_tool_removed),
+ object, 0);
+ g_signal_connect_object (gimp->tool_info_list, "thaw",
+ G_CALLBACK (gimp_context_tool_list_thaw),
+ object, 0);
+
+ g_signal_connect_object (gimp->paint_info_list, "remove",
+ G_CALLBACK (gimp_context_paint_info_removed),
+ object, 0);
+ g_signal_connect_object (gimp->paint_info_list, "thaw",
+ G_CALLBACK (gimp_context_paint_info_list_thaw),
+ object, 0);
+
+ container = gimp_data_factory_get_container (gimp->brush_factory);
+ g_signal_connect_object (container, "remove",
+ G_CALLBACK (gimp_context_brush_removed),
+ object, 0);
+ g_signal_connect_object (container, "thaw",
+ G_CALLBACK (gimp_context_brush_list_thaw),
+ object, 0);
+
+ container = gimp_data_factory_get_container (gimp->dynamics_factory);
+ g_signal_connect_object (container, "remove",
+ G_CALLBACK (gimp_context_dynamics_removed),
+ object, 0);
+ g_signal_connect_object (container, "thaw",
+ G_CALLBACK (gimp_context_dynamics_list_thaw),
+ object, 0);
+
+ container = gimp_data_factory_get_container (gimp->mybrush_factory);
+ g_signal_connect_object (container, "remove",
+ G_CALLBACK (gimp_context_mybrush_removed),
+ object, 0);
+ g_signal_connect_object (container, "thaw",
+ G_CALLBACK (gimp_context_mybrush_list_thaw),
+ object, 0);
+
+ container = gimp_data_factory_get_container (gimp->pattern_factory);
+ g_signal_connect_object (container, "remove",
+ G_CALLBACK (gimp_context_pattern_removed),
+ object, 0);
+ g_signal_connect_object (container, "thaw",
+ G_CALLBACK (gimp_context_pattern_list_thaw),
+ object, 0);
+
+ container = gimp_data_factory_get_container (gimp->gradient_factory);
+ g_signal_connect_object (container, "remove",
+ G_CALLBACK (gimp_context_gradient_removed),
+ object, 0);
+ g_signal_connect_object (container, "thaw",
+ G_CALLBACK (gimp_context_gradient_list_thaw),
+ object, 0);
+
+ container = gimp_data_factory_get_container (gimp->palette_factory);
+ g_signal_connect_object (container, "remove",
+ G_CALLBACK (gimp_context_palette_removed),
+ object, 0);
+ g_signal_connect_object (container, "thaw",
+ G_CALLBACK (gimp_context_palette_list_thaw),
+ object, 0);
+
+ container = gimp_data_factory_get_container (gimp->font_factory);
+ g_signal_connect_object (container, "remove",
+ G_CALLBACK (gimp_context_font_removed),
+ object, 0);
+ g_signal_connect_object (container, "thaw",
+ G_CALLBACK (gimp_context_font_list_thaw),
+ object, 0);
+
+ container = gimp_data_factory_get_container (gimp->tool_preset_factory);
+ g_signal_connect_object (container, "remove",
+ G_CALLBACK (gimp_context_tool_preset_removed),
+ object, 0);
+ g_signal_connect_object (container, "thaw",
+ G_CALLBACK (gimp_context_tool_preset_list_thaw),
+ object, 0);
+
+ g_signal_connect_object (gimp->named_buffers, "remove",
+ G_CALLBACK (gimp_context_buffer_removed),
+ object, 0);
+ g_signal_connect_object (gimp->named_buffers, "thaw",
+ G_CALLBACK (gimp_context_buffer_list_thaw),
+ object, 0);
+
+ g_signal_connect_object (gimp->documents, "remove",
+ G_CALLBACK (gimp_context_imagefile_removed),
+ object, 0);
+ g_signal_connect_object (gimp->documents, "thaw",
+ G_CALLBACK (gimp_context_imagefile_list_thaw),
+ object, 0);
+
+ g_signal_connect_object (gimp->templates, "remove",
+ G_CALLBACK (gimp_context_template_removed),
+ object, 0);
+ g_signal_connect_object (gimp->templates, "thaw",
+ G_CALLBACK (gimp_context_template_list_thaw),
+ object, 0);
+
+ gimp_context_set_paint_info (GIMP_CONTEXT (object),
+ gimp_paint_info_get_standard (gimp));
+}
+
+static void
+gimp_context_dispose (GObject *object)
+{
+ GimpContext *context = GIMP_CONTEXT (object);
+
+ gimp_context_set_parent (context, NULL);
+
+ if (context->gimp)
+ {
+ context->gimp->context_list = g_list_remove (context->gimp->context_list,
+ context);
+ context->gimp = NULL;
+ }
+
+ g_clear_object (&context->tool_info);
+ g_clear_object (&context->paint_info);
+ g_clear_object (&context->brush);
+ g_clear_object (&context->dynamics);
+ g_clear_object (&context->mybrush);
+ g_clear_object (&context->pattern);
+ g_clear_object (&context->gradient);
+ g_clear_object (&context->palette);
+ g_clear_object (&context->font);
+ g_clear_object (&context->tool_preset);
+ g_clear_object (&context->buffer);
+ g_clear_object (&context->imagefile);
+ g_clear_object (&context->template);
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gimp_context_finalize (GObject *object)
+{
+ GimpContext *context = GIMP_CONTEXT (object);
+
+ context->parent = NULL;
+ context->image = NULL;
+ context->display = NULL;
+
+ g_clear_pointer (&context->tool_name, g_free);
+ g_clear_pointer (&context->paint_name, g_free);
+ g_clear_pointer (&context->brush_name, g_free);
+ g_clear_pointer (&context->dynamics_name, g_free);
+ g_clear_pointer (&context->mybrush_name, g_free);
+ g_clear_pointer (&context->pattern_name, g_free);
+ g_clear_pointer (&context->gradient_name, g_free);
+ g_clear_pointer (&context->palette_name, g_free);
+ g_clear_pointer (&context->font_name, g_free);
+ g_clear_pointer (&context->tool_preset_name, g_free);
+ g_clear_pointer (&context->buffer_name, g_free);
+ g_clear_pointer (&context->imagefile_name, g_free);
+ g_clear_pointer (&context->template_name, g_free);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gimp_context_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GimpContext *context = GIMP_CONTEXT (object);
+
+ switch (property_id)
+ {
+ case GIMP_CONTEXT_PROP_GIMP:
+ context->gimp = g_value_get_object (value);
+ break;
+ case GIMP_CONTEXT_PROP_IMAGE:
+ gimp_context_set_image (context, g_value_get_object (value));
+ break;
+ case GIMP_CONTEXT_PROP_DISPLAY:
+ gimp_context_set_display (context, g_value_get_object (value));
+ break;
+ case GIMP_CONTEXT_PROP_TOOL:
+ gimp_context_set_tool (context, g_value_get_object (value));
+ break;
+ case GIMP_CONTEXT_PROP_PAINT_INFO:
+ gimp_context_set_paint_info (context, g_value_get_object (value));
+ break;
+ case GIMP_CONTEXT_PROP_FOREGROUND:
+ gimp_context_set_foreground (context, g_value_get_boxed (value));
+ break;
+ case GIMP_CONTEXT_PROP_BACKGROUND:
+ gimp_context_set_background (context, g_value_get_boxed (value));
+ break;
+ case GIMP_CONTEXT_PROP_OPACITY:
+ gimp_context_set_opacity (context, g_value_get_double (value));
+ break;
+ case GIMP_CONTEXT_PROP_PAINT_MODE:
+ gimp_context_set_paint_mode (context, g_value_get_enum (value));
+ break;
+ case GIMP_CONTEXT_PROP_BRUSH:
+ gimp_context_set_brush (context, g_value_get_object (value));
+ break;
+ case GIMP_CONTEXT_PROP_DYNAMICS:
+ gimp_context_set_dynamics (context, g_value_get_object (value));
+ break;
+ case GIMP_CONTEXT_PROP_MYBRUSH:
+ gimp_context_set_mybrush (context, g_value_get_object (value));
+ break;
+ case GIMP_CONTEXT_PROP_PATTERN:
+ gimp_context_set_pattern (context, g_value_get_object (value));
+ break;
+ case GIMP_CONTEXT_PROP_GRADIENT:
+ gimp_context_set_gradient (context, g_value_get_object (value));
+ break;
+ case GIMP_CONTEXT_PROP_PALETTE:
+ gimp_context_set_palette (context, g_value_get_object (value));
+ break;
+ case GIMP_CONTEXT_PROP_FONT:
+ gimp_context_set_font (context, g_value_get_object (value));
+ break;
+ case GIMP_CONTEXT_PROP_TOOL_PRESET:
+ gimp_context_set_tool_preset (context, g_value_get_object (value));
+ break;
+ case GIMP_CONTEXT_PROP_BUFFER:
+ gimp_context_set_buffer (context, g_value_get_object (value));
+ break;
+ case GIMP_CONTEXT_PROP_IMAGEFILE:
+ gimp_context_set_imagefile (context, g_value_get_object (value));
+ break;
+ case GIMP_CONTEXT_PROP_TEMPLATE:
+ gimp_context_set_template (context, g_value_get_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gimp_context_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GimpContext *context = GIMP_CONTEXT (object);
+
+ switch (property_id)
+ {
+ case GIMP_CONTEXT_PROP_GIMP:
+ g_value_set_object (value, context->gimp);
+ break;
+ case GIMP_CONTEXT_PROP_IMAGE:
+ g_value_set_object (value, gimp_context_get_image (context));
+ break;
+ case GIMP_CONTEXT_PROP_DISPLAY:
+ g_value_set_object (value, gimp_context_get_display (context));
+ break;
+ case GIMP_CONTEXT_PROP_TOOL:
+ g_value_set_object (value, gimp_context_get_tool (context));
+ break;
+ case GIMP_CONTEXT_PROP_PAINT_INFO:
+ g_value_set_object (value, gimp_context_get_paint_info (context));
+ break;
+ case GIMP_CONTEXT_PROP_FOREGROUND:
+ {
+ GimpRGB color;
+
+ gimp_context_get_foreground (context, &color);
+ g_value_set_boxed (value, &color);
+ }
+ break;
+ case GIMP_CONTEXT_PROP_BACKGROUND:
+ {
+ GimpRGB color;
+
+ gimp_context_get_background (context, &color);
+ g_value_set_boxed (value, &color);
+ }
+ break;
+ case GIMP_CONTEXT_PROP_OPACITY:
+ g_value_set_double (value, gimp_context_get_opacity (context));
+ break;
+ case GIMP_CONTEXT_PROP_PAINT_MODE:
+ g_value_set_enum (value, gimp_context_get_paint_mode (context));
+ break;
+ case GIMP_CONTEXT_PROP_BRUSH:
+ g_value_set_object (value, gimp_context_get_brush (context));
+ break;
+ case GIMP_CONTEXT_PROP_DYNAMICS:
+ g_value_set_object (value, gimp_context_get_dynamics (context));
+ break;
+ case GIMP_CONTEXT_PROP_MYBRUSH:
+ g_value_set_object (value, gimp_context_get_mybrush (context));
+ break;
+ case GIMP_CONTEXT_PROP_PATTERN:
+ g_value_set_object (value, gimp_context_get_pattern (context));
+ break;
+ case GIMP_CONTEXT_PROP_GRADIENT:
+ g_value_set_object (value, gimp_context_get_gradient (context));
+ break;
+ case GIMP_CONTEXT_PROP_PALETTE:
+ g_value_set_object (value, gimp_context_get_palette (context));
+ break;
+ case GIMP_CONTEXT_PROP_FONT:
+ g_value_set_object (value, gimp_context_get_font (context));
+ break;
+ case GIMP_CONTEXT_PROP_TOOL_PRESET:
+ g_value_set_object (value, gimp_context_get_tool_preset (context));
+ break;
+ case GIMP_CONTEXT_PROP_BUFFER:
+ g_value_set_object (value, gimp_context_get_buffer (context));
+ break;
+ case GIMP_CONTEXT_PROP_IMAGEFILE:
+ g_value_set_object (value, gimp_context_get_imagefile (context));
+ break;
+ case GIMP_CONTEXT_PROP_TEMPLATE:
+ g_value_set_object (value, gimp_context_get_template (context));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static gint64
+gimp_context_get_memsize (GimpObject *object,
+ gint64 *gui_size)
+{
+ GimpContext *context = GIMP_CONTEXT (object);
+ gint64 memsize = 0;
+
+ memsize += gimp_string_get_memsize (context->tool_name);
+ memsize += gimp_string_get_memsize (context->paint_name);
+ memsize += gimp_string_get_memsize (context->brush_name);
+ memsize += gimp_string_get_memsize (context->dynamics_name);
+ memsize += gimp_string_get_memsize (context->mybrush_name);
+ memsize += gimp_string_get_memsize (context->pattern_name);
+ memsize += gimp_string_get_memsize (context->palette_name);
+ memsize += gimp_string_get_memsize (context->font_name);
+ memsize += gimp_string_get_memsize (context->tool_preset_name);
+ memsize += gimp_string_get_memsize (context->buffer_name);
+ memsize += gimp_string_get_memsize (context->imagefile_name);
+ memsize += gimp_string_get_memsize (context->template_name);
+
+ return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
+ gui_size);
+}
+
+static gboolean
+gimp_context_serialize (GimpConfig *config,
+ GimpConfigWriter *writer,
+ gpointer data)
+{
+ return gimp_config_serialize_changed_properties (config, writer);
+}
+
+static gboolean
+gimp_context_deserialize (GimpConfig *config,
+ GScanner *scanner,
+ gint nest_level,
+ gpointer data)
+{
+ GimpContext *context = GIMP_CONTEXT (config);
+ GimpLayerMode old_paint_mode = context->paint_mode;
+ gboolean success;
+
+ success = gimp_config_deserialize_properties (config, scanner, nest_level);
+
+ if (context->paint_mode != old_paint_mode)
+ {
+ if (context->paint_mode == GIMP_LAYER_MODE_OVERLAY_LEGACY)
+ g_object_set (context,
+ "paint-mode", GIMP_LAYER_MODE_SOFTLIGHT_LEGACY,
+ NULL);
+ }
+
+ return success;
+}
+
+static gboolean
+gimp_context_serialize_property (GimpConfig *config,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec,
+ GimpConfigWriter *writer)
+{
+ GimpContext *context = GIMP_CONTEXT (config);
+ GimpObject *serialize_obj;
+
+ /* serialize nothing if the property is not in serialize_props */
+ if (! ((1 << property_id) & context->serialize_props))
+ return TRUE;
+
+ switch (property_id)
+ {
+ case GIMP_CONTEXT_PROP_TOOL:
+ case GIMP_CONTEXT_PROP_PAINT_INFO:
+ case GIMP_CONTEXT_PROP_BRUSH:
+ case GIMP_CONTEXT_PROP_DYNAMICS:
+ case GIMP_CONTEXT_PROP_MYBRUSH:
+ case GIMP_CONTEXT_PROP_PATTERN:
+ case GIMP_CONTEXT_PROP_GRADIENT:
+ case GIMP_CONTEXT_PROP_PALETTE:
+ case GIMP_CONTEXT_PROP_FONT:
+ case GIMP_CONTEXT_PROP_TOOL_PRESET:
+ serialize_obj = g_value_get_object (value);
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ gimp_config_writer_open (writer, pspec->name);
+
+ if (serialize_obj)
+ gimp_config_writer_string (writer, gimp_object_get_name (serialize_obj));
+ else
+ gimp_config_writer_print (writer, "NULL", 4);
+
+ gimp_config_writer_close (writer);
+
+ return TRUE;
+}
+
+static gboolean
+gimp_context_deserialize_property (GimpConfig *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec,
+ GScanner *scanner,
+ GTokenType *expected)
+{
+ GimpContext *context = GIMP_CONTEXT (object);
+ GimpContainer *container;
+ gpointer standard;
+ gchar **name_loc;
+ gchar *object_name;
+
+ switch (property_id)
+ {
+ case GIMP_CONTEXT_PROP_TOOL:
+ container = context->gimp->tool_info_list;
+ standard = gimp_tool_info_get_standard (context->gimp);
+ name_loc = &context->tool_name;
+ break;
+
+ case GIMP_CONTEXT_PROP_PAINT_INFO:
+ container = context->gimp->paint_info_list;
+ standard = gimp_paint_info_get_standard (context->gimp);
+ name_loc = &context->paint_name;
+ break;
+
+ case GIMP_CONTEXT_PROP_BRUSH:
+ container = gimp_data_factory_get_container (context->gimp->brush_factory);
+ standard = gimp_brush_get_standard (context);
+ name_loc = &context->brush_name;
+ break;
+
+ case GIMP_CONTEXT_PROP_DYNAMICS:
+ container = gimp_data_factory_get_container (context->gimp->dynamics_factory);
+ standard = gimp_dynamics_get_standard (context);
+ name_loc = &context->dynamics_name;
+ break;
+
+ case GIMP_CONTEXT_PROP_MYBRUSH:
+ container = gimp_data_factory_get_container (context->gimp->mybrush_factory);
+ standard = gimp_mybrush_get_standard (context);
+ name_loc = &context->mybrush_name;
+ break;
+
+ case GIMP_CONTEXT_PROP_PATTERN:
+ container = gimp_data_factory_get_container (context->gimp->pattern_factory);
+ standard = gimp_pattern_get_standard (context);
+ name_loc = &context->pattern_name;
+ break;
+
+ case GIMP_CONTEXT_PROP_GRADIENT:
+ container = gimp_data_factory_get_container (context->gimp->gradient_factory);
+ standard = gimp_gradient_get_standard (context);
+ name_loc = &context->gradient_name;
+ break;
+
+ case GIMP_CONTEXT_PROP_PALETTE:
+ container = gimp_data_factory_get_container (context->gimp->palette_factory);
+ standard = gimp_palette_get_standard (context);
+ name_loc = &context->palette_name;
+ break;
+
+ case GIMP_CONTEXT_PROP_FONT:
+ container = gimp_data_factory_get_container (context->gimp->font_factory);
+ standard = gimp_font_get_standard ();
+ name_loc = &context->font_name;
+ break;
+
+ case GIMP_CONTEXT_PROP_TOOL_PRESET:
+ container = gimp_data_factory_get_container (context->gimp->tool_preset_factory);
+ standard = NULL;
+ name_loc = &context->tool_preset_name;
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ if (gimp_scanner_parse_identifier (scanner, "NULL"))
+ {
+ g_value_set_object (value, NULL);
+ }
+ else if (gimp_scanner_parse_string (scanner, &object_name))
+ {
+ GimpObject *deserialize_obj;
+
+ if (! object_name)
+ object_name = g_strdup ("");
+
+ deserialize_obj = gimp_container_get_child_by_name (container,
+ object_name);
+
+ if (! deserialize_obj)
+ {
+ g_value_set_object (value, standard);
+
+ g_free (*name_loc);
+ *name_loc = g_strdup (object_name);
+ }
+ else
+ {
+ g_value_set_object (value, deserialize_obj);
+ }
+
+ g_free (object_name);
+ }
+ else
+ {
+ *expected = G_TOKEN_STRING;
+ }
+
+ return TRUE;
+}
+
+static GimpConfig *
+gimp_context_duplicate (GimpConfig *config)
+{
+ GimpContext *context = GIMP_CONTEXT (config);
+ GimpContext *new;
+
+ new = GIMP_CONTEXT (parent_config_iface->duplicate (config));
+
+ COPY_NAME (context, new, tool_name);
+ COPY_NAME (context, new, paint_name);
+ COPY_NAME (context, new, brush_name);
+ COPY_NAME (context, new, dynamics_name);
+ COPY_NAME (context, new, mybrush_name);
+ COPY_NAME (context, new, pattern_name);
+ COPY_NAME (context, new, gradient_name);
+ COPY_NAME (context, new, palette_name);
+ COPY_NAME (context, new, font_name);
+ COPY_NAME (context, new, tool_preset_name);
+ COPY_NAME (context, new, buffer_name);
+ COPY_NAME (context, new, imagefile_name);
+ COPY_NAME (context, new, template_name);
+
+ return GIMP_CONFIG (new);
+}
+
+static gboolean
+gimp_context_copy (GimpConfig *src,
+ GimpConfig *dest,
+ GParamFlags flags)
+{
+ GimpContext *src_context = GIMP_CONTEXT (src);
+ GimpContext *dest_context = GIMP_CONTEXT (dest);
+ gboolean success = parent_config_iface->copy (src, dest, flags);
+
+ COPY_NAME (src_context, dest_context, tool_name);
+ COPY_NAME (src_context, dest_context, paint_name);
+ COPY_NAME (src_context, dest_context, brush_name);
+ COPY_NAME (src_context, dest_context, dynamics_name);
+ COPY_NAME (src_context, dest_context, mybrush_name);
+ COPY_NAME (src_context, dest_context, pattern_name);
+ COPY_NAME (src_context, dest_context, gradient_name);
+ COPY_NAME (src_context, dest_context, palette_name);
+ COPY_NAME (src_context, dest_context, font_name);
+ COPY_NAME (src_context, dest_context, tool_preset_name);
+ COPY_NAME (src_context, dest_context, buffer_name);
+ COPY_NAME (src_context, dest_context, imagefile_name);
+ COPY_NAME (src_context, dest_context, template_name);
+
+ return success;
+}
+
+
+/*****************************************************************************/
+/* public functions ********************************************************/
+
+GimpContext *
+gimp_context_new (Gimp *gimp,
+ const gchar *name,
+ GimpContext *template)
+{
+ GimpContext *context;
+
+ g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (template == NULL || GIMP_IS_CONTEXT (template), NULL);
+
+ context = g_object_new (GIMP_TYPE_CONTEXT,
+ "name", name,
+ "gimp", gimp,
+ NULL);
+
+ if (template)
+ {
+ context->defined_props = template->defined_props;
+
+ gimp_context_copy_properties (template, context,
+ GIMP_CONTEXT_PROP_MASK_ALL);
+ }
+
+ return context;
+}
+
+GimpContext *
+gimp_context_get_parent (GimpContext *context)
+{
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+
+ return context->parent;
+}
+
+static void
+gimp_context_parent_notify (GimpContext *parent,
+ GParamSpec *pspec,
+ GimpContext *context)
+{
+ if (pspec->owner_type == GIMP_TYPE_CONTEXT)
+ {
+ GimpContextPropType prop = pspec->param_id;
+
+ /* copy from parent if the changed property is undefined;
+ * ignore properties that are not context properties, for
+ * example notifications on the context's "gimp" property
+ */
+ if ((prop >= GIMP_CONTEXT_PROP_FIRST) &&
+ (prop <= GIMP_CONTEXT_PROP_LAST) &&
+ ! ((1 << prop) & context->defined_props))
+ {
+ gimp_context_copy_property (parent, context, prop);
+ }
+ }
+}
+
+void
+gimp_context_set_parent (GimpContext *context,
+ GimpContext *parent)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+ g_return_if_fail (parent == NULL || GIMP_IS_CONTEXT (parent));
+ g_return_if_fail (parent == NULL || parent->parent != context);
+ g_return_if_fail (context != parent);
+
+ if (context->parent == parent)
+ return;
+
+ if (context->parent)
+ {
+ g_signal_handlers_disconnect_by_func (context->parent,
+ gimp_context_parent_notify,
+ context);
+
+ g_object_remove_weak_pointer (G_OBJECT (context->parent),
+ (gpointer) &context->parent);
+ }
+
+ context->parent = parent;
+
+ if (parent)
+ {
+ g_object_add_weak_pointer (G_OBJECT (context->parent),
+ (gpointer) &context->parent);
+
+ /* copy all undefined properties from the new parent */
+ gimp_context_copy_properties (parent, context,
+ ~context->defined_props &
+ GIMP_CONTEXT_PROP_MASK_ALL);
+
+ g_signal_connect_object (parent, "notify",
+ G_CALLBACK (gimp_context_parent_notify),
+ context,
+ 0);
+ }
+}
+
+
+/* define / undefinine context properties */
+
+void
+gimp_context_define_property (GimpContext *context,
+ GimpContextPropType prop,
+ gboolean defined)
+{
+ GimpContextPropMask mask;
+
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+ g_return_if_fail ((prop >= GIMP_CONTEXT_PROP_FIRST) &&
+ (prop <= GIMP_CONTEXT_PROP_LAST));
+
+ mask = (1 << prop);
+
+ if (defined)
+ {
+ if (! (context->defined_props & mask))
+ {
+ context->defined_props |= mask;
+ }
+ }
+ else
+ {
+ if (context->defined_props & mask)
+ {
+ context->defined_props &= ~mask;
+
+ if (context->parent)
+ gimp_context_copy_property (context->parent, context, prop);
+ }
+ }
+}
+
+gboolean
+gimp_context_property_defined (GimpContext *context,
+ GimpContextPropType prop)
+{
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), FALSE);
+
+ return (context->defined_props & (1 << prop)) ? TRUE : FALSE;
+}
+
+void
+gimp_context_define_properties (GimpContext *context,
+ GimpContextPropMask prop_mask,
+ gboolean defined)
+{
+ GimpContextPropType prop;
+
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ for (prop = GIMP_CONTEXT_PROP_FIRST; prop <= GIMP_CONTEXT_PROP_LAST; prop++)
+ if ((1 << prop) & prop_mask)
+ gimp_context_define_property (context, prop, defined);
+}
+
+
+/* specify which context properties will be serialized */
+
+void
+gimp_context_set_serialize_properties (GimpContext *context,
+ GimpContextPropMask props_mask)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ context->serialize_props = props_mask;
+}
+
+GimpContextPropMask
+gimp_context_get_serialize_properties (GimpContext *context)
+{
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), 0);
+
+ return context->serialize_props;
+}
+
+
+/* copying context properties */
+
+void
+gimp_context_copy_property (GimpContext *src,
+ GimpContext *dest,
+ GimpContextPropType prop)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (src));
+ g_return_if_fail (GIMP_IS_CONTEXT (dest));
+ g_return_if_fail ((prop >= GIMP_CONTEXT_PROP_FIRST) &&
+ (prop <= GIMP_CONTEXT_PROP_LAST));
+
+ switch (prop)
+ {
+ case GIMP_CONTEXT_PROP_IMAGE:
+ gimp_context_real_set_image (dest, src->image);
+ break;
+
+ case GIMP_CONTEXT_PROP_DISPLAY:
+ gimp_context_real_set_display (dest, src->display);
+ break;
+
+ case GIMP_CONTEXT_PROP_TOOL:
+ gimp_context_real_set_tool (dest, src->tool_info);
+ COPY_NAME (src, dest, tool_name);
+ break;
+
+ case GIMP_CONTEXT_PROP_PAINT_INFO:
+ gimp_context_real_set_paint_info (dest, src->paint_info);
+ COPY_NAME (src, dest, paint_name);
+ break;
+
+ case GIMP_CONTEXT_PROP_FOREGROUND:
+ gimp_context_real_set_foreground (dest, &src->foreground);
+ break;
+
+ case GIMP_CONTEXT_PROP_BACKGROUND:
+ gimp_context_real_set_background (dest, &src->background);
+ break;
+
+ case GIMP_CONTEXT_PROP_OPACITY:
+ gimp_context_real_set_opacity (dest, src->opacity);
+ break;
+
+ case GIMP_CONTEXT_PROP_PAINT_MODE:
+ gimp_context_real_set_paint_mode (dest, src->paint_mode);
+ break;
+
+ case GIMP_CONTEXT_PROP_BRUSH:
+ gimp_context_real_set_brush (dest, src->brush);
+ COPY_NAME (src, dest, brush_name);
+ break;
+
+ case GIMP_CONTEXT_PROP_DYNAMICS:
+ gimp_context_real_set_dynamics (dest, src->dynamics);
+ COPY_NAME (src, dest, dynamics_name);
+ break;
+
+ case GIMP_CONTEXT_PROP_MYBRUSH:
+ gimp_context_real_set_mybrush (dest, src->mybrush);
+ COPY_NAME (src, dest, mybrush_name);
+ break;
+
+ case GIMP_CONTEXT_PROP_PATTERN:
+ gimp_context_real_set_pattern (dest, src->pattern);
+ COPY_NAME (src, dest, pattern_name);
+ break;
+
+ case GIMP_CONTEXT_PROP_GRADIENT:
+ gimp_context_real_set_gradient (dest, src->gradient);
+ COPY_NAME (src, dest, gradient_name);
+ break;
+
+ case GIMP_CONTEXT_PROP_PALETTE:
+ gimp_context_real_set_palette (dest, src->palette);
+ COPY_NAME (src, dest, palette_name);
+ break;
+
+ case GIMP_CONTEXT_PROP_FONT:
+ gimp_context_real_set_font (dest, src->font);
+ COPY_NAME (src, dest, font_name);
+ break;
+
+ case GIMP_CONTEXT_PROP_TOOL_PRESET:
+ gimp_context_real_set_tool_preset (dest, src->tool_preset);
+ COPY_NAME (src, dest, tool_preset_name);
+ break;
+
+ case GIMP_CONTEXT_PROP_BUFFER:
+ gimp_context_real_set_buffer (dest, src->buffer);
+ COPY_NAME (src, dest, buffer_name);
+ break;
+
+ case GIMP_CONTEXT_PROP_IMAGEFILE:
+ gimp_context_real_set_imagefile (dest, src->imagefile);
+ COPY_NAME (src, dest, imagefile_name);
+ break;
+
+ case GIMP_CONTEXT_PROP_TEMPLATE:
+ gimp_context_real_set_template (dest, src->template);
+ COPY_NAME (src, dest, template_name);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void
+gimp_context_copy_properties (GimpContext *src,
+ GimpContext *dest,
+ GimpContextPropMask prop_mask)
+{
+ GimpContextPropType prop;
+
+ g_return_if_fail (GIMP_IS_CONTEXT (src));
+ g_return_if_fail (GIMP_IS_CONTEXT (dest));
+
+ for (prop = GIMP_CONTEXT_PROP_FIRST; prop <= GIMP_CONTEXT_PROP_LAST; prop++)
+ if ((1 << prop) & prop_mask)
+ gimp_context_copy_property (src, dest, prop);
+}
+
+
+/* attribute access functions */
+
+/*****************************************************************************/
+/* manipulate by GType *****************************************************/
+
+GimpContextPropType
+gimp_context_type_to_property (GType type)
+{
+ GimpContextPropType prop;
+
+ for (prop = GIMP_CONTEXT_PROP_FIRST; prop <= GIMP_CONTEXT_PROP_LAST; prop++)
+ {
+ if (g_type_is_a (type, gimp_context_prop_types[prop]))
+ return prop;
+ }
+
+ return -1;
+}
+
+const gchar *
+gimp_context_type_to_prop_name (GType type)
+{
+ GimpContextPropType prop;
+
+ for (prop = GIMP_CONTEXT_PROP_FIRST; prop <= GIMP_CONTEXT_PROP_LAST; prop++)
+ {
+ if (g_type_is_a (type, gimp_context_prop_types[prop]))
+ return gimp_context_prop_names[prop];
+ }
+
+ return NULL;
+}
+
+const gchar *
+gimp_context_type_to_signal_name (GType type)
+{
+ GimpContextPropType prop;
+
+ for (prop = GIMP_CONTEXT_PROP_FIRST; prop <= GIMP_CONTEXT_PROP_LAST; prop++)
+ {
+ if (g_type_is_a (type, gimp_context_prop_types[prop]))
+ return g_signal_name (gimp_context_signals[prop]);
+ }
+
+ return NULL;
+}
+
+GimpObject *
+gimp_context_get_by_type (GimpContext *context,
+ GType type)
+{
+ GimpContextPropType prop;
+ GimpObject *object = NULL;
+
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+
+ prop = gimp_context_type_to_property (type);
+
+ g_return_val_if_fail (prop != -1, NULL);
+
+ g_object_get (context,
+ gimp_context_prop_names[prop], &object,
+ NULL);
+
+ /* g_object_get() refs the object, this function however is a getter,
+ * which usually doesn't ref it's return value
+ */
+ if (object)
+ g_object_unref (object);
+
+ return object;
+}
+
+void
+gimp_context_set_by_type (GimpContext *context,
+ GType type,
+ GimpObject *object)
+{
+ GimpContextPropType prop;
+ GParamSpec *pspec;
+ GValue value = G_VALUE_INIT;
+
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+ g_return_if_fail (object == NULL || G_IS_OBJECT (object));
+
+ prop = gimp_context_type_to_property (type);
+
+ g_return_if_fail (prop != -1);
+
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (context),
+ gimp_context_prop_names[prop]);
+
+ g_return_if_fail (pspec != NULL);
+
+ g_value_init (&value, pspec->value_type);
+ g_value_set_object (&value, object);
+
+ /* we use gimp_context_set_property() (which in turn only calls
+ * gimp_context_set_foo() functions) instead of the much more obvious
+ * g_object_set(); this avoids g_object_freeze_notify()/thaw_notify()
+ * around the g_object_set() and makes GimpContext callbacks being
+ * called in a much more predictable order. See bug #731279.
+ */
+ gimp_context_set_property (G_OBJECT (context),
+ pspec->param_id,
+ (const GValue *) &value,
+ pspec);
+
+ g_value_unset (&value);
+}
+
+void
+gimp_context_changed_by_type (GimpContext *context,
+ GType type)
+{
+ GimpContextPropType prop;
+ GimpObject *object;
+
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ prop = gimp_context_type_to_property (type);
+
+ g_return_if_fail (prop != -1);
+
+ object = gimp_context_get_by_type (context, type);
+
+ g_signal_emit (context,
+ gimp_context_signals[prop], 0,
+ object);
+}
+
+
+/*****************************************************************************/
+/* image *******************************************************************/
+
+GimpImage *
+gimp_context_get_image (GimpContext *context)
+{
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+
+ return context->image;
+}
+
+void
+gimp_context_set_image (GimpContext *context,
+ GimpImage *image)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+ g_return_if_fail (image == NULL || GIMP_IS_IMAGE (image));
+
+ context_find_defined (context, GIMP_CONTEXT_PROP_IMAGE);
+
+ gimp_context_real_set_image (context, image);
+}
+
+void
+gimp_context_image_changed (GimpContext *context)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ g_signal_emit (context,
+ gimp_context_signals[IMAGE_CHANGED], 0,
+ context->image);
+}
+
+static void
+gimp_context_image_removed (GimpContainer *container,
+ GimpImage *image,
+ GimpContext *context)
+{
+ if (context->image == image)
+ gimp_context_real_set_image (context, NULL);
+}
+
+static void
+gimp_context_real_set_image (GimpContext *context,
+ GimpImage *image)
+{
+ if (context->image == image)
+ return;
+
+ context->image = image;
+
+ g_object_notify (G_OBJECT (context), "image");
+ gimp_context_image_changed (context);
+}
+
+
+/*****************************************************************************/
+/* display *****************************************************************/
+
+gpointer
+gimp_context_get_display (GimpContext *context)
+{
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+
+ return context->display;
+}
+
+void
+gimp_context_set_display (GimpContext *context,
+ gpointer display)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+ g_return_if_fail (display == NULL || GIMP_IS_OBJECT (display));
+
+ context_find_defined (context, GIMP_CONTEXT_PROP_DISPLAY);
+
+ gimp_context_real_set_display (context, display);
+}
+
+void
+gimp_context_display_changed (GimpContext *context)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ g_signal_emit (context,
+ gimp_context_signals[DISPLAY_CHANGED], 0,
+ context->display);
+}
+
+static void
+gimp_context_display_removed (GimpContainer *container,
+ gpointer display,
+ GimpContext *context)
+{
+ if (context->display == display)
+ gimp_context_real_set_display (context, NULL);
+}
+
+static void
+gimp_context_real_set_display (GimpContext *context,
+ gpointer display)
+{
+ GimpObject *old_display;
+
+ if (context->display == display)
+ {
+ /* make sure that setting a display *always* sets the image
+ * to that display's image, even if the display already
+ * matches
+ */
+ if (display)
+ {
+ GimpImage *image;
+
+ g_object_get (display, "image", &image, NULL);
+
+ gimp_context_real_set_image (context, image);
+
+ if (image)
+ g_object_unref (image);
+ }
+
+ return;
+ }
+
+ old_display = context->display;
+
+ context->display = display;
+
+ if (context->display)
+ {
+ GimpImage *image;
+
+ g_object_get (display, "image", &image, NULL);
+
+ gimp_context_real_set_image (context, image);
+
+ if (image)
+ g_object_unref (image);
+ }
+ else if (old_display)
+ {
+ gimp_context_real_set_image (context, NULL);
+ }
+
+ g_object_notify (G_OBJECT (context), "display");
+ gimp_context_display_changed (context);
+}
+
+
+/*****************************************************************************/
+/* tool ********************************************************************/
+
+GimpToolInfo *
+gimp_context_get_tool (GimpContext *context)
+{
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+
+ return context->tool_info;
+}
+
+void
+gimp_context_set_tool (GimpContext *context,
+ GimpToolInfo *tool_info)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+ g_return_if_fail (tool_info == NULL || GIMP_IS_TOOL_INFO (tool_info));
+
+ context_find_defined (context, GIMP_CONTEXT_PROP_TOOL);
+
+ gimp_context_real_set_tool (context, tool_info);
+}
+
+void
+gimp_context_tool_changed (GimpContext *context)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ g_signal_emit (context,
+ gimp_context_signals[TOOL_CHANGED], 0,
+ context->tool_info);
+}
+
+static void
+gimp_context_tool_dirty (GimpToolInfo *tool_info,
+ GimpContext *context)
+{
+ g_free (context->tool_name);
+ context->tool_name = g_strdup (gimp_object_get_name (tool_info));
+
+ g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
+ GIMP_CONTEXT_PROP_TOOL);
+}
+
+static void
+gimp_context_tool_list_thaw (GimpContainer *container,
+ GimpContext *context)
+{
+ GimpToolInfo *tool_info;
+
+ if (! context->tool_name)
+ context->tool_name = g_strdup ("gimp-paintbrush-tool");
+
+ tool_info = gimp_context_find_object (context, container,
+ context->tool_name,
+ gimp_tool_info_get_standard (context->gimp));
+
+ gimp_context_real_set_tool (context, tool_info);
+}
+
+static void
+gimp_context_tool_removed (GimpContainer *container,
+ GimpToolInfo *tool_info,
+ GimpContext *context)
+{
+ if (tool_info == context->tool_info)
+ {
+ g_signal_handlers_disconnect_by_func (context->tool_info,
+ gimp_context_tool_dirty,
+ context);
+ g_clear_object (&context->tool_info);
+
+ if (! gimp_container_frozen (container))
+ gimp_context_tool_list_thaw (container, context);
+ }
+}
+
+static void
+gimp_context_real_set_tool (GimpContext *context,
+ GimpToolInfo *tool_info)
+{
+ if (context->tool_info == tool_info)
+ return;
+
+ if (context->tool_name &&
+ tool_info != gimp_tool_info_get_standard (context->gimp))
+ {
+ g_clear_pointer (&context->tool_name, g_free);
+ }
+
+ if (context->tool_info)
+ g_signal_handlers_disconnect_by_func (context->tool_info,
+ gimp_context_tool_dirty,
+ context);
+
+ g_set_object (&context->tool_info, tool_info);
+
+ if (tool_info)
+ {
+ g_signal_connect_object (tool_info, "name-changed",
+ G_CALLBACK (gimp_context_tool_dirty),
+ context,
+ 0);
+
+ if (tool_info != gimp_tool_info_get_standard (context->gimp))
+ context->tool_name = g_strdup (gimp_object_get_name (tool_info));
+
+ if (tool_info->paint_info)
+ gimp_context_real_set_paint_info (context, tool_info->paint_info);
+ }
+
+ g_object_notify (G_OBJECT (context), "tool");
+ gimp_context_tool_changed (context);
+}
+
+
+/*****************************************************************************/
+/* paint info **************************************************************/
+
+GimpPaintInfo *
+gimp_context_get_paint_info (GimpContext *context)
+{
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+
+ return context->paint_info;
+}
+
+void
+gimp_context_set_paint_info (GimpContext *context,
+ GimpPaintInfo *paint_info)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+ g_return_if_fail (paint_info == NULL || GIMP_IS_PAINT_INFO (paint_info));
+
+ context_find_defined (context, GIMP_CONTEXT_PROP_PAINT_INFO);
+
+ gimp_context_real_set_paint_info (context, paint_info);
+}
+
+void
+gimp_context_paint_info_changed (GimpContext *context)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ g_signal_emit (context,
+ gimp_context_signals[PAINT_INFO_CHANGED], 0,
+ context->paint_info);
+}
+
+static void
+gimp_context_paint_info_dirty (GimpPaintInfo *paint_info,
+ GimpContext *context)
+{
+ g_free (context->paint_name);
+ context->paint_name = g_strdup (gimp_object_get_name (paint_info));
+
+ g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
+ GIMP_CONTEXT_PROP_PAINT_INFO);
+}
+
+/* the global paint info list is there again after refresh */
+static void
+gimp_context_paint_info_list_thaw (GimpContainer *container,
+ GimpContext *context)
+{
+ GimpPaintInfo *paint_info;
+
+ if (! context->paint_name)
+ context->paint_name = g_strdup ("gimp-paintbrush");
+
+ paint_info = gimp_context_find_object (context, container,
+ context->paint_name,
+ gimp_paint_info_get_standard (context->gimp));
+
+ gimp_context_real_set_paint_info (context, paint_info);
+}
+
+static void
+gimp_context_paint_info_removed (GimpContainer *container,
+ GimpPaintInfo *paint_info,
+ GimpContext *context)
+{
+ if (paint_info == context->paint_info)
+ {
+ g_signal_handlers_disconnect_by_func (context->paint_info,
+ gimp_context_paint_info_dirty,
+ context);
+ g_clear_object (&context->paint_info);
+
+ if (! gimp_container_frozen (container))
+ gimp_context_paint_info_list_thaw (container, context);
+ }
+}
+
+static void
+gimp_context_real_set_paint_info (GimpContext *context,
+ GimpPaintInfo *paint_info)
+{
+ if (context->paint_info == paint_info)
+ return;
+
+ if (context->paint_name &&
+ paint_info != gimp_paint_info_get_standard (context->gimp))
+ {
+ g_clear_pointer (&context->paint_name, g_free);
+ }
+
+ if (context->paint_info)
+ g_signal_handlers_disconnect_by_func (context->paint_info,
+ gimp_context_paint_info_dirty,
+ context);
+
+ g_set_object (&context->paint_info, paint_info);
+
+ if (paint_info)
+ {
+ g_signal_connect_object (paint_info, "name-changed",
+ G_CALLBACK (gimp_context_paint_info_dirty),
+ context,
+ 0);
+
+ if (paint_info != gimp_paint_info_get_standard (context->gimp))
+ context->paint_name = g_strdup (gimp_object_get_name (paint_info));
+ }
+
+ g_object_notify (G_OBJECT (context), "paint-info");
+ gimp_context_paint_info_changed (context);
+}
+
+
+/*****************************************************************************/
+/* foreground color ********************************************************/
+
+void
+gimp_context_get_foreground (GimpContext *context,
+ GimpRGB *color)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+ g_return_if_fail (color != NULL);
+
+ *color = context->foreground;
+}
+
+void
+gimp_context_set_foreground (GimpContext *context,
+ const GimpRGB *color)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+ g_return_if_fail (color != NULL);
+
+ context_find_defined (context, GIMP_CONTEXT_PROP_FOREGROUND);
+
+ gimp_context_real_set_foreground (context, color);
+}
+
+void
+gimp_context_foreground_changed (GimpContext *context)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ g_signal_emit (context,
+ gimp_context_signals[FOREGROUND_CHANGED], 0,
+ &context->foreground);
+}
+
+static void
+gimp_context_real_set_foreground (GimpContext *context,
+ const GimpRGB *color)
+{
+ if (gimp_rgba_distance (&context->foreground, color) < RGBA_EPSILON)
+ return;
+
+ context->foreground = *color;
+ gimp_rgb_set_alpha (&context->foreground, GIMP_OPACITY_OPAQUE);
+
+ g_object_notify (G_OBJECT (context), "foreground");
+ gimp_context_foreground_changed (context);
+}
+
+
+/*****************************************************************************/
+/* background color ********************************************************/
+
+void
+gimp_context_get_background (GimpContext *context,
+ GimpRGB *color)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ g_return_if_fail (color != NULL);
+
+ *color = context->background;
+}
+
+void
+gimp_context_set_background (GimpContext *context,
+ const GimpRGB *color)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+ g_return_if_fail (color != NULL);
+
+ context_find_defined (context, GIMP_CONTEXT_PROP_BACKGROUND);
+
+ gimp_context_real_set_background (context, color);
+}
+
+void
+gimp_context_background_changed (GimpContext *context)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ g_signal_emit (context,
+ gimp_context_signals[BACKGROUND_CHANGED], 0,
+ &context->background);
+}
+
+static void
+gimp_context_real_set_background (GimpContext *context,
+ const GimpRGB *color)
+{
+ if (gimp_rgba_distance (&context->background, color) < RGBA_EPSILON)
+ return;
+
+ context->background = *color;
+ gimp_rgb_set_alpha (&context->background, GIMP_OPACITY_OPAQUE);
+
+ g_object_notify (G_OBJECT (context), "background");
+ gimp_context_background_changed (context);
+}
+
+
+/*****************************************************************************/
+/* color utility functions *************************************************/
+
+void
+gimp_context_set_default_colors (GimpContext *context)
+{
+ GimpContext *bg_context;
+ GimpRGB fg;
+ GimpRGB bg;
+
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ bg_context = context;
+
+ context_find_defined (context, GIMP_CONTEXT_PROP_FOREGROUND);
+ context_find_defined (bg_context, GIMP_CONTEXT_PROP_BACKGROUND);
+
+ gimp_rgba_set (&fg, 0.0, 0.0, 0.0, GIMP_OPACITY_OPAQUE);
+ gimp_rgba_set (&bg, 1.0, 1.0, 1.0, GIMP_OPACITY_OPAQUE);
+
+ gimp_context_real_set_foreground (context, &fg);
+ gimp_context_real_set_background (bg_context, &bg);
+}
+
+void
+gimp_context_swap_colors (GimpContext *context)
+{
+ GimpContext *bg_context;
+ GimpRGB fg;
+ GimpRGB bg;
+
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ bg_context = context;
+
+ context_find_defined (context, GIMP_CONTEXT_PROP_FOREGROUND);
+ context_find_defined (bg_context, GIMP_CONTEXT_PROP_BACKGROUND);
+
+ gimp_context_get_foreground (context, &fg);
+ gimp_context_get_background (bg_context, &bg);
+
+ gimp_context_real_set_foreground (context, &bg);
+ gimp_context_real_set_background (bg_context, &fg);
+}
+
+
+/*****************************************************************************/
+/* opacity *****************************************************************/
+
+gdouble
+gimp_context_get_opacity (GimpContext *context)
+{
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), GIMP_OPACITY_OPAQUE);
+
+ return context->opacity;
+}
+
+void
+gimp_context_set_opacity (GimpContext *context,
+ gdouble opacity)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ context_find_defined (context, GIMP_CONTEXT_PROP_OPACITY);
+
+ gimp_context_real_set_opacity (context, opacity);
+}
+
+void
+gimp_context_opacity_changed (GimpContext *context)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ g_signal_emit (context,
+ gimp_context_signals[OPACITY_CHANGED], 0,
+ context->opacity);
+}
+
+static void
+gimp_context_real_set_opacity (GimpContext *context,
+ gdouble opacity)
+{
+ if (context->opacity == opacity)
+ return;
+
+ context->opacity = opacity;
+
+ g_object_notify (G_OBJECT (context), "opacity");
+ gimp_context_opacity_changed (context);
+}
+
+
+/*****************************************************************************/
+/* paint mode **************************************************************/
+
+GimpLayerMode
+gimp_context_get_paint_mode (GimpContext *context)
+{
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), GIMP_LAYER_MODE_NORMAL);
+
+ return context->paint_mode;
+}
+
+void
+gimp_context_set_paint_mode (GimpContext *context,
+ GimpLayerMode paint_mode)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ context_find_defined (context, GIMP_CONTEXT_PROP_PAINT_MODE);
+
+ gimp_context_real_set_paint_mode (context, paint_mode);
+}
+
+void
+gimp_context_paint_mode_changed (GimpContext *context)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ g_signal_emit (context,
+ gimp_context_signals[PAINT_MODE_CHANGED], 0,
+ context->paint_mode);
+}
+
+static void
+gimp_context_real_set_paint_mode (GimpContext *context,
+ GimpLayerMode paint_mode)
+{
+ if (context->paint_mode == paint_mode)
+ return;
+
+ context->paint_mode = paint_mode;
+
+ g_object_notify (G_OBJECT (context), "paint-mode");
+ gimp_context_paint_mode_changed (context);
+}
+
+
+/*****************************************************************************/
+/* brush *******************************************************************/
+
+GimpBrush *
+gimp_context_get_brush (GimpContext *context)
+{
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+
+ return context->brush;
+}
+
+void
+gimp_context_set_brush (GimpContext *context,
+ GimpBrush *brush)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+ g_return_if_fail (brush == NULL || GIMP_IS_BRUSH (brush));
+
+ context_find_defined (context, GIMP_CONTEXT_PROP_BRUSH);
+
+ gimp_context_real_set_brush (context, brush);
+}
+
+void
+gimp_context_brush_changed (GimpContext *context)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ g_signal_emit (context,
+ gimp_context_signals[BRUSH_CHANGED], 0,
+ context->brush);
+}
+
+static void
+gimp_context_brush_dirty (GimpBrush *brush,
+ GimpContext *context)
+{
+ g_free (context->brush_name);
+ context->brush_name = g_strdup (gimp_object_get_name (brush));
+
+ g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
+ GIMP_CONTEXT_PROP_BRUSH);
+}
+
+static void
+gimp_context_brush_list_thaw (GimpContainer *container,
+ GimpContext *context)
+{
+ GimpBrush *brush;
+
+ if (! context->brush_name)
+ context->brush_name = g_strdup (context->gimp->config->default_brush);
+
+ brush = gimp_context_find_object (context, container,
+ context->brush_name,
+ gimp_brush_get_standard (context));
+
+ gimp_context_real_set_brush (context, brush);
+}
+
+/* the active brush disappeared */
+static void
+gimp_context_brush_removed (GimpContainer *container,
+ GimpBrush *brush,
+ GimpContext *context)
+{
+ if (brush == context->brush)
+ {
+ g_signal_handlers_disconnect_by_func (context->brush,
+ gimp_context_brush_dirty,
+ context);
+ g_clear_object (&context->brush);
+
+ if (! gimp_container_frozen (container))
+ gimp_context_brush_list_thaw (container, context);
+ }
+}
+
+static void
+gimp_context_real_set_brush (GimpContext *context,
+ GimpBrush *brush)
+{
+ if (context->brush == brush)
+ return;
+
+ if (context->brush_name &&
+ brush != GIMP_BRUSH (gimp_brush_get_standard (context)))
+ {
+ g_clear_pointer (&context->brush_name, g_free);
+ }
+
+ if (context->brush)
+ g_signal_handlers_disconnect_by_func (context->brush,
+ gimp_context_brush_dirty,
+ context);
+
+ g_set_object (&context->brush, brush);
+
+ if (brush)
+ {
+ g_signal_connect_object (brush, "name-changed",
+ G_CALLBACK (gimp_context_brush_dirty),
+ context,
+ 0);
+
+ if (brush != GIMP_BRUSH (gimp_brush_get_standard (context)))
+ context->brush_name = g_strdup (gimp_object_get_name (brush));
+ }
+
+ g_object_notify (G_OBJECT (context), "brush");
+ gimp_context_brush_changed (context);
+}
+
+
+/*****************************************************************************/
+/* dynamics *****************************************************************/
+
+GimpDynamics *
+gimp_context_get_dynamics (GimpContext *context)
+{
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+
+ return context->dynamics;
+}
+
+void
+gimp_context_set_dynamics (GimpContext *context,
+ GimpDynamics *dynamics)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+ g_return_if_fail (dynamics == NULL || GIMP_IS_DYNAMICS (dynamics));
+
+ context_find_defined (context, GIMP_CONTEXT_PROP_DYNAMICS);
+
+ gimp_context_real_set_dynamics (context, dynamics);
+}
+
+void
+gimp_context_dynamics_changed (GimpContext *context)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ g_signal_emit (context,
+ gimp_context_signals[DYNAMICS_CHANGED], 0,
+ context->dynamics);
+}
+
+static void
+gimp_context_dynamics_dirty (GimpDynamics *dynamics,
+ GimpContext *context)
+{
+ g_free (context->dynamics_name);
+ context->dynamics_name = g_strdup (gimp_object_get_name (dynamics));
+
+ g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
+ GIMP_CONTEXT_PROP_DYNAMICS);
+}
+
+static void
+gimp_context_dynamics_removed (GimpContainer *container,
+ GimpDynamics *dynamics,
+ GimpContext *context)
+{
+ if (dynamics == context->dynamics)
+ {
+ g_signal_handlers_disconnect_by_func (context->dynamics,
+ gimp_context_dynamics_dirty,
+ context);
+ g_clear_object (&context->dynamics);
+
+ if (! gimp_container_frozen (container))
+ gimp_context_dynamics_list_thaw (container, context);
+ }
+}
+
+static void
+gimp_context_dynamics_list_thaw (GimpContainer *container,
+ GimpContext *context)
+{
+ GimpDynamics *dynamics;
+
+ if (! context->dynamics_name)
+ context->dynamics_name = g_strdup (context->gimp->config->default_dynamics);
+
+ dynamics = gimp_context_find_object (context, container,
+ context->dynamics_name,
+ gimp_dynamics_get_standard (context));
+
+ gimp_context_real_set_dynamics (context, dynamics);
+}
+
+static void
+gimp_context_real_set_dynamics (GimpContext *context,
+ GimpDynamics *dynamics)
+{
+ if (context->dynamics == dynamics)
+ return;
+
+ if (context->dynamics_name &&
+ dynamics != GIMP_DYNAMICS (gimp_dynamics_get_standard (context)))
+ {
+ g_clear_pointer (&context->dynamics_name, g_free);
+ }
+
+ if (context->dynamics)
+ g_signal_handlers_disconnect_by_func (context->dynamics,
+ gimp_context_dynamics_dirty,
+ context);
+
+ g_set_object (&context->dynamics, dynamics);
+
+ if (dynamics)
+ {
+ g_signal_connect_object (dynamics, "name-changed",
+ G_CALLBACK (gimp_context_dynamics_dirty),
+ context,
+ 0);
+
+ if (dynamics != GIMP_DYNAMICS (gimp_dynamics_get_standard (context)))
+ context->dynamics_name = g_strdup (gimp_object_get_name (dynamics));
+ }
+
+ g_object_notify (G_OBJECT (context), "dynamics");
+ gimp_context_dynamics_changed (context);
+}
+
+
+/*****************************************************************************/
+/* mybrush *****************************************************************/
+
+GimpMybrush *
+gimp_context_get_mybrush (GimpContext *context)
+{
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+
+ return context->mybrush;
+}
+
+void
+gimp_context_set_mybrush (GimpContext *context,
+ GimpMybrush *brush)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+ g_return_if_fail (brush == NULL || GIMP_IS_MYBRUSH (brush));
+
+ context_find_defined (context, GIMP_CONTEXT_PROP_MYBRUSH);
+
+ gimp_context_real_set_mybrush (context, brush);
+}
+
+void
+gimp_context_mybrush_changed (GimpContext *context)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ g_signal_emit (context,
+ gimp_context_signals[MYBRUSH_CHANGED], 0,
+ context->mybrush);
+}
+
+static void
+gimp_context_mybrush_dirty (GimpMybrush *brush,
+ GimpContext *context)
+{
+ g_free (context->mybrush_name);
+ context->mybrush_name = g_strdup (gimp_object_get_name (brush));
+
+ g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
+ GIMP_CONTEXT_PROP_MYBRUSH);
+}
+
+static void
+gimp_context_mybrush_list_thaw (GimpContainer *container,
+ GimpContext *context)
+{
+ GimpMybrush *brush;
+
+ if (! context->mybrush_name)
+ context->mybrush_name = g_strdup (context->gimp->config->default_mypaint_brush);
+
+ brush = gimp_context_find_object (context, container,
+ context->mybrush_name,
+ gimp_mybrush_get_standard (context));
+
+ gimp_context_real_set_mybrush (context, brush);
+}
+
+static void
+gimp_context_mybrush_removed (GimpContainer *container,
+ GimpMybrush *brush,
+ GimpContext *context)
+{
+ if (brush == context->mybrush)
+ {
+ g_signal_handlers_disconnect_by_func (context->mybrush,
+ gimp_context_mybrush_dirty,
+ context);
+ g_clear_object (&context->mybrush);
+
+ if (! gimp_container_frozen (container))
+ gimp_context_mybrush_list_thaw (container, context);
+ }
+}
+
+static void
+gimp_context_real_set_mybrush (GimpContext *context,
+ GimpMybrush *brush)
+{
+ if (context->mybrush == brush)
+ return;
+
+ if (context->mybrush_name &&
+ brush != GIMP_MYBRUSH (gimp_mybrush_get_standard (context)))
+ {
+ g_clear_pointer (&context->mybrush_name, g_free);
+ }
+
+ if (context->mybrush)
+ g_signal_handlers_disconnect_by_func (context->mybrush,
+ gimp_context_mybrush_dirty,
+ context);
+
+ g_set_object (&context->mybrush, brush);
+
+ if (brush)
+ {
+ g_signal_connect_object (brush, "name-changed",
+ G_CALLBACK (gimp_context_mybrush_dirty),
+ context,
+ 0);
+
+ if (brush != GIMP_MYBRUSH (gimp_mybrush_get_standard (context)))
+ context->mybrush_name = g_strdup (gimp_object_get_name (brush));
+ }
+
+ g_object_notify (G_OBJECT (context), "mybrush");
+ gimp_context_mybrush_changed (context);
+}
+
+
+/*****************************************************************************/
+/* pattern *****************************************************************/
+
+GimpPattern *
+gimp_context_get_pattern (GimpContext *context)
+{
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+
+ return context->pattern;
+}
+
+void
+gimp_context_set_pattern (GimpContext *context,
+ GimpPattern *pattern)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+ g_return_if_fail (pattern == NULL || GIMP_IS_PATTERN (pattern));
+
+ context_find_defined (context, GIMP_CONTEXT_PROP_PATTERN);
+
+ gimp_context_real_set_pattern (context, pattern);
+}
+
+void
+gimp_context_pattern_changed (GimpContext *context)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ g_signal_emit (context,
+ gimp_context_signals[PATTERN_CHANGED], 0,
+ context->pattern);
+}
+
+static void
+gimp_context_pattern_dirty (GimpPattern *pattern,
+ GimpContext *context)
+{
+ g_free (context->pattern_name);
+ context->pattern_name = g_strdup (gimp_object_get_name (pattern));
+
+ g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
+ GIMP_CONTEXT_PROP_PATTERN);
+}
+
+static void
+gimp_context_pattern_list_thaw (GimpContainer *container,
+ GimpContext *context)
+{
+ GimpPattern *pattern;
+
+ if (! context->pattern_name)
+ context->pattern_name = g_strdup (context->gimp->config->default_pattern);
+
+ pattern = gimp_context_find_object (context, container,
+ context->pattern_name,
+ gimp_pattern_get_standard (context));
+
+ gimp_context_real_set_pattern (context, pattern);
+}
+
+static void
+gimp_context_pattern_removed (GimpContainer *container,
+ GimpPattern *pattern,
+ GimpContext *context)
+{
+ if (pattern == context->pattern)
+ {
+ g_signal_handlers_disconnect_by_func (context->pattern,
+ gimp_context_pattern_dirty,
+ context);
+ g_clear_object (&context->pattern);
+
+ if (! gimp_container_frozen (container))
+ gimp_context_pattern_list_thaw (container, context);
+ }
+}
+
+static void
+gimp_context_real_set_pattern (GimpContext *context,
+ GimpPattern *pattern)
+{
+ if (context->pattern == pattern)
+ return;
+
+ if (context->pattern_name &&
+ pattern != GIMP_PATTERN (gimp_pattern_get_standard (context)))
+ {
+ g_clear_pointer (&context->pattern_name, g_free);
+ }
+
+ if (context->pattern)
+ g_signal_handlers_disconnect_by_func (context->pattern,
+ gimp_context_pattern_dirty,
+ context);
+
+ g_set_object (&context->pattern, pattern);
+
+ if (pattern)
+ {
+ g_signal_connect_object (pattern, "name-changed",
+ G_CALLBACK (gimp_context_pattern_dirty),
+ context,
+ 0);
+
+ if (pattern != GIMP_PATTERN (gimp_pattern_get_standard (context)))
+ context->pattern_name = g_strdup (gimp_object_get_name (pattern));
+ }
+
+ g_object_notify (G_OBJECT (context), "pattern");
+ gimp_context_pattern_changed (context);
+}
+
+
+/*****************************************************************************/
+/* gradient ****************************************************************/
+
+GimpGradient *
+gimp_context_get_gradient (GimpContext *context)
+{
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+
+ return context->gradient;
+}
+
+void
+gimp_context_set_gradient (GimpContext *context,
+ GimpGradient *gradient)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+ g_return_if_fail (gradient == NULL || GIMP_IS_GRADIENT (gradient));
+
+ context_find_defined (context, GIMP_CONTEXT_PROP_GRADIENT);
+
+ gimp_context_real_set_gradient (context, gradient);
+}
+
+void
+gimp_context_gradient_changed (GimpContext *context)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ g_signal_emit (context,
+ gimp_context_signals[GRADIENT_CHANGED], 0,
+ context->gradient);
+}
+
+static void
+gimp_context_gradient_dirty (GimpGradient *gradient,
+ GimpContext *context)
+{
+ g_free (context->gradient_name);
+ context->gradient_name = g_strdup (gimp_object_get_name (gradient));
+
+ g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
+ GIMP_CONTEXT_PROP_GRADIENT);
+}
+
+static void
+gimp_context_gradient_list_thaw (GimpContainer *container,
+ GimpContext *context)
+{
+ GimpGradient *gradient;
+
+ if (! context->gradient_name)
+ context->gradient_name = g_strdup (context->gimp->config->default_gradient);
+
+ gradient = gimp_context_find_object (context, container,
+ context->gradient_name,
+ gimp_gradient_get_standard (context));
+
+ gimp_context_real_set_gradient (context, gradient);
+}
+
+static void
+gimp_context_gradient_removed (GimpContainer *container,
+ GimpGradient *gradient,
+ GimpContext *context)
+{
+ if (gradient == context->gradient)
+ {
+ g_signal_handlers_disconnect_by_func (context->gradient,
+ gimp_context_gradient_dirty,
+ context);
+ g_clear_object (&context->gradient);
+
+ if (! gimp_container_frozen (container))
+ gimp_context_gradient_list_thaw (container, context);
+ }
+}
+
+static void
+gimp_context_real_set_gradient (GimpContext *context,
+ GimpGradient *gradient)
+{
+ if (context->gradient == gradient)
+ return;
+
+ if (context->gradient_name &&
+ gradient != GIMP_GRADIENT (gimp_gradient_get_standard (context)))
+ {
+ g_clear_pointer (&context->gradient_name, g_free);
+ }
+
+ if (context->gradient)
+ g_signal_handlers_disconnect_by_func (context->gradient,
+ gimp_context_gradient_dirty,
+ context);
+
+ g_set_object (&context->gradient, gradient);
+
+ if (gradient)
+ {
+ g_signal_connect_object (gradient, "name-changed",
+ G_CALLBACK (gimp_context_gradient_dirty),
+ context,
+ 0);
+
+ if (gradient != GIMP_GRADIENT (gimp_gradient_get_standard (context)))
+ context->gradient_name = g_strdup (gimp_object_get_name (gradient));
+ }
+
+ g_object_notify (G_OBJECT (context), "gradient");
+ gimp_context_gradient_changed (context);
+}
+
+
+/*****************************************************************************/
+/* palette *****************************************************************/
+
+GimpPalette *
+gimp_context_get_palette (GimpContext *context)
+{
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+
+ return context->palette;
+}
+
+void
+gimp_context_set_palette (GimpContext *context,
+ GimpPalette *palette)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+ g_return_if_fail (palette == NULL || GIMP_IS_PALETTE (palette));
+
+ context_find_defined (context, GIMP_CONTEXT_PROP_PALETTE);
+
+ gimp_context_real_set_palette (context, palette);
+}
+
+void
+gimp_context_palette_changed (GimpContext *context)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ g_signal_emit (context,
+ gimp_context_signals[PALETTE_CHANGED], 0,
+ context->palette);
+}
+
+static void
+gimp_context_palette_dirty (GimpPalette *palette,
+ GimpContext *context)
+{
+ g_free (context->palette_name);
+ context->palette_name = g_strdup (gimp_object_get_name (palette));
+
+ g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
+ GIMP_CONTEXT_PROP_PALETTE);
+}
+
+static void
+gimp_context_palette_list_thaw (GimpContainer *container,
+ GimpContext *context)
+{
+ GimpPalette *palette;
+
+ if (! context->palette_name)
+ context->palette_name = g_strdup (context->gimp->config->default_palette);
+
+ palette = gimp_context_find_object (context, container,
+ context->palette_name,
+ gimp_palette_get_standard (context));
+
+ gimp_context_real_set_palette (context, palette);
+}
+
+static void
+gimp_context_palette_removed (GimpContainer *container,
+ GimpPalette *palette,
+ GimpContext *context)
+{
+ if (palette == context->palette)
+ {
+ g_signal_handlers_disconnect_by_func (context->palette,
+ gimp_context_palette_dirty,
+ context);
+ g_clear_object (&context->palette);
+
+ if (! gimp_container_frozen (container))
+ gimp_context_palette_list_thaw (container, context);
+ }
+}
+
+static void
+gimp_context_real_set_palette (GimpContext *context,
+ GimpPalette *palette)
+{
+ if (context->palette == palette)
+ return;
+
+ if (context->palette_name &&
+ palette != GIMP_PALETTE (gimp_palette_get_standard (context)))
+ {
+ g_clear_pointer (&context->palette_name, g_free);
+ }
+
+ if (context->palette)
+ g_signal_handlers_disconnect_by_func (context->palette,
+ gimp_context_palette_dirty,
+ context);
+
+ g_set_object (&context->palette, palette);
+
+ if (palette)
+ {
+ g_signal_connect_object (palette, "name-changed",
+ G_CALLBACK (gimp_context_palette_dirty),
+ context,
+ 0);
+
+ if (palette != GIMP_PALETTE (gimp_palette_get_standard (context)))
+ context->palette_name = g_strdup (gimp_object_get_name (palette));
+ }
+
+ g_object_notify (G_OBJECT (context), "palette");
+ gimp_context_palette_changed (context);
+}
+
+
+/*****************************************************************************/
+/* font *****************************************************************/
+
+GimpFont *
+gimp_context_get_font (GimpContext *context)
+{
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+
+ return context->font;
+}
+
+void
+gimp_context_set_font (GimpContext *context,
+ GimpFont *font)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+ g_return_if_fail (font == NULL || GIMP_IS_FONT (font));
+
+ context_find_defined (context, GIMP_CONTEXT_PROP_FONT);
+
+ gimp_context_real_set_font (context, font);
+}
+
+const gchar *
+gimp_context_get_font_name (GimpContext *context)
+{
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+
+ return context->font_name;
+}
+
+void
+gimp_context_set_font_name (GimpContext *context,
+ const gchar *name)
+{
+ GimpContainer *container;
+ GimpObject *font;
+
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ container = gimp_data_factory_get_container (context->gimp->font_factory);
+ font = gimp_container_get_child_by_name (container, name);
+
+ if (font)
+ {
+ gimp_context_set_font (context, GIMP_FONT (font));
+ }
+ else
+ {
+ /* No font with this name exists, use the standard font, but
+ * keep the intended name around
+ */
+ gimp_context_set_font (context, GIMP_FONT (gimp_font_get_standard ()));
+
+ g_free (context->font_name);
+ context->font_name = g_strdup (name);
+ }
+}
+
+void
+gimp_context_font_changed (GimpContext *context)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ g_signal_emit (context,
+ gimp_context_signals[FONT_CHANGED], 0,
+ context->font);
+}
+
+static void
+gimp_context_font_dirty (GimpFont *font,
+ GimpContext *context)
+{
+ g_free (context->font_name);
+ context->font_name = g_strdup (gimp_object_get_name (font));
+
+ g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
+ GIMP_CONTEXT_PROP_FONT);
+}
+
+static void
+gimp_context_font_list_thaw (GimpContainer *container,
+ GimpContext *context)
+{
+ GimpFont *font;
+
+ if (! context->font_name)
+ context->font_name = g_strdup (context->gimp->config->default_font);
+
+ font = gimp_context_find_object (context, container,
+ context->font_name,
+ gimp_font_get_standard ());
+
+ gimp_context_real_set_font (context, font);
+}
+
+static void
+gimp_context_font_removed (GimpContainer *container,
+ GimpFont *font,
+ GimpContext *context)
+{
+ if (font == context->font)
+ {
+ g_signal_handlers_disconnect_by_func (context->font,
+ gimp_context_font_dirty,
+ context);
+ g_clear_object (&context->font);
+
+ if (! gimp_container_frozen (container))
+ gimp_context_font_list_thaw (container, context);
+ }
+}
+
+static void
+gimp_context_real_set_font (GimpContext *context,
+ GimpFont *font)
+{
+ if (context->font == font)
+ return;
+
+ if (context->font_name &&
+ font != GIMP_FONT (gimp_font_get_standard ()))
+ {
+ g_clear_pointer (&context->font_name, g_free);
+ }
+
+ if (context->font)
+ g_signal_handlers_disconnect_by_func (context->font,
+ gimp_context_font_dirty,
+ context);
+
+ g_set_object (&context->font, font);
+
+ if (font)
+ {
+ g_signal_connect_object (font, "name-changed",
+ G_CALLBACK (gimp_context_font_dirty),
+ context,
+ 0);
+
+ if (font != GIMP_FONT (gimp_font_get_standard ()))
+ context->font_name = g_strdup (gimp_object_get_name (font));
+ }
+
+ g_object_notify (G_OBJECT (context), "font");
+ gimp_context_font_changed (context);
+}
+
+
+/********************************************************************************/
+/* tool preset *****************************************************************/
+
+GimpToolPreset *
+gimp_context_get_tool_preset (GimpContext *context)
+{
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+
+ return context->tool_preset;
+}
+
+void
+gimp_context_set_tool_preset (GimpContext *context,
+ GimpToolPreset *tool_preset)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+ g_return_if_fail (tool_preset == NULL || GIMP_IS_TOOL_PRESET (tool_preset));
+
+ context_find_defined (context, GIMP_CONTEXT_PROP_TOOL_PRESET);
+
+ gimp_context_real_set_tool_preset (context, tool_preset);
+}
+
+void
+gimp_context_tool_preset_changed (GimpContext *context)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ g_signal_emit (context,
+ gimp_context_signals[TOOL_PRESET_CHANGED], 0,
+ context->tool_preset);
+}
+
+static void
+gimp_context_tool_preset_dirty (GimpToolPreset *tool_preset,
+ GimpContext *context)
+{
+ g_free (context->tool_preset_name);
+ context->tool_preset_name = g_strdup (gimp_object_get_name (tool_preset));
+
+ g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
+ GIMP_CONTEXT_PROP_TOOL_PRESET);
+}
+
+static void
+gimp_context_tool_preset_removed (GimpContainer *container,
+ GimpToolPreset *tool_preset,
+ GimpContext *context)
+{
+ if (tool_preset == context->tool_preset)
+ {
+ g_signal_handlers_disconnect_by_func (context->tool_preset,
+ gimp_context_tool_preset_dirty,
+ context);
+ g_clear_object (&context->tool_preset);
+
+ if (! gimp_container_frozen (container))
+ gimp_context_tool_preset_list_thaw (container, context);
+ }
+}
+
+static void
+gimp_context_tool_preset_list_thaw (GimpContainer *container,
+ GimpContext *context)
+{
+ GimpToolPreset *tool_preset;
+
+ tool_preset = gimp_context_find_object (context, container,
+ context->tool_preset_name,
+ NULL);
+
+ gimp_context_real_set_tool_preset (context, tool_preset);
+}
+
+static void
+gimp_context_real_set_tool_preset (GimpContext *context,
+ GimpToolPreset *tool_preset)
+{
+ if (context->tool_preset == tool_preset)
+ return;
+
+ if (context->tool_preset_name)
+ {
+ g_clear_pointer (&context->tool_preset_name, g_free);
+ }
+
+ if (context->tool_preset)
+ g_signal_handlers_disconnect_by_func (context->tool_preset,
+ gimp_context_tool_preset_dirty,
+ context);
+
+ g_set_object (&context->tool_preset, tool_preset);
+
+ if (tool_preset)
+ {
+ g_signal_connect_object (tool_preset, "name-changed",
+ G_CALLBACK (gimp_context_tool_preset_dirty),
+ context,
+ 0);
+
+ context->tool_preset_name = g_strdup (gimp_object_get_name (tool_preset));
+ }
+
+ g_object_notify (G_OBJECT (context), "tool-preset");
+ gimp_context_tool_preset_changed (context);
+}
+
+
+/*****************************************************************************/
+/* buffer ******************************************************************/
+
+GimpBuffer *
+gimp_context_get_buffer (GimpContext *context)
+{
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+
+ return context->buffer;
+}
+
+void
+gimp_context_set_buffer (GimpContext *context,
+ GimpBuffer *buffer)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+ g_return_if_fail (buffer == NULL || GIMP_IS_BUFFER (buffer));
+
+ context_find_defined (context, GIMP_CONTEXT_PROP_BUFFER);
+
+ gimp_context_real_set_buffer (context, buffer);
+}
+
+void
+gimp_context_buffer_changed (GimpContext *context)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ g_signal_emit (context,
+ gimp_context_signals[BUFFER_CHANGED], 0,
+ context->buffer);
+}
+
+static void
+gimp_context_buffer_dirty (GimpBuffer *buffer,
+ GimpContext *context)
+{
+ g_free (context->buffer_name);
+ context->buffer_name = g_strdup (gimp_object_get_name (buffer));
+
+ g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
+ GIMP_CONTEXT_PROP_BUFFER);
+}
+
+static void
+gimp_context_buffer_list_thaw (GimpContainer *container,
+ GimpContext *context)
+{
+ GimpBuffer *buffer;
+
+ buffer = gimp_context_find_object (context, container,
+ context->buffer_name,
+ NULL);
+
+ if (buffer)
+ {
+ gimp_context_real_set_buffer (context, buffer);
+ }
+ else
+ {
+ g_object_notify (G_OBJECT (context), "buffer");
+ gimp_context_buffer_changed (context);
+ }
+}
+
+static void
+gimp_context_buffer_removed (GimpContainer *container,
+ GimpBuffer *buffer,
+ GimpContext *context)
+{
+ if (buffer == context->buffer)
+ {
+ g_signal_handlers_disconnect_by_func (context->buffer,
+ gimp_context_buffer_dirty,
+ context);
+ g_clear_object (&context->buffer);
+
+ if (! gimp_container_frozen (container))
+ gimp_context_buffer_list_thaw (container, context);
+ }
+}
+
+static void
+gimp_context_real_set_buffer (GimpContext *context,
+ GimpBuffer *buffer)
+{
+ if (context->buffer == buffer)
+ return;
+
+ if (context->buffer_name)
+ {
+ g_clear_pointer (&context->buffer_name, g_free);
+ }
+
+ if (context->buffer)
+ g_signal_handlers_disconnect_by_func (context->buffer,
+ gimp_context_buffer_dirty,
+ context);
+
+ g_set_object (&context->buffer, buffer);
+
+ if (buffer)
+ {
+ g_signal_connect_object (buffer, "name-changed",
+ G_CALLBACK (gimp_context_buffer_dirty),
+ context,
+ 0);
+
+ context->buffer_name = g_strdup (gimp_object_get_name (buffer));
+ }
+
+ g_object_notify (G_OBJECT (context), "buffer");
+ gimp_context_buffer_changed (context);
+}
+
+
+/*****************************************************************************/
+/* imagefile ***************************************************************/
+
+GimpImagefile *
+gimp_context_get_imagefile (GimpContext *context)
+{
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+
+ return context->imagefile;
+}
+
+void
+gimp_context_set_imagefile (GimpContext *context,
+ GimpImagefile *imagefile)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+ g_return_if_fail (imagefile == NULL || GIMP_IS_IMAGEFILE (imagefile));
+
+ context_find_defined (context, GIMP_CONTEXT_PROP_IMAGEFILE);
+
+ gimp_context_real_set_imagefile (context, imagefile);
+}
+
+void
+gimp_context_imagefile_changed (GimpContext *context)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ g_signal_emit (context,
+ gimp_context_signals[IMAGEFILE_CHANGED], 0,
+ context->imagefile);
+}
+
+static void
+gimp_context_imagefile_dirty (GimpImagefile *imagefile,
+ GimpContext *context)
+{
+ g_free (context->imagefile_name);
+ context->imagefile_name = g_strdup (gimp_object_get_name (imagefile));
+
+ g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
+ GIMP_CONTEXT_PROP_IMAGEFILE);
+}
+
+static void
+gimp_context_imagefile_list_thaw (GimpContainer *container,
+ GimpContext *context)
+{
+ GimpImagefile *imagefile;
+
+ imagefile = gimp_context_find_object (context, container,
+ context->imagefile_name,
+ NULL);
+
+ if (imagefile)
+ {
+ gimp_context_real_set_imagefile (context, imagefile);
+ }
+ else
+ {
+ g_object_notify (G_OBJECT (context), "imagefile");
+ gimp_context_imagefile_changed (context);
+ }
+}
+
+static void
+gimp_context_imagefile_removed (GimpContainer *container,
+ GimpImagefile *imagefile,
+ GimpContext *context)
+{
+ if (imagefile == context->imagefile)
+ {
+ g_signal_handlers_disconnect_by_func (context->imagefile,
+ gimp_context_imagefile_dirty,
+ context);
+ g_clear_object (&context->imagefile);
+
+ if (! gimp_container_frozen (container))
+ gimp_context_imagefile_list_thaw (container, context);
+ }
+}
+
+static void
+gimp_context_real_set_imagefile (GimpContext *context,
+ GimpImagefile *imagefile)
+{
+ if (context->imagefile == imagefile)
+ return;
+
+ if (context->imagefile_name)
+ {
+ g_clear_pointer (&context->imagefile_name, g_free);
+ }
+
+ if (context->imagefile)
+ g_signal_handlers_disconnect_by_func (context->imagefile,
+ gimp_context_imagefile_dirty,
+ context);
+
+ g_set_object (&context->imagefile, imagefile);
+
+ if (imagefile)
+ {
+ g_signal_connect_object (imagefile, "name-changed",
+ G_CALLBACK (gimp_context_imagefile_dirty),
+ context,
+ 0);
+
+ context->imagefile_name = g_strdup (gimp_object_get_name (imagefile));
+ }
+
+ g_object_notify (G_OBJECT (context), "imagefile");
+ gimp_context_imagefile_changed (context);
+}
+
+
+/*****************************************************************************/
+/* template ***************************************************************/
+
+GimpTemplate *
+gimp_context_get_template (GimpContext *context)
+{
+ g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
+
+ return context->template;
+}
+
+void
+gimp_context_set_template (GimpContext *context,
+ GimpTemplate *template)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+ g_return_if_fail (template == NULL || GIMP_IS_TEMPLATE (template));
+
+ context_find_defined (context, GIMP_CONTEXT_PROP_TEMPLATE);
+
+ gimp_context_real_set_template (context, template);
+}
+
+void
+gimp_context_template_changed (GimpContext *context)
+{
+ g_return_if_fail (GIMP_IS_CONTEXT (context));
+
+ g_signal_emit (context,
+ gimp_context_signals[TEMPLATE_CHANGED], 0,
+ context->template);
+}
+
+static void
+gimp_context_template_dirty (GimpTemplate *template,
+ GimpContext *context)
+{
+ g_free (context->template_name);
+ context->template_name = g_strdup (gimp_object_get_name (template));
+
+ g_signal_emit (context, gimp_context_signals[PROP_NAME_CHANGED], 0,
+ GIMP_CONTEXT_PROP_TEMPLATE);
+}
+
+static void
+gimp_context_template_list_thaw (GimpContainer *container,
+ GimpContext *context)
+{
+ GimpTemplate *template;
+
+ template = gimp_context_find_object (context, container,
+ context->template_name,
+ NULL);
+
+ if (template)
+ {
+ gimp_context_real_set_template (context, template);
+ }
+ else
+ {
+ g_object_notify (G_OBJECT (context), "template");
+ gimp_context_template_changed (context);
+ }
+}
+
+static void
+gimp_context_template_removed (GimpContainer *container,
+ GimpTemplate *template,
+ GimpContext *context)
+{
+ if (template == context->template)
+ {
+ g_signal_handlers_disconnect_by_func (context->template,
+ gimp_context_template_dirty,
+ context);
+ g_clear_object (&context->template);
+
+ if (! gimp_container_frozen (container))
+ gimp_context_template_list_thaw (container, context);
+ }
+}
+
+static void
+gimp_context_real_set_template (GimpContext *context,
+ GimpTemplate *template)
+{
+ if (context->template == template)
+ return;
+
+ if (context->template_name)
+ {
+ g_clear_pointer (&context->template_name, g_free);
+ }
+
+ if (context->template)
+ g_signal_handlers_disconnect_by_func (context->template,
+ gimp_context_template_dirty,
+ context);
+
+ g_set_object (&context->template, template);
+
+ if (template)
+ {
+ g_signal_connect_object (template, "name-changed",
+ G_CALLBACK (gimp_context_template_dirty),
+ context,
+ 0);
+
+ context->template_name = g_strdup (gimp_object_get_name (template));
+ }
+
+ g_object_notify (G_OBJECT (context), "template");
+ gimp_context_template_changed (context);
+}
+
+
+/*****************************************************************************/
+/* utility functions *******************************************************/
+
+static gpointer
+gimp_context_find_object (GimpContext *context,
+ GimpContainer *container,
+ const gchar *object_name,
+ gpointer standard_object)
+{
+ GimpObject *object = NULL;
+
+ if (object_name)
+ object = gimp_container_get_child_by_name (container, object_name);
+
+ if (! object && ! gimp_container_is_empty (container))
+ object = gimp_container_get_child_by_index (container, 0);
+
+ if (! object)
+ object = standard_object;
+
+ return object;
+}