Merge theme handling code (WIP).
This commit is contained in:
36
AUTHORS
36
AUTHORS
@ -1,6 +1,34 @@
|
|||||||
eekboard is written by Daiki Ueno <ueno@unixuser.org>
|
eekboard is written by Daiki Ueno <ueno@unixuser.org>. The following
|
||||||
|
files contain code derived from other free software packages:
|
||||||
|
|
||||||
Cairo keyboard drawing functions are borrowed from the libgnomekbd
|
eek/eek-keyboard-drawing.h
|
||||||
library by Sergey V. Udaltsov <svu@gnome.org>. See the comments in
|
eek/eek-keyboard-drawing.c
|
||||||
eek/eek-drawing.c for detail.
|
|
||||||
|
|
||||||
|
These files contain code derived from the libgnomekbd library.
|
||||||
|
Copyright (C) 2006 Sergey V. Udaltsov <svu@gnome.org>
|
||||||
|
|
||||||
|
eek/eek-theme-node.h
|
||||||
|
eek/eek-theme-node.c
|
||||||
|
eek/eek-theme.h
|
||||||
|
eek/eek-theme.c
|
||||||
|
|
||||||
|
These files contain code derived from gnome-shell.
|
||||||
|
|
||||||
|
Copyright 2008-2010 Red Hat, Inc.
|
||||||
|
Copyright 2009 Steve Frécinaux
|
||||||
|
Copyright 2009, 2010 Florian Müllner
|
||||||
|
Copyright 2010 Adel Gadllah
|
||||||
|
Copyright 2010 Giovanni Campagna
|
||||||
|
Copyright 2003-2004 Dodji Seketeli
|
||||||
|
|
||||||
|
data/icons/8x8/Makefile.am
|
||||||
|
data/icons/16x16/Makefile.am
|
||||||
|
data/icons/22x22/Makefile.am
|
||||||
|
data/icons/24x24/Makefile.am
|
||||||
|
data/icons/32x32/Makefile.am
|
||||||
|
data/icons/48x48/Makefile.am
|
||||||
|
data/icons/scalable/Makefile.am
|
||||||
|
|
||||||
|
These files contain code derived from im-chooser.
|
||||||
|
|
||||||
|
Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved.
|
||||||
|
|||||||
2
README
2
README
@ -7,7 +7,7 @@ tools to implement desktop virtual keyboards.
|
|||||||
|
|
||||||
** Dependencies
|
** Dependencies
|
||||||
|
|
||||||
REQUIRED: GLib2, GTK, GConf2, PangoCairo, libxklavier
|
REQUIRED: GLib2, GTK, GConf2, PangoCairo, libxklavier, libcroco
|
||||||
OPTIONAL: fakekey, CSPI, Clutter, Clutter-Gtk, Vala, gobject-introspection
|
OPTIONAL: fakekey, CSPI, Clutter, Clutter-Gtk, Vala, gobject-introspection
|
||||||
|
|
||||||
** Build from git repo
|
** Build from git repo
|
||||||
|
|||||||
@ -101,6 +101,8 @@ PKG_CHECK_MODULES([XKB], [x11], ,
|
|||||||
[AC_MSG_ERROR([XKB support not found])])
|
[AC_MSG_ERROR([XKB support not found])])
|
||||||
PKG_CHECK_MODULES([LIBXKLAVIER], [libxklavier x11], ,
|
PKG_CHECK_MODULES([LIBXKLAVIER], [libxklavier x11], ,
|
||||||
[AC_MSG_ERROR([Libxklavier not found])])
|
[AC_MSG_ERROR([Libxklavier not found])])
|
||||||
|
PKG_CHECK_MODULES([LIBCROCO], [libcroco-0.6], ,
|
||||||
|
[AC_MSG_ERROR([libcroco not found])])
|
||||||
|
|
||||||
dnl use libfakekey to generate key events
|
dnl use libfakekey to generate key events
|
||||||
AC_MSG_CHECKING([whether you enable fakekey])
|
AC_MSG_CHECKING([whether you enable fakekey])
|
||||||
|
|||||||
@ -39,6 +39,7 @@ libeek_public_headers = \
|
|||||||
$(srcdir)/eek-xml.h \
|
$(srcdir)/eek-xml.h \
|
||||||
$(srcdir)/eek-xml-layout.h \
|
$(srcdir)/eek-xml-layout.h \
|
||||||
$(srcdir)/eek-serializable.h \
|
$(srcdir)/eek-serializable.h \
|
||||||
|
$(srcdir)/eek-theme.h \
|
||||||
$(srcdir)/eek.h
|
$(srcdir)/eek.h
|
||||||
|
|
||||||
libeek_private_headers = \
|
libeek_private_headers = \
|
||||||
@ -46,7 +47,8 @@ libeek_private_headers = \
|
|||||||
$(srcdir)/eek-special-keysym-entries.h \
|
$(srcdir)/eek-special-keysym-entries.h \
|
||||||
$(srcdir)/eek-unicode-keysym-entries.h \
|
$(srcdir)/eek-unicode-keysym-entries.h \
|
||||||
$(srcdir)/eek-xkeysym-keysym-entries.h \
|
$(srcdir)/eek-xkeysym-keysym-entries.h \
|
||||||
$(srcdir)/eek-marshalers.h
|
$(srcdir)/eek-marshalers.h \
|
||||||
|
$(srcdir)/eek-theme-node.h
|
||||||
|
|
||||||
libeek_sources = \
|
libeek_sources = \
|
||||||
$(srcdir)/eek-layout.c \
|
$(srcdir)/eek-layout.c \
|
||||||
@ -62,7 +64,9 @@ libeek_sources = \
|
|||||||
$(srcdir)/eek-xml.c \
|
$(srcdir)/eek-xml.c \
|
||||||
$(srcdir)/eek-xml-layout.c \
|
$(srcdir)/eek-xml-layout.c \
|
||||||
$(srcdir)/eek-renderer.c \
|
$(srcdir)/eek-renderer.c \
|
||||||
$(srcdir)/eek-keyboard-drawing.c
|
$(srcdir)/eek-keyboard-drawing.c \
|
||||||
|
$(srcdir)/eek-theme.c \
|
||||||
|
$(srcdir)/eek-theme-node.c
|
||||||
|
|
||||||
libeek_keysym_sources = \
|
libeek_keysym_sources = \
|
||||||
$(srcdir)/eek-special-keysym-entries.h \
|
$(srcdir)/eek-special-keysym-entries.h \
|
||||||
@ -85,8 +89,8 @@ libeek_la_SOURCES = \
|
|||||||
$(libeek_sources) \
|
$(libeek_sources) \
|
||||||
$(srcdir)/eek-marshalers.c
|
$(srcdir)/eek-marshalers.c
|
||||||
|
|
||||||
libeek_la_CFLAGS = $(GIO2_CFLAGS) $(PANGOCAIRO_CFLAGS)
|
libeek_la_CFLAGS = $(GIO2_CFLAGS) $(PANGOCAIRO_CFLAGS) $(LIBCROCO_CFLAGS)
|
||||||
libeek_la_LIBADD = $(GIO2_LIBS) $(PANGOCAIRO_LIBS) -lm
|
libeek_la_LIBADD = $(GIO2_LIBS) $(PANGOCAIRO_LIBS) $(LIBCROCO_LIBS) -lm
|
||||||
|
|
||||||
if ENABLE_CLUTTER
|
if ENABLE_CLUTTER
|
||||||
libeek_clutter_public_headers = \
|
libeek_clutter_public_headers = \
|
||||||
|
|||||||
@ -50,6 +50,7 @@ struct _EekClutterKeyboardPrivate
|
|||||||
{
|
{
|
||||||
EekKeyboard *keyboard;
|
EekKeyboard *keyboard;
|
||||||
EekClutterRenderer *renderer;
|
EekClutterRenderer *renderer;
|
||||||
|
EekTheme *theme;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _CreateSectionCallbackData {
|
struct _CreateSectionCallbackData {
|
||||||
@ -78,6 +79,9 @@ eek_clutter_keyboard_real_realize (ClutterActor *self)
|
|||||||
|
|
||||||
priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self);
|
priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self);
|
||||||
|
|
||||||
|
if (priv->theme)
|
||||||
|
eek_renderer_set_theme (EEK_RENDERER(priv->renderer), priv->theme);
|
||||||
|
|
||||||
scale = eek_renderer_get_scale (EEK_RENDERER(priv->renderer));
|
scale = eek_renderer_get_scale (EEK_RENDERER(priv->renderer));
|
||||||
clutter_actor_set_position (CLUTTER_ACTOR(self),
|
clutter_actor_set_position (CLUTTER_ACTOR(self),
|
||||||
bounds.x * scale,
|
bounds.x * scale,
|
||||||
@ -126,7 +130,6 @@ eek_clutter_keyboard_real_allocate (ClutterActor *self,
|
|||||||
{
|
{
|
||||||
EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self);
|
EekClutterKeyboardPrivate *priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(self);
|
||||||
|
|
||||||
g_assert (priv->renderer);
|
|
||||||
eek_renderer_set_allocation_size (EEK_RENDERER(priv->renderer),
|
eek_renderer_set_allocation_size (EEK_RENDERER(priv->renderer),
|
||||||
box->x2 - box->x1,
|
box->x2 - box->x1,
|
||||||
box->y2 - box->y1);
|
box->y2 - box->y1);
|
||||||
@ -193,6 +196,11 @@ eek_clutter_keyboard_dispose (GObject *object)
|
|||||||
priv->keyboard = NULL;
|
priv->keyboard = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (priv->theme) {
|
||||||
|
g_object_unref (priv->theme);
|
||||||
|
priv->keyboard = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
G_OBJECT_CLASS (eek_clutter_keyboard_parent_class)->dispose (object);
|
G_OBJECT_CLASS (eek_clutter_keyboard_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,3 +257,16 @@ eek_clutter_keyboard_new (EekKeyboard *keyboard)
|
|||||||
{
|
{
|
||||||
return g_object_new (EEK_TYPE_CLUTTER_KEYBOARD, "keyboard", keyboard, NULL);
|
return g_object_new (EEK_TYPE_CLUTTER_KEYBOARD, "keyboard", keyboard, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
eek_clutter_keyboard_set_theme (EekClutterKeyboard *keyboard,
|
||||||
|
EekTheme *theme)
|
||||||
|
{
|
||||||
|
EekClutterKeyboardPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (EEK_IS_CLUTTER_KEYBOARD(keyboard));
|
||||||
|
g_return_if_fail (EEK_IS_THEME(theme));
|
||||||
|
|
||||||
|
priv = EEK_CLUTTER_KEYBOARD_GET_PRIVATE(keyboard);
|
||||||
|
priv->theme = g_object_ref (theme);
|
||||||
|
}
|
||||||
|
|||||||
@ -54,7 +54,9 @@ struct _EekClutterKeyboardClass
|
|||||||
};
|
};
|
||||||
|
|
||||||
GType eek_clutter_keyboard_get_type (void) G_GNUC_CONST;
|
GType eek_clutter_keyboard_get_type (void) G_GNUC_CONST;
|
||||||
ClutterActor *eek_clutter_keyboard_new (EekKeyboard *keyboard);
|
ClutterActor *eek_clutter_keyboard_new (EekKeyboard *keyboard);
|
||||||
|
void eek_clutter_keyboard_set_theme (EekClutterKeyboard *keyboard,
|
||||||
|
EekTheme *theme);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
#endif /* EEK_CLUTTER_KEYBOARD_H */
|
#endif /* EEK_CLUTTER_KEYBOARD_H */
|
||||||
|
|||||||
@ -119,7 +119,8 @@ eek_clutter_renderer_render_key (EekClutterRenderer *renderer,
|
|||||||
CoglHandle *outline_texture;
|
CoglHandle *outline_texture;
|
||||||
PangoLayout *layout;
|
PangoLayout *layout;
|
||||||
PangoRectangle extents = { 0, };
|
PangoRectangle extents = { 0, };
|
||||||
CoglColor color = { 0x00, 0x00, 0x00, 0xFF };
|
const EekColor *foreground;
|
||||||
|
CoglColor color;
|
||||||
ClutterGeometry geom;
|
ClutterGeometry geom;
|
||||||
gulong oref;
|
gulong oref;
|
||||||
EekKeyboard *keyboard;
|
EekKeyboard *keyboard;
|
||||||
@ -200,6 +201,17 @@ eek_clutter_renderer_render_key (EekClutterRenderer *renderer,
|
|||||||
layout = eek_renderer_create_pango_layout (EEK_RENDERER(renderer));
|
layout = eek_renderer_create_pango_layout (EEK_RENDERER(renderer));
|
||||||
eek_renderer_render_key_label (EEK_RENDERER(renderer), layout, key);
|
eek_renderer_render_key_label (EEK_RENDERER(renderer), layout, key);
|
||||||
pango_layout_get_extents (layout, NULL, &extents);
|
pango_layout_get_extents (layout, NULL, &extents);
|
||||||
|
|
||||||
|
foreground = eek_renderer_get_foreground_color (EEK_RENDERER(renderer),
|
||||||
|
EEK_ELEMENT(key));
|
||||||
|
|
||||||
|
cogl_color_set_from_4f (&color,
|
||||||
|
foreground->red,
|
||||||
|
foreground->green,
|
||||||
|
foreground->blue,
|
||||||
|
foreground->alpha);
|
||||||
|
eek_color_free (foreground);
|
||||||
|
|
||||||
cogl_pango_render_layout (layout,
|
cogl_pango_render_layout (layout,
|
||||||
(geom.width - extents.width / PANGO_SCALE) / 2,
|
(geom.width - extents.width / PANGO_SCALE) / 2,
|
||||||
(geom.height - extents.height / PANGO_SCALE) / 2,
|
(geom.height - extents.height / PANGO_SCALE) / 2,
|
||||||
|
|||||||
@ -61,6 +61,7 @@ struct _EekGtkKeyboardPrivate
|
|||||||
gulong key_pressed_handler;
|
gulong key_pressed_handler;
|
||||||
gulong key_released_handler;
|
gulong key_released_handler;
|
||||||
gulong symbol_index_changed_handler;
|
gulong symbol_index_changed_handler;
|
||||||
|
EekTheme *theme;
|
||||||
};
|
};
|
||||||
|
|
||||||
static EekColor * color_from_gdk_color (GdkColor *gdk_color);
|
static EekColor * color_from_gdk_color (GdkColor *gdk_color);
|
||||||
@ -108,6 +109,8 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
|
|||||||
|
|
||||||
pcontext = gtk_widget_get_pango_context (self);
|
pcontext = gtk_widget_get_pango_context (self);
|
||||||
priv->renderer = eek_gtk_renderer_new (priv->keyboard, pcontext, self);
|
priv->renderer = eek_gtk_renderer_new (priv->keyboard, pcontext, self);
|
||||||
|
if (priv->theme)
|
||||||
|
eek_renderer_set_theme (priv->renderer, priv->theme);
|
||||||
|
|
||||||
eek_renderer_set_allocation_size (priv->renderer,
|
eek_renderer_set_allocation_size (priv->renderer,
|
||||||
allocation.width,
|
allocation.width,
|
||||||
@ -117,11 +120,11 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
|
|||||||
state = gtk_widget_get_state (self);
|
state = gtk_widget_get_state (self);
|
||||||
|
|
||||||
color = color_from_gdk_color (&style->fg[state]);
|
color = color_from_gdk_color (&style->fg[state]);
|
||||||
eek_renderer_set_foreground (priv->renderer, color);
|
eek_renderer_set_default_foreground_color (priv->renderer, color);
|
||||||
eek_color_free (color);
|
eek_color_free (color);
|
||||||
|
|
||||||
color = color_from_gdk_color (&style->bg[state]);
|
color = color_from_gdk_color (&style->bg[state]);
|
||||||
eek_renderer_set_background (priv->renderer, color);
|
eek_renderer_set_default_background_color (priv->renderer, color);
|
||||||
eek_color_free (color);
|
eek_color_free (color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,7 +276,12 @@ eek_gtk_keyboard_dispose (GObject *object)
|
|||||||
g_object_unref (priv->keyboard);
|
g_object_unref (priv->keyboard);
|
||||||
priv->keyboard = NULL;
|
priv->keyboard = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (priv->theme) {
|
||||||
|
g_object_unref (priv->theme);
|
||||||
|
priv->theme = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
G_OBJECT_CLASS (eek_gtk_keyboard_parent_class)->dispose (object);
|
G_OBJECT_CLASS (eek_gtk_keyboard_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,3 +436,16 @@ on_symbol_index_changed (EekKeyboard *keyboard,
|
|||||||
|
|
||||||
gtk_widget_queue_draw (widget);
|
gtk_widget_queue_draw (widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
eek_gtk_keyboard_set_theme (EekGtkKeyboard *keyboard,
|
||||||
|
EekTheme *theme)
|
||||||
|
{
|
||||||
|
EekGtkKeyboardPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (EEK_IS_GTK_KEYBOARD(keyboard));
|
||||||
|
g_return_if_fail (EEK_IS_THEME(theme));
|
||||||
|
|
||||||
|
priv = EEK_GTK_KEYBOARD_GET_PRIVATE(keyboard);
|
||||||
|
priv->theme = g_object_ref (theme);
|
||||||
|
}
|
||||||
|
|||||||
@ -55,8 +55,10 @@ struct _EekGtkKeyboardClass
|
|||||||
gpointer pdummy[24];
|
gpointer pdummy[24];
|
||||||
};
|
};
|
||||||
|
|
||||||
GType eek_gtk_keyboard_get_type (void) G_GNUC_CONST;
|
GType eek_gtk_keyboard_get_type (void) G_GNUC_CONST;
|
||||||
GtkWidget *eek_gtk_keyboard_new (EekKeyboard *keyboard);
|
GtkWidget *eek_gtk_keyboard_new (EekKeyboard *keyboard);
|
||||||
|
void eek_gtk_keyboard_set_theme (EekGtkKeyboard *keyboard,
|
||||||
|
EekTheme *theme);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
#endif /* EEK_GTK_KEYBOARD_H */
|
#endif /* EEK_GTK_KEYBOARD_H */
|
||||||
|
|||||||
@ -45,8 +45,8 @@ struct _EekRendererPrivate
|
|||||||
EekKeyboard *keyboard;
|
EekKeyboard *keyboard;
|
||||||
PangoContext *pcontext;
|
PangoContext *pcontext;
|
||||||
|
|
||||||
EekColor *foreground;
|
EekColor *default_foreground;
|
||||||
EekColor *background;
|
EekColor *default_background;
|
||||||
gdouble border_width;
|
gdouble border_width;
|
||||||
|
|
||||||
gdouble allocation_width;
|
gdouble allocation_width;
|
||||||
@ -57,6 +57,10 @@ struct _EekRendererPrivate
|
|||||||
GHashTable *outline_surface_cache;
|
GHashTable *outline_surface_cache;
|
||||||
cairo_surface_t *keyboard_surface;
|
cairo_surface_t *keyboard_surface;
|
||||||
gulong symbol_index_changed_handler;
|
gulong symbol_index_changed_handler;
|
||||||
|
|
||||||
|
EekTheme *theme;
|
||||||
|
/* a mapping from EekElement to EekThemeNode */
|
||||||
|
GHashTable *theme_node_hash;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@ -147,6 +151,14 @@ create_keyboard_surface (EekRenderer *renderer)
|
|||||||
EekBounds bounds;
|
EekBounds bounds;
|
||||||
cairo_surface_t *keyboard_surface;
|
cairo_surface_t *keyboard_surface;
|
||||||
CreateKeyboardSurfaceCallbackData data;
|
CreateKeyboardSurfaceCallbackData data;
|
||||||
|
EekColor *foreground, *background;
|
||||||
|
|
||||||
|
foreground =
|
||||||
|
eek_renderer_get_foreground_color (renderer,
|
||||||
|
EEK_ELEMENT(priv->keyboard));
|
||||||
|
background =
|
||||||
|
eek_renderer_get_background_color (renderer,
|
||||||
|
EEK_ELEMENT(priv->keyboard));
|
||||||
|
|
||||||
eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
|
eek_element_get_bounds (EEK_ELEMENT(priv->keyboard), &bounds);
|
||||||
keyboard_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
keyboard_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||||
@ -159,10 +171,10 @@ create_keyboard_surface (EekRenderer *renderer)
|
|||||||
|
|
||||||
/* blank background */
|
/* blank background */
|
||||||
cairo_set_source_rgba (data.cr,
|
cairo_set_source_rgba (data.cr,
|
||||||
priv->background->red,
|
background->red,
|
||||||
priv->background->green,
|
background->green,
|
||||||
priv->background->blue,
|
background->blue,
|
||||||
priv->background->alpha);
|
background->alpha);
|
||||||
cairo_rectangle (data.cr,
|
cairo_rectangle (data.cr,
|
||||||
0.0,
|
0.0,
|
||||||
0.0,
|
0.0,
|
||||||
@ -170,11 +182,21 @@ create_keyboard_surface (EekRenderer *renderer)
|
|||||||
cairo_image_surface_get_height (keyboard_surface));
|
cairo_image_surface_get_height (keyboard_surface));
|
||||||
cairo_fill (data.cr);
|
cairo_fill (data.cr);
|
||||||
|
|
||||||
|
cairo_set_source_rgba (data.cr,
|
||||||
|
foreground->red,
|
||||||
|
foreground->green,
|
||||||
|
foreground->blue,
|
||||||
|
foreground->alpha);
|
||||||
|
|
||||||
/* draw sections */
|
/* draw sections */
|
||||||
eek_container_foreach_child (EEK_CONTAINER(priv->keyboard),
|
eek_container_foreach_child (EEK_CONTAINER(priv->keyboard),
|
||||||
create_keyboard_surface_section_callback,
|
create_keyboard_surface_section_callback,
|
||||||
&data);
|
&data);
|
||||||
cairo_destroy (data.cr);
|
cairo_destroy (data.cr);
|
||||||
|
|
||||||
|
eek_color_free (foreground);
|
||||||
|
eek_color_free (background);
|
||||||
|
|
||||||
return keyboard_surface;
|
return keyboard_surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,6 +212,8 @@ render_key_outline (EekRenderer *renderer,
|
|||||||
gdouble scale;
|
gdouble scale;
|
||||||
gint i;
|
gint i;
|
||||||
gulong oref;
|
gulong oref;
|
||||||
|
EekColor *foreground, *background;
|
||||||
|
EekGradient *gradient;
|
||||||
|
|
||||||
/* need to rescale so that the border fit inside the clipping
|
/* need to rescale so that the border fit inside the clipping
|
||||||
region */
|
region */
|
||||||
@ -212,25 +236,60 @@ render_key_outline (EekRenderer *renderer,
|
|||||||
priv->border_width / 2 * priv->scale,
|
priv->border_width / 2 * priv->scale,
|
||||||
priv->border_width / 2 * priv->scale);
|
priv->border_width / 2 * priv->scale);
|
||||||
|
|
||||||
/* paint the background with gradient */
|
foreground = eek_renderer_get_foreground_color (renderer, EEK_ELEMENT(key));
|
||||||
pat = cairo_pattern_create_linear (0.0,
|
background = eek_renderer_get_background_color (renderer, EEK_ELEMENT(key));
|
||||||
0.0,
|
|
||||||
0.0,
|
gradient = eek_renderer_get_background_gradient (renderer,
|
||||||
bounds.height * priv->scale * 5.0);
|
EEK_ELEMENT(key));
|
||||||
cairo_pattern_add_color_stop_rgba (pat,
|
|
||||||
1,
|
if (gradient) {
|
||||||
priv->background->red * 0.5,
|
switch (gradient->type) {
|
||||||
priv->background->green * 0.5,
|
case EEK_GRADIENT_VERTICAL:
|
||||||
priv->background->blue * 0.5,
|
pat = cairo_pattern_create_linear (bounds.width / 2 * priv->scale,
|
||||||
priv->background->alpha);
|
0.0,
|
||||||
cairo_pattern_add_color_stop_rgba (pat,
|
bounds.width / 2 * priv->scale,
|
||||||
0,
|
bounds.height * priv->scale);
|
||||||
priv->background->red,
|
break;
|
||||||
priv->background->green,
|
case EEK_GRADIENT_HORIZONTAL:
|
||||||
priv->background->blue,
|
pat = cairo_pattern_create_linear (0.0,
|
||||||
priv->background->alpha);
|
bounds.height / 2 * priv->scale,
|
||||||
|
bounds.width * priv->scale,
|
||||||
|
bounds.height / 2 * priv->scale);
|
||||||
|
break;
|
||||||
|
case EEK_GRADIENT_RADIAL:
|
||||||
|
pat = cairo_pattern_create_radial (0.0,
|
||||||
|
0.0,
|
||||||
|
0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
MIN(bounds.width, bounds.height) * priv->scale);
|
||||||
|
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->stop->red,
|
||||||
|
gradient->stop->green,
|
||||||
|
gradient->stop->blue,
|
||||||
|
gradient->stop->alpha);
|
||||||
|
cairo_set_source (cr, pat);
|
||||||
|
} else {
|
||||||
|
cairo_set_source_rgba (cr,
|
||||||
|
background->red,
|
||||||
|
background->green,
|
||||||
|
background->blue,
|
||||||
|
background->alpha);
|
||||||
|
}
|
||||||
|
|
||||||
cairo_set_source (cr, pat);
|
|
||||||
_eek_rounded_polygon (cr,
|
_eek_rounded_polygon (cr,
|
||||||
outline->corner_radius,
|
outline->corner_radius,
|
||||||
outline->points,
|
outline->points,
|
||||||
@ -239,16 +298,16 @@ render_key_outline (EekRenderer *renderer,
|
|||||||
|
|
||||||
cairo_pattern_destroy (pat);
|
cairo_pattern_destroy (pat);
|
||||||
|
|
||||||
/* paint the border */
|
/* paint the border - FIXME: should be configured through theme */
|
||||||
cairo_set_line_width (cr, priv->border_width);
|
cairo_set_line_width (cr, priv->border_width);
|
||||||
cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
|
cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
|
||||||
|
|
||||||
cairo_set_source_rgba
|
cairo_set_source_rgba
|
||||||
(cr,
|
(cr,
|
||||||
ABS(priv->background->red - priv->foreground->red) * 0.7,
|
ABS(background->red - foreground->red) * 0.7,
|
||||||
ABS(priv->background->green - priv->foreground->green) * 0.7,
|
ABS(background->green - foreground->green) * 0.7,
|
||||||
ABS(priv->background->blue - priv->foreground->blue) * 0.7,
|
ABS(background->blue - foreground->blue) * 0.7,
|
||||||
priv->foreground->alpha);
|
foreground->alpha);
|
||||||
|
|
||||||
_eek_rounded_polygon (cr,
|
_eek_rounded_polygon (cr,
|
||||||
outline->corner_radius,
|
outline->corner_radius,
|
||||||
@ -257,6 +316,12 @@ render_key_outline (EekRenderer *renderer,
|
|||||||
cairo_stroke (cr);
|
cairo_stroke (cr);
|
||||||
|
|
||||||
eek_outline_free (outline);
|
eek_outline_free (outline);
|
||||||
|
|
||||||
|
eek_color_free (foreground);
|
||||||
|
eek_color_free (background);
|
||||||
|
|
||||||
|
if (gradient)
|
||||||
|
eek_gradient_free (gradient);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct _CalculateFontSizeCallbackData {
|
struct _CalculateFontSizeCallbackData {
|
||||||
@ -400,6 +465,7 @@ render_key (EekRenderer *self,
|
|||||||
} else {
|
} else {
|
||||||
PangoLayout *layout;
|
PangoLayout *layout;
|
||||||
PangoRectangle extents = { 0, };
|
PangoRectangle extents = { 0, };
|
||||||
|
EekColor *foreground;
|
||||||
|
|
||||||
layout = pango_cairo_create_layout (cr);
|
layout = pango_cairo_create_layout (cr);
|
||||||
eek_renderer_render_key_label (self, layout, key);
|
eek_renderer_render_key_label (self, layout, key);
|
||||||
@ -410,11 +476,14 @@ render_key (EekRenderer *self,
|
|||||||
(cr,
|
(cr,
|
||||||
(bounds.width * priv->scale - extents.width / PANGO_SCALE) / 2,
|
(bounds.width * priv->scale - extents.width / PANGO_SCALE) / 2,
|
||||||
(bounds.height * priv->scale - extents.height / PANGO_SCALE) / 2);
|
(bounds.height * priv->scale - extents.height / PANGO_SCALE) / 2);
|
||||||
|
|
||||||
|
foreground = eek_renderer_get_foreground_color (self, EEK_ELEMENT(key));
|
||||||
cairo_set_source_rgba (cr,
|
cairo_set_source_rgba (cr,
|
||||||
priv->foreground->red,
|
foreground->red,
|
||||||
priv->foreground->green,
|
foreground->green,
|
||||||
priv->foreground->blue,
|
foreground->blue,
|
||||||
priv->foreground->alpha);
|
foreground->alpha);
|
||||||
|
eek_color_free (foreground);
|
||||||
|
|
||||||
pango_cairo_show_layout (cr, layout);
|
pango_cairo_show_layout (cr, layout);
|
||||||
cairo_restore (cr);
|
cairo_restore (cr);
|
||||||
@ -535,6 +604,7 @@ eek_renderer_real_render_keyboard (EekRenderer *self,
|
|||||||
cairo_t *cr)
|
cairo_t *cr)
|
||||||
{
|
{
|
||||||
EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(self);
|
EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(self);
|
||||||
|
EekColor *background;
|
||||||
|
|
||||||
g_return_if_fail (priv->keyboard);
|
g_return_if_fail (priv->keyboard);
|
||||||
g_return_if_fail (priv->allocation_width > 0.0);
|
g_return_if_fail (priv->allocation_width > 0.0);
|
||||||
@ -544,11 +614,15 @@ eek_renderer_real_render_keyboard (EekRenderer *self,
|
|||||||
priv->keyboard_surface = create_keyboard_surface (self);
|
priv->keyboard_surface = create_keyboard_surface (self);
|
||||||
|
|
||||||
/* blank background */
|
/* blank background */
|
||||||
|
background = eek_renderer_get_background_color (self,
|
||||||
|
EEK_ELEMENT(priv->keyboard));
|
||||||
cairo_set_source_rgba (cr,
|
cairo_set_source_rgba (cr,
|
||||||
priv->background->red,
|
background->red,
|
||||||
priv->background->green,
|
background->green,
|
||||||
priv->background->blue,
|
background->blue,
|
||||||
priv->background->alpha);
|
background->alpha);
|
||||||
|
eek_color_free (background);
|
||||||
|
|
||||||
cairo_rectangle (cr,
|
cairo_rectangle (cr,
|
||||||
0.0,
|
0.0,
|
||||||
0.0,
|
0.0,
|
||||||
@ -639,9 +713,10 @@ eek_renderer_finalize (GObject *object)
|
|||||||
{
|
{
|
||||||
EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(object);
|
EekRendererPrivate *priv = EEK_RENDERER_GET_PRIVATE(object);
|
||||||
g_hash_table_destroy (priv->outline_surface_cache);
|
g_hash_table_destroy (priv->outline_surface_cache);
|
||||||
eek_color_free (priv->foreground);
|
eek_color_free (priv->default_foreground);
|
||||||
eek_color_free (priv->background);
|
eek_color_free (priv->default_background);
|
||||||
pango_font_description_free (priv->font);
|
pango_font_description_free (priv->font);
|
||||||
|
g_hash_table_destroy (priv->theme_node_hash);
|
||||||
G_OBJECT_CLASS (eek_renderer_parent_class)->finalize (object);
|
G_OBJECT_CLASS (eek_renderer_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -691,8 +766,8 @@ eek_renderer_init (EekRenderer *self)
|
|||||||
priv = self->priv = EEK_RENDERER_GET_PRIVATE(self);
|
priv = self->priv = EEK_RENDERER_GET_PRIVATE(self);
|
||||||
priv->keyboard = NULL;
|
priv->keyboard = NULL;
|
||||||
priv->pcontext = NULL;
|
priv->pcontext = NULL;
|
||||||
priv->foreground = eek_color_new (0.3, 0.3, 0.3, 1.0);
|
priv->default_foreground = eek_color_new (0.3, 0.3, 0.3, 1.0);
|
||||||
priv->background = eek_color_new (1.0, 1.0, 1.0, 1.0);
|
priv->default_background = eek_color_new (1.0, 1.0, 1.0, 1.0);
|
||||||
priv->border_width = 1.0;
|
priv->border_width = 1.0;
|
||||||
priv->allocation_width = 0.0;
|
priv->allocation_width = 0.0;
|
||||||
priv->allocation_height = 0.0;
|
priv->allocation_height = 0.0;
|
||||||
@ -705,6 +780,11 @@ eek_renderer_init (EekRenderer *self)
|
|||||||
(GDestroyNotify)cairo_surface_destroy);
|
(GDestroyNotify)cairo_surface_destroy);
|
||||||
priv->keyboard_surface = NULL;
|
priv->keyboard_surface = NULL;
|
||||||
priv->symbol_index_changed_handler = 0;
|
priv->symbol_index_changed_handler = 0;
|
||||||
|
priv->theme_node_hash =
|
||||||
|
g_hash_table_new_full (g_direct_hash,
|
||||||
|
g_direct_equal,
|
||||||
|
NULL,
|
||||||
|
(GDestroyNotify)g_object_unref);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -956,8 +1036,8 @@ eek_renderer_render_keyboard (EekRenderer *renderer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
eek_renderer_set_foreground (EekRenderer *renderer,
|
eek_renderer_set_default_foreground_color (EekRenderer *renderer,
|
||||||
EekColor *foreground)
|
EekColor *foreground)
|
||||||
{
|
{
|
||||||
EekRendererPrivate *priv;
|
EekRendererPrivate *priv;
|
||||||
|
|
||||||
@ -965,14 +1045,14 @@ eek_renderer_set_foreground (EekRenderer *renderer,
|
|||||||
g_return_if_fail (foreground);
|
g_return_if_fail (foreground);
|
||||||
|
|
||||||
priv = EEK_RENDERER_GET_PRIVATE(renderer);
|
priv = EEK_RENDERER_GET_PRIVATE(renderer);
|
||||||
if (priv->foreground)
|
if (priv->default_foreground)
|
||||||
eek_color_free (priv->foreground);
|
eek_color_free (priv->default_foreground);
|
||||||
priv->foreground = eek_color_copy (foreground);
|
priv->default_foreground = eek_color_copy (foreground);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
eek_renderer_set_background (EekRenderer *renderer,
|
eek_renderer_set_default_background_color (EekRenderer *renderer,
|
||||||
EekColor *background)
|
EekColor *background)
|
||||||
{
|
{
|
||||||
EekRendererPrivate *priv;
|
EekRendererPrivate *priv;
|
||||||
|
|
||||||
@ -980,35 +1060,66 @@ eek_renderer_set_background (EekRenderer *renderer,
|
|||||||
g_return_if_fail (background);
|
g_return_if_fail (background);
|
||||||
|
|
||||||
priv = EEK_RENDERER_GET_PRIVATE(renderer);
|
priv = EEK_RENDERER_GET_PRIVATE(renderer);
|
||||||
if (priv->background)
|
if (priv->default_background)
|
||||||
eek_color_free (priv->background);
|
eek_color_free (priv->default_background);
|
||||||
priv->background = eek_color_copy (background);
|
priv->default_background = eek_color_copy (background);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
EekColor *
|
||||||
eek_renderer_get_foreground (EekRenderer *renderer,
|
eek_renderer_get_foreground_color (EekRenderer *renderer, EekElement *element)
|
||||||
EekColor *foreground)
|
|
||||||
{
|
{
|
||||||
EekRendererPrivate *priv;
|
EekRendererPrivate *priv;
|
||||||
|
EekThemeNode *theme_node;
|
||||||
|
|
||||||
g_return_if_fail (EEK_IS_RENDERER(renderer));
|
g_assert (EEK_IS_RENDERER(renderer));
|
||||||
g_return_if_fail (foreground);
|
|
||||||
|
|
||||||
priv = EEK_RENDERER_GET_PRIVATE(renderer);
|
priv = EEK_RENDERER_GET_PRIVATE(renderer);
|
||||||
*foreground = *priv->foreground;
|
|
||||||
|
theme_node = g_hash_table_lookup (priv->theme_node_hash, element);
|
||||||
|
if (theme_node) {
|
||||||
|
EekColor *color = eek_theme_node_get_foreground_color (theme_node);
|
||||||
|
if (color)
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
return eek_color_copy (priv->default_foreground);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
EekColor *
|
||||||
eek_renderer_get_background (EekRenderer *renderer,
|
eek_renderer_get_background_color (EekRenderer *renderer, EekElement *element)
|
||||||
EekColor *background)
|
|
||||||
{
|
{
|
||||||
EekRendererPrivate *priv;
|
EekRendererPrivate *priv;
|
||||||
|
EekThemeNode *theme_node;
|
||||||
|
|
||||||
g_return_if_fail (EEK_IS_RENDERER(renderer));
|
g_assert (EEK_IS_RENDERER(renderer));
|
||||||
g_return_if_fail (background);
|
|
||||||
|
|
||||||
priv = EEK_RENDERER_GET_PRIVATE(renderer);
|
priv = EEK_RENDERER_GET_PRIVATE(renderer);
|
||||||
*background = *priv->background;
|
|
||||||
|
theme_node = g_hash_table_lookup (priv->theme_node_hash, element);
|
||||||
|
if (theme_node) {
|
||||||
|
EekColor *color = eek_theme_node_get_background_color (theme_node);
|
||||||
|
if (color)
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
return eek_color_copy (priv->default_background);
|
||||||
|
}
|
||||||
|
|
||||||
|
EekGradient *
|
||||||
|
eek_renderer_get_background_gradient (EekRenderer *renderer, EekElement *element)
|
||||||
|
{
|
||||||
|
EekRendererPrivate *priv;
|
||||||
|
EekThemeNode *theme_node;
|
||||||
|
|
||||||
|
g_assert (EEK_IS_RENDERER(renderer));
|
||||||
|
|
||||||
|
priv = EEK_RENDERER_GET_PRIVATE(renderer);
|
||||||
|
|
||||||
|
theme_node = g_hash_table_lookup (priv->theme_node_hash, element);
|
||||||
|
if (theme_node)
|
||||||
|
return eek_theme_node_get_background_gradient (theme_node);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct _FindKeyByPositionCallbackData {
|
struct _FindKeyByPositionCallbackData {
|
||||||
@ -1136,3 +1247,91 @@ eek_renderer_find_key_by_position (EekRenderer *renderer,
|
|||||||
&data);
|
&data);
|
||||||
return data.key;
|
return data.key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct _CreateThemeNodeData {
|
||||||
|
EekThemeNode *parent;
|
||||||
|
EekRenderer *renderer;
|
||||||
|
};
|
||||||
|
typedef struct _CreateThemeNodeData CreateThemeNodeData;
|
||||||
|
|
||||||
|
void
|
||||||
|
create_theme_node_key_callback (EekElement *element,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
CreateThemeNodeData *data = user_data;
|
||||||
|
EekRendererPrivate *priv;
|
||||||
|
EekThemeNode *node;
|
||||||
|
|
||||||
|
priv = EEK_RENDERER_GET_PRIVATE(data->renderer);
|
||||||
|
|
||||||
|
node = eek_theme_node_new (data->parent,
|
||||||
|
priv->theme,
|
||||||
|
EEK_TYPE_KEY,
|
||||||
|
eek_element_get_name (element),
|
||||||
|
"key",
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
g_hash_table_insert (priv->theme_node_hash, element, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
create_theme_node_section_callback (EekElement *element,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
CreateThemeNodeData *data = user_data;
|
||||||
|
EekRendererPrivate *priv;
|
||||||
|
EekThemeNode *node, *parent;
|
||||||
|
|
||||||
|
priv = EEK_RENDERER_GET_PRIVATE(data->renderer);
|
||||||
|
|
||||||
|
node = eek_theme_node_new (data->parent,
|
||||||
|
priv->theme,
|
||||||
|
EEK_TYPE_SECTION,
|
||||||
|
eek_element_get_name (element),
|
||||||
|
"section",
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
g_hash_table_insert (priv->theme_node_hash, element, node);
|
||||||
|
|
||||||
|
parent = data->parent;
|
||||||
|
data->parent = 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)
|
||||||
|
{
|
||||||
|
EekRendererPrivate *priv;
|
||||||
|
EekThemeNode *node;
|
||||||
|
CreateThemeNodeData data;
|
||||||
|
|
||||||
|
g_assert (EEK_IS_RENDERER(renderer));
|
||||||
|
g_assert (EEK_IS_THEME(theme));
|
||||||
|
|
||||||
|
priv = EEK_RENDERER_GET_PRIVATE(renderer);
|
||||||
|
|
||||||
|
if (priv->theme)
|
||||||
|
g_object_unref (priv->theme);
|
||||||
|
priv->theme = g_object_ref (theme);
|
||||||
|
|
||||||
|
g_hash_table_remove_all (priv->theme_node_hash);
|
||||||
|
|
||||||
|
node = eek_theme_node_new (NULL,
|
||||||
|
priv->theme,
|
||||||
|
EEK_TYPE_KEYBOARD,
|
||||||
|
"keyboard",
|
||||||
|
"keyboard",
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
g_hash_table_insert (priv->theme_node_hash, priv->keyboard, node);
|
||||||
|
|
||||||
|
data.parent = node;
|
||||||
|
data.renderer = renderer;
|
||||||
|
eek_container_foreach_child (EEK_CONTAINER(priv->keyboard),
|
||||||
|
create_theme_node_section_callback,
|
||||||
|
&data);
|
||||||
|
}
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
#include "eek-keyboard.h"
|
#include "eek-keyboard.h"
|
||||||
#include "eek-keysym.h"
|
#include "eek-keysym.h"
|
||||||
#include "eek-types.h"
|
#include "eek-types.h"
|
||||||
|
#include "eek-theme.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
@ -79,67 +80,74 @@ struct _EekRendererClass
|
|||||||
gpointer pdummy[23];
|
gpointer pdummy[23];
|
||||||
};
|
};
|
||||||
|
|
||||||
GType eek_renderer_get_type (void) G_GNUC_CONST;
|
GType eek_renderer_get_type (void) G_GNUC_CONST;
|
||||||
EekRenderer *eek_renderer_new (EekKeyboard *keyboard,
|
EekRenderer *eek_renderer_new (EekKeyboard *keyboard,
|
||||||
PangoContext *pcontext);
|
PangoContext *pcontext);
|
||||||
void eek_renderer_set_allocation_size (EekRenderer *renderer,
|
void eek_renderer_set_allocation_size (EekRenderer *renderer,
|
||||||
gdouble width,
|
gdouble width,
|
||||||
gdouble height);
|
gdouble height);
|
||||||
void eek_renderer_get_size (EekRenderer *renderer,
|
void eek_renderer_get_size (EekRenderer *renderer,
|
||||||
gdouble *width,
|
gdouble *width,
|
||||||
gdouble *height);
|
gdouble *height);
|
||||||
void eek_renderer_get_key_bounds (EekRenderer *renderer,
|
void eek_renderer_get_key_bounds (EekRenderer *renderer,
|
||||||
EekKey *key,
|
EekKey *key,
|
||||||
EekBounds *bounds,
|
EekBounds *bounds,
|
||||||
gboolean rotate);
|
gboolean rotate);
|
||||||
|
|
||||||
gdouble eek_renderer_get_scale (EekRenderer *renderer);
|
gdouble eek_renderer_get_scale (EekRenderer *renderer);
|
||||||
|
|
||||||
PangoLayout *eek_renderer_create_pango_layout (EekRenderer *renderer);
|
PangoLayout *eek_renderer_create_pango_layout (EekRenderer *renderer);
|
||||||
void eek_renderer_render_key_label (EekRenderer *renderer,
|
void eek_renderer_render_key_label (EekRenderer *renderer,
|
||||||
PangoLayout *layout,
|
PangoLayout *layout,
|
||||||
EekKey *key);
|
EekKey *key);
|
||||||
|
|
||||||
void eek_renderer_render_key_outline (EekRenderer *renderer,
|
void eek_renderer_render_key_outline (EekRenderer *renderer,
|
||||||
cairo_t *cr,
|
cairo_t *cr,
|
||||||
EekKey *key,
|
EekKey *key,
|
||||||
gdouble scale,
|
gdouble scale,
|
||||||
gboolean rotate);
|
gboolean rotate);
|
||||||
|
|
||||||
void eek_renderer_render_key (EekRenderer *renderer,
|
void eek_renderer_render_key (EekRenderer *renderer,
|
||||||
cairo_t *cr,
|
cairo_t *cr,
|
||||||
EekKey *key,
|
EekKey *key,
|
||||||
gdouble scale,
|
gdouble scale,
|
||||||
gboolean rotate);
|
gboolean rotate);
|
||||||
|
|
||||||
void eek_renderer_render_key_icon (EekRenderer *renderer,
|
void eek_renderer_render_key_icon (EekRenderer *renderer,
|
||||||
cairo_t *cr,
|
cairo_t *cr,
|
||||||
EekKey *key,
|
EekKey *key,
|
||||||
gdouble scale,
|
gdouble scale,
|
||||||
gboolean rotate);
|
gboolean rotate);
|
||||||
|
|
||||||
void eek_renderer_render_keyboard (EekRenderer *renderer,
|
void eek_renderer_render_keyboard (EekRenderer *renderer,
|
||||||
cairo_t *cr);
|
cairo_t *cr);
|
||||||
|
|
||||||
void eek_renderer_set_foreground (EekRenderer *renderer,
|
void eek_renderer_set_default_foreground_color
|
||||||
EekColor *foreground);
|
(EekRenderer *renderer,
|
||||||
void eek_renderer_set_background (EekRenderer *renderer,
|
EekColor *foreground);
|
||||||
EekColor *background);
|
void eek_renderer_set_default_background_color
|
||||||
void eek_renderer_get_foreground (EekRenderer *renderer,
|
(EekRenderer *renderer,
|
||||||
EekColor *foreground);
|
EekColor *background);
|
||||||
void eek_renderer_get_background (EekRenderer *renderer,
|
EekColor *eek_renderer_get_foreground_color (EekRenderer *renderer,
|
||||||
EekColor *background);
|
EekElement *element);
|
||||||
void eek_renderer_set_border_width (EekRenderer *renderer,
|
EekColor *eek_renderer_get_background_color (EekRenderer *renderer,
|
||||||
gdouble border_width);
|
EekElement *element);
|
||||||
EekKey *eek_renderer_find_key_by_position (EekRenderer *renderer,
|
EekGradient *eek_renderer_get_background_gradient (EekRenderer *renderer,
|
||||||
gdouble x,
|
EekElement *element);
|
||||||
gdouble y);
|
void eek_renderer_set_border_width (EekRenderer *renderer,
|
||||||
|
gdouble border_width);
|
||||||
|
EekKey *eek_renderer_find_key_by_position (EekRenderer *renderer,
|
||||||
|
gdouble x,
|
||||||
|
gdouble y);
|
||||||
void eek_renderer_apply_transformation_for_key
|
void eek_renderer_apply_transformation_for_key
|
||||||
(EekRenderer *renderer,
|
(EekRenderer *renderer,
|
||||||
cairo_t *cr,
|
cairo_t *cr,
|
||||||
EekKey *key,
|
EekKey *key,
|
||||||
gdouble scale,
|
gdouble scale,
|
||||||
gboolean rotate);
|
gboolean rotate);
|
||||||
|
|
||||||
|
void eek_renderer_set_theme (EekRenderer *renderer,
|
||||||
|
EekTheme *theme);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
#endif /* EEK_RENDERER_H */
|
#endif /* EEK_RENDERER_H */
|
||||||
|
|||||||
745
eek/eek-theme-node.c
Normal file
745
eek/eek-theme-node.c
Normal file
@ -0,0 +1,745 @@
|
|||||||
|
/*
|
||||||
|
* st-theme-node.c: style information for one node in a tree of themed objects
|
||||||
|
*
|
||||||
|
* Copyright 2008-2010 Red Hat, Inc.
|
||||||
|
* Copyright 2009 Steve Frécinaux
|
||||||
|
* Copyright 2009, 2010 Florian Müllner
|
||||||
|
* Copyright 2010 Adel Gadllah
|
||||||
|
* Copyright 2010 Giovanni Campagna
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <libcroco/libcroco.h>
|
||||||
|
|
||||||
|
#include "eek-theme-node.h"
|
||||||
|
#include "eek-theme-private.h"
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (EekThemeNode, eek_theme_node, G_TYPE_OBJECT);
|
||||||
|
|
||||||
|
#define EEK_THEME_NODE_GET_PRIVATE(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_THEME_NODE, EekThemeNodePrivate))
|
||||||
|
|
||||||
|
struct _EekThemeNodePrivate
|
||||||
|
{
|
||||||
|
EekThemeNode *parent_node;
|
||||||
|
EekTheme *theme;
|
||||||
|
|
||||||
|
EekColor *transparent_color;
|
||||||
|
EekColor *black_color;
|
||||||
|
|
||||||
|
EekGradientType background_gradient_type;
|
||||||
|
|
||||||
|
EekColor *background_color;
|
||||||
|
EekColor *background_gradient_end;
|
||||||
|
EekColor *foreground_color;
|
||||||
|
|
||||||
|
GType element_type;
|
||||||
|
char *element_id;
|
||||||
|
char *element_class;
|
||||||
|
char *pseudo_class;
|
||||||
|
char *inline_style;
|
||||||
|
|
||||||
|
CRDeclaration **properties;
|
||||||
|
int n_properties;
|
||||||
|
|
||||||
|
/* We hold onto these separately so we can destroy them on finalize */
|
||||||
|
CRDeclaration *inline_properties;
|
||||||
|
|
||||||
|
guint properties_computed : 1;
|
||||||
|
guint background_computed : 1;
|
||||||
|
guint foreground_computed : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
eek_theme_node_dispose (GObject *gobject)
|
||||||
|
{
|
||||||
|
EekThemeNodePrivate *priv = EEK_THEME_NODE_GET_PRIVATE (gobject);
|
||||||
|
|
||||||
|
if (priv->theme) {
|
||||||
|
g_object_unref (priv->theme);
|
||||||
|
priv->theme = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->parent_node) {
|
||||||
|
g_object_unref (priv->parent_node);
|
||||||
|
priv->parent_node = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (eek_theme_node_parent_class)->dispose (gobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
eek_theme_node_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
EekThemeNodePrivate *priv = EEK_THEME_NODE_GET_PRIVATE (object);
|
||||||
|
|
||||||
|
eek_color_free (priv->transparent_color);
|
||||||
|
eek_color_free (priv->black_color);
|
||||||
|
eek_color_free (priv->background_color);
|
||||||
|
eek_color_free (priv->background_gradient_end);
|
||||||
|
eek_color_free (priv->foreground_color);
|
||||||
|
|
||||||
|
g_free (priv->element_id);
|
||||||
|
g_free (priv->element_class);
|
||||||
|
g_free (priv->pseudo_class);
|
||||||
|
g_free (priv->inline_style);
|
||||||
|
|
||||||
|
if (priv->properties) {
|
||||||
|
g_free (priv->properties);
|
||||||
|
priv->properties = NULL;
|
||||||
|
priv->n_properties = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->inline_properties) {
|
||||||
|
/* This destroys the list, not just the head of the list */
|
||||||
|
cr_declaration_destroy (priv->inline_properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (eek_theme_node_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
eek_theme_node_class_init (EekThemeNodeClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
g_type_class_add_private (gobject_class,
|
||||||
|
sizeof (EekThemeNodePrivate));
|
||||||
|
|
||||||
|
gobject_class->dispose = eek_theme_node_dispose;
|
||||||
|
gobject_class->finalize = eek_theme_node_finalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
eek_theme_node_init (EekThemeNode *self)
|
||||||
|
{
|
||||||
|
EekThemeNodePrivate *priv;
|
||||||
|
|
||||||
|
priv = self->priv = EEK_THEME_NODE_GET_PRIVATE(self);
|
||||||
|
|
||||||
|
priv->transparent_color = eek_color_new (0.0, 0.0, 0.0, 0.0);
|
||||||
|
priv->black_color = eek_color_new (0.0, 0.0, 0.0, 1.0);
|
||||||
|
priv->background_color = eek_color_copy (priv->transparent_color);
|
||||||
|
priv->background_gradient_end = eek_color_copy (priv->transparent_color);
|
||||||
|
priv->foreground_color = eek_color_copy (priv->black_color);
|
||||||
|
priv->background_gradient_type = EEK_GRADIENT_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* eek_theme_node_new:
|
||||||
|
* @parent_node: (allow-none): the parent node of this node
|
||||||
|
* @theme: (allow-none): a theme (stylesheet set) that overrides the
|
||||||
|
* theme inherited from the parent node
|
||||||
|
* @element_type: the type of the GObject represented by this node
|
||||||
|
* in the tree (corresponding to an element if we were theming an XML
|
||||||
|
* document. %G_TYPE_NONE means this style was created for the stage
|
||||||
|
* actor and matches a selector element name of 'stage'.
|
||||||
|
* @element_id: (allow-none): the ID to match CSS rules against
|
||||||
|
* @element_class: (allow-none): a whitespace-separated list of classes
|
||||||
|
* to match CSS rules against
|
||||||
|
* @pseudo_class: (allow-none): a whitespace-separated list of pseudo-classes
|
||||||
|
* (like 'hover' or 'visited') to match CSS rules against
|
||||||
|
*
|
||||||
|
* Creates a new #EekThemeNode. Once created, a node is immutable. Of any
|
||||||
|
* of the attributes of the node (like the @element_class) change the node
|
||||||
|
* and its child nodes must be destroyed and recreated.
|
||||||
|
*
|
||||||
|
* Return value: (transfer full): the theme node
|
||||||
|
*/
|
||||||
|
EekThemeNode *
|
||||||
|
eek_theme_node_new (EekThemeNode *parent_node,
|
||||||
|
EekTheme *theme,
|
||||||
|
GType element_type,
|
||||||
|
const char *element_id,
|
||||||
|
const char *element_class,
|
||||||
|
const char *pseudo_class,
|
||||||
|
const char *inline_style)
|
||||||
|
{
|
||||||
|
EekThemeNode *node;
|
||||||
|
EekThemeNodePrivate *priv;
|
||||||
|
|
||||||
|
g_return_val_if_fail (parent_node == NULL || EEK_IS_THEME_NODE (parent_node), NULL);
|
||||||
|
|
||||||
|
node = g_object_new (EEK_TYPE_THEME_NODE, NULL);
|
||||||
|
priv = EEK_THEME_NODE_GET_PRIVATE(node);
|
||||||
|
|
||||||
|
if (parent_node != NULL)
|
||||||
|
priv->parent_node = g_object_ref (parent_node);
|
||||||
|
else
|
||||||
|
priv->parent_node = NULL;
|
||||||
|
|
||||||
|
if (theme == NULL && parent_node != NULL)
|
||||||
|
theme = eek_theme_node_get_theme (parent_node);
|
||||||
|
|
||||||
|
if (theme != NULL)
|
||||||
|
priv->theme = g_object_ref (theme);
|
||||||
|
|
||||||
|
priv->element_type = element_type;
|
||||||
|
priv->element_id = g_strdup (element_id);
|
||||||
|
priv->element_class = g_strdup (element_class);
|
||||||
|
priv->pseudo_class = g_strdup (pseudo_class);
|
||||||
|
priv->inline_style = g_strdup (inline_style);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* eek_theme_node_get_parent:
|
||||||
|
* @node: a #EekThemeNode
|
||||||
|
*
|
||||||
|
* Gets the parent themed element node.
|
||||||
|
*
|
||||||
|
* Return value: (transfer none): the parent #EekThemeNode, or %NULL if this
|
||||||
|
* is the root node of the tree of theme elements.
|
||||||
|
*/
|
||||||
|
EekThemeNode *
|
||||||
|
eek_theme_node_get_parent (EekThemeNode *node)
|
||||||
|
{
|
||||||
|
EekThemeNodePrivate *priv;
|
||||||
|
|
||||||
|
g_return_val_if_fail (EEK_IS_THEME_NODE (node), NULL);
|
||||||
|
|
||||||
|
priv = EEK_THEME_NODE_GET_PRIVATE(node);
|
||||||
|
return priv->parent_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* eek_theme_node_get_theme:
|
||||||
|
* @node: a #EekThemeNode
|
||||||
|
*
|
||||||
|
* Gets the theme stylesheet set that styles this node
|
||||||
|
*
|
||||||
|
* Return value: (transfer none): the theme stylesheet set
|
||||||
|
*/
|
||||||
|
EekTheme *
|
||||||
|
eek_theme_node_get_theme (EekThemeNode *node)
|
||||||
|
{
|
||||||
|
EekThemeNodePrivate *priv;
|
||||||
|
|
||||||
|
g_return_val_if_fail (EEK_IS_THEME_NODE (node), NULL);
|
||||||
|
|
||||||
|
priv = EEK_THEME_NODE_GET_PRIVATE(node);
|
||||||
|
return priv->theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
GType
|
||||||
|
eek_theme_node_get_element_type (EekThemeNode *node)
|
||||||
|
{
|
||||||
|
EekThemeNodePrivate *priv;
|
||||||
|
|
||||||
|
g_return_val_if_fail (EEK_IS_THEME_NODE (node), G_TYPE_NONE);
|
||||||
|
|
||||||
|
priv = EEK_THEME_NODE_GET_PRIVATE(node);
|
||||||
|
return priv->element_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
eek_theme_node_get_element_id (EekThemeNode *node)
|
||||||
|
{
|
||||||
|
EekThemeNodePrivate *priv;
|
||||||
|
|
||||||
|
g_return_val_if_fail (EEK_IS_THEME_NODE (node), NULL);
|
||||||
|
|
||||||
|
priv = EEK_THEME_NODE_GET_PRIVATE(node);
|
||||||
|
return priv->element_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
eek_theme_node_get_element_class (EekThemeNode *node)
|
||||||
|
{
|
||||||
|
EekThemeNodePrivate *priv;
|
||||||
|
|
||||||
|
g_return_val_if_fail (EEK_IS_THEME_NODE (node), NULL);
|
||||||
|
|
||||||
|
priv = EEK_THEME_NODE_GET_PRIVATE(node);
|
||||||
|
return priv->element_class;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
eek_theme_node_get_pseudo_class (EekThemeNode *node)
|
||||||
|
{
|
||||||
|
EekThemeNodePrivate *priv;
|
||||||
|
|
||||||
|
g_return_val_if_fail (EEK_IS_THEME_NODE (node), NULL);
|
||||||
|
|
||||||
|
priv = EEK_THEME_NODE_GET_PRIVATE(node);
|
||||||
|
return priv->pseudo_class;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ensure_properties (EekThemeNode *node)
|
||||||
|
{
|
||||||
|
EekThemeNodePrivate *priv = EEK_THEME_NODE_GET_PRIVATE(node);
|
||||||
|
|
||||||
|
if (!priv->properties_computed) {
|
||||||
|
GPtrArray *properties = NULL;
|
||||||
|
|
||||||
|
priv->properties_computed = TRUE;
|
||||||
|
|
||||||
|
if (priv->theme)
|
||||||
|
properties = _eek_theme_get_matched_properties (priv->theme, node);
|
||||||
|
|
||||||
|
if (priv->inline_style) {
|
||||||
|
CRDeclaration *cur_decl;
|
||||||
|
|
||||||
|
if (!properties)
|
||||||
|
properties = g_ptr_array_new ();
|
||||||
|
|
||||||
|
priv->inline_properties =
|
||||||
|
_eek_theme_parse_declaration_list (priv->inline_style);
|
||||||
|
for (cur_decl = priv->inline_properties;
|
||||||
|
cur_decl;
|
||||||
|
cur_decl = cur_decl->next)
|
||||||
|
g_ptr_array_add (properties, cur_decl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (properties) {
|
||||||
|
priv->n_properties = properties->len;
|
||||||
|
priv->properties = (CRDeclaration **)g_ptr_array_free (properties,
|
||||||
|
FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
VALUE_FOUND,
|
||||||
|
VALUE_NOT_FOUND,
|
||||||
|
VALUE_INHERIT
|
||||||
|
} GetFromTermResult;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
term_is_none (CRTerm *term)
|
||||||
|
{
|
||||||
|
return (term->type == TERM_IDENT &&
|
||||||
|
strcmp (term->content.str->stryng->str, "none") == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
term_is_transparent (CRTerm *term)
|
||||||
|
{
|
||||||
|
return (term->type == TERM_IDENT &&
|
||||||
|
strcmp (term->content.str->stryng->str, "transparent") == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GetFromTermResult
|
||||||
|
get_color_from_rgba_term (CRTerm *term,
|
||||||
|
EekColor **color)
|
||||||
|
{
|
||||||
|
CRTerm *arg = term->ext_content.func_param;
|
||||||
|
CRNum *num;
|
||||||
|
double r = 0, g = 0, b = 0, a = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
double value;
|
||||||
|
|
||||||
|
if (arg == NULL)
|
||||||
|
return VALUE_NOT_FOUND;
|
||||||
|
|
||||||
|
if ((i == 0 && arg->the_operator != NO_OP) ||
|
||||||
|
(i > 0 && arg->the_operator != COMMA))
|
||||||
|
return VALUE_NOT_FOUND;
|
||||||
|
|
||||||
|
if (arg->type != TERM_NUMBER)
|
||||||
|
return VALUE_NOT_FOUND;
|
||||||
|
|
||||||
|
num = arg->content.num;
|
||||||
|
|
||||||
|
/* For simplicity, we convert a,r,g,b to [0,1.0] floats and then
|
||||||
|
* convert them back below. Then when we set them on a cairo content
|
||||||
|
* we convert them back to floats, and then cairo converts them
|
||||||
|
* back to integers to pass them to X, and so forth...
|
||||||
|
*/
|
||||||
|
if (i < 3) {
|
||||||
|
if (num->type == NUM_PERCENTAGE)
|
||||||
|
value = num->val / 100;
|
||||||
|
else if (num->type == NUM_GENERIC)
|
||||||
|
value = num->val / 255;
|
||||||
|
else
|
||||||
|
return VALUE_NOT_FOUND;
|
||||||
|
} else {
|
||||||
|
if (num->type != NUM_GENERIC)
|
||||||
|
return VALUE_NOT_FOUND;
|
||||||
|
|
||||||
|
value = num->val;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = CLAMP (value, 0, 1);
|
||||||
|
|
||||||
|
switch (i) {
|
||||||
|
case 0:
|
||||||
|
r = value;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
g = value;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
b = value;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
a = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
arg = arg->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
*color = eek_color_new (CLAMP(r, 0.0, 1.0),
|
||||||
|
CLAMP(g, 0.0, 1.0),
|
||||||
|
CLAMP(b, 0.0, 1.0),
|
||||||
|
CLAMP(a, 0.0, 1.0));
|
||||||
|
|
||||||
|
return VALUE_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GetFromTermResult
|
||||||
|
get_color_from_term (EekThemeNode *node,
|
||||||
|
CRTerm *term,
|
||||||
|
EekColor **color)
|
||||||
|
{
|
||||||
|
EekThemeNodePrivate *priv = EEK_THEME_NODE_GET_PRIVATE(node);
|
||||||
|
CRRgb rgb;
|
||||||
|
enum CRStatus status;
|
||||||
|
|
||||||
|
/* Since libcroco doesn't know about rgba colors, it can't handle
|
||||||
|
* the transparent keyword
|
||||||
|
*/
|
||||||
|
if (term_is_transparent (term)) {
|
||||||
|
*color = eek_color_copy (priv->transparent_color);
|
||||||
|
return VALUE_FOUND;
|
||||||
|
}
|
||||||
|
/* rgba () colors - a CSS3 addition, are not supported by libcroco,
|
||||||
|
* but they are parsed as a "function", so we can emulate the
|
||||||
|
* functionality.
|
||||||
|
*
|
||||||
|
* libcroco < 0.6.2 has a bug where functions starting with 'r' are
|
||||||
|
* misparsed. We workaround this by pre-converting 'rgba' to 'RGBA'
|
||||||
|
* before parsing the stylesheet. Since libcroco isn't
|
||||||
|
* case-insensitive (a bug), it's fine with functions starting with
|
||||||
|
* 'R'. (In theory, we should be doing a case-insensitive compare
|
||||||
|
* everywhere, not just here, but that doesn't make much sense when
|
||||||
|
* the built-in parsing of libcroco is case-sensitive and things
|
||||||
|
* like 10PX don't work.)
|
||||||
|
*/
|
||||||
|
else if (term->type == TERM_FUNCTION &&
|
||||||
|
term->content.str &&
|
||||||
|
term->content.str->stryng &&
|
||||||
|
term->content.str->stryng->str &&
|
||||||
|
g_ascii_strcasecmp (term->content.str->stryng->str, "rgba") == 0) {
|
||||||
|
return get_color_from_rgba_term (term, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
status = cr_rgb_set_from_term (&rgb, term);
|
||||||
|
if (status != CR_OK)
|
||||||
|
return VALUE_NOT_FOUND;
|
||||||
|
|
||||||
|
if (rgb.inherit)
|
||||||
|
return VALUE_INHERIT;
|
||||||
|
|
||||||
|
if (rgb.is_percentage)
|
||||||
|
cr_rgb_compute_from_percentage (&rgb);
|
||||||
|
|
||||||
|
*color = eek_color_new (rgb.red / (gdouble)0xff,
|
||||||
|
rgb.green / (gdouble)0xff,
|
||||||
|
rgb.blue / (gdouble)0xff,
|
||||||
|
1.0);
|
||||||
|
|
||||||
|
return VALUE_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* eek_theme_node_get_color:
|
||||||
|
* @node: a #EekThemeNode
|
||||||
|
* @property_name: The name of the color property
|
||||||
|
* @inherit: if %TRUE, if a value is not found for the property on the
|
||||||
|
* node, then it will be looked up on the parent node, and then on the
|
||||||
|
* parent's parent, and so forth. Note that if the property has a
|
||||||
|
* value of 'inherit' it will be inherited even if %FALSE is passed
|
||||||
|
* in for @inherit; this only affects the default behavior for inheritance.
|
||||||
|
* @color: location to store the color that was determined.
|
||||||
|
* If the property is not found, the value in this location
|
||||||
|
* will not be changed.
|
||||||
|
*
|
||||||
|
* Generically looks up a property containing a single color value. When
|
||||||
|
* specific getters (like eek_theme_node_get_background_color()) exist, they
|
||||||
|
* should be used instead. They are cached, so more efficient, and have
|
||||||
|
* handling for shortcut properties and other details of CSS.
|
||||||
|
*
|
||||||
|
* Return value: %TRUE if the property was found in the properties for this
|
||||||
|
* theme node (or in the properties of parent nodes when inheriting.)
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
eek_theme_node_get_color (EekThemeNode *node,
|
||||||
|
const char *property_name,
|
||||||
|
gboolean inherit,
|
||||||
|
EekColor **color)
|
||||||
|
{
|
||||||
|
EekThemeNodePrivate *priv;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
g_return_val_if_fail (EEK_IS_THEME_NODE(node), FALSE);
|
||||||
|
|
||||||
|
priv = EEK_THEME_NODE_GET_PRIVATE(node);
|
||||||
|
|
||||||
|
ensure_properties (node);
|
||||||
|
|
||||||
|
for (i = priv->n_properties - 1; i >= 0; i--) {
|
||||||
|
CRDeclaration *decl = priv->properties[i];
|
||||||
|
|
||||||
|
if (strcmp (decl->property->stryng->str, property_name) == 0) {
|
||||||
|
GetFromTermResult result = get_color_from_term (node, decl->value, color);
|
||||||
|
if (result == VALUE_FOUND) {
|
||||||
|
return TRUE;
|
||||||
|
} else if (result == VALUE_INHERIT) {
|
||||||
|
if (priv->parent_node)
|
||||||
|
return eek_theme_node_get_color (priv->parent_node, property_name, inherit, color);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GetFromTermResult
|
||||||
|
get_background_color_from_term (EekThemeNode *node,
|
||||||
|
CRTerm *term,
|
||||||
|
EekColor **color)
|
||||||
|
{
|
||||||
|
EekThemeNodePrivate *priv = EEK_THEME_NODE_GET_PRIVATE(node);
|
||||||
|
GetFromTermResult result = get_color_from_term (node, term, color);
|
||||||
|
if (result == VALUE_NOT_FOUND) {
|
||||||
|
if (term_is_transparent (term)) {
|
||||||
|
*color = eek_color_copy (priv->transparent_color);
|
||||||
|
return VALUE_FOUND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_eek_theme_node_ensure_background (EekThemeNode *node)
|
||||||
|
{
|
||||||
|
EekThemeNodePrivate *priv = EEK_THEME_NODE_GET_PRIVATE(node);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (priv->background_computed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
priv->background_computed = TRUE;
|
||||||
|
|
||||||
|
eek_color_free (priv->background_color);
|
||||||
|
priv->background_color = eek_color_copy (priv->transparent_color);
|
||||||
|
eek_color_free (priv->background_gradient_end);
|
||||||
|
priv->background_gradient_end = eek_color_copy (priv->background_color);
|
||||||
|
priv->background_gradient_type = EEK_GRADIENT_NONE;
|
||||||
|
|
||||||
|
ensure_properties (node);
|
||||||
|
|
||||||
|
for (i = 0; i < priv->n_properties; i++) {
|
||||||
|
CRDeclaration *decl = priv->properties[i];
|
||||||
|
const char *property_name = decl->property->stryng->str;
|
||||||
|
GetFromTermResult result;
|
||||||
|
EekColor *color;
|
||||||
|
|
||||||
|
if (g_str_has_prefix (property_name, "background"))
|
||||||
|
property_name += 10;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (strcmp (property_name, "") == 0) {
|
||||||
|
/* We're very liberal here ... if we recognize any term in
|
||||||
|
* the expression we take it, and we ignore the rest. The
|
||||||
|
* actual specification is:
|
||||||
|
*
|
||||||
|
* background: [<'background-color'> ||
|
||||||
|
* <'background-image'> || <'background-repeat'> ||
|
||||||
|
* <'background-attachment'> || <'background-position'>] |
|
||||||
|
* inherit
|
||||||
|
*/
|
||||||
|
|
||||||
|
CRTerm *term;
|
||||||
|
/* background: property sets all terms to specified or
|
||||||
|
default values */
|
||||||
|
eek_color_free (priv->background_color);
|
||||||
|
priv->background_color = eek_color_copy (priv->transparent_color);
|
||||||
|
|
||||||
|
for (term = decl->value; term; term = term->next) {
|
||||||
|
result = get_background_color_from_term (node, term, &color);
|
||||||
|
if (result == VALUE_FOUND) {
|
||||||
|
eek_color_free (priv->background_color);
|
||||||
|
priv->background_color = color;
|
||||||
|
} else if (result == VALUE_INHERIT) {
|
||||||
|
if (priv->parent_node) {
|
||||||
|
color = eek_theme_node_get_background_color (priv->parent_node);
|
||||||
|
if (color) {
|
||||||
|
eek_color_free (priv->background_color);
|
||||||
|
priv->background_color = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (term_is_none (term)) {
|
||||||
|
/* leave priv->background_color as transparent */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (strcmp (property_name, "-color") == 0) {
|
||||||
|
if (decl->value == NULL || decl->value->next != NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
result = get_background_color_from_term (node, decl->value, &color);
|
||||||
|
if (result == VALUE_FOUND) {
|
||||||
|
eek_color_free (priv->background_color);
|
||||||
|
priv->background_color = color;
|
||||||
|
} else if (result == VALUE_INHERIT) {
|
||||||
|
if (priv->parent_node) {
|
||||||
|
color =
|
||||||
|
eek_theme_node_get_background_color (priv->parent_node);
|
||||||
|
if (color) {
|
||||||
|
eek_color_free (priv->background_color);
|
||||||
|
priv->background_color = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (strcmp (property_name, "-gradient-direction") == 0) {
|
||||||
|
CRTerm *term = decl->value;
|
||||||
|
if (strcmp (term->content.str->stryng->str, "vertical") == 0) {
|
||||||
|
priv->background_gradient_type = EEK_GRADIENT_VERTICAL;
|
||||||
|
} else if (strcmp (term->content.str->stryng->str, "horizontal") == 0) {
|
||||||
|
priv->background_gradient_type = EEK_GRADIENT_HORIZONTAL;
|
||||||
|
} else if (strcmp (term->content.str->stryng->str, "radial") == 0) {
|
||||||
|
priv->background_gradient_type = EEK_GRADIENT_RADIAL;
|
||||||
|
} else if (strcmp (term->content.str->stryng->str, "none") == 0) {
|
||||||
|
priv->background_gradient_type = EEK_GRADIENT_NONE;
|
||||||
|
} else {
|
||||||
|
g_warning ("Unrecognized background-gradient-direction \"%s\"",
|
||||||
|
term->content.str->stryng->str);
|
||||||
|
}
|
||||||
|
} else if (strcmp (property_name, "-gradient-start") == 0) {
|
||||||
|
result = get_color_from_term (node, decl->value, &color);
|
||||||
|
if (result == VALUE_FOUND) {
|
||||||
|
eek_color_free (priv->background_color);
|
||||||
|
priv->background_color = color;
|
||||||
|
}
|
||||||
|
} else if (strcmp (property_name, "-gradient-end") == 0) {
|
||||||
|
result = get_color_from_term (node, decl->value, &color);
|
||||||
|
if (result == VALUE_FOUND) {
|
||||||
|
eek_color_free (priv->background_gradient_end);
|
||||||
|
priv->background_gradient_end = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EekColor *
|
||||||
|
eek_theme_node_get_background_color (EekThemeNode *node)
|
||||||
|
{
|
||||||
|
EekThemeNodePrivate *priv;
|
||||||
|
|
||||||
|
g_assert (EEK_IS_THEME_NODE (node));
|
||||||
|
|
||||||
|
priv = EEK_THEME_NODE_GET_PRIVATE(node);
|
||||||
|
|
||||||
|
_eek_theme_node_ensure_background (node);
|
||||||
|
|
||||||
|
if (priv->background_gradient_type == EEK_GRADIENT_NONE)
|
||||||
|
return eek_color_copy (priv->background_color);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
EekColor *
|
||||||
|
eek_theme_node_get_foreground_color (EekThemeNode *node)
|
||||||
|
{
|
||||||
|
EekThemeNodePrivate *priv;
|
||||||
|
|
||||||
|
g_assert (EEK_IS_THEME_NODE (node));
|
||||||
|
|
||||||
|
priv = EEK_THEME_NODE_GET_PRIVATE(node);
|
||||||
|
|
||||||
|
if (!priv->foreground_computed) {
|
||||||
|
int i;
|
||||||
|
EekColor *color;
|
||||||
|
|
||||||
|
priv->foreground_computed = TRUE;
|
||||||
|
|
||||||
|
ensure_properties (node);
|
||||||
|
|
||||||
|
for (i = priv->n_properties - 1; i >= 0; i--) {
|
||||||
|
CRDeclaration *decl = priv->properties[i];
|
||||||
|
|
||||||
|
if (strcmp (decl->property->stryng->str, "color") == 0) {
|
||||||
|
GetFromTermResult result =
|
||||||
|
get_color_from_term (node, decl->value, &color);
|
||||||
|
if (result == VALUE_FOUND) {
|
||||||
|
eek_color_free (priv->foreground_color);
|
||||||
|
priv->foreground_color = color;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (result == VALUE_INHERIT)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->parent_node) {
|
||||||
|
color = eek_theme_node_get_foreground_color (priv->parent_node);
|
||||||
|
if (color) {
|
||||||
|
eek_color_free (priv->foreground_color);
|
||||||
|
priv->foreground_color = color;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* default to black */
|
||||||
|
eek_color_free (priv->foreground_color);
|
||||||
|
priv->foreground_color = eek_color_copy (priv->black_color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return eek_color_copy (priv->foreground_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* eek_theme_node_get_background_gradient:
|
||||||
|
* @node: A #EekThemeNode
|
||||||
|
*
|
||||||
|
* Get the background gradient of @node. If the node does not have
|
||||||
|
* gradient property, returns %NULL.
|
||||||
|
*
|
||||||
|
* Returns: an #EekGradient, which should be freed with
|
||||||
|
* eek_gradient_free() or %NULL.
|
||||||
|
*/
|
||||||
|
EekGradient *
|
||||||
|
eek_theme_node_get_background_gradient (EekThemeNode *node)
|
||||||
|
{
|
||||||
|
EekThemeNodePrivate *priv;
|
||||||
|
|
||||||
|
g_assert (EEK_IS_THEME_NODE (node));
|
||||||
|
|
||||||
|
priv = EEK_THEME_NODE_GET_PRIVATE(node);
|
||||||
|
|
||||||
|
_eek_theme_node_ensure_background (node);
|
||||||
|
|
||||||
|
if (priv->background_gradient_type == EEK_GRADIENT_NONE)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return eek_gradient_new (priv->background_gradient_type,
|
||||||
|
priv->background_color,
|
||||||
|
priv->background_gradient_end);
|
||||||
|
}
|
||||||
114
eek/eek-theme-node.h
Normal file
114
eek/eek-theme-node.h
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
|
||||||
|
* Copyright (C) 2010-2011 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#ifndef __EEK_THEME_NODE_H__
|
||||||
|
#define __EEK_THEME_NODE_H__
|
||||||
|
|
||||||
|
#include "eek-types.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:EekThemeNode
|
||||||
|
* @short_description: style information for one node in a tree of
|
||||||
|
* themed objects
|
||||||
|
*
|
||||||
|
* A #EekThemeNode represents the CSS style information (the set of
|
||||||
|
* CSS properties) for one node in a tree of themed objects. In
|
||||||
|
* typical usage, it represents the style information for a single
|
||||||
|
* #EekElement. A #EekThemeNode is immutable: attributes such as the
|
||||||
|
* CSS classes for the node are passed in at construction. If the
|
||||||
|
* attributes of the node or any parent node change, the node should
|
||||||
|
* be discarded and a new node created. #EekThemeNode has generic
|
||||||
|
* accessors to look up properties by name and specific accessors for
|
||||||
|
* standard CSS properties that add caching and handling of various
|
||||||
|
* details of the CSS specification. #EekThemeNode also has
|
||||||
|
* convenience functions to help in implementing a #EekElement with
|
||||||
|
* borders and padding.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define EEK_TYPE_THEME_NODE (eek_theme_node_get_type())
|
||||||
|
#define EEK_THEME_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_THEME_NODE, EekThemeNode))
|
||||||
|
#define EEK_THEME_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_THEME_NODE, EekThemeNodeClass))
|
||||||
|
#define EEK_IS_THEME_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_THEME_NODE))
|
||||||
|
#define EEK_IS_THEME_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_THEME_NODE))
|
||||||
|
#define EEK_THEME_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_THEME_NODE, EekThemeNodeClass))
|
||||||
|
|
||||||
|
typedef struct _EekThemeNodeClass EekThemeNodeClass;
|
||||||
|
typedef struct _EekThemeNodePrivate EekThemeNodePrivate;
|
||||||
|
|
||||||
|
struct _EekThemeNode {
|
||||||
|
GObject parent;
|
||||||
|
|
||||||
|
EekThemeNodePrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _EekThemeNodeClass {
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType eek_theme_node_get_type
|
||||||
|
(void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
EekThemeNode *eek_theme_node_new (EekThemeNode *parent_node,
|
||||||
|
/* can be null */ EekTheme *theme,
|
||||||
|
/* can be null */ GType element_type,
|
||||||
|
const char *element_id,
|
||||||
|
const char *element_class,
|
||||||
|
const char *pseudo_class,
|
||||||
|
const char *inline_style);
|
||||||
|
|
||||||
|
EekThemeNode *eek_theme_node_get_parent
|
||||||
|
(EekThemeNode *node);
|
||||||
|
|
||||||
|
EekTheme *eek_theme_node_get_theme
|
||||||
|
(EekThemeNode *node);
|
||||||
|
|
||||||
|
GType eek_theme_node_get_element_type
|
||||||
|
(EekThemeNode *node);
|
||||||
|
const char *eek_theme_node_get_element_id
|
||||||
|
(EekThemeNode *node);
|
||||||
|
const char *eek_theme_node_get_element_class
|
||||||
|
(EekThemeNode *node);
|
||||||
|
const char *eek_theme_node_get_pseudo_class
|
||||||
|
(EekThemeNode *node);
|
||||||
|
|
||||||
|
/* Generic getters ... these are not cached so are less efficient. The other
|
||||||
|
* reason for adding the more specific version is that we can handle the
|
||||||
|
* details of the actual CSS rules, which can be complicated, especially
|
||||||
|
* for fonts
|
||||||
|
*/
|
||||||
|
gboolean eek_theme_node_get_color
|
||||||
|
(EekThemeNode *node,
|
||||||
|
const char *property_name,
|
||||||
|
gboolean inherit,
|
||||||
|
EekColor **color);
|
||||||
|
|
||||||
|
/* Specific getters for particular properties: cached
|
||||||
|
*/
|
||||||
|
EekColor *eek_theme_node_get_background_color
|
||||||
|
(EekThemeNode *node);
|
||||||
|
EekColor *eek_theme_node_get_foreground_color
|
||||||
|
(EekThemeNode *node);
|
||||||
|
EekGradient *eek_theme_node_get_background_gradient
|
||||||
|
(EekThemeNode *node);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __EEK_THEME_NODE_H__ */
|
||||||
1130
eek/eek-theme.c
Normal file
1130
eek/eek-theme.c
Normal file
File diff suppressed because it is too large
Load Diff
44
eek/eek-theme.h
Normal file
44
eek/eek-theme.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
#ifndef __EEK_THEME_H__
|
||||||
|
#define __EEK_THEME_H__
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "eek-theme-node.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:EekTheme
|
||||||
|
* @short_description: a set of stylesheets
|
||||||
|
*
|
||||||
|
* #EekTheme holds a set of stylesheets. (The "cascade" of the name
|
||||||
|
* Cascading Stylesheets.) An #EekTheme can be set to apply to all the
|
||||||
|
* keyboard elements.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct _EekThemeClass EekThemeClass;
|
||||||
|
|
||||||
|
#define EEK_TYPE_THEME (eek_theme_get_type())
|
||||||
|
#define EEK_THEME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_THEME, EekTheme))
|
||||||
|
#define EEK_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_THEME, EekThemeClass))
|
||||||
|
#define EEK_IS_THEME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_THEME))
|
||||||
|
#define EEK_IS_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_THEME))
|
||||||
|
#define EEK_THEME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_THEME, EekThemeClass))
|
||||||
|
|
||||||
|
GType eek_theme_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
EekTheme *eek_theme_new (const char *application_stylesheet,
|
||||||
|
const char *theme_stylesheet,
|
||||||
|
const char *default_stylesheet);
|
||||||
|
|
||||||
|
gboolean eek_theme_load_stylesheet (EekTheme *theme,
|
||||||
|
const char *path,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
void eek_theme_unload_stylesheet (EekTheme *theme,
|
||||||
|
const char *path);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __EEK_THEME_H__ */
|
||||||
@ -222,3 +222,46 @@ eek_color_new (gdouble red,
|
|||||||
|
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GType
|
||||||
|
eek_gradient_get_type (void)
|
||||||
|
{
|
||||||
|
static GType our_type = 0;
|
||||||
|
|
||||||
|
if (our_type == 0)
|
||||||
|
our_type =
|
||||||
|
g_boxed_type_register_static ("EekGradient",
|
||||||
|
(GBoxedCopyFunc)eek_gradient_copy,
|
||||||
|
(GBoxedFreeFunc)eek_gradient_free);
|
||||||
|
return our_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
EekGradient *
|
||||||
|
eek_gradient_new (EekGradientType type,
|
||||||
|
EekColor *start,
|
||||||
|
EekColor *stop)
|
||||||
|
{
|
||||||
|
EekGradient *gradient;
|
||||||
|
|
||||||
|
gradient = g_slice_new (EekGradient);
|
||||||
|
gradient->type = type;
|
||||||
|
gradient->start = eek_color_copy (start);
|
||||||
|
gradient->stop = eek_color_copy (stop);
|
||||||
|
|
||||||
|
return gradient;
|
||||||
|
}
|
||||||
|
|
||||||
|
EekGradient *
|
||||||
|
eek_gradient_copy (const EekGradient *gradient)
|
||||||
|
{
|
||||||
|
return eek_gradient_new (gradient->type, gradient->start, gradient->stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
eek_gradient_free (EekGradient *gradient)
|
||||||
|
{
|
||||||
|
if (gradient->start)
|
||||||
|
eek_color_free (gradient->start);
|
||||||
|
if (gradient->stop)
|
||||||
|
eek_color_free (gradient->stop);
|
||||||
|
}
|
||||||
|
|||||||
@ -136,6 +136,8 @@ typedef struct _EekSection EekSection;
|
|||||||
typedef struct _EekKeyboard EekKeyboard;
|
typedef struct _EekKeyboard EekKeyboard;
|
||||||
typedef struct _EekSymbol EekSymbol;
|
typedef struct _EekSymbol EekSymbol;
|
||||||
typedef struct _EekKeysym EekKeysym;
|
typedef struct _EekKeysym EekKeysym;
|
||||||
|
typedef struct _EekTheme EekTheme;
|
||||||
|
typedef struct _EekThemeNode EekThemeNode;
|
||||||
|
|
||||||
typedef struct _EekSymbolMatrix EekSymbolMatrix;
|
typedef struct _EekSymbolMatrix EekSymbolMatrix;
|
||||||
typedef struct _EekPoint EekPoint;
|
typedef struct _EekPoint EekPoint;
|
||||||
@ -253,5 +255,28 @@ EekColor *eek_color_new (gdouble red,
|
|||||||
EekColor *eek_color_copy (const EekColor *color);
|
EekColor *eek_color_copy (const EekColor *color);
|
||||||
void eek_color_free (EekColor *color);
|
void eek_color_free (EekColor *color);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
EEK_GRADIENT_NONE,
|
||||||
|
EEK_GRADIENT_VERTICAL,
|
||||||
|
EEK_GRADIENT_HORIZONTAL,
|
||||||
|
EEK_GRADIENT_RADIAL
|
||||||
|
} EekGradientType;
|
||||||
|
|
||||||
|
struct _EekGradient
|
||||||
|
{
|
||||||
|
EekGradientType type;
|
||||||
|
EekColor *start;
|
||||||
|
EekColor *stop;
|
||||||
|
};
|
||||||
|
typedef struct _EekGradient EekGradient;
|
||||||
|
|
||||||
|
GType eek_gradient_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
EekGradient *eek_gradient_new (EekGradientType type,
|
||||||
|
EekColor *start,
|
||||||
|
EekColor *stop);
|
||||||
|
EekGradient *eek_gradient_copy (const EekGradient *gradient);
|
||||||
|
void eek_gradient_free (EekGradient *gradient);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
#endif /* EEK_TYPES_H */
|
#endif /* EEK_TYPES_H */
|
||||||
|
|||||||
@ -28,5 +28,6 @@
|
|||||||
#include "eek-keysym.h"
|
#include "eek-keysym.h"
|
||||||
#include "eek-xml.h"
|
#include "eek-xml.h"
|
||||||
#include "eek-serializable.h"
|
#include "eek-serializable.h"
|
||||||
|
#include "eek-theme.h"
|
||||||
|
|
||||||
#endif /* EEK_H */
|
#endif /* EEK_H */
|
||||||
|
|||||||
@ -47,6 +47,7 @@ static gchar *opt_layouts = NULL;
|
|||||||
static gchar *opt_options = NULL;
|
static gchar *opt_options = NULL;
|
||||||
static gchar *opt_list = NULL;
|
static gchar *opt_list = NULL;
|
||||||
static guint opt_group = 0;
|
static guint opt_group = 0;
|
||||||
|
static gchar *opt_theme = NULL;
|
||||||
|
|
||||||
static const GOptionEntry options[] = {
|
static const GOptionEntry options[] = {
|
||||||
{"load", 'l', 0, G_OPTION_ARG_STRING, &opt_load,
|
{"load", 'l', 0, G_OPTION_ARG_STRING, &opt_load,
|
||||||
@ -63,6 +64,8 @@ static const GOptionEntry options[] = {
|
|||||||
N_("Specify options")},
|
N_("Specify options")},
|
||||||
{"group", 'g', 0, G_OPTION_ARG_INT, &opt_group,
|
{"group", 'g', 0, G_OPTION_ARG_INT, &opt_group,
|
||||||
N_("Specify group")},
|
N_("Specify group")},
|
||||||
|
{"theme", 't', 0, G_OPTION_ARG_STRING, &opt_theme,
|
||||||
|
N_("Specify theme")},
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -112,6 +115,8 @@ main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL);
|
||||||
|
|
||||||
context = g_option_context_new ("eek-example-xml");
|
context = g_option_context_new ("eek-example-xml");
|
||||||
g_option_context_add_main_entries (context, options, NULL);
|
g_option_context_add_main_entries (context, options, NULL);
|
||||||
g_option_context_parse (context, &argc, &argv, NULL);
|
g_option_context_parse (context, &argc, &argv, NULL);
|
||||||
@ -151,6 +156,12 @@ main (int argc, char **argv)
|
|||||||
widget = gtk_clutter_embed_new ();
|
widget = gtk_clutter_embed_new ();
|
||||||
stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED(widget));
|
stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED(widget));
|
||||||
actor = eek_clutter_keyboard_new (keyboard);
|
actor = eek_clutter_keyboard_new (keyboard);
|
||||||
|
if (opt_theme) {
|
||||||
|
EekTheme *theme = eek_theme_new (opt_theme, NULL, NULL);
|
||||||
|
|
||||||
|
eek_clutter_keyboard_set_theme (EEK_CLUTTER_KEYBOARD(actor), theme);
|
||||||
|
g_object_unref (theme);
|
||||||
|
}
|
||||||
clutter_container_add_actor (CLUTTER_CONTAINER(stage), actor);
|
clutter_container_add_actor (CLUTTER_CONTAINER(stage), actor);
|
||||||
|
|
||||||
clutter_stage_set_color (CLUTTER_STAGE(stage), &stage_color);
|
clutter_stage_set_color (CLUTTER_STAGE(stage), &stage_color);
|
||||||
@ -164,6 +175,12 @@ main (int argc, char **argv)
|
|||||||
actor);
|
actor);
|
||||||
#else
|
#else
|
||||||
widget = eek_gtk_keyboard_new (keyboard);
|
widget = eek_gtk_keyboard_new (keyboard);
|
||||||
|
if (opt_theme) {
|
||||||
|
EekTheme *theme = eek_theme_new (opt_theme, NULL, NULL);
|
||||||
|
|
||||||
|
eek_gtk_keyboard_set_theme (EEK_GTK_KEYBOARD(widget), theme);
|
||||||
|
g_object_unref (theme);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
g_object_unref (keyboard);
|
g_object_unref (keyboard);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user