From c40a6f9920c963cee214aaf067b51f08e7400bcf Mon Sep 17 00:00:00 2001
From: Michael Natterer <mitch@gimp.org>
Date: Mon, 24 Mar 2003 17:58:28 +0000
Subject: [PATCH] register GimpPaintApplicationMode with the type system.

2003-03-24  Michael Natterer  <mitch@gimp.org>

	* app/paint/paint-enums.[ch]: register GimpPaintApplicationMode
	with the type system.

	* app/paint/gimppaintoptions.[ch]: replaced "gboolean incremental"
	with "GimpPaintApplicationMode application_mode"

	* app/paint/gimpairbrush.c
	* app/paint/gimperaser.c
	* app/paint/gimppaintbrush.c
	* app/paint/gimppencil.c: changed accordingly.

	* tools/pdbgen/pdb/paint_tools.pdb: ditto. Set all paint options
	values using g_object_set().

	* app/widgets/gimppropwidgets.[ch]: added
	gimp_prop_enum_check_button_new() which can represent two
	specified enum values and renders itself "inconsistent" for all
	other values.

	* app/tools/paint_options.c: use it for the "Incremental" toggle.

	* app/pdb/paint_tools_cmds.c
	* tools/pdbgen/enums.pl: regenerated.
---
 ChangeLog                        |  26 +++++++
 app/paint/gimpairbrush.c         |   5 +-
 app/paint/gimperaser.c           |   6 +-
 app/paint/gimppaintbrush.c       |   3 +-
 app/paint/gimppaintoptions.c     |  31 ++++----
 app/paint/gimppaintoptions.h     |  10 +--
 app/paint/gimppencil.c           |   3 +-
 app/paint/paint-enums.c          |  19 +++++
 app/paint/paint-enums.h          |  17 +++--
 app/pdb/paint_tools_cmds.c       |  34 +++++----
 app/tools/gimppaintoptions-gui.c |   9 ++-
 app/tools/paint_options.c        |   9 ++-
 app/widgets/gimppropwidgets.c    | 121 +++++++++++++++++++++++++++++++
 app/widgets/gimppropwidgets.h    |   6 ++
 libgimpwidgets/gimppropwidgets.c | 121 +++++++++++++++++++++++++++++++
 libgimpwidgets/gimppropwidgets.h |   6 ++
 tools/pdbgen/enums.pl            |  14 ++--
 tools/pdbgen/pdb/paint_tools.pdb |  43 ++++++-----
 18 files changed, 402 insertions(+), 81 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 8b589053de..c5b4c061a8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2003-03-24  Michael Natterer  <mitch@gimp.org>
+
+	* app/paint/paint-enums.[ch]: register GimpPaintApplicationMode
+	with the type system.
+
+	* app/paint/gimppaintoptions.[ch]: replaced "gboolean incremental"
+	with "GimpPaintApplicationMode application_mode"
+
+	* app/paint/gimpairbrush.c
+	* app/paint/gimperaser.c
+	* app/paint/gimppaintbrush.c
+	* app/paint/gimppencil.c: changed accordingly.
+
+	* tools/pdbgen/pdb/paint_tools.pdb: ditto. Set all paint options
+	values using g_object_set().
+
+	* app/widgets/gimppropwidgets.[ch]: added
+	gimp_prop_enum_check_button_new() which can represent two
+	specified enum values and renders itself "inconsistent" for all
+	other values.
+
+	* app/tools/paint_options.c: use it for the "Incremental" toggle.
+
+	* app/pdb/paint_tools_cmds.c
+	* tools/pdbgen/enums.pl: regenerated.
+
 2003-03-24  Sven Neumann  <sven@gimp.org>
 
 	* plug-ins/common/compose.c: added some stock icons to the dialog.
diff --git a/app/paint/gimpairbrush.c b/app/paint/gimpairbrush.c
index 886371b053..e0b66a9132 100644
--- a/app/paint/gimpairbrush.c
+++ b/app/paint/gimpairbrush.c
@@ -226,10 +226,9 @@ gimp_airbrush_motion (GimpPaintCore    *paint_core,
 
   context = GIMP_CONTEXT (paint_options);
 
-  paint_appl_mode = (paint_options->incremental ? 
-                     GIMP_PAINT_INCREMENTAL : GIMP_PAINT_CONSTANT);
+  paint_appl_mode = paint_options->application_mode;
 
-  pressure = ((GimpAirbrushOptions *) paint_options)->pressure / 100.0;
+  pressure = GIMP_AIRBRUSH_OPTIONS (paint_options)->pressure / 100.0;
 
   if (paint_options->pressure_options->size)
     scale = paint_core->cur_coords.pressure;
diff --git a/app/paint/gimperaser.c b/app/paint/gimperaser.c
index e324f3ca56..612477f333 100644
--- a/app/paint/gimperaser.c
+++ b/app/paint/gimperaser.c
@@ -145,7 +145,6 @@ gimp_eraser_motion (GimpPaintCore    *paint_core,
   guchar                    col[MAX_CHANNELS];
   gdouble                   scale;
   GimpBrushApplicationMode  brush_mode;
-  GimpPaintApplicationMode  paint_appl_mode;
 
   if (! (gimage = gimp_item_get_image (GIMP_ITEM (drawable))))
     return;
@@ -157,9 +156,6 @@ gimp_eraser_motion (GimpPaintCore    *paint_core,
 
   gimp_image_get_background (gimage, drawable, col);
 
-  paint_appl_mode = (paint_options->incremental ?
-                     GIMP_PAINT_INCREMENTAL : GIMP_PAINT_CONSTANT);
-
   if (pressure_options->size)
     scale = paint_core->cur_coords.pressure;
   else
@@ -198,5 +194,5 @@ gimp_eraser_motion (GimpPaintCore    *paint_core,
                                  GIMP_ANTI_ERASE_MODE : GIMP_ERASE_MODE),
 				brush_mode,
 				scale,
-				paint_appl_mode);
+				paint_options->application_mode);
 }
diff --git a/app/paint/gimppaintbrush.c b/app/paint/gimppaintbrush.c
index 794d884fdb..1592b9ea06 100644
--- a/app/paint/gimppaintbrush.c
+++ b/app/paint/gimppaintbrush.c
@@ -159,8 +159,7 @@ gimp_paintbrush_motion (GimpPaintCore         *paint_core,
   pressure_options = paint_options->pressure_options;
   gradient_options = paint_options->gradient_options;
 
-  paint_appl_mode = (paint_options->incremental ? 
-                     GIMP_PAINT_INCREMENTAL : GIMP_PAINT_CONSTANT);
+  paint_appl_mode = paint_options->application_mode;
 
   if (gradient_options->use_fade)
     {
diff --git a/app/paint/gimppaintoptions.c b/app/paint/gimppaintoptions.c
index 628adfdc67..38b0710cdf 100644
--- a/app/paint/gimppaintoptions.c
+++ b/app/paint/gimppaintoptions.c
@@ -31,7 +31,7 @@
 #include "gimppaintoptions.h"
 
 
-#define DEFAULT_INCREMENTAL       FALSE
+#define DEFAULT_APPLICATION_MODE  GIMP_PAINT_CONSTANT
 
 #define DEFAULT_PRESSURE_OPACITY  TRUE
 #define DEFAULT_PRESSURE_PRESSURE TRUE
@@ -51,7 +51,7 @@
 enum
 {
   PROP_0,
-  PROP_INCREMENTAL,
+  PROP_APPLICATION_MODE,
   PROP_PRESSURE_OPACITY,
   PROP_PRESSURE_PRESSURE,
   PROP_PRESSURE_RATE,
@@ -126,10 +126,11 @@ gimp_paint_options_class_init (GimpPaintOptionsClass *klass)
   object_class->get_property = gimp_paint_options_get_property;
   object_class->notify       = gimp_paint_options_notify;
 
-  GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_INCREMENTAL,
-                                    "incremental", NULL,
-                                    DEFAULT_INCREMENTAL,
-                                    0);
+  GIMP_CONFIG_INSTALL_PROP_ENUM (object_class, PROP_APPLICATION_MODE,
+                                 "application-mode", NULL,
+                                 GIMP_TYPE_PAINT_APPLICATION_MODE,
+                                 DEFAULT_APPLICATION_MODE,
+                                 0);
 
   GIMP_CONFIG_INSTALL_PROP_BOOLEAN (object_class, PROP_PRESSURE_OPACITY,
                                     "pressure-opacity", NULL,
@@ -186,7 +187,7 @@ gimp_paint_options_class_init (GimpPaintOptionsClass *klass)
 static void
 gimp_paint_options_init (GimpPaintOptions *options)
 {
-  options->incremental_save = DEFAULT_INCREMENTAL;
+  options->application_mode_save = DEFAULT_APPLICATION_MODE;
 
   options->pressure_options = g_new0 (GimpPressureOptions, 1);
   options->gradient_options = g_new0 (GimpGradientOptions, 1);
@@ -209,8 +210,8 @@ gimp_paint_options_set_property (GObject      *object,
 
   switch (property_id)
     {
-    case PROP_INCREMENTAL:
-      options->incremental = g_value_get_boolean (value);
+    case PROP_APPLICATION_MODE:
+      options->application_mode = g_value_get_enum (value);
       break;
 
     case PROP_PRESSURE_OPACITY:
@@ -275,8 +276,8 @@ gimp_paint_options_get_property (GObject    *object,
 
   switch (property_id)
     {
-    case PROP_INCREMENTAL:
-      g_value_set_boolean (value, options->incremental);
+    case PROP_APPLICATION_MODE:
+      g_value_set_enum (value, options->application_mode);
       break;
 
     case PROP_PRESSURE_OPACITY:
@@ -336,15 +337,15 @@ gimp_paint_options_notify (GObject    *object,
     {
       if (options->gradient_options->use_gradient)
         {
-          options->incremental_save = options->incremental;
-          options->incremental      = TRUE;
+          options->application_mode_save = options->application_mode;
+          options->application_mode      = GIMP_PAINT_INCREMENTAL;
         }
       else
         {
-          options->incremental = options->incremental_save;
+          options->application_mode = options->application_mode_save;
         }
 
-      g_object_notify (object, "incremental");
+      g_object_notify (object, "application-mode");
     }
 
   if (G_OBJECT_CLASS (parent_class)->notify)
diff --git a/app/paint/gimppaintoptions.h b/app/paint/gimppaintoptions.h
index c1fbf16984..9d8fcf8f1c 100644
--- a/app/paint/gimppaintoptions.h
+++ b/app/paint/gimppaintoptions.h
@@ -60,13 +60,13 @@ typedef struct _GimpPaintOptionsClass GimpPaintOptionsClass;
 
 struct _GimpPaintOptions
 {
-  GimpToolOptions      parent_instance;
+  GimpToolOptions           parent_instance;
 
-  gboolean             incremental;
-  gboolean             incremental_save;
+  GimpPaintApplicationMode  application_mode;
+  GimpPaintApplicationMode  application_mode_save;
 
-  GimpPressureOptions *pressure_options;
-  GimpGradientOptions *gradient_options;
+  GimpPressureOptions      *pressure_options;
+  GimpGradientOptions      *gradient_options;
 };
 
 struct _GimpPaintOptionsClass
diff --git a/app/paint/gimppencil.c b/app/paint/gimppencil.c
index fe623c9391..89c55ee614 100644
--- a/app/paint/gimppencil.c
+++ b/app/paint/gimppencil.c
@@ -153,8 +153,7 @@ gimp_pencil_motion (GimpPaintCore    *paint_core,
 
   gimage = gimp_item_get_image (GIMP_ITEM (drawable));
 
-  paint_appl_mode = (paint_options->incremental ?
-                     GIMP_PAINT_INCREMENTAL : GIMP_PAINT_CONSTANT);
+  paint_appl_mode = paint_options->application_mode;
 
   if (pressure_options->size)
     scale = paint_core->cur_coords.pressure;
diff --git a/app/paint/paint-enums.c b/app/paint/paint-enums.c
index 1112a99cb2..87afece27c 100644
--- a/app/paint/paint-enums.c
+++ b/app/paint/paint-enums.c
@@ -126,5 +126,24 @@ gimp_ink_blob_type_get_type (void)
 }
 
 
+static const GEnumValue gimp_paint_application_mode_enum_values[] =
+{
+  { GIMP_PAINT_CONSTANT, N_("Constant"), "constant" },
+  { GIMP_PAINT_INCREMENTAL, N_("Incremental"), "incremental" },
+  { 0, NULL, NULL }
+};
+
+GType
+gimp_paint_application_mode_get_type (void)
+{
+  static GType enum_type = 0;
+
+  if (!enum_type)
+    enum_type = g_enum_register_static ("GimpPaintApplicationMode", gimp_paint_application_mode_enum_values);
+
+  return enum_type;
+}
+
+
 /* Generated data ends here */
 
diff --git a/app/paint/paint-enums.h b/app/paint/paint-enums.h
index bcb81c3e3a..50916d1f30 100644
--- a/app/paint/paint-enums.h
+++ b/app/paint/paint-enums.h
@@ -107,6 +107,17 @@ typedef enum  /*< pdb-skip >*/
 } GimpInkBlobType;
 
 
+#define GIMP_TYPE_PAINT_APPLICATION_MODE (gimp_paint_application_mode_get_type ())
+
+GType gimp_paint_application_mode_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+  GIMP_PAINT_CONSTANT,    /*< desc="Constant"    >*/
+  GIMP_PAINT_INCREMENTAL  /*< desc="Incremental" >*/
+} GimpPaintApplicationMode;
+
+
 /*
  * non-registered enums; register them if needed
  */
@@ -118,11 +129,5 @@ typedef enum  /*< skip >*/
   GIMP_BRUSH_PRESSURE  /*< skip >*/
 } GimpBrushApplicationMode;
 
-typedef enum  /*< skip >*/
-{
-  GIMP_PAINT_CONSTANT,
-  GIMP_PAINT_INCREMENTAL
-} GimpPaintApplicationMode;
-
 
 #endif /* __PAINT_ENUMS_H__ */
diff --git a/app/pdb/paint_tools_cmds.c b/app/pdb/paint_tools_cmds.c
index 5b37f55ab7..b8f22e8c8f 100644
--- a/app/pdb/paint_tools_cmds.c
+++ b/app/pdb/paint_tools_cmds.c
@@ -514,8 +514,10 @@ convolve_invoker (Gimp     *gimp,
     {
       options = gimp_paint_options_new (gimp, GIMP_TYPE_CONVOLVE_OPTIONS);
     
-      GIMP_CONVOLVE_OPTIONS (options)->type = convolve_type;
-      GIMP_CONVOLVE_OPTIONS (options)->rate = pressure;
+      g_object_set (options,
+		    "type", convolve_type,
+		    "rate", pressure,
+		    NULL);
     
       success = paint_tools_stroke (gimp,
 				    GIMP_TYPE_CONVOLVE,
@@ -684,9 +686,11 @@ dodgeburn_invoker (Gimp     *gimp,
     {
       options = gimp_paint_options_new (gimp, GIMP_TYPE_DODGE_BURN_OPTIONS);
     
-      GIMP_DODGE_BURN_OPTIONS (options)->exposure = exposure;
-      GIMP_DODGE_BURN_OPTIONS (options)->type     = dodgeburn_type;
-      GIMP_DODGE_BURN_OPTIONS (options)->mode     = dodgeburn_mode;
+      g_object_set (options,
+		    "type",     dodgeburn_type,
+		    "mode",     dodgeburn_mode,
+		    "exposure", exposure,
+		    NULL);
     
       success = paint_tools_stroke (gimp,
 				    GIMP_TYPE_DODGE_BURN,
@@ -855,9 +859,10 @@ eraser_invoker (Gimp     *gimp,
     {
       options = gimp_paint_options_new (gimp, GIMP_TYPE_ERASER_OPTIONS);
     
-      options->incremental = method;
-    
-      GIMP_ERASER_OPTIONS (options)->hard = hardness;
+      g_object_set (options,
+		    "application-mode", method,
+		    "hard",             hardness,
+		    NULL);
     
       success = paint_tools_stroke (gimp,
 				    GIMP_TYPE_ERASER,
@@ -1026,10 +1031,11 @@ paintbrush_invoker (Gimp     *gimp,
     {
       options = gimp_paint_options_new (gimp, GIMP_TYPE_PAINT_OPTIONS);
     
-      options->incremental = method;
-    
-      options->gradient_options->fade_length     = fade_out;
-      options->gradient_options->gradient_length = gradient_length;
+      g_object_set (options,
+		    "application-mode", method,
+		    "fade-length",      fade_out,
+		    "gradient-length",  gradient_length,
+		    NULL);
     
       success = paint_tools_stroke (gimp,
 				    GIMP_TYPE_PAINTBRUSH,
@@ -1264,7 +1270,9 @@ smudge_invoker (Gimp     *gimp,
     {
       options = gimp_paint_options_new (gimp, GIMP_TYPE_SMUDGE_OPTIONS);
     
-      GIMP_SMUDGE_OPTIONS (options)->rate = pressure;
+      g_object_set (options,
+		    "rate", pressure,
+		    NULL);
     
       success = paint_tools_stroke (gimp,
 				    GIMP_TYPE_SMUDGE,
diff --git a/app/tools/gimppaintoptions-gui.c b/app/tools/gimppaintoptions-gui.c
index de6f6696ec..1ee283e417 100644
--- a/app/tools/gimppaintoptions-gui.c
+++ b/app/tools/gimppaintoptions-gui.c
@@ -155,9 +155,12 @@ gimp_paint_options_gui (GimpToolOptions *tool_options)
       tool_options->tool_info->tool_type == GIMP_TYPE_PAINTBRUSH_TOOL ||
       tool_options->tool_info->tool_type == GIMP_TYPE_PENCIL_TOOL)
     {
-      incremental_toggle = gimp_prop_check_button_new (config,
-                                                       "incremental",
-                                                       _("Incremental"));
+      incremental_toggle =
+        gimp_prop_enum_check_button_new (config,
+                                         "application-mode",
+                                         _("Incremental"),
+                                         GIMP_PAINT_CONSTANT,
+                                         GIMP_PAINT_INCREMENTAL);
       gtk_box_pack_start (GTK_BOX (vbox), incremental_toggle, FALSE, FALSE, 0);
       gtk_widget_show (incremental_toggle);
     }
diff --git a/app/tools/paint_options.c b/app/tools/paint_options.c
index de6f6696ec..1ee283e417 100644
--- a/app/tools/paint_options.c
+++ b/app/tools/paint_options.c
@@ -155,9 +155,12 @@ gimp_paint_options_gui (GimpToolOptions *tool_options)
       tool_options->tool_info->tool_type == GIMP_TYPE_PAINTBRUSH_TOOL ||
       tool_options->tool_info->tool_type == GIMP_TYPE_PENCIL_TOOL)
     {
-      incremental_toggle = gimp_prop_check_button_new (config,
-                                                       "incremental",
-                                                       _("Incremental"));
+      incremental_toggle =
+        gimp_prop_enum_check_button_new (config,
+                                         "application-mode",
+                                         _("Incremental"),
+                                         GIMP_PAINT_CONSTANT,
+                                         GIMP_PAINT_INCREMENTAL);
       gtk_box_pack_start (GTK_BOX (vbox), incremental_toggle, FALSE, FALSE, 0);
       gtk_widget_show (incremental_toggle);
     }
diff --git a/app/widgets/gimppropwidgets.c b/app/widgets/gimppropwidgets.c
index 6c04832284..0051424f81 100644
--- a/app/widgets/gimppropwidgets.c
+++ b/app/widgets/gimppropwidgets.c
@@ -156,6 +156,127 @@ gimp_prop_check_button_notify (GObject    *config,
 }
 
 
+static void   gimp_prop_enum_check_button_callback (GtkWidget  *widget,
+                                                    GObject    *config);
+static void   gimp_prop_enum_check_button_notify   (GObject    *config,
+                                                    GParamSpec *param_spec,
+                                                    GtkWidget  *button);
+
+GtkWidget *
+gimp_prop_enum_check_button_new (GObject     *config,
+                                 const gchar *property_name,
+                                 const gchar *label,
+                                 gint         false_value,
+                                 gint         true_value)
+{
+  GParamSpec  *param_spec;
+  GtkWidget   *button;
+  gint        value;
+
+  param_spec = check_param_spec (config, property_name,
+                                 G_TYPE_PARAM_ENUM, G_STRLOC);
+  if (! param_spec)
+    return NULL;
+
+  g_object_get (config,
+                property_name, &value,
+                NULL);
+
+  button = gtk_check_button_new_with_mnemonic (label);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), value == true_value);
+
+  if (value != false_value && value != true_value)
+    gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (button), TRUE);
+
+  set_param_spec (G_OBJECT (button), button, param_spec);
+
+  g_object_set_data (G_OBJECT (button), "false-value",
+                     GINT_TO_POINTER (false_value));
+  g_object_set_data (G_OBJECT (button), "true-value",
+                     GINT_TO_POINTER (true_value));
+
+  g_signal_connect (button, "toggled",
+		    G_CALLBACK (gimp_prop_enum_check_button_callback),
+		    config);
+
+  connect_notify (config, property_name,
+                  G_CALLBACK (gimp_prop_enum_check_button_notify),
+                  button);
+
+  return button;
+}
+
+static void
+gimp_prop_enum_check_button_callback (GtkWidget *widget,
+                                      GObject   *config)
+{
+  GParamSpec *param_spec;
+  gint        false_value;
+  gint        true_value;
+
+  param_spec = get_param_spec (G_OBJECT (widget));
+  if (! param_spec)
+    return;
+
+  false_value = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
+                                                    "false-value"));
+  true_value  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
+                                                    "true-value"));
+
+  g_object_set (config,
+                param_spec->name,
+                GTK_TOGGLE_BUTTON (widget)->active ? true_value : false_value,
+                NULL);
+
+  gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (widget), FALSE);
+
+  gimp_toggle_button_sensitive_update (GTK_TOGGLE_BUTTON (widget));
+}
+
+static void
+gimp_prop_enum_check_button_notify (GObject    *config,
+                                    GParamSpec *param_spec,
+                                    GtkWidget  *button)
+{
+  gint     value;
+  gint     false_value;
+  gint     true_value;
+  gboolean active       = FALSE;
+  gboolean inconsistent = FALSE;
+
+  g_object_get (config,
+                param_spec->name, &value,
+                NULL);
+
+  false_value = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),
+                                                    "false-value"));
+  true_value  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),
+                                                    "true-value"));
+
+  if (value == true_value)
+    active = TRUE;
+  else if (value != false_value)
+    inconsistent = TRUE;
+
+  gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (button),
+                                      inconsistent);
+
+  if (GTK_TOGGLE_BUTTON (button)->active != active)
+    {
+      g_signal_handlers_block_by_func (button,
+                                       gimp_prop_enum_check_button_callback,
+                                       config);
+
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), active);
+      gimp_toggle_button_sensitive_update (GTK_TOGGLE_BUTTON (button));
+
+      g_signal_handlers_unblock_by_func (button,
+                                         gimp_prop_enum_check_button_callback,
+                                         config);
+    }
+}
+
+
 /******************/
 /*  option menus  */
 /******************/
diff --git a/app/widgets/gimppropwidgets.h b/app/widgets/gimppropwidgets.h
index ffe602fe0c..96f529e60d 100644
--- a/app/widgets/gimppropwidgets.h
+++ b/app/widgets/gimppropwidgets.h
@@ -49,6 +49,12 @@ GtkWidget     * gimp_prop_paint_mode_menu_new     (GObject     *config,
                                                    const gchar *property_name,
                                                    gboolean     with_behind_mode);
 
+GtkWidget     * gimp_prop_enum_check_button_new   (GObject     *config,
+                                                   const gchar *property_name,
+                                                   const gchar *label,
+                                                   gint         false_value,
+                                                   gint         true_value);
+
 GtkWidget     * gimp_prop_enum_radio_frame_new    (GObject     *config,
                                                    const gchar *property_name,
                                                    const gchar *title,
diff --git a/libgimpwidgets/gimppropwidgets.c b/libgimpwidgets/gimppropwidgets.c
index 6c04832284..0051424f81 100644
--- a/libgimpwidgets/gimppropwidgets.c
+++ b/libgimpwidgets/gimppropwidgets.c
@@ -156,6 +156,127 @@ gimp_prop_check_button_notify (GObject    *config,
 }
 
 
+static void   gimp_prop_enum_check_button_callback (GtkWidget  *widget,
+                                                    GObject    *config);
+static void   gimp_prop_enum_check_button_notify   (GObject    *config,
+                                                    GParamSpec *param_spec,
+                                                    GtkWidget  *button);
+
+GtkWidget *
+gimp_prop_enum_check_button_new (GObject     *config,
+                                 const gchar *property_name,
+                                 const gchar *label,
+                                 gint         false_value,
+                                 gint         true_value)
+{
+  GParamSpec  *param_spec;
+  GtkWidget   *button;
+  gint        value;
+
+  param_spec = check_param_spec (config, property_name,
+                                 G_TYPE_PARAM_ENUM, G_STRLOC);
+  if (! param_spec)
+    return NULL;
+
+  g_object_get (config,
+                property_name, &value,
+                NULL);
+
+  button = gtk_check_button_new_with_mnemonic (label);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), value == true_value);
+
+  if (value != false_value && value != true_value)
+    gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (button), TRUE);
+
+  set_param_spec (G_OBJECT (button), button, param_spec);
+
+  g_object_set_data (G_OBJECT (button), "false-value",
+                     GINT_TO_POINTER (false_value));
+  g_object_set_data (G_OBJECT (button), "true-value",
+                     GINT_TO_POINTER (true_value));
+
+  g_signal_connect (button, "toggled",
+		    G_CALLBACK (gimp_prop_enum_check_button_callback),
+		    config);
+
+  connect_notify (config, property_name,
+                  G_CALLBACK (gimp_prop_enum_check_button_notify),
+                  button);
+
+  return button;
+}
+
+static void
+gimp_prop_enum_check_button_callback (GtkWidget *widget,
+                                      GObject   *config)
+{
+  GParamSpec *param_spec;
+  gint        false_value;
+  gint        true_value;
+
+  param_spec = get_param_spec (G_OBJECT (widget));
+  if (! param_spec)
+    return;
+
+  false_value = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
+                                                    "false-value"));
+  true_value  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
+                                                    "true-value"));
+
+  g_object_set (config,
+                param_spec->name,
+                GTK_TOGGLE_BUTTON (widget)->active ? true_value : false_value,
+                NULL);
+
+  gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (widget), FALSE);
+
+  gimp_toggle_button_sensitive_update (GTK_TOGGLE_BUTTON (widget));
+}
+
+static void
+gimp_prop_enum_check_button_notify (GObject    *config,
+                                    GParamSpec *param_spec,
+                                    GtkWidget  *button)
+{
+  gint     value;
+  gint     false_value;
+  gint     true_value;
+  gboolean active       = FALSE;
+  gboolean inconsistent = FALSE;
+
+  g_object_get (config,
+                param_spec->name, &value,
+                NULL);
+
+  false_value = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),
+                                                    "false-value"));
+  true_value  = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),
+                                                    "true-value"));
+
+  if (value == true_value)
+    active = TRUE;
+  else if (value != false_value)
+    inconsistent = TRUE;
+
+  gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (button),
+                                      inconsistent);
+
+  if (GTK_TOGGLE_BUTTON (button)->active != active)
+    {
+      g_signal_handlers_block_by_func (button,
+                                       gimp_prop_enum_check_button_callback,
+                                       config);
+
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), active);
+      gimp_toggle_button_sensitive_update (GTK_TOGGLE_BUTTON (button));
+
+      g_signal_handlers_unblock_by_func (button,
+                                         gimp_prop_enum_check_button_callback,
+                                         config);
+    }
+}
+
+
 /******************/
 /*  option menus  */
 /******************/
diff --git a/libgimpwidgets/gimppropwidgets.h b/libgimpwidgets/gimppropwidgets.h
index ffe602fe0c..96f529e60d 100644
--- a/libgimpwidgets/gimppropwidgets.h
+++ b/libgimpwidgets/gimppropwidgets.h
@@ -49,6 +49,12 @@ GtkWidget     * gimp_prop_paint_mode_menu_new     (GObject     *config,
                                                    const gchar *property_name,
                                                    gboolean     with_behind_mode);
 
+GtkWidget     * gimp_prop_enum_check_button_new   (GObject     *config,
+                                                   const gchar *property_name,
+                                                   const gchar *label,
+                                                   gint         false_value,
+                                                   gint         true_value);
+
 GtkWidget     * gimp_prop_enum_radio_frame_new    (GObject     *config,
                                                    const gchar *property_name,
                                                    const gchar *title,
diff --git a/tools/pdbgen/enums.pl b/tools/pdbgen/enums.pl
index b082cf4207..b64f0db9f2 100644
--- a/tools/pdbgen/enums.pl
+++ b/tools/pdbgen/enums.pl
@@ -397,13 +397,6 @@ package Gimp::CodeGen::enums;
 	  mapping => { GIMP_BLUR_CONVOLVE => '0',
 		       GIMP_SHARPEN_CONVOLVE => '1' }
 	},
-    GimpBrushApplicationMode =>
-	{ contig => 1,
-	  header => 'paint/paint-enums.h',
-	  symbols => [ qw(GIMP_BRUSH_HARD GIMP_BRUSH_SOFT) ],
-	  mapping => { GIMP_BRUSH_HARD => '0',
-		       GIMP_BRUSH_SOFT => '1' }
-	},
     GimpPaintApplicationMode =>
 	{ contig => 1,
 	  header => 'paint/paint-enums.h',
@@ -411,6 +404,13 @@ package Gimp::CodeGen::enums;
 	  mapping => { GIMP_PAINT_CONSTANT => '0',
 		       GIMP_PAINT_INCREMENTAL => '1' }
 	},
+    GimpBrushApplicationMode =>
+	{ contig => 1,
+	  header => 'paint/paint-enums.h',
+	  symbols => [ qw(GIMP_BRUSH_HARD GIMP_BRUSH_SOFT) ],
+	  mapping => { GIMP_BRUSH_HARD => '0',
+		       GIMP_BRUSH_SOFT => '1' }
+	},
     GimpRunMode =>
 	{ contig => 1,
 	  header => 'plug-in/plug-in-types.h',
diff --git a/tools/pdbgen/pdb/paint_tools.pdb b/tools/pdbgen/pdb/paint_tools.pdb
index 290077963d..a6568c123d 100644
--- a/tools/pdbgen/pdb/paint_tools.pdb
+++ b/tools/pdbgen/pdb/paint_tools.pdb
@@ -290,8 +290,10 @@ HELP
 {
   options = gimp_paint_options_new (gimp, GIMP_TYPE_CONVOLVE_OPTIONS);
 
-  GIMP_CONVOLVE_OPTIONS (options)->type = convolve_type;
-  GIMP_CONVOLVE_OPTIONS (options)->rate = pressure;
+  g_object_set (options,
+                "type", convolve_type,
+                "rate", pressure,
+                NULL);
 
   success = paint_tools_stroke (gimp,
                                 GIMP_TYPE_CONVOLVE,
@@ -367,9 +369,10 @@ HELP
 {
   options = gimp_paint_options_new (gimp, GIMP_TYPE_ERASER_OPTIONS);
 
-  options->incremental = method;
-
-  GIMP_ERASER_OPTIONS (options)->hard = hardness;
+  g_object_set (options,
+                "application-mode", method,
+                "hard",             hardness,
+                NULL);
 
   success = paint_tools_stroke (gimp,
                                 GIMP_TYPE_ERASER,
@@ -410,10 +413,11 @@ HELP
 {
   options = gimp_paint_options_new (gimp, GIMP_TYPE_ERASER_OPTIONS);
 
-  options->incremental = method;
-
-  GIMP_ERASER_OPTIONS (options)->hard       = hardness;
-  GIMP_ERASER_OPTIONS (options)->anti_erase = TRUE;
+  g_object_set (options,
+                "application-mode", method,
+                "hard",             hardness,
+                "anti-erase",       TRUE,
+                NULL);
 
   success = paint_tools_stroke (gimp,
                                 GIMP_TYPE_ERASER,
@@ -462,10 +466,11 @@ HELP
 {
   options = gimp_paint_options_new (gimp, GIMP_TYPE_PAINT_OPTIONS);
 
-  options->incremental = method;
-
-  options->gradient_options->fade_length     = fade_out;
-  options->gradient_options->gradient_length = gradient_length;
+  g_object_set (options,
+                "application-mode", method,
+                "fade-length",      fade_out,
+                "gradient-length",  gradient_length,
+                NULL);
 
   success = paint_tools_stroke (gimp,
                                 GIMP_TYPE_PAINTBRUSH,
@@ -583,7 +588,9 @@ HELP
 {
   options = gimp_paint_options_new (gimp, GIMP_TYPE_SMUDGE_OPTIONS);
 
-  GIMP_SMUDGE_OPTIONS (options)->rate = pressure;
+  g_object_set (options,
+                "rate", pressure,
+                NULL);
 
   success = paint_tools_stroke (gimp,
                                 GIMP_TYPE_SMUDGE,
@@ -663,9 +670,11 @@ HELP
 {
   options = gimp_paint_options_new (gimp, GIMP_TYPE_DODGE_BURN_OPTIONS);
 
-  GIMP_DODGE_BURN_OPTIONS (options)->exposure = exposure;
-  GIMP_DODGE_BURN_OPTIONS (options)->type     = dodgeburn_type;
-  GIMP_DODGE_BURN_OPTIONS (options)->mode     = dodgeburn_mode;
+  g_object_set (options,
+                "type",     dodgeburn_type,
+                "mode",     dodgeburn_mode,
+                "exposure", exposure,
+                NULL);
 
   success = paint_tools_stroke (gimp,
                                 GIMP_TYPE_DODGE_BURN,