[gimp] Issue #2235 - Color reset/swap keyboard shortcuts not discoverable...



commit ae9d84dd2273a9420c1d92468aac178e508f2307
Author: Michael Natterer <mitch gimp org>
Date:   Thu Oct 25 14:45:55 2018 +0200

    Issue #2235 - Color reset/swap keyboard shortcuts not discoverable...
    
    ...via hover tooltips
    
    Use the GtkWidget::query_tooltip() signal on GimpFgBgEditor to emit an
    own signal "tooltip" that has the hovered widget area as parameter.
    
    Connect to GimpFgBgEditor::tooltip() in gimptoolbox-color-area.c and
    set separate tooltips on the widget's areas, including the shortcuts
    for "Swap colors" and "Default colors".

 app/core/gimpmarshal.list            |   1 +
 app/widgets/gimpfgbgeditor.c         | 100 +++++++++++++++++++++-----------
 app/widgets/gimpfgbgeditor.h         |  14 +++++
 app/widgets/gimptoolbox-color-area.c | 109 ++++++++++++++++++++++++++++++++---
 4 files changed, 184 insertions(+), 40 deletions(-)
---
diff --git a/app/core/gimpmarshal.list b/app/core/gimpmarshal.list
index 4232c475d2..b08acf9391 100644
--- a/app/core/gimpmarshal.list
+++ b/app/core/gimpmarshal.list
@@ -53,6 +53,7 @@ VOID: INT, BOOLEAN
 VOID: INT, INT
 VOID: INT, INT, INT, INT
 VOID: INT, INT, BOOLEAN, BOOLEAN
+VOID: INT, OBJECT
 VOID: OBJECT
 VOID: OBJECT, BOOLEAN
 VOID: OBJECT, INT
diff --git a/app/widgets/gimpfgbgeditor.c b/app/widgets/gimpfgbgeditor.c
index 565a100a53..200be0ba39 100644
--- a/app/widgets/gimpfgbgeditor.c
+++ b/app/widgets/gimpfgbgeditor.c
@@ -52,18 +52,10 @@ enum
 enum
 {
   COLOR_CLICKED,
+  TOOLTIP,
   LAST_SIGNAL
 };
 
-typedef enum
-{
-  INVALID_AREA,
-  FOREGROUND_AREA,
-  BACKGROUND_AREA,
-  SWAP_AREA,
-  DEFAULT_AREA
-} FgBgTarget;
-
 
 static void     gimp_fg_bg_editor_dispose           (GObject          *object);
 static void     gimp_fg_bg_editor_set_property      (GObject          *object,
@@ -87,6 +79,11 @@ static gboolean gimp_fg_bg_editor_drag_motion       (GtkWidget        *widget,
                                                      gint              x,
                                                      gint              y,
                                                      guint             time);
+static gboolean gimp_fg_bg_editor_query_tooltip     (GtkWidget        *widget,
+                                                     gint              x,
+                                                     gint              y,
+                                                     gboolean          keyboard_mode,
+                                                     GtkTooltip       *tooltip);
 
 static void     gimp_fg_bg_editor_drag_color        (GtkWidget        *widget,
                                                      GimpRGB          *color,
@@ -124,6 +121,17 @@ gimp_fg_bg_editor_class_init (GimpFgBgEditorClass *klass)
                   G_TYPE_NONE, 1,
                   GIMP_TYPE_ACTIVE_COLOR);
 
+  editor_signals[TOOLTIP] =
+    g_signal_new ("tooltip",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_FIRST,
+                  G_STRUCT_OFFSET (GimpFgBgEditorClass, tooltip),
+                  NULL, NULL,
+                  gimp_marshal_VOID__INT_OBJECT,
+                  G_TYPE_NONE, 2,
+                  G_TYPE_INT,
+                  GTK_TYPE_TOOLTIP);
+
   object_class->dispose              = gimp_fg_bg_editor_dispose;
   object_class->set_property         = gimp_fg_bg_editor_set_property;
   object_class->get_property         = gimp_fg_bg_editor_get_property;
@@ -133,6 +141,7 @@ gimp_fg_bg_editor_class_init (GimpFgBgEditorClass *klass)
   widget_class->button_press_event   = gimp_fg_bg_editor_button_press;
   widget_class->button_release_event = gimp_fg_bg_editor_button_release;
   widget_class->drag_motion          = gimp_fg_bg_editor_drag_motion;
+  widget_class->query_tooltip        = gimp_fg_bg_editor_query_tooltip;
 
   g_object_class_install_property (object_class, PROP_CONTEXT,
                                    g_param_spec_object ("context",
@@ -439,7 +448,7 @@ gimp_fg_bg_editor_draw (GtkWidget *widget,
   return TRUE;
 }
 
-static FgBgTarget
+static GimpFgBgTarget
 gimp_fg_bg_editor_target (GimpFgBgEditor *editor,
                           gint            x,
                           gint            y)
@@ -476,31 +485,31 @@ gimp_fg_bg_editor_target (GimpFgBgEditor *editor,
       y > border.top           &&
       y < border.top + rect_h)
     {
-      return FOREGROUND_AREA;
+      return GIMP_FG_BG_TARGET_FOREGROUND;
     }
   else if (x > width  - border.right - rect_w  &&
            x < width  - border.right           &&
            y > height - border.bottom - rect_h &&
            y < height - border.bottom)
     {
-      return BACKGROUND_AREA;
+      return GIMP_FG_BG_TARGET_BACKGROUND;
     }
   else if (x > border.left                &&
            x < border.left + button_width &&
            y > border.top + rect_h        &&
            y < height - border.bottom)
     {
-      return DEFAULT_AREA;
+      return GIMP_FG_BG_TARGET_DEFAULT;
     }
   else if (x > border.left + rect_w &&
            x < width - border.right &&
            y > border.top           &&
            y < border.top + button_height)
     {
-      return SWAP_AREA;
+      return GIMP_FG_BG_TARGET_SWAP;
     }
 
-  return INVALID_AREA;
+  return GIMP_FG_BG_TARGET_INVALID;
 }
 
 static gboolean
@@ -511,33 +520,33 @@ gimp_fg_bg_editor_button_press (GtkWidget      *widget,
 
   if (bevent->button == 1 && bevent->type == GDK_BUTTON_PRESS)
     {
-      FgBgTarget target = gimp_fg_bg_editor_target (editor,
-                                                    bevent->x, bevent->y);
+      GimpFgBgTarget target = gimp_fg_bg_editor_target (editor,
+                                                        bevent->x, bevent->y);
 
-      editor->click_target = INVALID_AREA;
+      editor->click_target = GIMP_FG_BG_TARGET_INVALID;
 
       switch (target)
         {
-        case FOREGROUND_AREA:
+        case GIMP_FG_BG_TARGET_FOREGROUND:
           if (editor->active_color != GIMP_ACTIVE_COLOR_FOREGROUND)
             gimp_fg_bg_editor_set_active (editor,
                                           GIMP_ACTIVE_COLOR_FOREGROUND);
-          editor->click_target = FOREGROUND_AREA;
+          editor->click_target = GIMP_FG_BG_TARGET_FOREGROUND;
           break;
 
-        case BACKGROUND_AREA:
+        case GIMP_FG_BG_TARGET_BACKGROUND:
           if (editor->active_color != GIMP_ACTIVE_COLOR_BACKGROUND)
             gimp_fg_bg_editor_set_active (editor,
                                           GIMP_ACTIVE_COLOR_BACKGROUND);
-          editor->click_target = BACKGROUND_AREA;
+          editor->click_target = GIMP_FG_BG_TARGET_BACKGROUND;
           break;
 
-        case SWAP_AREA:
+        case GIMP_FG_BG_TARGET_SWAP:
           if (editor->context)
             gimp_context_swap_colors (editor->context);
           break;
 
-        case DEFAULT_AREA:
+        case GIMP_FG_BG_TARGET_DEFAULT:
           if (editor->context)
             gimp_context_set_default_colors (editor->context);
           break;
@@ -558,19 +567,19 @@ gimp_fg_bg_editor_button_release (GtkWidget      *widget,
 
   if (bevent->button == 1)
     {
-      FgBgTarget target = gimp_fg_bg_editor_target (editor,
-                                                    bevent->x, bevent->y);
+      GimpFgBgTarget target = gimp_fg_bg_editor_target (editor,
+                                                        bevent->x, bevent->y);
 
       if (target == editor->click_target)
         {
           switch (target)
             {
-            case FOREGROUND_AREA:
+            case GIMP_FG_BG_TARGET_FOREGROUND:
               g_signal_emit (editor, editor_signals[COLOR_CLICKED], 0,
                              GIMP_ACTIVE_COLOR_FOREGROUND);
               break;
 
-            case BACKGROUND_AREA:
+            case GIMP_FG_BG_TARGET_BACKGROUND:
               g_signal_emit (editor, editor_signals[COLOR_CLICKED], 0,
                              GIMP_ACTIVE_COLOR_BACKGROUND);
               break;
@@ -580,7 +589,7 @@ gimp_fg_bg_editor_button_release (GtkWidget      *widget,
             }
         }
 
-      editor->click_target = INVALID_AREA;
+      editor->click_target = GIMP_FG_BG_TARGET_INVALID;
     }
 
   return FALSE;
@@ -594,9 +603,10 @@ gimp_fg_bg_editor_drag_motion (GtkWidget      *widget,
                                guint           time)
 {
   GimpFgBgEditor *editor = GIMP_FG_BG_EDITOR (widget);
-  FgBgTarget      target = gimp_fg_bg_editor_target (editor, x, y);
+  GimpFgBgTarget  target = gimp_fg_bg_editor_target (editor, x, y);
 
-  if (target == FOREGROUND_AREA || target == BACKGROUND_AREA)
+  if (target == GIMP_FG_BG_TARGET_FOREGROUND ||
+      target == GIMP_FG_BG_TARGET_BACKGROUND)
     {
       gdk_drag_status (context, GDK_ACTION_COPY, time);
 
@@ -608,6 +618,30 @@ gimp_fg_bg_editor_drag_motion (GtkWidget      *widget,
   return FALSE;
 }
 
+static gboolean
+gimp_fg_bg_editor_query_tooltip (GtkWidget  *widget,
+                                 gint        x,
+                                 gint        y,
+                                 gboolean    keyboard_mode,
+                                 GtkTooltip *tooltip)
+{
+  if (! keyboard_mode)
+    {
+      GimpFgBgEditor *editor = GIMP_FG_BG_EDITOR (widget);
+      GimpFgBgTarget  target = gimp_fg_bg_editor_target (editor, x, y);
+
+      if (target != GIMP_FG_BG_TARGET_INVALID)
+        {
+          g_signal_emit (widget, editor_signals[TOOLTIP], 0,
+                         target, tooltip);
+
+          return TRUE;
+        }
+    }
+
+  return FALSE;
+}
+
 
 /*  public functions  */
 
@@ -718,11 +752,11 @@ gimp_fg_bg_editor_drop_color (GtkWidget     *widget,
     {
       switch (gimp_fg_bg_editor_target (editor, x, y))
         {
-        case FOREGROUND_AREA:
+        case GIMP_FG_BG_TARGET_FOREGROUND:
           gimp_context_set_foreground (editor->context, color);
           break;
 
-        case BACKGROUND_AREA:
+        case GIMP_FG_BG_TARGET_BACKGROUND:
           gimp_context_set_background (editor->context, color);
           break;
 
diff --git a/app/widgets/gimpfgbgeditor.h b/app/widgets/gimpfgbgeditor.h
index a3d4bb3846..7c425afc7d 100644
--- a/app/widgets/gimpfgbgeditor.h
+++ b/app/widgets/gimpfgbgeditor.h
@@ -22,6 +22,16 @@
 #define __GIMP_FG_BG_EDITOR_H__
 
 
+typedef enum
+{
+  GIMP_FG_BG_TARGET_INVALID,
+  GIMP_FG_BG_TARGET_FOREGROUND,
+  GIMP_FG_BG_TARGET_BACKGROUND,
+  GIMP_FG_BG_TARGET_SWAP,
+  GIMP_FG_BG_TARGET_DEFAULT
+} GimpFgBgTarget;
+
+
 #define GIMP_TYPE_FG_BG_EDITOR            (gimp_fg_bg_editor_get_type ())
 #define GIMP_FG_BG_EDITOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_FG_BG_EDITOR, 
GimpFgBgEditor))
 #define GIMP_FG_BG_EDITOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_FG_BG_EDITOR, 
GimpFgBgEditorClass))
@@ -58,6 +68,10 @@ struct _GimpFgBgEditorClass
 
   void (* color_clicked) (GimpFgBgEditor  *editor,
                           GimpActiveColor  color);
+
+  void (* tooltip)       (GimpFgBgEditor *editor,
+                          GimpFgBgTarget  target,
+                          GtkTooltip      tooltip);
 };
 
 
diff --git a/app/widgets/gimptoolbox-color-area.c b/app/widgets/gimptoolbox-color-area.c
index 57854e4bd2..feea1b5f77 100644
--- a/app/widgets/gimptoolbox-color-area.c
+++ b/app/widgets/gimptoolbox-color-area.c
@@ -36,6 +36,7 @@
 #include "gimpsessioninfo.h"
 #include "gimptoolbox.h"
 #include "gimptoolbox-color-area.h"
+#include "gimpuimanager.h"
 
 #include "gimp-intl.h"
 
@@ -57,6 +58,10 @@ static void   color_area_dialog_update      (GimpColorDialog      *dialog,
 static void   color_area_color_clicked      (GimpFgBgEditor       *editor,
                                              GimpActiveColor       active_color,
                                              GimpContext          *context);
+static void   color_area_tooltip            (GimpFgBgEditor       *editor,
+                                             GimpFgBgTarget        target,
+                                             GtkTooltip           *tooltip,
+                                             GimpToolbox          *toolbox);
 
 
 /*  local variables  */
@@ -85,18 +90,18 @@ gimp_toolbox_color_area_create (GimpToolbox *toolbox,
   color_area = gimp_fg_bg_editor_new (context);
   gtk_widget_set_size_request (color_area, width, height);
 
-  gimp_help_set_help_data
-    (color_area,
-     _("Foreground & background colors.\n"
-       "The black and white squares reset colors.\n"
-       "The arrows swap colors.\n"
-       "Click to open the color selection dialog."),
-     GIMP_HELP_TOOLBOX_COLOR_AREA);
+  gimp_help_set_help_data (color_area, NULL,
+                           GIMP_HELP_TOOLBOX_COLOR_AREA);
+  g_object_set (color_area, "has-tooltip", TRUE, NULL);
 
   g_signal_connect (color_area, "color-clicked",
                     G_CALLBACK (color_area_color_clicked),
                     context);
 
+  g_signal_connect (color_area, "tooltip",
+                    G_CALLBACK (color_area_tooltip),
+                    toolbox);
+
   return color_area;
 }
 
@@ -281,3 +286,93 @@ color_area_color_clicked (GimpFgBgEditor  *editor,
   gtk_window_present (GTK_WINDOW (color_dialog));
   color_dialog_active = TRUE;
 }
+
+static gboolean
+accel_find_func (GtkAccelKey *key,
+                 GClosure    *closure,
+                 gpointer     data)
+{
+  return (GClosure *) data == closure;
+}
+
+static void
+color_area_tooltip (GimpFgBgEditor *editor,
+                    GimpFgBgTarget  target,
+                    GtkTooltip     *tooltip,
+                    GimpToolbox    *toolbox)
+{
+  GimpUIManager *manager = gimp_dock_get_ui_manager (GIMP_DOCK (toolbox));
+  GtkAction     *action  = NULL;
+  const gchar   *text    = NULL;
+
+  switch (target)
+    {
+    case GIMP_FG_BG_TARGET_FOREGROUND:
+      text = _("The active foreground color.\n"
+               "Click to open the color selection dialog.");
+      break;
+
+    case GIMP_FG_BG_TARGET_BACKGROUND:
+      text = _("The active background color.\n"
+               "Click to open the color selection dialog.");
+      break;
+
+    case GIMP_FG_BG_TARGET_SWAP:
+      action = gimp_ui_manager_find_action (manager, "context",
+                                            "context-colors-swap");
+      text = gtk_action_get_tooltip (action);
+      break;
+
+    case GIMP_FG_BG_TARGET_DEFAULT:
+      action = gimp_ui_manager_find_action (manager, "context",
+                                            "context-colors-default");
+      text = gtk_action_get_tooltip (action);
+      break;
+
+    default:
+      break;
+    }
+
+  if (text)
+    {
+      gchar *markup = NULL;
+
+      if (action)
+        {
+          GtkAccelGroup *accel_group;
+          GClosure      *accel_closure;
+          GtkAccelKey   *accel_key;
+
+          accel_closure = gtk_action_get_accel_closure (action);
+          accel_group   = gtk_accel_group_from_accel_closure (accel_closure);
+
+          accel_key = gtk_accel_group_find (accel_group,
+                                            accel_find_func,
+                                            accel_closure);
+
+          if (accel_key            &&
+              accel_key->accel_key &&
+              (accel_key->accel_flags & GTK_ACCEL_VISIBLE))
+            {
+              gchar *escaped = g_markup_escape_text (text, -1);
+              gchar *accel   = gtk_accelerator_get_label (accel_key->accel_key,
+                                                          accel_key->accel_mods);
+
+              markup = g_strdup_printf ("%s  <b>%s</b>", escaped, accel);
+
+              g_free (accel);
+              g_free (escaped);
+            }
+        }
+
+      if (markup)
+        {
+          gtk_tooltip_set_markup (tooltip, markup);
+          g_free (markup);
+        }
+      else
+        {
+          gtk_tooltip_set_text (tooltip, text);
+        }
+    }
+}


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