[gimp/symmetry: 8/8] app: symmetry is now set through a dock, not through tool options anymore.



commit 4d0ef2e67a98efeb283990144def0af5a6938960
Author: Jehan <jehan girinstud io>
Date:   Mon Dec 14 20:22:09 2015 +0100

    app: symmetry is now set through a dock, not through tool options anymore.
    
    Some add fix.

 app/actions/dialogs-actions.c      |    6 +
 app/core/gimpcontext.c             |   18 --
 app/core/gimpimage-symmetry.c      |   54 ++---
 app/core/gimpimage.c               |   49 ++++-
 app/dialogs/dialogs-constructors.c |   12 +
 app/dialogs/dialogs-constructors.h |    4 +
 app/dialogs/dialogs.c              |    4 +
 app/paint/gimppaintoptions.c       |   70 +-----
 app/paint/gimppaintoptions.h       |    5 -
 app/paint/paint-types.h            |    5 -
 app/tools/gimppaintoptions-gui.c   |  230 -----------------
 app/tools/tool_manager.c           |    9 -
 app/widgets/Makefile.am            |    2 +
 app/widgets/gimphelp-ids.h         |    1 +
 app/widgets/gimpsymmetryeditor.c   |  489 ++++++++++++++++++++++++++++++++++++
 app/widgets/gimpsymmetryeditor.h   |   58 +++++
 app/widgets/widgets-types.h        |    1 +
 icons/Default/16/gimp-symmetry.png |  Bin 0 -> 4828 bytes
 icons/Default/24/gimp-symmetry.png |  Bin 0 -> 1352 bytes
 icons/Default/24/gimp-symmetry.xcf |  Bin 0 -> 2456 bytes
 icons/Default/Makefile.am          |    2 +
 libgimpwidgets/gimpicons.h         |    1 +
 menus/dialogs-menuitems.xml        |    1 +
 23 files changed, 649 insertions(+), 372 deletions(-)
---
diff --git a/app/actions/dialogs-actions.c b/app/actions/dialogs-actions.c
index 23e7893..cd4032a 100644
--- a/app/actions/dialogs-actions.c
+++ b/app/actions/dialogs-actions.c
@@ -61,6 +61,12 @@ const GimpStringActionEntry dialogs_dockable_actions[] =
     "gimp-device-status",
     GIMP_HELP_DEVICE_STATUS_DIALOG },
 
+  { "dialogs-symmetry", GIMP_STOCK_SYMMETRY,
+    NC_("dialogs-action", "_Symmetry painting"), NULL,
+    NC_("dialogs-action", "Open the symmetry dialog"),
+    "gimp-symmetry-editor",
+    GIMP_HELP_SYMMETRY_DIALOG },
+
   { "dialogs-layers", GIMP_STOCK_LAYERS,
     NC_("dialogs-action", "_Layers"), "<primary>L",
     NC_("dialogs-action", "Open the layers dialog"),
diff --git a/app/core/gimpcontext.c b/app/core/gimpcontext.c
index b29b283..3933626 100644
--- a/app/core/gimpcontext.c
+++ b/app/core/gimpcontext.c
@@ -43,12 +43,10 @@
 #include "gimpimagefile.h"
 #include "gimpgradient.h"
 #include "gimpimage.h"
-#include "gimpimage-symmetry.h"
 #include "gimpmarshal.h"
 #include "gimppaintinfo.h"
 #include "gimppalette.h"
 #include "gimppattern.h"
-#include "gimpsymmetry.h"
 #include "gimptemplate.h"
 #include "gimptoolinfo.h"
 #include "gimptoolpreset.h"
@@ -1927,22 +1925,6 @@ gimp_context_real_set_image (GimpContext *context,
 
   context->image = image;
 
-  if (context->tool_info &&
-      GIMP_IS_PAINT_OPTIONS (context->tool_info->tool_options))
-    {
-      GimpPaintOptions *paint_options;
-      GimpSymmetry  *sym = NULL;
-
-      paint_options = GIMP_PAINT_OPTIONS (context->tool_info->tool_options);
-
-      if (image)
-        sym = gimp_image_symmetry_selected (image);
-
-      g_object_set (paint_options, "symmetry",
-                    sym ? sym->type : G_TYPE_NONE,
-                    NULL);
-    }
-
   g_object_notify (G_OBJECT (context), "image");
   gimp_context_image_changed (context);
 }
diff --git a/app/core/gimpimage-symmetry.c b/app/core/gimpimage-symmetry.c
index 75af480..1fc300f 100644
--- a/app/core/gimpimage-symmetry.c
+++ b/app/core/gimpimage-symmetry.c
@@ -33,6 +33,11 @@
 #include "gimpsymmetry-mirror.h"
 #include "gimpsymmetry-tiling.h"
 
+/**
+ * gimp_image_symmetry_list:
+ *
+ * Returns a list of #GType of all existing symmetries.
+ **/
 GList *
 gimp_image_symmetry_list (void)
 {
@@ -44,6 +49,15 @@ gimp_image_symmetry_list (void)
   return list;
 }
 
+/**
+ * gimp_image_symmetry_new:
+ * @image: the #GimpImage
+ * @type:  the #GType of the symmetry
+ *
+ * Creates a new #GimpSymmetry of @type attached to @image.
+ *
+ * Returns: the new #GimpSymmetry.
+ **/
 GimpSymmetry *
 gimp_image_symmetry_new (GimpImage *image,
                          GType      type)
@@ -114,7 +128,7 @@ gimp_image_symmetry_remove (GimpImage    *image,
  * gimp_image_symmetry_get:
  * @image: the #GimpImage
  *
- * Returns the list of #GimpSymmetry set on @image.
+ * Returns: the list of #GimpSymmetry set on @image.
  * The returned list belongs to @image and should not be freed.
  **/
 GList *
@@ -144,43 +158,13 @@ gboolean
 gimp_image_symmetry_select (GimpImage *image,
                             GType      type)
 {
-  GimpImagePrivate *private;
-  GList *iter;
-
   g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
 
-  private = GIMP_IMAGE_GET_PRIVATE (image);
-
-  if (type == G_TYPE_NONE)
-    {
-      if (private->selected_symmetry)
-        g_object_set (private->selected_symmetry,
-                      "active", FALSE,
-                      NULL);
-      private->selected_symmetry = NULL;
-      return TRUE;
-    }
-  else
-    {
-      for (iter = private->symmetries; iter; iter = g_list_next (iter))
-        {
-          GimpSymmetry *sym = iter->data;
-          if (g_type_is_a (sym->type, type))
-            {
-              if (private->selected_symmetry)
-                g_object_set (private->selected_symmetry,
-                              "active", FALSE,
-                              NULL);
-              private->selected_symmetry = iter->data;
-              g_object_set (private->selected_symmetry,
-                            "active", TRUE,
-                            NULL);
-              return TRUE;
-            }
-        }
-    }
+  g_object_set (image,
+                "symmetry", type,
+                NULL);
 
-  return FALSE;
+  return TRUE;
 }
 
 /**
diff --git a/app/core/gimpimage.c b/app/core/gimpimage.c
index 1e2b6c7..f98e66e 100644
--- a/app/core/gimpimage.c
+++ b/app/core/gimpimage.c
@@ -133,7 +133,8 @@ enum
   PROP_BASE_TYPE,
   PROP_PRECISION,
   PROP_METADATA,
-  PROP_BUFFER
+  PROP_BUFFER,
+  PROP_SYMMETRY
 };
 
 
@@ -627,6 +628,11 @@ gimp_image_class_init (GimpImageClass *klass)
 
   g_object_class_override_property (object_class, PROP_BUFFER, "buffer");
 
+  g_object_class_install_property (object_class, PROP_SYMMETRY,
+                                   g_param_spec_int ("symmetry",
+                                                     NULL, _("Symmetry"),
+                                                     G_TYPE_NONE, G_MAXINT, G_TYPE_NONE,
+                                                     GIMP_PARAM_READWRITE));
   g_type_class_add_private (klass, sizeof (GimpImagePrivate));
 }
 
@@ -865,6 +871,42 @@ gimp_image_set_property (GObject      *object,
       break;
     case PROP_METADATA:
     case PROP_BUFFER:
+      break;
+    case PROP_SYMMETRY:
+      {
+        GType type = g_value_get_int (value);
+
+        if (private->selected_symmetry)
+          g_object_set (private->selected_symmetry,
+                        "active", FALSE,
+                        NULL);
+        private->selected_symmetry = NULL;
+
+        if (type != G_TYPE_NONE)
+          {
+            GList *iter;
+
+            for (iter = private->symmetries; iter; iter = g_list_next (iter))
+              {
+                GimpSymmetry *sym = iter->data;
+                if (g_type_is_a (sym->type, type))
+                  private->selected_symmetry = iter->data;
+              }
+
+            if (private->selected_symmetry == NULL)
+              {
+                GimpSymmetry *sym;
+
+                sym = gimp_image_symmetry_new (image, type);
+                gimp_image_symmetry_add (image, sym);
+                private->selected_symmetry = sym;
+              }
+            g_object_set (private->selected_symmetry,
+                          "active", TRUE,
+                          NULL);
+          }
+      }
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
       break;
@@ -906,6 +948,11 @@ gimp_image_get_property (GObject    *object,
     case PROP_BUFFER:
       g_value_set_object (value, gimp_image_get_buffer (GIMP_PICKABLE (image)));
       break;
+    case PROP_SYMMETRY:
+      g_value_set_int (value,
+                       private->selected_symmetry ?
+                       private->selected_symmetry->type : G_TYPE_NONE);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
       break;
diff --git a/app/dialogs/dialogs-constructors.c b/app/dialogs/dialogs-constructors.c
index 267625f..9dfba17 100644
--- a/app/dialogs/dialogs-constructors.c
+++ b/app/dialogs/dialogs-constructors.c
@@ -53,6 +53,7 @@
 #include "widgets/gimppatternfactoryview.h"
 #include "widgets/gimpsamplepointeditor.h"
 #include "widgets/gimpselectioneditor.h"
+#include "widgets/gimpsymmetryeditor.h"
 #include "widgets/gimptemplateview.h"
 #include "widgets/gimptoolbox.h"
 #include "widgets/gimptooloptionseditor.h"
@@ -705,6 +706,17 @@ dialogs_selection_editor_new (GimpDialogFactory *factory,
 }
 
 GtkWidget *
+dialogs_symmetry_editor_new (GimpDialogFactory *factory,
+                             GimpContext       *context,
+                             GimpUIManager     *ui_manager,
+                             gint               view_size)
+{
+  return gimp_symmetry_editor_new (context->gimp,
+                                   gimp_context_get_image (context),
+                                   gimp_dialog_factory_get_menu_factory (factory));
+}
+
+GtkWidget *
 dialogs_undo_editor_new (GimpDialogFactory *factory,
                          GimpContext       *context,
                          GimpUIManager     *ui_manager,
diff --git a/app/dialogs/dialogs-constructors.h b/app/dialogs/dialogs-constructors.h
index 53b8d53..c033505 100644
--- a/app/dialogs/dialogs-constructors.h
+++ b/app/dialogs/dialogs-constructors.h
@@ -238,6 +238,10 @@ GtkWidget * dialogs_selection_editor_new   (GimpDialogFactory *factory,
                                             GimpContext       *context,
                                             GimpUIManager     *ui_manager,
                                             gint               view_size);
+GtkWidget * dialogs_symmetry_editor_new    (GimpDialogFactory *factory,
+                                            GimpContext       *context,
+                                            GimpUIManager     *ui_manager,
+                                            gint               view_size);
 GtkWidget * dialogs_undo_editor_new        (GimpDialogFactory *factory,
                                             GimpContext       *context,
                                             GimpUIManager     *ui_manager,
diff --git a/app/dialogs/dialogs.c b/app/dialogs/dialogs.c
index 17eae74..c3ee20d 100644
--- a/app/dialogs/dialogs.c
+++ b/app/dialogs/dialogs.c
@@ -371,6 +371,10 @@ static const GimpDialogFactoryEntry entries[] =
             N_("Selection"), N_("Selection Editor"), GIMP_STOCK_SELECTION,
             GIMP_HELP_SELECTION_DIALOG,
             dialogs_selection_editor_new, 0, FALSE),
+  DOCKABLE ("gimp-symmetry-editor",
+            N_("Symmetry Painting"), NULL, GIMP_STOCK_SYMMETRY,
+            GIMP_HELP_SYMMETRY_DIALOG,
+            dialogs_symmetry_editor_new, 0, FALSE),
   DOCKABLE ("gimp-undo-history",
             N_("Undo"), N_("Undo History"), GIMP_STOCK_UNDO_HISTORY,
             GIMP_HELP_UNDO_DIALOG,
diff --git a/app/paint/gimppaintoptions.c b/app/paint/gimppaintoptions.c
index 0d6cbcb..90e224d 100644
--- a/app/paint/gimppaintoptions.c
+++ b/app/paint/gimppaintoptions.c
@@ -29,12 +29,10 @@
 #include "core/gimp.h"
 #include "core/gimpbrushgenerated.h"
 #include "core/gimpimage.h"
-#include "core/gimpimage-symmetry.h"
 #include "core/gimpdynamics.h"
 #include "core/gimpdynamicsoutput.h"
 #include "core/gimpgradient.h"
 #include "core/gimppaintinfo.h"
-#include "core/gimpsymmetry.h"
 
 #include "gimppaintoptions.h"
 
@@ -129,9 +127,7 @@ enum
   PROP_BRUSH_LINK_ASPECT_RATIO,
   PROP_BRUSH_LINK_ANGLE,
   PROP_BRUSH_LINK_SPACING,
-  PROP_BRUSH_LINK_HARDNESS,
-
-  PROP_SYMMETRY
+  PROP_BRUSH_LINK_HARDNESS
 };
 
 
@@ -372,11 +368,6 @@ gimp_paint_options_class_init (GimpPaintOptionsClass *klass)
                                     * less than velcoty results in numeric
                                     * instablility */
                                    GIMP_PARAM_STATIC_STRINGS);
-
-  GIMP_CONFIG_INSTALL_PROP_INT (object_class, PROP_SYMMETRY,
-                                "symmetry", _("Symmetry"),
-                                G_TYPE_NONE, INT_MAX, G_TYPE_NONE,
-                                GIMP_PARAM_STATIC_STRINGS);
 }
 
 static void
@@ -435,15 +426,12 @@ gimp_paint_options_set_property (GObject      *object,
                                  const GValue *value,
                                  GParamSpec   *pspec)
 {
-  GimpContext          *context;
   GimpPaintOptions     *options           = GIMP_PAINT_OPTIONS (object);
   GimpFadeOptions      *fade_options      = options->fade_options;
   GimpJitterOptions    *jitter_options    = options->jitter_options;
   GimpGradientOptions  *gradient_options  = options->gradient_options;
   GimpSmoothingOptions *smoothing_options = options->smoothing_options;
 
-  context = gimp_get_user_context (GIMP_CONTEXT (object)->gimp);
-
   switch (property_id)
     {
     case PROP_PAINT_INFO:
@@ -586,27 +574,6 @@ gimp_paint_options_set_property (GObject      *object,
       smoothing_options->smoothing_factor = g_value_get_double (value);
       break;
 
-    case PROP_SYMMETRY:
-      options->symmetry = g_value_get_int (value);
-      if (context && context->image)
-        {
-          if (! gimp_image_symmetry_select (context->image,
-                                            options->symmetry))
-            {
-              GimpSymmetry *sym;
-
-              sym = gimp_image_symmetry_new (context->image,
-                                             options->symmetry);
-              gimp_image_symmetry_add (context->image, sym);
-              gimp_image_symmetry_select (context->image, options->symmetry);
-            }
-        }
-      else
-        {
-          options->symmetry = G_TYPE_NONE;
-        }
-      break;
-
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
       break;
@@ -767,10 +734,6 @@ gimp_paint_options_get_property (GObject    *object,
       g_value_set_double (value, smoothing_options->smoothing_factor);
       break;
 
-    case PROP_SYMMETRY:
-      g_value_set_int (value, options->symmetry);
-      break;
-
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
       break;
@@ -1180,34 +1143,3 @@ gimp_paint_options_copy_gradient_props (GimpPaintOptions *src,
                 "gradient-reverse", gradient_reverse,
                 NULL);
 }
-
-/**
- * Update the paint options of the current tool according to image settings.
- * Symmetry settings are actually attached to an image, and therefore
- * depends on the current context image.
- */
-void
-gimp_paint_options_set_symmetry_props (GimpPaintOptions *src,
-                                       GimpPaintOptions *dest)
-{
-  GimpContext *context;
-  GimpImage   *image;
-
-  g_return_if_fail (GIMP_IS_PAINT_OPTIONS (src));
-  g_return_if_fail (GIMP_IS_PAINT_OPTIONS (dest));
-
-  context = gimp_get_user_context (GIMP_CONTEXT (dest)->gimp);
-  image   = context->image;
-
-  if (image)
-    {
-      GimpSymmetry  *sym;
-
-      sym = gimp_image_symmetry_selected (image);
-
-      g_object_set (dest,
-                    "symmetry",
-                    sym ? sym->type : G_TYPE_NONE,
-                    NULL);
-    }
-}
diff --git a/app/paint/gimppaintoptions.h b/app/paint/gimppaintoptions.h
index f1856ed..abe7319 100644
--- a/app/paint/gimppaintoptions.h
+++ b/app/paint/gimppaintoptions.h
@@ -116,8 +116,6 @@ struct _GimpPaintOptions
   GimpViewSize              pattern_view_size;
   GimpViewType              gradient_view_type;
   GimpViewSize              gradient_view_size;
-
-  GType                     symmetry;
 };
 
 struct _GimpPaintOptionsClass
@@ -165,7 +163,4 @@ void    gimp_paint_options_copy_dynamics_props (GimpPaintOptions *src,
 void    gimp_paint_options_copy_gradient_props (GimpPaintOptions *src,
                                                 GimpPaintOptions *dest);
 
-void    gimp_paint_options_set_symmetry_props   (GimpPaintOptions *src,
-                                                 GimpPaintOptions *dest);
-
 #endif  /*  __GIMP_PAINT_OPTIONS_H__  */
diff --git a/app/paint/paint-types.h b/app/paint/paint-types.h
index 8f73d74..1bd9fb0 100644
--- a/app/paint/paint-types.h
+++ b/app/paint/paint-types.h
@@ -42,11 +42,6 @@ typedef struct _GimpPencil           GimpPencil;
 typedef struct _GimpPerspectiveClone GimpPerspectiveClone;
 typedef struct _GimpSmudge           GimpSmudge;
 
-/* Multi-stroke transformations */
-typedef struct _GimpMultiStroke      GimpMultiStroke;
-typedef struct _GimpMirror           GimpMirror;
-typedef struct _GimpTiling           GimpTiling;
-
 /*  paint options  */
 
 typedef struct _GimpPaintOptions            GimpPaintOptions;
diff --git a/app/tools/gimppaintoptions-gui.c b/app/tools/gimppaintoptions-gui.c
index d503081..817919a 100644
--- a/app/tools/gimppaintoptions-gui.c
+++ b/app/tools/gimppaintoptions-gui.c
@@ -28,8 +28,6 @@
 
 #include "core/gimp.h"
 #include "core/gimpimage.h"
-#include "core/gimpimage-symmetry.h"
-#include "core/gimpsymmetry.h"
 #include "core/gimptoolinfo.h"
 
 #include "paint/gimppaintoptions.h"
@@ -98,18 +96,6 @@ static GtkWidget * gimp_paint_options_gui_scale_with_buttons
                                                 GCallback     reset_callback,
                                                 GtkSizeGroup *link_group);
 
-static void
-         gimp_paint_options_symmetry_update_cb (GimpSymmetry     *sym,
-                                                GimpImage        *image,
-                                                GtkWidget        *frame);
-static void
-          gimp_paint_options_symmetry_callback (GimpPaintOptions *options,
-                                                GParamSpec       *pspec,
-                                                GtkWidget        *frame);
-static void     gimp_paint_options_symmetry_ui (GimpSymmetry     *sym,
-                                                GtkWidget        *frame);
-
-
 /*  public functions  */
 
 GtkWidget *
@@ -253,62 +239,6 @@ gimp_paint_options_gui (GimpToolOptions *tool_options)
   if (g_type_is_a (tool_type, GIMP_TYPE_PAINT_TOOL))
     {
       GtkWidget *frame;
-      GimpGuiConfig *guiconfig;
-
-      guiconfig = GIMP_GUI_CONFIG (tool_options->tool_info->gimp->config);
-      if (guiconfig->playground_symmetry)
-        {
-          /* Symmetry Painting */
-          GtkListStore *store;
-          GtkTreeIter   iter;
-          GList        *syms;
-          GList        *sym_iter;
-
-          store = gimp_int_store_new ();
-
-          syms = gimp_image_symmetry_list ();
-          for (sym_iter = syms; sym_iter; sym_iter = g_list_next (sym_iter))
-            {
-              GimpSymmetryClass *klass;
-              GType              type;
-
-              type = (GType) sym_iter->data;
-              klass = g_type_class_ref (type);
-
-              gtk_list_store_prepend (store, &iter);
-              gtk_list_store_set (store, &iter,
-                                  GIMP_INT_STORE_LABEL,
-                                  klass->label,
-                                  GIMP_INT_STORE_VALUE,
-                                  sym_iter->data,
-                                  -1);
-              g_type_class_unref (klass);
-            }
-          g_list_free (syms);
-
-          gtk_list_store_prepend (store, &iter);
-          gtk_list_store_set (store, &iter,
-                              GIMP_INT_STORE_LABEL, _("None"),
-                              GIMP_INT_STORE_VALUE, G_TYPE_NONE,
-                              -1);
-          menu = gimp_prop_int_combo_box_new (config, "symmetry",
-                                              GIMP_INT_STORE (store));
-          g_object_unref (store);
-
-          gimp_int_combo_box_set_label (GIMP_INT_COMBO_BOX (menu), _("Symmetry"));
-          gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (menu), G_TYPE_NONE);
-          g_object_set (menu, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
-
-          gtk_box_pack_start (GTK_BOX (vbox), menu, FALSE, FALSE, 0);
-          gtk_widget_show (menu);
-
-          frame = gimp_frame_new ("");
-          gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
-          g_signal_connect (options, "notify::symmetry",
-                            G_CALLBACK (gimp_paint_options_symmetry_callback),
-                            frame);
-
-        }
 
       /*  the "smooth stroke" options  */
       frame = smoothing_options_gui (options, tool_type);
@@ -634,163 +564,3 @@ gimp_paint_options_gui_scale_with_buttons (GObject      *config,
 
   return hbox;
 }
-
-static void
-gimp_paint_options_symmetry_update_cb (GimpSymmetry *sym,
-                                       GimpImage    *image,
-                                       GtkWidget    *frame)
-{
-  GimpContext *context;
-
-  g_return_if_fail (GIMP_IS_SYMMETRY (sym));
-
-  context = gimp_get_user_context (sym->image->gimp);
-  if (image != context->image ||
-      sym != gimp_image_symmetry_selected (image))
-    {
-      g_signal_handlers_disconnect_by_func (G_OBJECT (sym),
-                                            gimp_paint_options_symmetry_update_cb,
-                                            frame);
-      return;
-    }
-
-  gimp_paint_options_symmetry_ui (sym, frame);
-}
-
-static void
-gimp_paint_options_symmetry_callback (GimpPaintOptions *options,
-                                      GParamSpec       *pspec,
-                                      GtkWidget        *frame)
-{
-  GimpSymmetry *sym = NULL;
-  GimpContext  *context;
-  GimpImage    *image;
-
-  g_return_if_fail (GIMP_IS_PAINT_OPTIONS (options));
-
-  context = gimp_get_user_context (GIMP_CONTEXT (options)->gimp);
-  image   = context->image;
-
-  if (image &&
-      (sym = gimp_image_symmetry_selected (image)))
-    {
-      g_signal_connect (sym, "update-ui",
-                        G_CALLBACK (gimp_paint_options_symmetry_update_cb),
-                        frame);
-    }
-
-  gimp_paint_options_symmetry_ui (sym, frame);
-}
-
-static void
-gimp_paint_options_symmetry_ui (GimpSymmetry *sym,
-                                GtkWidget    *frame)
-{
-  GimpSymmetryClass  *klass;
-  GtkWidget          *vbox;
-  GParamSpec        **specs;
-  gint                n_properties;
-  gint                i;
-
-  /* Clean the old frame */
-  gtk_widget_hide (frame);
-  gtk_container_foreach (GTK_CONTAINER (frame),
-                         (GtkCallback) gtk_widget_destroy, NULL);
-
-  if (! sym)
-    return;
-
-  if (sym->type == GIMP_TYPE_SYMMETRY)
-    return;
-
-  klass = g_type_class_ref (sym->type);
-  gtk_frame_set_label (GTK_FRAME (frame),
-                       klass->label);
-  g_type_class_unref (klass);
-
-  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
-  gtk_container_add (GTK_CONTAINER (frame), vbox);
-  gtk_widget_show (vbox);
-
-  specs = gimp_symmetry_get_settings (sym, &n_properties);
-
-  for (i = 0; i < n_properties; i++)
-    {
-      GParamSpec  *spec;
-      const gchar *name;
-      const gchar *blurb;
-
-      if (specs[i] == NULL)
-        {
-          GtkWidget *separator;
-
-          separator = gtk_hseparator_new ();
-          gtk_box_pack_start (GTK_BOX (vbox), separator,
-                              FALSE, FALSE, 0);
-          gtk_widget_show (separator);
-          continue;
-        }
-      spec = G_PARAM_SPEC (specs[i]);
-
-      name = g_param_spec_get_name (spec);
-      blurb = g_param_spec_get_blurb (spec);
-
-      switch (spec->value_type)
-        {
-        case G_TYPE_BOOLEAN:
-            {
-              GtkWidget *checkbox;
-
-              checkbox = gimp_prop_check_button_new (G_OBJECT (sym),
-                                                     name,
-                                                     blurb);
-              gtk_box_pack_start (GTK_BOX (vbox), checkbox,
-                                  FALSE, FALSE, 0);
-              gtk_widget_show (checkbox);
-            }
-          break;
-        case G_TYPE_DOUBLE:
-        case G_TYPE_INT:
-        case G_TYPE_UINT:
-            {
-              GtkWidget *scale;
-              gdouble    minimum;
-              gdouble    maximum;
-
-              if (spec->value_type == G_TYPE_DOUBLE)
-                {
-                  minimum = G_PARAM_SPEC_DOUBLE (spec)->minimum;
-                  maximum = G_PARAM_SPEC_DOUBLE (spec)->maximum;
-                }
-              else if (spec->value_type == G_TYPE_INT)
-                {
-                  minimum = G_PARAM_SPEC_INT (spec)->minimum;
-                  maximum = G_PARAM_SPEC_INT (spec)->maximum;
-                }
-              else
-                {
-                  minimum = G_PARAM_SPEC_UINT (spec)->minimum;
-                  maximum = G_PARAM_SPEC_UINT (spec)->maximum;
-                }
-
-              scale = gimp_prop_spin_scale_new (G_OBJECT (sym),
-                                                name, blurb,
-                                                1.0, 10.0, 1);
-              gimp_spin_scale_set_scale_limits (GIMP_SPIN_SCALE (scale),
-                                                minimum,
-                                                maximum);
-              gtk_box_pack_start (GTK_BOX (vbox), scale, TRUE, TRUE, 0);
-              gtk_widget_show (scale);
-            }
-          break;
-        default:
-          /* Type of parameter we haven't handled yet. */
-          continue;
-        }
-    }
-
-  g_free (specs);
-
-  /* Finally show the frame. */
-  gtk_widget_show (frame);
-}
diff --git a/app/tools/tool_manager.c b/app/tools/tool_manager.c
index edb4759..48d7bfa 100644
--- a/app/tools/tool_manager.c
+++ b/app/tools/tool_manager.c
@@ -774,9 +774,6 @@ tool_manager_preset_changed (GimpContext     *user_context,
       if (config->global_gradient && preset->use_gradient)
         gimp_paint_options_copy_gradient_props (GIMP_PAINT_OPTIONS (src),
                                                 GIMP_PAINT_OPTIONS (dest));
-
-      gimp_paint_options_set_symmetry_props (GIMP_PAINT_OPTIONS (src),
-                                             GIMP_PAINT_OPTIONS (dest));
     }
 }
 
@@ -845,9 +842,6 @@ tool_manager_connect_options (GimpToolManager *tool_manager,
           if (config->global_gradient)
             gimp_paint_options_copy_gradient_props (tool_manager->shared_paint_options,
                                                     GIMP_PAINT_OPTIONS (tool_info->tool_options));
-
-          gimp_paint_options_set_symmetry_props (tool_manager->shared_paint_options,
-                                                 GIMP_PAINT_OPTIONS (tool_info->tool_options));
         }
     }
 }
@@ -872,9 +866,6 @@ tool_manager_disconnect_options (GimpToolManager *tool_manager,
 
           gimp_paint_options_copy_gradient_props (GIMP_PAINT_OPTIONS (tool_info->tool_options),
                                                   tool_manager->shared_paint_options);
-
-          gimp_paint_options_set_symmetry_props (GIMP_PAINT_OPTIONS (tool_info->tool_options),
-                                                 tool_manager->shared_paint_options);
         }
 
       gimp_context_set_parent (GIMP_CONTEXT (tool_info->tool_options), NULL);
diff --git a/app/widgets/Makefile.am b/app/widgets/Makefile.am
index 2b8c82e..53f3e58 100644
--- a/app/widgets/Makefile.am
+++ b/app/widgets/Makefile.am
@@ -335,6 +335,8 @@ libappwidgets_a_sources = \
        gimpstringaction.h              \
        gimpstrokeeditor.c              \
        gimpstrokeeditor.h              \
+       gimpsymmetryeditor.c            \
+       gimpsymmetryeditor.h            \
        gimptagentry.c                  \
        gimptagentry.h                  \
        gimptagpopup.c                  \
diff --git a/app/widgets/gimphelp-ids.h b/app/widgets/gimphelp-ids.h
index 96a178b..0d72981 100644
--- a/app/widgets/gimphelp-ids.h
+++ b/app/widgets/gimphelp-ids.h
@@ -548,6 +548,7 @@
 #define GIMP_HELP_INFO_DIALOG                     "gimp-info-dialog"
 #define GIMP_HELP_MODULE_DIALOG                   "gimp-module-dialog"
 #define GIMP_HELP_NAVIGATION_DIALOG               "gimp-navigation-dialog"
+#define GIMP_HELP_SYMMETRY_DIALOG                 "gimp-symmetry-dialog"
 #define GIMP_HELP_TEXT_EDITOR_DIALOG              "gimp-text-editor-dialog"
 #define GIMP_HELP_TIPS_DIALOG                     "gimp-tips-dialog"
 #define GIMP_HELP_UNDO_DIALOG                     "gimp-undo-dialog"
diff --git a/app/widgets/gimpsymmetryeditor.c b/app/widgets/gimpsymmetryeditor.c
new file mode 100644
index 0000000..729a059
--- /dev/null
+++ b/app/widgets/gimpsymmetryeditor.c
@@ -0,0 +1,489 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpsymmetryeditor.c
+ * Copyright (C) 2015 Jehan <jehan girinstud io>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "widgets-types.h"
+
+#include "config/gimpguiconfig.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontext.h"
+#include "core/gimpimage.h"
+#include "core/gimpimage-symmetry.h"
+#include "core/gimpsymmetry.h"
+
+#include "gimpdocked.h"
+#include "gimpmenufactory.h"
+#include "gimppropwidgets.h"
+#include "gimpspinscale.h"
+#include "gimpsymmetryeditor.h"
+
+#include "gimp-intl.h"
+
+enum
+{
+  PROP_0,
+  PROP_GIMP,
+};
+
+struct _GimpSymmetryEditorPrivate
+{
+  Gimp            *gimp;
+  GimpImage       *image;
+
+  GtkWidget       *menu;
+  GtkWidget       *options_frame;
+};
+
+static void        gimp_symmetry_editor_docked_iface_init (GimpDockedInterface   *iface);
+
+/* Signal handlers on the GObject. */
+static void        gimp_symmetry_editor_constructed       (GObject               *object);
+static void        gimp_symmetry_editor_dispose           (GObject               *object);
+static void        gimp_symmetry_editor_set_property      (GObject               *object,
+                                                           guint                  property_id,
+                                                           const GValue          *value,
+                                                           GParamSpec            *pspec);
+static void        gimp_symmetry_editor_get_property      (GObject               *object,
+                                                           guint                  property_id,
+                                                           GValue                *value,
+                                                           GParamSpec            *pspec);
+
+/* Signal handlers on the context. */
+static void        gimp_symmetry_editor_image_changed     (GimpContext           *context,
+                                                           GimpImage             *image,
+                                                           GimpSymmetryEditor    *editor);
+
+/* Signal handlers on the contextual image. */
+static void        gimp_symmetry_editor_symmetry_notify   (GimpImage             *image,
+                                                           GParamSpec            *pspec,
+                                                           GimpSymmetryEditor    *editor);
+
+/* Signal handlers on the symmetry. */
+static void        gimp_symmetry_editor_symmetry_updated  (GimpSymmetry          *symmetry,
+                                                           GimpImage             *image,
+                                                           GimpSymmetryEditor    *editor);
+
+/* Private functions. */
+static void        gimp_symmetry_editor_set_options       (GimpSymmetryEditor    *editor,
+                                                           GimpSymmetry          *symmetry);
+
+
+G_DEFINE_TYPE_WITH_CODE (GimpSymmetryEditor, gimp_symmetry_editor,
+                         GIMP_TYPE_EDITOR,
+                         G_IMPLEMENT_INTERFACE (GIMP_TYPE_DOCKED,
+                                                gimp_symmetry_editor_docked_iface_init))
+
+#define parent_class gimp_symmetry_editor_parent_class
+
+static void
+gimp_symmetry_editor_class_init (GimpSymmetryEditorClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->constructed  = gimp_symmetry_editor_constructed;
+  object_class->dispose      = gimp_symmetry_editor_dispose;
+  object_class->set_property = gimp_symmetry_editor_set_property;
+  object_class->get_property = gimp_symmetry_editor_get_property;
+
+  g_object_class_install_property (object_class, PROP_GIMP,
+                                   g_param_spec_object ("gimp",
+                                                        NULL, NULL,
+                                                        GIMP_TYPE_GIMP,
+                                                        GIMP_PARAM_READWRITE |
+                                                        G_PARAM_CONSTRUCT_ONLY));
+
+  g_type_class_add_private (klass, sizeof (GimpSymmetryEditorPrivate));
+}
+
+static void
+gimp_symmetry_editor_docked_iface_init (GimpDockedInterface *docked_iface)
+{
+}
+
+static void
+gimp_symmetry_editor_init (GimpSymmetryEditor *editor)
+{
+  GtkScrolledWindow *scrolled_window;
+
+  editor->p = G_TYPE_INSTANCE_GET_PRIVATE (editor,
+                                           GIMP_TYPE_SYMMETRY_EDITOR,
+                                           GimpSymmetryEditorPrivate);
+
+  gtk_widget_set_size_request (GTK_WIDGET (editor), -1, 200);
+
+  /* Scrolled window to keep the dock size reasonable. */
+  scrolled_window = GTK_SCROLLED_WINDOW (gtk_scrolled_window_new (NULL, NULL));
+
+  gtk_scrolled_window_set_policy (scrolled_window,
+                                  GTK_POLICY_AUTOMATIC,
+                                  GTK_POLICY_AUTOMATIC);
+
+  gtk_box_pack_start (GTK_BOX (editor),
+                      GTK_WIDGET (scrolled_window),
+                      TRUE, TRUE, 0);
+  gtk_widget_show (GTK_WIDGET (scrolled_window));
+
+  /* A frame to hold the symmetry options. */
+  editor->p->options_frame = gimp_frame_new ("");
+  gtk_scrolled_window_add_with_viewport (scrolled_window,
+                                         editor->p->options_frame);
+}
+
+static void
+gimp_symmetry_editor_constructed (GObject *object)
+{
+  GimpSymmetryEditor *editor = GIMP_SYMMETRY_EDITOR (object);
+  GimpContext           *user_context;
+
+  G_OBJECT_CLASS (parent_class)->constructed (object);
+
+  user_context = gimp_get_user_context (editor->p->gimp);
+
+  g_signal_connect_object (user_context, "image-changed",
+                           G_CALLBACK (gimp_symmetry_editor_image_changed),
+                           editor,
+                           0);
+
+  gimp_symmetry_editor_image_changed (user_context,
+                                      gimp_context_get_image (user_context),
+                                      editor);
+}
+
+static void
+gimp_symmetry_editor_dispose (GObject *object)
+{
+  GimpSymmetryEditor *editor = GIMP_SYMMETRY_EDITOR (object);
+
+  g_clear_object (&editor->p->image);
+
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gimp_symmetry_editor_set_property (GObject      *object,
+                                   guint         property_id,
+                                   const GValue *value,
+                                   GParamSpec   *pspec)
+{
+  GimpSymmetryEditor *editor = GIMP_SYMMETRY_EDITOR (object);
+
+  switch (property_id)
+    {
+    case PROP_GIMP:
+      editor->p->gimp = g_value_get_object (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gimp_symmetry_editor_get_property (GObject    *object,
+                                   guint       property_id,
+                                   GValue     *value,
+                                   GParamSpec *pspec)
+{
+  GimpSymmetryEditor *editor = GIMP_SYMMETRY_EDITOR (object);
+
+  switch (property_id)
+    {
+    case PROP_GIMP:
+      g_value_set_object (value, editor->p->gimp);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gimp_symmetry_editor_image_changed (GimpContext        *context,
+                                    GimpImage          *image,
+                                    GimpSymmetryEditor *editor)
+{
+  GimpGuiConfig *guiconfig;
+
+  if (image == editor->p->image)
+    return;
+
+  guiconfig = GIMP_GUI_CONFIG (editor->p->gimp->config);
+
+  /* Disconnect and unref the previous image. */
+  if (editor->p->image)
+    {
+      g_signal_handlers_disconnect_by_func (editor->p->image,
+                                            G_CALLBACK (gimp_symmetry_editor_symmetry_notify),
+                                            editor);
+      g_object_unref (editor->p->image);
+      editor->p->image = NULL;
+    }
+
+  /* Destroy the previous menu. */
+  if (editor->p->menu)
+    gtk_widget_destroy (editor->p->menu);
+  editor->p->menu = NULL;
+
+  if (image && guiconfig->playground_symmetry)
+    {
+      GtkListStore *store;
+      GtkTreeIter   iter;
+      GList        *syms;
+      GList        *sym_iter;
+      GimpSymmetry *symmetry;
+
+      store = gimp_int_store_new ();
+
+      /* The menu of available symmetries. */
+      syms = gimp_image_symmetry_list ();
+      for (sym_iter = syms; sym_iter; sym_iter = g_list_next (sym_iter))
+        {
+          GimpSymmetryClass *klass;
+          GType              type;
+
+          type = (GType) sym_iter->data;
+          klass = g_type_class_ref (type);
+
+          gtk_list_store_prepend (store, &iter);
+          gtk_list_store_set (store, &iter,
+                              GIMP_INT_STORE_LABEL,
+                              klass->label,
+                              GIMP_INT_STORE_VALUE,
+                              sym_iter->data,
+                              -1);
+          g_type_class_unref (klass);
+        }
+      g_list_free (syms);
+
+      gtk_list_store_prepend (store, &iter);
+      gtk_list_store_set (store, &iter,
+                          GIMP_INT_STORE_LABEL, _("None"),
+                          GIMP_INT_STORE_VALUE, G_TYPE_NONE,
+                          -1);
+      editor->p->menu = gimp_prop_int_combo_box_new (G_OBJECT (image),
+                                          "symmetry",
+                                          GIMP_INT_STORE (store));
+      g_object_unref (store);
+
+      gimp_int_combo_box_set_label (GIMP_INT_COMBO_BOX (editor->p->menu),
+                                    _("Symmetry"));
+      g_object_set (editor->p->menu, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+
+      gtk_box_pack_start (GTK_BOX (editor), editor->p->menu,
+                          FALSE, FALSE, 0);
+      gtk_box_reorder_child (GTK_BOX (editor), editor->p->menu, 0);
+      gtk_widget_show (editor->p->menu);
+
+      /* Connect to symmetry change. */
+      g_signal_connect (image, "notify::symmetry",
+                        G_CALLBACK (gimp_symmetry_editor_symmetry_notify),
+                        editor);
+
+      /* Update the symmetry options. */
+      symmetry = gimp_image_symmetry_selected (image);
+      gimp_symmetry_editor_set_options (editor, symmetry);
+      editor->p->image = g_object_ref (image);
+    }
+}
+
+static void
+gimp_symmetry_editor_symmetry_notify (GimpImage           *image,
+                                      GParamSpec          *pspec,
+                                      GimpSymmetryEditor  *editor)
+{
+  GimpSymmetry *symmetry = NULL;
+
+  if (image &&
+      (symmetry = gimp_image_symmetry_selected (image)))
+    {
+      g_signal_connect (symmetry, "update-ui",
+                        G_CALLBACK (gimp_symmetry_editor_symmetry_updated),
+                        editor);
+    }
+
+  gimp_symmetry_editor_set_options (editor, symmetry);
+}
+
+static void
+gimp_symmetry_editor_symmetry_updated (GimpSymmetry       *symmetry,
+                                       GimpImage          *image,
+                                       GimpSymmetryEditor *editor)
+{
+  GimpContext *context;
+
+  g_return_if_fail (GIMP_IS_SYMMETRY (symmetry));
+
+  context = gimp_get_user_context (editor->p->gimp);
+  if (image != context->image ||
+      symmetry != gimp_image_symmetry_selected (image))
+    {
+      g_signal_handlers_disconnect_by_func (G_OBJECT (symmetry),
+                                            gimp_symmetry_editor_symmetry_updated,
+                                            editor);
+      return;
+    }
+
+  gimp_symmetry_editor_set_options (editor, symmetry);
+}
+
+/*  private functions  */
+
+static void
+gimp_symmetry_editor_set_options (GimpSymmetryEditor *editor,
+                                  GimpSymmetry       *symmetry)
+{
+  GimpSymmetryClass  *klass;
+  GtkWidget          *frame;
+  GtkWidget          *vbox;
+  GParamSpec        **specs;
+  gint                n_properties;
+  gint                i;
+
+  frame = editor->p->options_frame;
+
+  /* Clean the old frame */
+  gtk_widget_hide (frame);
+  gtk_container_foreach (GTK_CONTAINER (frame),
+                         (GtkCallback) gtk_widget_destroy, NULL);
+
+  if (! symmetry || symmetry->type == GIMP_TYPE_SYMMETRY)
+    return;
+
+  klass = g_type_class_ref (symmetry->type);
+  gtk_frame_set_label (GTK_FRAME (frame),
+                       klass->label);
+  g_type_class_unref (klass);
+
+  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
+  gtk_container_add (GTK_CONTAINER (frame), vbox);
+  gtk_widget_show (vbox);
+
+  specs = gimp_symmetry_get_settings (symmetry, &n_properties);
+
+  for (i = 0; i < n_properties; i++)
+    {
+      GParamSpec  *spec;
+      const gchar *name;
+      const gchar *blurb;
+
+      if (specs[i] == NULL)
+        {
+          GtkWidget *separator;
+
+          separator = gtk_hseparator_new ();
+          gtk_box_pack_start (GTK_BOX (vbox), separator,
+                              FALSE, FALSE, 0);
+          gtk_widget_show (separator);
+          continue;
+        }
+      spec = G_PARAM_SPEC (specs[i]);
+
+      name = g_param_spec_get_name (spec);
+      blurb = g_param_spec_get_blurb (spec);
+
+      switch (spec->value_type)
+        {
+        case G_TYPE_BOOLEAN:
+            {
+              GtkWidget *checkbox;
+
+              checkbox = gimp_prop_check_button_new (G_OBJECT (symmetry),
+                                                     name,
+                                                     blurb);
+              gtk_box_pack_start (GTK_BOX (vbox), checkbox,
+                                  FALSE, FALSE, 0);
+              gtk_widget_show (checkbox);
+            }
+          break;
+        case G_TYPE_DOUBLE:
+        case G_TYPE_INT:
+        case G_TYPE_UINT:
+            {
+              GtkWidget *scale;
+              gdouble    minimum;
+              gdouble    maximum;
+
+              if (spec->value_type == G_TYPE_DOUBLE)
+                {
+                  minimum = G_PARAM_SPEC_DOUBLE (spec)->minimum;
+                  maximum = G_PARAM_SPEC_DOUBLE (spec)->maximum;
+                }
+              else if (spec->value_type == G_TYPE_INT)
+                {
+                  minimum = G_PARAM_SPEC_INT (spec)->minimum;
+                  maximum = G_PARAM_SPEC_INT (spec)->maximum;
+                }
+              else
+                {
+                  minimum = G_PARAM_SPEC_UINT (spec)->minimum;
+                  maximum = G_PARAM_SPEC_UINT (spec)->maximum;
+                }
+
+              scale = gimp_prop_spin_scale_new (G_OBJECT (symmetry),
+                                                name, blurb,
+                                                1.0, 10.0, 1);
+              gimp_spin_scale_set_scale_limits (GIMP_SPIN_SCALE (scale),
+                                                minimum,
+                                                maximum);
+              gtk_box_pack_start (GTK_BOX (vbox), scale, TRUE, TRUE, 0);
+              gtk_widget_show (scale);
+            }
+          break;
+        default:
+          /* Type of parameter we haven't handled yet. */
+          continue;
+        }
+    }
+
+  g_free (specs);
+
+  /* Finally show the frame. */
+  gtk_widget_show (frame);
+}
+
+/*  public functions  */
+
+GtkWidget *
+gimp_symmetry_editor_new (Gimp            *gimp,
+                          GimpImage       *image,
+                          GimpMenuFactory *menu_factory)
+{
+  GimpSymmetryEditor *editor;
+
+  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
+  g_return_val_if_fail (GIMP_IS_MENU_FACTORY (menu_factory), NULL);
+  g_return_val_if_fail (image == NULL || GIMP_IS_IMAGE (image), NULL);
+
+  editor = g_object_new (GIMP_TYPE_SYMMETRY_EDITOR,
+                         "gimp",            gimp,
+                         "menu-factory",    menu_factory,
+                         NULL);
+
+  return GTK_WIDGET (editor);
+}
diff --git a/app/widgets/gimpsymmetryeditor.h b/app/widgets/gimpsymmetryeditor.h
new file mode 100644
index 0000000..fd4d1cc
--- /dev/null
+++ b/app/widgets/gimpsymmetryeditor.h
@@ -0,0 +1,58 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpsymmetryeditor.h
+ * Copyright (C) 2015 Jehan <jehan girinstud io>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_SYMMETRY_EDITOR_H__
+#define __GIMP_SYMMETRY_EDITOR_H__
+
+
+#include "gimpeditor.h"
+
+
+#define GIMP_TYPE_SYMMETRY_EDITOR            (gimp_symmetry_editor_get_type ())
+#define GIMP_SYMMETRY_EDITOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_SYMMETRY_EDITOR, 
GimpSymmetryEditor))
+#define GIMP_SYMMETRY_EDITOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_SYMMETRY_EDITOR, 
GimpSymmetryEditorClass))
+#define GIMP_IS_SYMMETRY_EDITOR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_SYMMETRY_EDITOR))
+#define GIMP_IS_SYMMETRY_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_SYMMETRY_EDITOR))
+#define GIMP_SYMMETRY_EDITOR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_SYMMETRY_EDITOR, 
GimpSymmetryEditorClass))
+
+
+typedef struct _GimpSymmetryEditorPrivate  GimpSymmetryEditorPrivate;
+typedef struct _GimpSymmetryEditorClass    GimpSymmetryEditorClass;
+
+struct _GimpSymmetryEditor
+{
+  GimpEditor                 parent_instance;
+
+  GimpSymmetryEditorPrivate *p;
+};
+
+struct _GimpSymmetryEditorClass
+{
+  GimpEditorClass  parent_class;
+};
+
+
+GType             gimp_symmetry_editor_get_type         (void) G_GNUC_CONST;
+GtkWidget       * gimp_symmetry_editor_new              (Gimp               *gimp,
+                                                         GimpImage          *image,
+                                                         GimpMenuFactory    *menu_factory);
+
+
+#endif  /*  __GIMP_SYMMETRY_EDITOR_H__  */
diff --git a/app/widgets/widgets-types.h b/app/widgets/widgets-types.h
index 98a1620..813c227 100644
--- a/app/widgets/widgets-types.h
+++ b/app/widgets/widgets-types.h
@@ -76,6 +76,7 @@ typedef struct _GimpHistogramEditor          GimpHistogramEditor;
 typedef struct _GimpImageEditor              GimpImageEditor;
 typedef struct _GimpSamplePointEditor        GimpSamplePointEditor;
 typedef struct _GimpSelectionEditor          GimpSelectionEditor;
+typedef struct _GimpSymmetryEditor           GimpSymmetryEditor;
 typedef struct _GimpUndoEditor               GimpUndoEditor;
 
 
diff --git a/icons/Default/16/gimp-symmetry.png b/icons/Default/16/gimp-symmetry.png
new file mode 100644
index 0000000..32fa5a4
Binary files /dev/null and b/icons/Default/16/gimp-symmetry.png differ
diff --git a/icons/Default/24/gimp-symmetry.png b/icons/Default/24/gimp-symmetry.png
new file mode 100644
index 0000000..d7f4b2f
Binary files /dev/null and b/icons/Default/24/gimp-symmetry.png differ
diff --git a/icons/Default/24/gimp-symmetry.xcf b/icons/Default/24/gimp-symmetry.xcf
new file mode 100644
index 0000000..fb593e9
Binary files /dev/null and b/icons/Default/24/gimp-symmetry.xcf differ
diff --git a/icons/Default/Makefile.am b/icons/Default/Makefile.am
index 2dace18..2999fd3 100644
--- a/icons/Default/Makefile.am
+++ b/icons/Default/Makefile.am
@@ -161,6 +161,7 @@ icons16_DATA = \
        16/gimp-shape-circle.png                        \
        16/gimp-shape-diamond.png                       \
        16/gimp-shape-square.png                        \
+       16/gimp-symmetry.png                    \
        16/gimp-template.png                            \
        16/gimp-text-layer.png                          \
        16/gimp-toilet-paper.png                        \
@@ -376,6 +377,7 @@ icons24_DATA = \
        24/gimp-move-to-screen.png              \
        24/gimp-print-resolution.png            \
        24/gimp-sample-point.png                \
+       24/gimp-symmetry.png                    \
        24/gimp-template.png                    \
        24/gimp-text-dir-ltr.png                \
        24/gimp-text-dir-rtl.png                \
diff --git a/libgimpwidgets/gimpicons.h b/libgimpwidgets/gimpicons.h
index 1a0a285..76aa4fc 100644
--- a/libgimpwidgets/gimpicons.h
+++ b/libgimpwidgets/gimpicons.h
@@ -232,6 +232,7 @@ G_BEGIN_DECLS
 #define GIMP_STOCK_INPUT_DEVICE             "gimp-input-device"
 #define GIMP_STOCK_CURSOR                   "gimp-cursor"
 #define GIMP_STOCK_SAMPLE_POINT             "gimp-sample-point"
+#define GIMP_STOCK_SYMMETRY                 "gimp-symmetry"
 #define GIMP_STOCK_DYNAMICS                 "gimp-dynamics"
 #define GIMP_STOCK_TOOL_PRESET              "gimp-tool-preset"
 
diff --git a/menus/dialogs-menuitems.xml b/menus/dialogs-menuitems.xml
index bf06bcb..28c745a 100644
--- a/menus/dialogs-menuitems.xml
+++ b/menus/dialogs-menuitems.xml
@@ -14,6 +14,7 @@
   <menuitem action="dialogs-undo-history" />
   <menuitem action="dialogs-cursor" />
   <menuitem action="dialogs-sample-points" />
+  <menuitem action="dialogs-symmetry"/>
   <separator />
   <menuitem action="dialogs-colors" />
   <menuitem action="dialogs-brushes" />


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]