Replace the Eek theme support with GTK classes

This brings the appearance of the keyboard basically in line with what
was there before. The background and key borders still need to be fixed
and the text and icons should probably be drawn using the style context.
This commit is contained in:
David Boddie
2019-07-31 15:49:01 +00:00
parent 64680664e3
commit 42b2b3b8f6
2 changed files with 69 additions and 315 deletions

View File

@ -33,6 +33,7 @@ enum {
PROP_0,
PROP_KEYBOARD,
PROP_PCONTEXT,
PROP_STYLE_CONTEXT,
PROP_LAST
};
@ -40,6 +41,9 @@ typedef struct _EekRendererPrivate
{
EekKeyboard *keyboard;
PangoContext *pcontext;
GtkCssProvider *css_provider;
GtkStyleContext *scontext;
GtkStyleContext *key_context;
EekColor default_foreground_color;
EekColor default_background_color;
@ -60,7 +64,6 @@ typedef struct _EekRendererPrivate
cairo_surface_t *keyboard_surface;
gulong symbol_index_changed_handler;
EekTheme *theme;
} EekRendererPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (EekRenderer, eek_renderer, G_TYPE_OBJECT)
@ -145,14 +148,9 @@ render_keyboard_surface (EekRenderer *renderer)
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
EekBounds bounds;
CreateKeyboardSurfaceCallbackData data;
EekColor foreground, background;
EekColor foreground;
eek_renderer_get_foreground_color (renderer,
EEK_ELEMENT(priv->keyboard),
&foreground);
eek_renderer_get_background_color (renderer,
EEK_ELEMENT(priv->keyboard),
&background);
eek_renderer_get_foreground_color (renderer, priv->scontext, &foreground);
eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
@ -164,12 +162,14 @@ render_keyboard_surface (EekRenderer *renderer)
cairo_translate (data.cr, bounds.x, bounds.y);
/* blank background */
cairo_set_source_rgba (data.cr,
background.red,
background.green,
background.blue,
background.alpha);
cairo_paint (data.cr);
cairo_save (data.cr);
cairo_scale (data.cr, priv->scale, priv->scale);
gtk_render_background (priv->scontext,
data.cr,
-bounds.x, -bounds.y,
(bounds.x * 2) + bounds.width,
(bounds.y * 2) + bounds.height);
cairo_restore (data.cr);
cairo_set_source_rgba (data.cr,
foreground.red,
@ -196,7 +196,6 @@ render_key_outline (EekRenderer *renderer,
EekOutline *outline;
EekBounds bounds;
guint oref;
EekThemeNode *theme_node;
EekColor foreground, background, gradient_start, gradient_end, border_color;
EekGradientType gradient_type;
gint border_width;
@ -207,119 +206,17 @@ render_key_outline (EekRenderer *renderer,
if (outline == NULL)
return;
theme_node = g_object_get_data (G_OBJECT(key),
active ?
"theme-node-pressed" :
"theme-node");
if (theme_node) {
eek_theme_node_get_foreground_color (theme_node, &foreground);
eek_theme_node_get_background_color (theme_node, &background);
eek_theme_node_get_background_gradient (theme_node,
&gradient_type,
&gradient_start,
&gradient_end);
border_width = eek_theme_node_get_border_width (theme_node,
EEK_SIDE_TOP);
border_radius = eek_theme_node_get_border_radius (theme_node,
EEK_CORNER_TOPLEFT);
eek_theme_node_get_border_color (theme_node, EEK_SIDE_TOP,
&border_color);
} else {
foreground = priv->default_foreground_color;
background = priv->default_background_color;
gradient_type = EEK_GRADIENT_NONE;
border_width = (gint)round(priv->border_width);
border_radius = -1;
border_color.red = ABS(background.red - foreground.red) * 0.7;
border_color.green = ABS(background.green - foreground.green) * 0.7;
border_color.blue = ABS(background.blue - foreground.blue) * 0.7;
border_color.alpha = foreground.alpha;
}
eek_element_get_bounds(EEK_ELEMENT(key), &bounds);
outline = eek_outline_copy (outline);
gtk_style_context_set_state(priv->key_context,
active ? GTK_STATE_FLAG_ACTIVE : GTK_STATE_FLAG_NORMAL);
cairo_translate (cr, border_width, border_width);
gtk_render_background (priv->key_context,
cr,
0, 0,
bounds.width * priv->scale,
bounds.height * priv->scale);
if (gradient_type != EEK_GRADIENT_NONE) {
cairo_pattern_t *pat;
gdouble cx, cy;
switch (gradient_type) {
case EEK_GRADIENT_VERTICAL:
pat = cairo_pattern_create_linear (0.0,
0.0,
0.0,
bounds.height);
break;
case EEK_GRADIENT_HORIZONTAL:
pat = cairo_pattern_create_linear (0.0,
0.0,
bounds.width,
0.0);
break;
case EEK_GRADIENT_RADIAL:
cx = bounds.width / 2;
cy = bounds.height / 2;
pat = cairo_pattern_create_radial (cx,
cy,
0,
cx,
cy,
MIN(cx, cy));
break;
default:
g_assert_not_reached ();
break;
}
cairo_pattern_add_color_stop_rgba (pat,
1,
gradient_start.red * 0.5,
gradient_start.green * 0.5,
gradient_start.blue * 0.5,
gradient_start.alpha);
cairo_pattern_add_color_stop_rgba (pat,
0,
gradient_end.red,
gradient_end.green,
gradient_end.blue,
gradient_end.alpha);
cairo_set_source (cr, pat);
cairo_pattern_destroy (pat);
} else {
cairo_set_source_rgba (cr,
background.red,
background.green,
background.blue,
background.alpha);
}
_eek_rounded_polygon (cr,
border_radius >= 0 ? border_radius : outline->corner_radius,
outline->points,
outline->num_points);
cairo_fill (cr);
/* paint the border */
cairo_set_line_width (cr, border_width);
cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
cairo_set_source_rgba (cr,
border_color.red,
border_color.green,
border_color.blue,
border_color.alpha);
_eek_rounded_polygon (cr,
border_radius >= 0 ? border_radius : outline->corner_radius,
outline->points,
outline->num_points);
cairo_stroke (cr);
cairo_translate (cr, -border_width, -border_width);
eek_outline_free (outline);
gtk_style_context_set_state(priv->key_context, GTK_STATE_FLAG_NORMAL);
}
static void
@ -386,7 +283,7 @@ render_key (EekRenderer *self,
cairo_set_source_surface (cr, outline_surface, 0.0, 0.0);
cairo_paint (cr);
eek_renderer_get_foreground_color (self, EEK_ELEMENT(key), &foreground);
eek_renderer_get_foreground_color (self, priv->key_context, &foreground);
/* render icon (if any) */
symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
if (!symbol)
@ -512,12 +409,7 @@ eek_renderer_real_render_key_label (EekRenderer *self,
if (!priv->font) {
const PangoFontDescription *base_font;
gdouble ascii_size, size;
EekThemeNode *theme_node;
theme_node = g_object_get_data (G_OBJECT(key), "theme-node");
if (theme_node)
base_font = eek_theme_node_get_font (theme_node);
else
base_font = pango_context_get_font_description (priv->pcontext);
// FIXME: Base font size on the same size unit used for button sizing,
// and make the default about 1/3 of the current row height
@ -652,6 +544,10 @@ eek_renderer_set_property (GObject *object,
priv->pcontext = g_value_get_object (value);
g_object_ref (priv->pcontext);
break;
case PROP_STYLE_CONTEXT:
priv->scontext = g_value_get_object (value);
g_object_ref (priv->scontext);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -749,6 +645,15 @@ eek_renderer_class_init (EekRendererClass *klass)
g_object_class_install_property (gobject_class,
PROP_PCONTEXT,
pspec);
pspec = g_param_spec_object ("style-context",
"GTK Style Context",
"GTK Style Context",
GTK_TYPE_STYLE_CONTEXT,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE);
g_object_class_install_property (gobject_class,
PROP_STYLE_CONTEXT,
pspec);
}
static void
@ -786,6 +691,24 @@ eek_renderer_init (EekRenderer *self)
g_str_equal,
g_free,
(GDestroyNotify)cairo_surface_destroy);
/* Create a default CSS provider and load a style sheet */
priv->css_provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (priv->css_provider,
"/sm/puri/squeekboard/style.css");
/* Create a style context for keys */
priv->key_context = gtk_style_context_new ();
gtk_style_context_add_class (priv->key_context, "key");
gtk_style_context_add_provider (priv->key_context,
GTK_STYLE_PROVIDER(priv->css_provider),
GTK_STYLE_PROVIDER_PRIORITY_USER);
g_autoptr (GtkWidgetPath) path = NULL;
path = gtk_widget_path_new ();
gtk_widget_path_append_type (path, GTK_TYPE_BUTTON);
gtk_style_context_set_path (priv->key_context, path);
gtk_style_context_set_state (priv->key_context, GTK_STATE_FLAG_NORMAL);
}
static void
@ -817,11 +740,13 @@ on_symbol_index_changed (EekKeyboard *keyboard,
EekRenderer *
eek_renderer_new (EekKeyboard *keyboard,
PangoContext *pcontext)
PangoContext *pcontext,
GtkStyleContext *scontext)
{
return g_object_new (EEK_TYPE_RENDERER,
"keyboard", keyboard,
"pango-context", pcontext,
"style-context", scontext,
NULL);
}
@ -1065,64 +990,21 @@ eek_renderer_set_default_background_color (EekRenderer *renderer,
void
eek_renderer_get_foreground_color (EekRenderer *renderer,
EekElement *element,
GtkStyleContext *context,
EekColor *color)
{
EekThemeNode *theme_node;
g_return_if_fail (EEK_IS_RENDERER(renderer));
g_return_if_fail (color);
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
GtkStateFlags flags = GTK_STATE_FLAG_NORMAL;
GdkRGBA gcolor;
theme_node = g_object_get_data (G_OBJECT(element), "theme-node");
if (theme_node)
eek_theme_node_get_foreground_color (theme_node, color);
else
memcpy (color, &priv->default_foreground_color,
sizeof(EekColor));
}
void
eek_renderer_get_background_color (EekRenderer *renderer,
EekElement *element,
EekColor *color)
{
EekThemeNode *theme_node;
g_return_if_fail (EEK_IS_RENDERER(renderer));
g_return_if_fail (color);
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
theme_node = g_object_get_data (G_OBJECT(element), "theme-node");
if (theme_node)
eek_theme_node_get_background_color (theme_node, color);
else
memcpy (color, &priv->default_background_color,
sizeof(EekColor));
}
void
eek_renderer_get_background_gradient (EekRenderer *renderer,
EekElement *element,
EekGradientType *type,
EekColor *start,
EekColor *end)
{
EekThemeNode *theme_node;
g_return_if_fail (EEK_IS_RENDERER(renderer));
g_return_if_fail (EEK_IS_ELEMENT(element));
g_return_if_fail (type);
g_return_if_fail (start);
g_return_if_fail (end);
theme_node = g_object_get_data (G_OBJECT(element), "theme-node");
if (theme_node)
eek_theme_node_get_background_gradient (theme_node, type, start, end);
else
*type = EEK_GRADIENT_NONE;
gtk_style_context_get_color (context, flags, &gcolor);
color->red = gcolor.red;
color->green = gcolor.green;
color->blue = gcolor.blue;
color->alpha = gcolor.alpha;
}
struct _FindKeyByPositionCallbackData {
@ -1253,117 +1135,3 @@ eek_renderer_find_key_by_position (EekRenderer *renderer,
&data);
return data.key;
}
struct _CreateThemeNodeData {
EekThemeContext *context;
EekThemeNode *parent;
EekRenderer *renderer;
};
typedef struct _CreateThemeNodeData CreateThemeNodeData;
void
create_theme_node_key_callback (EekElement *element,
gpointer user_data)
{
CreateThemeNodeData *data = user_data;
EekThemeNode *theme_node;
EekRendererPrivate *priv = eek_renderer_get_instance_private (data->renderer);
theme_node = eek_theme_node_new (data->context,
data->parent,
priv->theme,
EEK_TYPE_KEY,
eek_element_get_name (element),
"key",
NULL,
NULL);
g_object_set_data_full (G_OBJECT(element),
"theme-node",
theme_node,
(GDestroyNotify)g_object_unref);
theme_node = eek_theme_node_new (data->context,
data->parent,
priv->theme,
EEK_TYPE_KEY,
eek_element_get_name (element),
"key",
"active",
NULL);
g_object_set_data_full (G_OBJECT(element),
"theme-node-pressed",
theme_node,
(GDestroyNotify)g_object_unref);
}
void
create_theme_node_section_callback (EekElement *element,
gpointer user_data)
{
CreateThemeNodeData *data = user_data;
EekThemeNode *theme_node, *parent;
EekRendererPrivate *priv = eek_renderer_get_instance_private (data->renderer);
theme_node = eek_theme_node_new (data->context,
data->parent,
priv->theme,
EEK_TYPE_SECTION,
eek_element_get_name (element),
"section",
NULL,
NULL);
g_object_set_data_full (G_OBJECT(element),
"theme-node",
theme_node,
(GDestroyNotify)g_object_unref);
parent = data->parent;
data->parent = theme_node;
eek_container_foreach_child (EEK_CONTAINER(element),
create_theme_node_key_callback,
data);
data->parent = parent;
}
void
eek_renderer_set_theme (EekRenderer *renderer,
EekTheme *theme)
{
EekThemeContext *theme_context;
EekThemeNode *theme_node;
CreateThemeNodeData data;
g_return_if_fail (EEK_IS_RENDERER(renderer));
g_return_if_fail (EEK_IS_THEME(theme));
EekRendererPrivate *priv = eek_renderer_get_instance_private (renderer);
g_return_if_fail (priv->keyboard);
if (priv->theme)
g_object_unref (priv->theme);
priv->theme = g_object_ref (theme);
theme_context = eek_theme_context_new ();
theme_node = eek_theme_node_new (theme_context,
NULL,
priv->theme,
EEK_TYPE_KEYBOARD,
"keyboard",
"keyboard",
NULL,
NULL);
g_object_set_data_full (G_OBJECT(priv->keyboard),
"theme-node",
theme_node,
(GDestroyNotify)g_object_unref);
data.context = theme_context;
data.parent = theme_node;
data.renderer = renderer;
eek_container_foreach_child (EEK_CONTAINER(priv->keyboard),
create_theme_node_section_callback,
&data);
}

View File

@ -25,8 +25,6 @@
#include "eek-keyboard.h"
#include "eek-keysym.h"
#include "eek-types.h"
#include "eek-theme.h"
#include "eek-theme-context.h"
G_BEGIN_DECLS
@ -64,7 +62,8 @@ struct _EekRendererClass
GType eek_renderer_get_type (void) G_GNUC_CONST;
EekRenderer *eek_renderer_new (EekKeyboard *keyboard,
PangoContext *pcontext);
PangoContext *pcontext,
GtkStyleContext *scontext);
void eek_renderer_set_allocation_size
(EekRenderer *renderer,
gdouble width,
@ -116,18 +115,8 @@ void eek_renderer_set_default_background_color
const EekColor *color);
void eek_renderer_get_foreground_color
(EekRenderer *renderer,
EekElement *element,
GtkStyleContext *context,
EekColor *color);
void eek_renderer_get_background_color
(EekRenderer *renderer,
EekElement *element,
EekColor *color);
void eek_renderer_get_background_gradient
(EekRenderer *renderer,
EekElement *element,
EekGradientType *type,
EekColor *start,
EekColor *end);
void eek_renderer_set_border_width (EekRenderer *renderer,
gdouble border_width);
EekKey *eek_renderer_find_key_by_position
@ -141,8 +130,5 @@ void eek_renderer_apply_transformation_for_key
gdouble scale,
gboolean rotate);
void eek_renderer_set_theme (EekRenderer *renderer,
EekTheme *theme);
G_END_DECLS
#endif /* EEK_RENDERER_H */