Commit c376e827 authored by Matthias Clasen's avatar Matthias Clasen

colorswatch: Convert to gadgets

Use gadgets for the widget and the overlay.
parent fcca4967
......@@ -30,6 +30,7 @@
#include "gtkintl.h"
#include "gtkrenderprivate.h"
#include "gtkcssnodeprivate.h"
#include "gtkcsscustomgadgetprivate.h"
#include "gtkwidgetprivate.h"
#include "gtkstylecontextprivate.h"
#include "a11y/gtkcolorswatchaccessibleprivate.h"
......@@ -59,7 +60,8 @@ struct _GtkColorSwatchPrivate
GtkGesture *long_press_gesture;
GtkGesture *multipress_gesture;
GtkCssNode *overlay_node;
GtkCssGadget *gadget;
GtkCssGadget *overlay_gadget;
GtkWidget *popover;
};
......@@ -81,85 +83,44 @@ enum
static guint signals[LAST_SIGNAL];
static void hold_action (GtkGestureLongPress *gesture,
gdouble x,
gdouble y,
GtkColorSwatch *swatch);
static void tap_action (GtkGestureMultiPress *gesture,
gint n_press,
gdouble x,
gdouble y,
GtkColorSwatch *swatch);
G_DEFINE_TYPE_WITH_PRIVATE (GtkColorSwatch, gtk_color_swatch, GTK_TYPE_WIDGET)
static void
gtk_color_swatch_init (GtkColorSwatch *swatch)
static gboolean
swatch_draw (GtkWidget *widget,
cairo_t *cr)
{
GtkCssNode *widget_node;
GtkStyleContext *context;
swatch->priv = gtk_color_swatch_get_instance_private (swatch);
swatch->priv->use_alpha = TRUE;
swatch->priv->selectable = TRUE;
swatch->priv->has_menu = TRUE;
gtk_widget_set_can_focus (GTK_WIDGET (swatch), TRUE);
gtk_widget_set_has_window (GTK_WIDGET (swatch), FALSE);
gtk_css_gadget_draw (GTK_COLOR_SWATCH (widget)->priv->gadget, cr);
swatch->priv->long_press_gesture = gtk_gesture_long_press_new (GTK_WIDGET (swatch));
gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (swatch->priv->long_press_gesture),
TRUE);
g_signal_connect (swatch->priv->long_press_gesture, "pressed",
G_CALLBACK (hold_action), swatch);
swatch->priv->multipress_gesture = gtk_gesture_multi_press_new (GTK_WIDGET (swatch));
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (swatch->priv->multipress_gesture), 0);
g_signal_connect (swatch->priv->multipress_gesture, "pressed",
G_CALLBACK (tap_action), swatch);
widget_node = gtk_widget_get_css_node (GTK_WIDGET (swatch));
swatch->priv->overlay_node = gtk_css_node_new ();
gtk_css_node_set_name (swatch->priv->overlay_node, I_("overlay"));
gtk_css_node_set_parent (swatch->priv->overlay_node, widget_node);
gtk_css_node_set_state (swatch->priv->overlay_node, gtk_css_node_get_state (widget_node));
g_object_unref (swatch->priv->overlay_node);
context = gtk_widget_get_style_context (GTK_WIDGET (swatch));
gtk_style_context_add_class (context, "activatable");
return FALSE;
}
#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
#define PIXBUF_SIZE 16
static gboolean
swatch_draw (GtkWidget *widget,
cairo_t *cr)
{
GtkColorSwatch *swatch = (GtkColorSwatch*)widget;
gdouble width, height;
gtk_color_swatch_render (GtkCssGadget *gadget,
cairo_t *cr,
int x,
int y,
int width,
int height,
gpointer data)
{
GtkWidget *widget;
GtkColorSwatch *swatch;
GtkStyleContext *context;
GtkStateFlags state;
GtkIconTheme *theme;
GtkBorder border, padding;
GdkRectangle rect;
GtkIconInfo *icon_info = NULL;
gint scale;
theme = gtk_icon_theme_get_default ();
widget = gtk_css_gadget_get_owner (gadget);
swatch = GTK_COLOR_SWATCH (widget);
context = gtk_widget_get_style_context (widget);
state = gtk_style_context_get_state (context);
width = gtk_widget_get_allocated_width (widget);
height = gtk_widget_get_allocated_height (widget);
gtk_render_background (context, cr, 0, 0, width, height);
if (swatch->priv->has_color)
{
cairo_pattern_t *pattern;
cairo_matrix_t matrix;
gtk_render_content_path (context, cr, 0, 0, width, height);
gtk_render_content_path (context, cr, x, y, width, height);
if (swatch->priv->use_alpha)
{
......@@ -193,7 +154,36 @@ swatch_draw (GtkWidget *widget,
cairo_fill (cr);
}
gtk_render_frame (context, cr, 0, 0, width, height);
gtk_render_frame (context, cr, x, y, width, height);
gtk_css_gadget_draw (swatch->priv->overlay_gadget, cr);
return gtk_widget_has_visible_focus (widget);
}
static gboolean
gtk_color_swatch_render_overlay (GtkCssGadget *gadget,
cairo_t *cr,
int x,
int y,
int width,
int height,
gpointer data)
{
GtkWidget *widget;
GtkColorSwatch *swatch;
GtkStyleContext *context;
GtkStateFlags state;
GtkIconTheme *theme;
GtkIconInfo *icon_info = NULL;
gint scale;
widget = gtk_css_gadget_get_owner (gadget);
swatch = GTK_COLOR_SWATCH (widget);
theme = gtk_icon_theme_get_default ();
context = gtk_widget_get_style_context (widget);
state = gtk_style_context_get_state (context);
scale = gtk_widget_get_scale_factor (widget);
if (swatch->priv->icon)
......@@ -218,18 +208,6 @@ swatch_draw (GtkWidget *widget,
}
/* now draw the overlay image */
gtk_style_context_get_border (context, state, &border);
gtk_style_context_get_padding (context, state, &padding);
rect.width = width - (border.left + border.right + padding.left + padding.right);
rect.height = height - (border.top + border.bottom + padding.top + padding.bottom);
rect.x = border.left + padding.left;
rect.y = border.top + padding.top;
gtk_style_context_save_to_node (context, swatch->priv->overlay_node);
gtk_render_background (context, cr, rect.x, rect.y, rect.width, rect.height);
gtk_render_frame (context, cr, rect.x, rect.y, rect.width, rect.height);
if (icon_info != NULL)
{
GdkPixbuf *pixbuf;
......@@ -240,9 +218,7 @@ swatch_draw (GtkWidget *widget,
cairo_surface_t *surface;
surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale, gtk_widget_get_window (widget));
gtk_render_icon_surface (context, cr, surface,
rect.x + (rect.width - (gdk_pixbuf_get_width (pixbuf) / scale)) / 2,
rect.y + (rect.height - (gdk_pixbuf_get_height (pixbuf) / scale)) / 2);
gtk_render_icon_surface (context, cr, surface, x, y);
cairo_surface_destroy (surface);
g_object_unref (pixbuf);
}
......@@ -250,11 +226,6 @@ swatch_draw (GtkWidget *widget,
g_object_unref (icon_info);
}
if (gtk_widget_has_visible_focus (widget))
gtk_render_focus (context, cr, 0, 0, width, height);
gtk_style_context_restore (context);
return FALSE;
}
......@@ -349,33 +320,49 @@ swatch_drag_data_received (GtkWidget *widget,
}
static void
swatch_get_preferred_width (GtkWidget *widget,
gint *min,
gint *nat)
{
gint w, h;
gtk_color_swatch_measure (GtkCssGadget *gadget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline,
gpointer unused)
{
GtkWidget *widget;
GtkColorSwatch *swatch;
gint w, h, min;
widget = gtk_css_gadget_get_owner (gadget);
swatch = GTK_COLOR_SWATCH (widget);
gtk_css_gadget_get_preferred_size (swatch->priv->overlay_gadget,
orientation,
-1,
minimum, natural,
NULL, NULL);
gtk_widget_get_size_request (widget, &w, &h);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
min = w < 0 ? 48 : w;
else
min = h < 0 ? 32 : h;
if (w < 0)
w = 48;
*min = *nat = w;
*minimum = MAX (*minimum, min);
*natural = MAX (*natural, min);
}
static void
swatch_get_preferred_height (GtkWidget *widget,
gint *min,
gint *nat)
gtk_color_swatch_measure_overlay (GtkCssGadget *gadget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline,
gpointer unused)
{
gint w, h;
gtk_widget_get_size_request (widget, &w, &h);
if (h < 0)
h = 32;
*min = *nat = h;
*minimum = *natural = 16;
}
static gboolean
......@@ -563,9 +550,7 @@ swatch_realize (GtkWidget *widget)
gtk_widget_set_window (widget, window);
g_object_ref (window);
swatch->priv->event_window =
gdk_window_new (window,
&attributes, attributes_mask);
swatch->priv->event_window = gdk_window_new (window, &attributes, attributes_mask);
gtk_widget_register_window (widget, swatch->priv->event_window);
}
......@@ -589,6 +574,7 @@ swatch_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
GtkAllocation clip;
gtk_widget_set_allocation (widget, allocation);
......@@ -599,7 +585,68 @@ swatch_size_allocate (GtkWidget *widget,
allocation->width,
allocation->height);
_gtk_widget_set_simple_clip (widget, NULL);
gtk_css_gadget_allocate (swatch->priv->gadget,
allocation,
gtk_widget_get_allocated_baseline (widget),
&clip);
gtk_widget_set_clip (widget, &clip);
}
static void
gtk_color_swatch_allocate (GtkCssGadget *gadget,
const GtkAllocation *allocation,
int baseline,
GtkAllocation *out_clip,
gpointer unused)
{
GtkColorSwatch *swatch;
GtkAllocation overlay_alloc;
gint overlay_width, overlay_height;
swatch = GTK_COLOR_SWATCH (gtk_css_gadget_get_owner (gadget));
gtk_css_gadget_get_preferred_size (swatch->priv->overlay_gadget,
GTK_ORIENTATION_HORIZONTAL,
-1,
&overlay_width, NULL,
NULL, NULL);
gtk_css_gadget_get_preferred_size (swatch->priv->overlay_gadget,
GTK_ORIENTATION_VERTICAL,
-1,
&overlay_height, NULL,
NULL, NULL);
overlay_alloc.x = allocation->x + (allocation->width - overlay_width) / 2;
overlay_alloc.y = allocation->y + (allocation->height - overlay_height) / 2;
overlay_alloc.width = overlay_width;
overlay_alloc.height = overlay_height;
gtk_css_gadget_allocate (swatch->priv->overlay_gadget, &overlay_alloc, baseline, out_clip);
}
static void
swatch_get_preferred_width (GtkWidget *widget,
gint *minimum,
gint *natural)
{
gtk_css_gadget_get_preferred_size (GTK_COLOR_SWATCH (widget)->priv->gadget,
GTK_ORIENTATION_HORIZONTAL,
-1,
minimum, natural,
NULL, NULL);
}
static void
swatch_get_preferred_height (GtkWidget *widget,
gint *minimum,
gint *natural)
{
gtk_css_gadget_get_preferred_size (GTK_COLOR_SWATCH (widget)->priv->gadget,
GTK_ORIENTATION_VERTICAL,
-1,
minimum, natural,
NULL, NULL);
}
static gboolean
......@@ -615,7 +662,8 @@ swatch_state_flags_changed (GtkWidget *widget,
{
GtkColorSwatch *swatch = GTK_COLOR_SWATCH (widget);
gtk_css_node_set_state (swatch->priv->overlay_node, gtk_widget_get_state_flags (widget));
gtk_css_node_set_state (gtk_css_gadget_get_node (swatch->priv->gadget), gtk_widget_get_state_flags (widget));
gtk_css_node_set_state (gtk_css_gadget_get_node (swatch->priv->overlay_gadget), gtk_widget_get_state_flags (widget));
GTK_WIDGET_CLASS (gtk_color_swatch_parent_class)->state_flags_changed (widget, previous_state);
}
......@@ -680,6 +728,8 @@ swatch_finalize (GObject *object)
GtkColorSwatch *swatch = GTK_COLOR_SWATCH (object);
g_free (swatch->priv->icon);
g_clear_object (&swatch->priv->gadget);
g_clear_object (&swatch->priv->overlay_gadget);
G_OBJECT_CLASS (gtk_color_swatch_parent_class)->finalize (object);
}
......@@ -757,6 +807,50 @@ gtk_color_swatch_class_init (GtkColorSwatchClass *class)
gtk_widget_class_set_css_name (widget_class, "colorswatch");
}
static void
gtk_color_swatch_init (GtkColorSwatch *swatch)
{
GtkCssNode *widget_node;
swatch->priv = gtk_color_swatch_get_instance_private (swatch);
swatch->priv->use_alpha = TRUE;
swatch->priv->selectable = TRUE;
swatch->priv->has_menu = TRUE;
gtk_widget_set_can_focus (GTK_WIDGET (swatch), TRUE);
gtk_widget_set_has_window (GTK_WIDGET (swatch), FALSE);
swatch->priv->long_press_gesture = gtk_gesture_long_press_new (GTK_WIDGET (swatch));
gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (swatch->priv->long_press_gesture),
TRUE);
g_signal_connect (swatch->priv->long_press_gesture, "pressed",
G_CALLBACK (hold_action), swatch);
swatch->priv->multipress_gesture = gtk_gesture_multi_press_new (GTK_WIDGET (swatch));
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (swatch->priv->multipress_gesture), 0);
g_signal_connect (swatch->priv->multipress_gesture, "pressed",
G_CALLBACK (tap_action), swatch);
widget_node = gtk_widget_get_css_node (GTK_WIDGET (swatch));
swatch->priv->gadget = gtk_css_custom_gadget_new_for_node (widget_node,
GTK_WIDGET (swatch),
gtk_color_swatch_measure,
gtk_color_swatch_allocate,
gtk_color_swatch_render,
NULL,
NULL);
swatch->priv->overlay_gadget = gtk_css_custom_gadget_new ("overlay",
GTK_WIDGET (swatch),
swatch->priv->gadget,
NULL,
gtk_color_swatch_measure_overlay,
NULL,
gtk_color_swatch_render_overlay,
NULL,
NULL);
gtk_css_gadget_add_class (swatch->priv->gadget, "activatable");
}
/* Public API {{{1 */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment