color chooser: Use a popover menu

Make the color chooser use a popover menu
and actions.
This commit is contained in:
Matthias Clasen 2019-06-12 03:02:15 +00:00
parent 6452aeef3c
commit 6f12c39a04
2 changed files with 120 additions and 90 deletions

View File

@ -90,6 +90,8 @@ struct _GtkColorChooserWidgetPrivate
gboolean has_default_palette;
GSettings *settings;
GActionMap *context_actions;
};
enum
@ -134,31 +136,6 @@ select_swatch (GtkColorChooserWidget *cc,
g_object_notify (G_OBJECT (cc), "rgba");
}
static void
swatch_activate (GtkColorSwatch *swatch,
GtkColorChooserWidget *cc)
{
GdkRGBA color;
gtk_color_swatch_get_rgba (swatch, &color);
_gtk_color_chooser_color_activated (GTK_COLOR_CHOOSER (cc), &color);
}
static void
swatch_customize (GtkColorSwatch *swatch,
GtkColorChooserWidget *cc)
{
GtkColorChooserWidgetPrivate *priv = gtk_color_chooser_widget_get_instance_private (cc);
GdkRGBA color;
gtk_color_swatch_get_rgba (swatch, &color);
gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (priv->editor), &color);
gtk_widget_hide (priv->palette);
gtk_widget_show (priv->editor);
g_object_notify (G_OBJECT (cc), "show-editor");
}
static void
swatch_selected (GtkColorSwatch *swatch,
GtkStateFlags previous,
@ -176,31 +153,14 @@ static void
connect_swatch_signals (GtkWidget *p,
gpointer data)
{
g_signal_connect (p, "activate", G_CALLBACK (swatch_activate), data);
g_signal_connect (p, "customize", G_CALLBACK (swatch_customize), data);
g_signal_connect (p, "state-flags-changed", G_CALLBACK (swatch_selected), data);
}
static void
button_activate (GtkColorSwatch *swatch,
GtkColorChooserWidget *cc)
{
GtkColorChooserWidgetPrivate *priv = gtk_color_chooser_widget_get_instance_private (cc);
/* somewhat random, makes the hairline nicely visible */
GdkRGBA color = { 0.75, 0.25, 0.25, 1.0 };
gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (priv->editor), &color);
gtk_widget_hide (priv->palette);
gtk_widget_show (priv->editor);
g_object_notify (G_OBJECT (cc), "show-editor");
}
static void
connect_button_signals (GtkWidget *p,
gpointer data)
{
g_signal_connect (p, "activate", G_CALLBACK (button_activate), data);
// g_signal_connect (p, "activate", G_CALLBACK (button_activate), data);
}
static void
@ -532,6 +492,57 @@ add_default_palette (GtkColorChooserWidget *cc)
priv->has_default_palette = TRUE;
}
static void
customize_color (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
GtkColorChooserWidget *cc = user_data;
GtkColorChooserWidgetPrivate *priv = gtk_color_chooser_widget_get_instance_private (cc);
GdkRGBA color;
g_variant_get (parameter, "(dddd)", &color.red, &color.green, &color.blue, &color.alpha);
gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (priv->editor), &color);
gtk_widget_hide (priv->palette);
gtk_widget_show (priv->editor);
g_object_notify (G_OBJECT (cc), "show-editor");
}
static void
select_color (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
GtkColorChooserWidget *cc = user_data;
GdkRGBA color;
g_variant_get (parameter, "(dddd)", &color.red, &color.green, &color.blue, &color.alpha);
_gtk_color_chooser_color_activated (GTK_COLOR_CHOOSER (cc), &color);
}
static void
gtk_color_chooser_widget_add_context_actions (GtkColorChooserWidget *cc)
{
GtkColorChooserWidgetPrivate *priv = gtk_color_chooser_widget_get_instance_private (cc);
GActionEntry entries[] = {
{ "select", select_color, "(dddd)", NULL, NULL },
{ "customize", customize_color, "(dddd)", NULL, NULL },
};
GSimpleActionGroup *actions = g_simple_action_group_new ();
priv->context_actions = G_ACTION_MAP (actions);
g_action_map_add_action_entries (G_ACTION_MAP (actions), entries, G_N_ELEMENTS (entries), cc);
gtk_widget_insert_action_group (GTK_WIDGET (cc), "color", G_ACTION_GROUP (actions));
}
static void
gtk_color_chooser_widget_init (GtkColorChooserWidget *cc)
{
@ -623,6 +634,8 @@ gtk_color_chooser_widget_init (GtkColorChooserWidget *cc)
priv->size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
gtk_size_group_add_widget (priv->size_group, priv->palette);
gtk_size_group_add_widget (priv->size_group, box);
gtk_color_chooser_widget_add_context_actions (cc);
}
/* GObject implementation {{{1 */

View File

@ -33,7 +33,7 @@
#include "gtkintl.h"
#include "gtkmain.h"
#include "gtkmodelbutton.h"
#include "gtkpopover.h"
#include "gtkpopovermenu.h"
#include "gtkprivate.h"
#include "gtksnapshot.h"
#include "gtkstylecontextprivate.h"
@ -76,16 +76,6 @@ enum
PROP_HAS_MENU
};
enum
{
ACTIVATE,
CUSTOMIZE,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
G_DEFINE_TYPE_WITH_PRIVATE (GtkColorSwatch, gtk_color_swatch, GTK_TYPE_WIDGET)
#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
@ -231,6 +221,32 @@ swatch_drag_data_received (GtkWidget *widget,
gtk_color_swatch_set_rgba (GTK_COLOR_SWATCH (widget), &color);
}
static void
activate_color (GtkColorSwatch *swatch)
{
GtkColorSwatchPrivate *priv = gtk_color_swatch_get_instance_private (swatch);
gtk_widget_activate_action (GTK_WIDGET (swatch),
"color.select",
g_variant_new ("(dddd)",
priv->color.red,
priv->color.green,
priv->color.blue,
priv->color.alpha));
}
static void
customize_color (GtkColorSwatch *swatch)
{
GtkColorSwatchPrivate *priv = gtk_color_swatch_get_instance_private (swatch);
gtk_widget_activate_action (GTK_WIDGET (swatch),
"color.customize",
g_variant_new ("(dddd)",
priv->color.red,
priv->color.green,
priv->color.blue,
priv->color.alpha));
}
static gboolean
key_controller_key_pressed (GtkEventControllerKey *controller,
guint keyval,
@ -252,40 +268,51 @@ key_controller_key_pressed (GtkEventControllerKey *controller,
(gtk_widget_get_state_flags (widget) & GTK_STATE_FLAG_SELECTED) == 0)
gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_SELECTED, FALSE);
else
g_signal_emit (swatch, signals[ACTIVATE], 0);
customize_color (swatch);
return TRUE;
}
return FALSE;
}
static void
emit_customize (GtkColorSwatch *swatch)
static GMenuModel *
gtk_color_swatch_get_menu_model (GtkColorSwatch *swatch)
{
g_signal_emit (swatch, signals[CUSTOMIZE], 0);
GtkColorSwatchPrivate *priv = gtk_color_swatch_get_instance_private (swatch);
GMenu *menu, *section;
GMenuItem *item;
menu = g_menu_new ();
section = g_menu_new ();
item = g_menu_item_new (_("Customize"), NULL);
g_menu_item_set_action_and_target_value (item, "color.customize",
g_variant_new ("(dddd)",
priv->color.red,
priv->color.green,
priv->color.blue,
priv->color.alpha));
g_menu_append_item (section, item);
g_menu_append_section (menu, NULL, G_MENU_MODEL (section));
g_object_unref (item);
g_object_unref (section);
return G_MENU_MODEL (menu);
}
static void
do_popup (GtkColorSwatch *swatch)
{
GtkColorSwatchPrivate *priv = gtk_color_swatch_get_instance_private (swatch);
GMenuModel *model;
if (priv->popover == NULL)
{
GtkWidget *box;
GtkWidget *item;
g_clear_pointer (&priv->popover, gtk_widget_unparent);
priv->popover = gtk_popover_new (GTK_WIDGET (swatch));
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_container_add (GTK_CONTAINER (priv->popover), box);
g_object_set (box, "margin", 10, NULL);
item = g_object_new (GTK_TYPE_MODEL_BUTTON,
"text", _("C_ustomize"),
NULL);
g_signal_connect_swapped (item, "clicked",
G_CALLBACK (emit_customize), swatch);
gtk_container_add (GTK_CONTAINER (box), item);
}
model = gtk_color_swatch_get_menu_model (swatch);
priv->popover = gtk_popover_menu_new_from_model (GTK_WIDGET (swatch), model);
g_object_unref (model);
gtk_popover_popup (GTK_POPOVER (priv->popover));
}
@ -300,7 +327,7 @@ swatch_primary_action (GtkColorSwatch *swatch)
flags = gtk_widget_get_state_flags (widget);
if (!priv->has_color)
{
g_signal_emit (swatch, signals[ACTIVATE], 0);
customize_color (swatch);
return TRUE;
}
else if (priv->selectable &&
@ -340,7 +367,7 @@ tap_action (GtkGestureClick *gesture,
if (n_press == 1)
swatch_primary_action (swatch);
else if (n_press > 1)
g_signal_emit (swatch, signals[ACTIVATE], 0);
activate_color (swatch);
}
else if (button == GDK_BUTTON_SECONDARY)
{
@ -505,7 +532,7 @@ swatch_dispose (GObject *object)
GtkColorSwatch *swatch = GTK_COLOR_SWATCH (object);
GtkColorSwatchPrivate *priv = gtk_color_swatch_get_instance_private (swatch);
g_clear_pointer (&priv->popover, gtk_widget_destroy);
g_clear_pointer (&priv->popover, gtk_widget_unparent);
G_OBJECT_CLASS (gtk_color_swatch_parent_class)->dispose (object);
}
@ -530,20 +557,6 @@ gtk_color_swatch_class_init (GtkColorSwatchClass *class)
widget_class->size_allocate = swatch_size_allocate;
widget_class->state_flags_changed = swatch_state_flags_changed;
signals[ACTIVATE] =
g_signal_new (I_("activate"),
GTK_TYPE_COLOR_SWATCH,
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GtkColorSwatchClass, activate),
NULL, NULL, NULL, G_TYPE_NONE, 0);
signals[CUSTOMIZE] =
g_signal_new (I_("customize"),
GTK_TYPE_COLOR_SWATCH,
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GtkColorSwatchClass, customize),
NULL, NULL, NULL, G_TYPE_NONE, 0);
g_object_class_install_property (object_class, PROP_RGBA,
g_param_spec_boxed ("rgba", P_("RGBA Color"), P_("Color as RGBA"),
GDK_TYPE_RGBA, GTK_PARAM_READWRITE));
@ -569,6 +582,10 @@ gtk_color_swatch_init (GtkColorSwatch *swatch)
priv->use_alpha = TRUE;
priv->selectable = TRUE;
priv->has_menu = TRUE;
priv->color.red = 0.75;
priv->color.green = 0.25;
priv->color.blue = 0.25;
priv->color.alpha = 1.0;
gtk_widget_set_can_focus (GTK_WIDGET (swatch), TRUE);
gtk_widget_set_overflow (GTK_WIDGET (swatch), GTK_OVERFLOW_HIDDEN);