[gimp] Bug 745835 - Small icons as Option, not theme



commit cfae83623cc291179a544ca8402e801596636f36
Author: Jehan <jehan girinstud io>
Date:   Thu Jan 7 05:09:01 2016 +0100

    Bug 745835 - Small icons as Option, not theme
    
    Allow overriding icon sizes set in themes from the preferences.
    This initial commit updates only toolbox icons. More to come.
    4 options are available: small, medium, large and huge (the later would
    likely be useful for HiDPI screens).
    Uses a new widget GimpIconSizeScale.

 app/config/config-enums.h        |   13 +
 app/config/gimpguiconfig.c       |   14 +
 app/config/gimpguiconfig.h       |    1 +
 app/config/gimprc-blurbs.h       |    3 +
 app/dialogs/preferences-dialog.c |    9 +-
 app/widgets/Makefile.am          |    2 +
 app/widgets/gimpiconsizescale.c  |  508 ++++++++++++++++++++++++++++++++++++++
 app/widgets/gimpiconsizescale.h  |   51 ++++
 app/widgets/gimptoolpalette.c    |  143 +++++++++++-
 app/widgets/widgets-types.h      |    1 +
 10 files changed, 739 insertions(+), 6 deletions(-)
---
diff --git a/app/config/config-enums.h b/app/config/config-enums.h
index 5b3e4c9..e4da201 100644
--- a/app/config/config-enums.h
+++ b/app/config/config-enums.h
@@ -124,4 +124,17 @@ typedef enum
   GIMP_POSITION_RIGHT   /*< desc="Right" >*/
 } GimpPosition;
 
+#define GIMP_TYPE_ICON_SIZE (gimp_icon_size_get_type ())
+
+GType gimp_icon_size_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+  GIMP_ICON_SIZE_DEFAULT, /*< desc="Default size" > */
+  GIMP_ICON_SIZE_SMALL,   /*< desc="Small size"   > */
+  GIMP_ICON_SIZE_MEDIUM,  /*< desc="Medium size"  > */
+  GIMP_ICON_SIZE_LARGE,   /*< desc="Large size"   > */
+  GIMP_ICON_SIZE_HUGE     /*< desc="Huge size"    > */
+} GimpIconSize;
+
 #endif /* __CONFIG_ENUMS_H__ */
diff --git a/app/config/gimpguiconfig.c b/app/config/gimpguiconfig.c
index aae44b3..3e31ff8 100644
--- a/app/config/gimpguiconfig.c
+++ b/app/config/gimpguiconfig.c
@@ -70,6 +70,7 @@ enum
   PROP_THEME,
   PROP_ICON_THEME_PATH,
   PROP_ICON_THEME,
+  PROP_ICON_SIZE,
   PROP_USE_HELP,
   PROP_SHOW_HELP_BUTTON,
   PROP_HELP_LOCALES,
@@ -304,6 +305,13 @@ gimp_gui_config_class_init (GimpGuiConfigClass *klass)
                            ICON_THEME_BLURB,
                            GIMP_CONFIG_DEFAULT_ICON_THEME,
                            GIMP_PARAM_STATIC_STRINGS);
+  GIMP_CONFIG_PROP_ENUM (object_class, PROP_ICON_SIZE,
+                         "icon-size",
+                         "icon-size",
+                         ICON_SIZE_BLURB,
+                         GIMP_TYPE_ICON_SIZE,
+                         GIMP_ICON_SIZE_DEFAULT,
+                         GIMP_PARAM_STATIC_STRINGS);
 
   GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_USE_HELP,
                             "use-help",
@@ -610,6 +618,9 @@ gimp_gui_config_set_property (GObject      *object,
       g_free (gui_config->icon_theme);
       gui_config->icon_theme = g_value_dup_string (value);
       break;
+    case PROP_ICON_SIZE:
+      gui_config->icon_size = g_value_get_enum (value);
+      break;
     case PROP_USE_HELP:
       gui_config->use_help = g_value_get_boolean (value);
       break;
@@ -766,6 +777,9 @@ gimp_gui_config_get_property (GObject    *object,
     case PROP_ICON_THEME:
       g_value_set_string (value, gui_config->icon_theme);
       break;
+    case PROP_ICON_SIZE:
+      g_value_set_enum (value, gui_config->icon_size);
+      break;
     case PROP_USE_HELP:
       g_value_set_boolean (value, gui_config->use_help);
       break;
diff --git a/app/config/gimpguiconfig.h b/app/config/gimpguiconfig.h
index 6e2d7c7..b9e5952 100644
--- a/app/config/gimpguiconfig.h
+++ b/app/config/gimpguiconfig.h
@@ -65,6 +65,7 @@ struct _GimpGuiConfig
   gchar               *theme;
   gchar               *icon_theme_path;
   gchar               *icon_theme;
+  GimpIconSize         icon_size;
   gboolean             use_help;
   gboolean             show_help_button;
   gchar               *help_locales;
diff --git a/app/config/gimprc-blurbs.h b/app/config/gimprc-blurbs.h
index 5a3975f..c14243f 100644
--- a/app/config/gimprc-blurbs.h
+++ b/app/config/gimprc-blurbs.h
@@ -433,6 +433,9 @@ _("Sets the folder for temporary storage. Files will appear here " \
 #define ICON_THEME_BLURB \
 "The name of the icon theme to use."
 
+#define ICON_SIZE_BLURB \
+"The size of the icons to use."
+
 #define ICON_THEME_PATH_BLURB \
 "Sets the icon theme search path."
 
diff --git a/app/dialogs/preferences-dialog.c b/app/dialogs/preferences-dialog.c
index 3fbf0b9..0235907 100644
--- a/app/dialogs/preferences-dialog.c
+++ b/app/dialogs/preferences-dialog.c
@@ -44,6 +44,7 @@
 #include "widgets/gimpgrideditor.h"
 #include "widgets/gimphelp.h"
 #include "widgets/gimphelp-ids.h"
+#include "widgets/gimpiconsizescale.h"
 #include "widgets/gimpmessagebox.h"
 #include "widgets/gimpmessagedialog.h"
 #include "widgets/gimpprefsbox.h"
@@ -123,7 +124,6 @@ static void   prefs_tool_options_save_callback    (GtkWidget  *widget,
 static void   prefs_tool_options_clear_callback   (GtkWidget  *widget,
                                                    Gimp       *gimp);
 
-
 /*  private variables  */
 
 static GtkWidget *prefs_dialog = NULL;
@@ -1684,6 +1684,7 @@ prefs_dialog_new (Gimp       *gimp,
 
   {
     GtkWidget         *scrolled_win;
+    GtkWidget         *icon_size_scale;
     GtkListStore      *list_store;
     GtkWidget         *view;
     GtkTreeSelection  *sel;
@@ -1783,8 +1784,12 @@ prefs_dialog_new (Gimp       *gimp,
     g_signal_connect (sel, "changed",
                       G_CALLBACK (prefs_icon_theme_select_callback),
                       gimp);
-  }
 
+    icon_size_scale = gimp_icon_size_scale_new (gimp);
+
+    gtk_box_pack_start (GTK_BOX (vbox2), icon_size_scale, FALSE, FALSE, 0);
+    gtk_widget_show (icon_size_scale);
+  }
 
   /*************************/
   /*  Interface / Toolbox  */
diff --git a/app/widgets/Makefile.am b/app/widgets/Makefile.am
index d06c6e1..bea870f 100644
--- a/app/widgets/Makefile.am
+++ b/app/widgets/Makefile.am
@@ -215,6 +215,8 @@ libappwidgets_a_sources = \
        gimphistogramview.h             \
        gimpiconpicker.c                \
        gimpiconpicker.h                \
+       gimpiconsizescale.c             \
+       gimpiconsizescale.h             \
        gimpimagecommenteditor.c        \
        gimpimagecommenteditor.h        \
        gimpimageeditor.c               \
diff --git a/app/widgets/gimpiconsizescale.c b/app/widgets/gimpiconsizescale.c
new file mode 100644
index 0000000..4bdd4f0
--- /dev/null
+++ b/app/widgets/gimpiconsizescale.c
@@ -0,0 +1,508 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpiconsizescale.c
+ * Copyright (C) 2016 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 <gtk/gtk.h>
+
+#include "widgets-types.h"
+
+#include "libgimpconfig/gimpconfig.h"
+
+#include "config/gimpguiconfig.h"
+
+#include "core/gimp.h"
+
+#include "gimpiconsizescale.h"
+
+#include "gimp-intl.h"
+
+enum
+{
+  PROP_0,
+  PROP_GIMP
+};
+
+typedef struct _GimpIconSizeScalePrivate GimpIconSizeScalePrivate;
+
+struct _GimpIconSizeScalePrivate
+{
+  Gimp      *gimp;
+
+  GtkWidget *scale;
+  GtkWidget *checkbox;
+};
+
+#define GET_PRIVATE(scale) \
+        G_TYPE_INSTANCE_GET_PRIVATE (scale, \
+                                     GIMP_TYPE_ICON_SIZE_SCALE, \
+                                     GimpIconSizeScalePrivate)
+
+
+static void   gimp_icon_size_scale_constructed    (GObject           *object);
+static void   gimp_icon_size_scale_finalize       (GObject           *object);
+static void   gimp_icon_size_scale_set_property   (GObject           *object,
+                                                   guint              property_id,
+                                                   const GValue      *value,
+                                                   GParamSpec        *pspec);
+static void   gimp_icon_size_scale_get_property   (GObject           *object,
+                                                   guint              property_id,
+                                                   GValue            *value,
+                                                   GParamSpec        *pspec);
+
+/* Signals on GimpGuiConfig properties. */
+static void   gimp_icon_size_scale_icon_theme_notify (GimpGuiConfig   *config,
+                                                      GParamSpec      *pspec,
+                                                      GtkRange        *scale);
+static void   gimp_icon_size_scale_icon_size_notify  (GimpGuiConfig   *config,
+                                                      GParamSpec      *pspec,
+                                                      GtkWidget       *size_scale);
+
+/* Signals on the checkbox. */
+static void   gimp_icon_size_scale_checkbox_toggled  (GtkToggleButton *checkbox,
+                                                      GimpGuiConfig   *config);
+/* Signals on the GtkScale. */
+static void   gimp_icon_size_scale_value_changed     (GtkRange        *range,
+                                                      GimpGuiConfig   *config);
+static gboolean gimp_icon_size_scale_change_value    (GtkRange        *range,
+                                                      GtkScrollType    scroll,
+                                                      gdouble          value,
+                                                      GimpGuiConfig   *config);
+
+G_DEFINE_TYPE (GimpIconSizeScale, gimp_icon_size_scale, GTK_TYPE_FRAME)
+
+#define parent_class gimp_icon_size_scale_parent_class
+
+static void
+gimp_icon_size_scale_class_init (GimpIconSizeScaleClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->constructed  = gimp_icon_size_scale_constructed;
+  object_class->finalize     = gimp_icon_size_scale_finalize;
+  object_class->set_property = gimp_icon_size_scale_set_property;
+  object_class->get_property = gimp_icon_size_scale_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 (object_class, sizeof (GimpIconSizeScalePrivate));
+}
+
+static void
+gimp_icon_size_scale_init (GimpIconSizeScale *object)
+{
+  GimpIconSizeScalePrivate *private = GET_PRIVATE (object);
+
+  private->checkbox = gtk_check_button_new_with_label (_("Override theme icon sizes"));
+  gtk_frame_set_label_widget (GTK_FRAME (object), private->checkbox);
+
+  private->scale = gtk_hscale_new_with_range (0.0, 3.0, 1.0);
+  /* 'draw_value' updates round_digits. So set it first. */
+  gtk_scale_set_draw_value (GTK_SCALE (private->scale), FALSE);
+  gtk_range_set_round_digits (GTK_RANGE (private->scale), 0.0);
+  gtk_widget_set_sensitive (GTK_WIDGET (private->scale), FALSE);
+  gtk_container_add (GTK_CONTAINER (object), private->scale);
+}
+
+static void
+gimp_icon_size_scale_constructed (GObject *object)
+{
+  GimpIconSizeScalePrivate *private = GET_PRIVATE (object);
+
+  G_OBJECT_CLASS (parent_class)->constructed (object);
+
+  g_signal_connect (private->checkbox, "toggled",
+                    G_CALLBACK (gimp_icon_size_scale_checkbox_toggled),
+                    private->gimp->config);
+
+  g_signal_connect (private->gimp->config, "notify::icon-theme",
+                    G_CALLBACK (gimp_icon_size_scale_icon_theme_notify),
+                    private->scale);
+  gimp_icon_size_scale_icon_theme_notify (GIMP_GUI_CONFIG (private->gimp->config),
+                                          NULL, GTK_RANGE (private->scale));
+
+  g_signal_connect (private->scale, "change-value",
+                    G_CALLBACK (gimp_icon_size_scale_change_value),
+                    private->gimp->config);
+  g_signal_connect (private->scale, "value-changed",
+                    G_CALLBACK (gimp_icon_size_scale_value_changed),
+                    private->gimp->config);
+
+  g_signal_connect (private->gimp->config, "notify::icon-size",
+                    G_CALLBACK (gimp_icon_size_scale_icon_size_notify),
+                    private->scale);
+  gimp_icon_size_scale_icon_size_notify (GIMP_GUI_CONFIG (private->gimp->config),
+                                         NULL, private->scale);
+
+  gtk_widget_show (private->checkbox);
+  gtk_widget_show (private->scale);
+}
+
+static void
+gimp_icon_size_scale_finalize (GObject *object)
+{
+  GimpIconSizeScalePrivate *private = GET_PRIVATE (object);
+
+  g_signal_handlers_disconnect_by_func (private->gimp->config,
+                                        G_CALLBACK (gimp_icon_size_scale_icon_size_notify),
+                                        private->scale);
+  g_signal_handlers_disconnect_by_func (private->gimp->config,
+                                        G_CALLBACK (gimp_icon_size_scale_icon_theme_notify),
+                                        private->scale);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gimp_icon_size_scale_set_property (GObject      *object,
+                                   guint         property_id,
+                                   const GValue *value,
+                                   GParamSpec   *pspec)
+{
+  GimpIconSizeScalePrivate *private = GET_PRIVATE (object);
+
+  switch (property_id)
+    {
+    case PROP_GIMP:
+      private->gimp = g_value_get_object (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gimp_icon_size_scale_get_property (GObject    *object,
+                                   guint       property_id,
+                                   GValue     *value,
+                                   GParamSpec *pspec)
+{
+  GimpIconSizeScalePrivate *private = GET_PRIVATE (object);
+
+  switch (property_id)
+    {
+    case PROP_GIMP:
+      g_value_set_object (value, private->gimp);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gimp_icon_size_scale_icon_theme_notify (GimpGuiConfig *config,
+                                        GParamSpec    *pspec,
+                                        GtkRange      *scale)
+{
+  GtkIconTheme *theme             = gtk_icon_theme_get_default();
+  gint         *icon_sizes;
+  const gchar  *markup;
+  gdouble       value             = gtk_range_get_value (scale);
+  gboolean      update_value      = FALSE;
+  gboolean      has_small_toolbar = FALSE;
+  gboolean      has_large_toolbar = FALSE;
+  gboolean      has_dnd           = FALSE;
+  gboolean      has_dialog        = FALSE;
+  gint          i;
+
+  icon_sizes = gtk_icon_theme_get_icon_sizes (theme, "gimp-tool-move");
+  for (i = 0; icon_sizes[i]; i++)
+    {
+      if (icon_sizes[i] == -1)
+        {
+          has_small_toolbar = TRUE;
+          has_large_toolbar = TRUE;
+          has_dnd           = TRUE;
+          has_dialog        = TRUE;
+          break;
+        }
+      else if (icon_sizes[i] > 13 && icon_sizes[i] < 19)
+        {
+          has_small_toolbar = TRUE;
+        }
+      else if (icon_sizes[i] > 21 && icon_sizes[i] < 27)
+        {
+          has_large_toolbar = TRUE;
+        }
+      else if (icon_sizes[i] > 29 && icon_sizes[i] < 35)
+        {
+          has_dnd = TRUE;
+        }
+      else if (icon_sizes[i] > 45 && icon_sizes[i] < 51)
+        {
+          has_dialog = TRUE;
+        }
+    }
+  g_free (icon_sizes);
+
+  gtk_scale_clear_marks (GTK_SCALE (scale));
+  if (has_small_toolbar)
+    markup = "Small";
+  else
+    {
+      markup = "<span strikethrough=\"true\">Small</span>";
+      if (value == 0.0)
+        update_value = TRUE;
+    }
+  gtk_scale_add_mark (GTK_SCALE (scale), 0.0, GTK_POS_BOTTOM,
+                      markup);
+  if (has_large_toolbar)
+    markup = "Medium";
+  else
+    {
+      markup = "<span strikethrough=\"true\">Medium</span>";
+      if (value == 1.0)
+        update_value = TRUE;
+    }
+  gtk_scale_add_mark (GTK_SCALE (scale), 1.0, GTK_POS_BOTTOM,
+                      markup);
+  if (has_dnd)
+    markup = "Large";
+  else
+    {
+      markup = "<span strikethrough=\"true\">Large</span>";
+      if (value == 2.0)
+        update_value = TRUE;
+    }
+  gtk_scale_add_mark (GTK_SCALE (scale), 2.0, GTK_POS_BOTTOM,
+                      markup);
+  if (has_dialog)
+    markup = "Huge";
+  else
+    {
+      markup = "<span strikethrough=\"true\">Huge</span>";
+      if (value == 3.0)
+        update_value = TRUE;
+    }
+  gtk_scale_add_mark (GTK_SCALE (scale), 3.0, GTK_POS_BOTTOM,
+                      markup);
+  if (update_value)
+    {
+      GimpIconSize *size;
+
+      g_object_get (config, "icon-size", &size, NULL);
+
+      if (size == GIMP_ICON_SIZE_DEFAULT)
+        {
+          g_signal_handlers_block_by_func (scale,
+                                           G_CALLBACK (gimp_icon_size_scale_value_changed),
+                                           config);
+        }
+      if (has_dialog)
+        gtk_range_set_value (scale, 3.0);
+      else if (has_dnd)
+        gtk_range_set_value (scale, 2.0);
+      else if (has_large_toolbar)
+        gtk_range_set_value (scale, 1.0);
+      else
+        gtk_range_set_value (scale, 0.0);
+      if (size == GIMP_ICON_SIZE_DEFAULT)
+        {
+          g_signal_handlers_unblock_by_func (scale,
+                                             G_CALLBACK (gimp_icon_size_scale_value_changed),
+                                             config);
+        }
+    }
+}
+
+static void
+gimp_icon_size_scale_icon_size_notify (GimpGuiConfig *config,
+                                       GParamSpec    *pspec,
+                                       GtkWidget     *size_scale)
+{
+  GtkWidget    *frame    = gtk_widget_get_parent (size_scale);
+  GtkWidget    *checkbox = gtk_frame_get_label_widget (GTK_FRAME (frame));
+  GimpIconSize  size;
+  gdouble       value    = 1.0;
+
+  g_object_get (config, "icon-size", &size, NULL);
+
+  switch (size)
+    {
+    case GIMP_ICON_SIZE_SMALL:
+      value = 0.0;
+      break;
+    case GIMP_ICON_SIZE_MEDIUM:
+      value = 1.0;
+      break;
+    case GIMP_ICON_SIZE_LARGE:
+      value = 2.0;
+      break;
+    case GIMP_ICON_SIZE_HUGE:
+      value = 3.0;
+      break;
+    default: /* GIMP_ICON_SIZE_DEFAULT */
+      break;
+    }
+  g_signal_handlers_block_by_func (checkbox,
+                                   G_CALLBACK (gimp_icon_size_scale_checkbox_toggled),
+                                   config);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbox),
+                                size != GIMP_ICON_SIZE_DEFAULT);
+  g_signal_handlers_unblock_by_func (checkbox,
+                                     G_CALLBACK (gimp_icon_size_scale_checkbox_toggled),
+                                     config);
+  gtk_widget_set_sensitive (GTK_WIDGET (size_scale),
+                            size != GIMP_ICON_SIZE_DEFAULT);
+
+
+  if (size != GIMP_ICON_SIZE_DEFAULT)
+    {
+      g_signal_handlers_block_by_func (size_scale,
+                                       G_CALLBACK (gimp_icon_size_scale_value_changed),
+                                       config);
+      gtk_range_set_value (GTK_RANGE (size_scale), value);
+      g_signal_handlers_unblock_by_func (size_scale,
+                                         G_CALLBACK (gimp_icon_size_scale_value_changed),
+                                         config);
+    }
+}
+
+static void
+gimp_icon_size_scale_checkbox_toggled (GtkToggleButton *checkbox,
+                                       GimpGuiConfig   *config)
+{
+  GtkWidget    *frame = gtk_widget_get_parent (GTK_WIDGET (checkbox));
+  GtkWidget    *scale = gtk_bin_get_child (GTK_BIN (frame));
+  GimpIconSize  size;
+
+  if (gtk_toggle_button_get_active (checkbox))
+    {
+      gdouble value = gtk_range_get_value (GTK_RANGE (scale));
+
+      if (value < 0.5)
+        size = GIMP_ICON_SIZE_SMALL;
+      else if (value < 1.5)
+        size = GIMP_ICON_SIZE_MEDIUM;
+      else if (value < 2.5)
+        size = GIMP_ICON_SIZE_LARGE;
+      else
+        size = GIMP_ICON_SIZE_HUGE;
+    }
+  else
+    {
+      size = GIMP_ICON_SIZE_DEFAULT;
+    }
+  gtk_widget_set_sensitive (GTK_WIDGET (scale),
+                            gtk_toggle_button_get_active (checkbox));
+
+  g_signal_handlers_block_by_func (config,
+                                   G_CALLBACK (gimp_icon_size_scale_icon_size_notify),
+                                   scale);
+  g_object_set (G_OBJECT (config),
+                "icon-size", size,
+                NULL);
+  g_signal_handlers_unblock_by_func (config,
+                                     G_CALLBACK (gimp_icon_size_scale_icon_size_notify),
+                                     scale);
+}
+
+static void
+gimp_icon_size_scale_value_changed (GtkRange      *range,
+                                    GimpGuiConfig *config)
+{
+  GimpIconSize size;
+  gdouble      value = gtk_range_get_value (range);
+
+  if (value < 0.5)
+    size = GIMP_ICON_SIZE_SMALL;
+  else if (value < 1.5)
+    size = GIMP_ICON_SIZE_MEDIUM;
+  else if (value < 2.5)
+    size = GIMP_ICON_SIZE_LARGE;
+  else
+    size = GIMP_ICON_SIZE_HUGE;
+
+  g_signal_handlers_block_by_func (config,
+                                   G_CALLBACK (gimp_icon_size_scale_icon_size_notify),
+                                   range);
+  g_object_set (G_OBJECT (config), "icon-size", size, NULL);
+  g_signal_handlers_unblock_by_func (config,
+                                     G_CALLBACK (gimp_icon_size_scale_icon_size_notify),
+                                     range);
+}
+
+static gboolean
+gimp_icon_size_scale_change_value (GtkRange      *range,
+                                   GtkScrollType  scroll,
+                                   gdouble        value,
+                                   GimpGuiConfig *config)
+{
+  GtkIconTheme *theme             = gtk_icon_theme_get_default();
+  gint         *icon_sizes;
+  gboolean      has_small_toolbar = FALSE;
+  gboolean      has_large_toolbar = FALSE;
+  gboolean      has_dnd           = FALSE;
+  gboolean      has_dialog        = FALSE;
+  gint          i;
+
+  /* We cannot check all icons. Use "gimp-tool-move" as template of
+   * available sizes. */
+  icon_sizes = gtk_icon_theme_get_icon_sizes (theme, "gimp-tool-move");
+  for (i = 0; icon_sizes[i]; i++)
+    {
+      if (icon_sizes[i] == -1)
+        {
+          has_small_toolbar = TRUE;
+          has_large_toolbar = TRUE;
+          has_dnd           = TRUE;
+          has_dialog        = TRUE;
+          break;
+        }
+      else if (icon_sizes[i] > 13 && icon_sizes[i] < 19)
+        has_small_toolbar = TRUE;
+      else if (icon_sizes[i] > 21 && icon_sizes[i] < 27)
+        has_large_toolbar = TRUE;
+      else if (icon_sizes[i] > 29 && icon_sizes[i] < 35)
+        has_dnd = TRUE;
+      else if (icon_sizes[i] > 45 && icon_sizes[i] < 51)
+        has_dialog = TRUE;
+    }
+  g_free (icon_sizes);
+
+  if ((value < 0.5 && ! has_small_toolbar)                 ||
+      (value >= 0.5 && value < 1.5 && ! has_large_toolbar) ||
+      (value >= 1.5 && value < 2.5 && ! has_dnd)           ||
+      (value >= 2.5 && ! has_dialog))
+    /* Refuse the update. */
+    return TRUE;
+  else
+    /* Accept the update. */
+    return FALSE;
+}
+
+GtkWidget *
+gimp_icon_size_scale_new (Gimp *gimp)
+{
+  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
+
+  return g_object_new (GIMP_TYPE_ICON_SIZE_SCALE,
+                       "gimp", gimp,
+                       NULL);
+}
diff --git a/app/widgets/gimpiconsizescale.h b/app/widgets/gimpiconsizescale.h
new file mode 100644
index 0000000..8db1ffd
--- /dev/null
+++ b/app/widgets/gimpiconsizescale.h
@@ -0,0 +1,51 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpiconsizescale.h
+ * Copyright (C) 2016 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_ICON_SIZE_SCALE_H__
+#define __GIMP_ICON_SIZE_SCALE_H__
+
+
+#define GIMP_TYPE_ICON_SIZE_SCALE            (gimp_icon_size_scale_get_type ())
+#define GIMP_ICON_SIZE_SCALE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_ICON_SIZE_SCALE, 
GimpIconSizeScale))
+#define GIMP_ICON_SIZE_SCALE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_ICON_SIZE_SCALE, 
GimpIconSizeScaleClass))
+#define GIMP_IS_ICON_SIZE_SCALE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_ICON_SIZE_SCALE))
+#define GIMP_IS_ICON_SIZE_SCALE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), GIMP_TYPE_ICON_SIZE_SCALE))
+#define GIMP_ICON_SIZE_SCALE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GIMP_TYPE_ICON_SIZE_SCALE, 
GimpIconSizeScaleClass))
+
+
+typedef struct _GimpIconSizeScaleClass GimpIconSizeScaleClass;
+
+struct _GimpIconSizeScale
+{
+  GtkFrame      parent_instance;
+};
+
+struct _GimpIconSizeScaleClass
+{
+  GtkFrameClass parent_class;
+};
+
+
+GType       gimp_icon_size_scale_get_type (void) G_GNUC_CONST;
+
+GtkWidget * gimp_icon_size_scale_new      (Gimp *gimp);
+
+
+#endif  /* __GIMP_ICON_SIZE_SCALE_H__ */
diff --git a/app/widgets/gimptoolpalette.c b/app/widgets/gimptoolpalette.c
index 76c8bc7..727eb5b 100644
--- a/app/widgets/gimptoolpalette.c
+++ b/app/widgets/gimptoolpalette.c
@@ -27,6 +27,8 @@
 
 #include "widgets-types.h"
 
+#include "config/gimpguiconfig.h"
+
 #include "core/gimp.h"
 #include "core/gimpcontext.h"
 #include "core/gimptoolinfo.h"
@@ -82,6 +84,9 @@ static gboolean gimp_tool_palette_tool_button_press   (GtkWidget       *widget,
                                                        GdkEventButton  *bevent,
                                                        GimpToolPalette *palette);
 
+static void     gimp_tool_palette_icon_size_notify    (GimpGuiConfig   *config,
+                                                       GParamSpec      *pspec,
+                                                       GimpToolPalette *palette);
 
 G_DEFINE_TYPE (GimpToolPalette, gimp_tool_palette, GTK_TYPE_TOOL_PALETTE)
 
@@ -173,7 +178,6 @@ gimp_tool_palette_style_set (GtkWidget *widget,
 {
   GimpToolPalettePrivate *private = GET_PRIVATE (widget);
   Gimp                   *gimp;
-  GtkIconSize             tool_icon_size;
   GtkReliefStyle          relief;
   GList                  *list;
 
@@ -185,12 +189,11 @@ gimp_tool_palette_style_set (GtkWidget *widget,
   gimp = gimp_toolbox_get_context (private->toolbox)->gimp;
 
   gtk_widget_style_get (widget,
-                        "tool-icon-size", &tool_icon_size,
                         "button-relief",  &relief,
                         NULL);
 
-  gtk_tool_palette_set_icon_size (GTK_TOOL_PALETTE (widget), tool_icon_size);
-
+  gimp_tool_palette_icon_size_notify (GIMP_GUI_CONFIG (gimp->config),
+                                      NULL, GIMP_TOOL_PALETTE (widget));
   for (list = gimp_get_tool_info_iter (gimp);
        list;
        list = g_list_next (list))
@@ -344,6 +347,14 @@ gimp_tool_palette_set_toolbox (GimpToolPalette *palette,
   gimp_tool_palette_tool_changed (context,
                                   gimp_context_get_tool (context),
                                   palette);
+
+  /* Update the toolbox icon size on config change. */
+  g_signal_connect (GIMP_GUI_CONFIG (context->gimp->config),
+                    "notify::icon-size",
+                    G_CALLBACK (gimp_tool_palette_icon_size_notify),
+                    palette);
+  gimp_tool_palette_icon_size_notify (GIMP_GUI_CONFIG (context->gimp->config),
+                                      NULL, palette);
 }
 
 gboolean
@@ -462,3 +473,127 @@ gimp_tool_palette_tool_button_press (GtkWidget       *widget,
 
   return FALSE;
 }
+
+static void
+gimp_tool_palette_initialize_tools (GimpToolPalette *palette)
+{
+  GimpContext            *context;
+  GimpToolInfo           *active_tool;
+  GList                  *list;
+  GSList                 *item_group = NULL;
+  GimpToolPalettePrivate *private    = GET_PRIVATE(palette);
+  GtkWidget              *group;
+
+  group = gtk_tool_item_group_new (_("Tools"));
+  gtk_tool_item_group_set_label_widget (GTK_TOOL_ITEM_GROUP (group), NULL);
+  gtk_container_add (GTK_CONTAINER (palette), group);
+  gtk_widget_show (group);
+
+  context     = gimp_toolbox_get_context (private->toolbox);
+  active_tool = gimp_context_get_tool (context);
+
+  for (list = gimp_get_tool_info_iter (context->gimp);
+       list;
+       list = g_list_next (list))
+    {
+      GimpToolInfo  *tool_info = list->data;
+      GtkToolItem   *item;
+      const gchar   *icon_name;
+      GimpUIManager *ui_manager;
+
+      icon_name = gimp_viewable_get_icon_name (GIMP_VIEWABLE (tool_info));
+
+      item = gtk_radio_tool_button_new (item_group);
+      gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (item), icon_name);
+      item_group = gtk_radio_tool_button_get_group (GTK_RADIO_TOOL_BUTTON (item));
+      gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (group), item, -1);
+      gtk_widget_show (GTK_WIDGET (item));
+
+      g_object_bind_property (tool_info, "visible",
+                              item,      "visible-horizontal",
+                              G_BINDING_SYNC_CREATE);
+      g_object_bind_property (tool_info, "visible",
+                              item,      "visible-vertical",
+                              G_BINDING_SYNC_CREATE);
+
+      g_object_set_data (G_OBJECT (tool_info), TOOL_BUTTON_DATA_KEY, item);
+      g_object_set_data (G_OBJECT (item)  ,    TOOL_INFO_DATA_KEY,   tool_info);
+
+      if (tool_info == active_tool)
+        gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (item), TRUE);
+
+      g_signal_connect (item, "toggled",
+                        G_CALLBACK (gimp_tool_palette_tool_button_toggled),
+                        palette);
+
+      g_signal_connect (gtk_bin_get_child (GTK_BIN (item)), "button-press-event",
+                        G_CALLBACK (gimp_tool_palette_tool_button_press),
+                        palette);
+
+      ui_manager = gimp_dock_get_ui_manager (GIMP_DOCK (private->toolbox));
+      if (ui_manager)
+        {
+          GtkAction   *action     = NULL;
+          const gchar *identifier = NULL;
+          gchar       *tmp        = NULL;
+          gchar       *name       = NULL;
+
+          identifier = gimp_object_get_name (tool_info);
+
+          tmp = g_strndup (identifier + strlen ("gimp-"),
+                           strlen (identifier) - strlen ("gimp--tool"));
+          name = g_strdup_printf ("tools-%s", tmp);
+          g_free (tmp);
+
+          action = gimp_ui_manager_find_action (ui_manager, "tools", name);
+          g_free (name);
+
+          if (action)
+            gimp_widget_set_accel_help (GTK_WIDGET (item), action);
+          else
+            gimp_help_set_help_data (GTK_WIDGET (item),
+                                     tool_info->help, tool_info->help_id);
+        }
+    }
+
+  /* We only need to initialize tools once */
+  g_signal_handlers_disconnect_by_func (private->toolbox,
+                                        gimp_tool_palette_initialize_tools,
+                                        palette);
+}
+
+static void
+gimp_tool_palette_icon_size_notify (GimpGuiConfig   *config,
+                                    GParamSpec      *pspec,
+                                    GimpToolPalette *palette)
+{
+  GimpIconSize size;
+  GtkIconSize  tool_icon_size;
+
+  g_object_get (config, "icon-size", &size, NULL);
+  /* Match GimpIconSize with GtkIconSize for the toolbox icons. */
+  switch (size)
+    {
+    case GIMP_ICON_SIZE_SMALL:
+      tool_icon_size = GTK_ICON_SIZE_SMALL_TOOLBAR;
+      break;
+    case GIMP_ICON_SIZE_MEDIUM:
+      tool_icon_size = GTK_ICON_SIZE_LARGE_TOOLBAR;
+      break;
+    case GIMP_ICON_SIZE_LARGE:
+      tool_icon_size = GTK_ICON_SIZE_DND;
+      break;
+    case GIMP_ICON_SIZE_HUGE:
+      tool_icon_size = GTK_ICON_SIZE_DIALOG;
+      break;
+    default:
+      /* GIMP_ICON_SIZE_DEFAULT:
+       * let's use the size set by the theme. */
+      gtk_widget_style_get (GTK_WIDGET (palette),
+                            "tool-icon-size", &tool_icon_size,
+                            NULL);
+      break;
+    }
+
+  gtk_tool_palette_set_icon_size (GTK_TOOL_PALETTE (palette), tool_icon_size);
+}
diff --git a/app/widgets/widgets-types.h b/app/widgets/widgets-types.h
index 0b9243f..e6d2dfb 100644
--- a/app/widgets/widgets-types.h
+++ b/app/widgets/widgets-types.h
@@ -191,6 +191,7 @@ typedef struct _GimpHandleBar                GimpHandleBar;
 typedef struct _GimpHistogramBox             GimpHistogramBox;
 typedef struct _GimpHistogramView            GimpHistogramView;
 typedef struct _GimpIconPicker               GimpIconPicker;
+typedef struct _GimpIconSizeScale            GimpIconSizeScale;
 typedef struct _GimpImageCommentEditor       GimpImageCommentEditor;
 typedef struct _GimpImageParasiteView        GimpImageParasiteView;
 typedef struct _GimpImageProfileView         GimpImageProfileView;


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