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".
This commit is contained in:
Michael Natterer 2018-10-25 14:45:55 +02:00
parent 231b82a7fe
commit ae9d84dd22
4 changed files with 184 additions and 40 deletions

View File

@ -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

View File

@ -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;

View File

@ -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);
};

View File

@ -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);
}
}
}