Import stylesheet code from hippo-canvas
Import: HippoCanvasTheme => ShellTheme HippoCanvasThemeImage => ShellThemeImage HippoCanvasStyle => ShellThemeNode ShellThemeContext is a new class managing the theme for a stage and global properties like resolution. test-theme.c is a newly written test program to do verification of the style matching and property handling rules. Various changes are made in the import: - Comprehensive reindentation - guint32 pixels replaced with ClutterColor - General pseudo-class support added - Old-fashioned (non-bordered) background image support added, though with no support for repeat, etc. - Bug fixes for problems revealed by test program
This commit is contained in:
parent
9dbafe156e
commit
98215f497d
1
.gitignore
vendored
1
.gitignore
vendored
@ -38,6 +38,7 @@ src/gnomeshell-taskpanel
|
||||
src/gnome-shell
|
||||
src/test-recorder
|
||||
src/test-recorder.ogg
|
||||
src/test-theme
|
||||
stamp-h1
|
||||
tests/run-test.sh
|
||||
xmldocs.make
|
||||
|
@ -60,6 +60,7 @@ PKG_CHECK_MODULES(TIDY, clutter-1.0)
|
||||
PKG_CHECK_MODULES(NBTK, clutter-1.0 gtk+-2.0 libccss-1 >= 0.3.1 clutter-imcontext-0.1)
|
||||
PKG_CHECK_MODULES(BIG, clutter-1.0 gtk+-2.0 librsvg-2.0)
|
||||
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-2.0)
|
||||
PKG_CHECK_MODULES(TOOLKIT, clutter-1.0 libcroco-0.6)
|
||||
PKG_CHECK_MODULES(TRAY, gtk+-2.0)
|
||||
|
||||
MUTTER_BIN_DIR=`$PKG_CONFIG --variable=exec_prefix mutter-plugins`/bin
|
||||
|
36
src/Makefile-toolkit.am
Normal file
36
src/Makefile-toolkit.am
Normal file
@ -0,0 +1,36 @@
|
||||
toolkit_cflags = \
|
||||
-I$(top_srcdir)/src \
|
||||
-DPREFIX=\""$(prefix)"\" \
|
||||
-DLIBDIR=\""$(libdir)"\" \
|
||||
-DG_DISABLE_DEPRECATED \
|
||||
-DG_LOG_DOMAIN=\"Shell\" \
|
||||
$(TOOLKIT_CFLAGS)
|
||||
|
||||
# please, keep this sorted alphabetically
|
||||
toolkit_sources = \
|
||||
toolkit/shell-theme.c \
|
||||
toolkit/shell-theme.h \
|
||||
toolkit/shell-theme-context.c \
|
||||
toolkit/shell-theme-context.h \
|
||||
toolkit/shell-theme-image.c \
|
||||
toolkit/shell-theme-image.h \
|
||||
toolkit/shell-theme-node.c \
|
||||
toolkit/shell-theme-node.h \
|
||||
toolkit/shell-theme-private.h
|
||||
|
||||
non_gir_toolkit_sources = \
|
||||
toolkit/shell-theme-private.h
|
||||
|
||||
noinst_LTLIBRARIES += libshell-toolkit.la
|
||||
|
||||
libshell_toolkit_la_LIBADD = $(TOOLKIT_LIBS)
|
||||
libshell_toolkit_la_SOURCES = $(toolkit_sources) $(toolkit_built_sources)
|
||||
libshell_toolkit_la_CPPFLAGS = $(toolkit_cflags)
|
||||
libshell_toolkit_la_LDFLAGS = $(LDADD)
|
||||
|
||||
noinst_PROGRAMS += test-theme
|
||||
|
||||
test_theme_CPPFLAGS = $(toolkit_cflags)
|
||||
test_theme_LDADD = libshell-toolkit.la
|
||||
|
||||
test_theme_SOURCES = toolkit/test-theme.c
|
@ -4,6 +4,7 @@ CLEANFILES =
|
||||
EXTRA_DIST =
|
||||
libexec_PROGRAMS =
|
||||
noinst_LTLIBRARIES =
|
||||
noinst_PROGRAMS =
|
||||
|
||||
.AUTOPARALLEL:
|
||||
|
||||
@ -25,6 +26,7 @@ EXTRA_DIST += gnome-shell.in
|
||||
include Makefile-big.am
|
||||
include Makefile-gdmuser.am
|
||||
include Makefile-nbtk.am
|
||||
include Makefile-toolkit.am
|
||||
include Makefile-tray.am
|
||||
|
||||
gnome_shell_cflags = \
|
||||
@ -97,7 +99,7 @@ libgnome_shell_la_SOURCES = \
|
||||
shell-wm.c \
|
||||
shell-wm.h
|
||||
|
||||
non_gir_sources = \
|
||||
non_gir_sources = \
|
||||
shell-embedded-window-private.h
|
||||
|
||||
shell_recorder_sources = \
|
||||
@ -115,7 +117,7 @@ if BUILD_RECORDER
|
||||
libgnome_shell_la_SOURCES += $(shell_recorder_sources)
|
||||
non_gir_sources += $(shell_recorder_non_gir_sources)
|
||||
|
||||
noinst_PROGRAMS = test-recorder
|
||||
noinst_PROGRAMS += test-recorder
|
||||
|
||||
test_recorder_CPPFLAGS = $(TEST_SHELL_RECORDER_CFLAGS)
|
||||
test_recorder_LDADD = $(TEST_SHELL_RECORDER_LIBS)
|
||||
@ -126,7 +128,7 @@ test_recorder_SOURCES = \
|
||||
endif BUILD_RECORDER
|
||||
|
||||
libgnome_shell_la_gir_sources = \
|
||||
$(filter-out $(non_gir_sources), $(libgnome_shell_la_SOURCES))
|
||||
$(filter-out $(non_gir_sources) $(non_gir_toolkit_sources), $(libgnome_shell_la_SOURCES) $(toolkit_sources))
|
||||
|
||||
shell-marshal.h: stamp-shell-marshal.h
|
||||
@true
|
||||
@ -155,6 +157,7 @@ libgnome_shell_la_LIBADD = \
|
||||
libbig-1.0.la \
|
||||
libnbtk-1.0.la \
|
||||
libgdmuser-1.0.la \
|
||||
libshell-toolkit.la \
|
||||
libtray.la
|
||||
libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags)
|
||||
|
||||
|
218
src/toolkit/shell-theme-context.c
Normal file
218
src/toolkit/shell-theme-context.c
Normal file
@ -0,0 +1,218 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "shell-theme.h"
|
||||
#include "shell-theme-context.h"
|
||||
|
||||
struct _ShellThemeContext {
|
||||
GObject parent;
|
||||
|
||||
double resolution;
|
||||
PangoFontDescription *font;
|
||||
ShellThemeNode *root_node;
|
||||
ShellTheme *theme;
|
||||
};
|
||||
|
||||
struct _ShellThemeContextClass {
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CHANGED,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
G_DEFINE_TYPE (ShellThemeContext, shell_theme_context, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
shell_theme_context_finalize (GObject *object)
|
||||
{
|
||||
ShellThemeContext *context = SHELL_THEME_CONTEXT (object);
|
||||
|
||||
if (context->root_node)
|
||||
g_object_unref (context->root_node);
|
||||
if (context->theme)
|
||||
g_object_unref (context->theme);
|
||||
|
||||
pango_font_description_free (context->font);
|
||||
|
||||
G_OBJECT_CLASS (shell_theme_context_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
shell_theme_context_class_init (ShellThemeContextClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = shell_theme_context_finalize;
|
||||
|
||||
signals[CHANGED] =
|
||||
g_signal_new ("changed",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0, /* no default handler slot */
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
shell_theme_context_init (ShellThemeContext *context)
|
||||
{
|
||||
context->resolution = 96.;
|
||||
context->font = pango_font_description_from_string ("sans-serif 10");
|
||||
}
|
||||
|
||||
ShellThemeContext *
|
||||
shell_theme_context_new (void)
|
||||
{
|
||||
ShellThemeContext *context;
|
||||
|
||||
context = g_object_new (SHELL_TYPE_THEME_CONTEXT, NULL);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
static void
|
||||
on_stage_destroy (ClutterStage *stage)
|
||||
{
|
||||
ShellThemeContext *context = shell_theme_context_get_for_stage (stage);
|
||||
|
||||
g_object_set_data (G_OBJECT (stage), "shell-theme-context", NULL);
|
||||
g_object_unref (context);
|
||||
}
|
||||
|
||||
/**
|
||||
* shell_theme_context_get_for_stage:
|
||||
* @stage: a #ClutterStage
|
||||
*
|
||||
* Gets a singleton theme context associated with the stage.
|
||||
*
|
||||
* Return value: (transfer none): the singleton theme context for the stage
|
||||
*/
|
||||
ShellThemeContext *
|
||||
shell_theme_context_get_for_stage (ClutterStage *stage)
|
||||
{
|
||||
ShellThemeContext *context;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
|
||||
|
||||
context = g_object_get_data (G_OBJECT (stage), "shell-theme-context");
|
||||
if (context)
|
||||
return context;
|
||||
|
||||
context = shell_theme_context_new ();
|
||||
g_object_set_data (G_OBJECT (stage), "shell-theme-context", context);
|
||||
g_signal_connect (stage, "destroy",
|
||||
G_CALLBACK (on_stage_destroy), NULL);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* shell_theme_context_set_theme:
|
||||
* @context: a #ShellThemeContext
|
||||
*
|
||||
* Sets the default set of theme stylesheets for the context. This theme will
|
||||
* be used for the root node and for nodes descending from it, unless some other
|
||||
* style is explicitely specified.
|
||||
*/
|
||||
void
|
||||
shell_theme_context_set_theme (ShellThemeContext *context,
|
||||
ShellTheme *theme)
|
||||
{
|
||||
g_return_if_fail (SHELL_IS_THEME_CONTEXT (context));
|
||||
g_return_if_fail (theme == NULL || SHELL_IS_THEME (theme));
|
||||
|
||||
if (context->theme != theme)
|
||||
{
|
||||
if (context->theme)
|
||||
g_object_unref (context->theme);
|
||||
|
||||
context->theme = theme;
|
||||
|
||||
if (context->theme)
|
||||
g_object_ref (context->theme);
|
||||
|
||||
g_signal_emit (context, signals[CHANGED], 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* shell_theme_context_get_theme:
|
||||
* @context: a #ShellThemeContext
|
||||
*
|
||||
* Gets the default theme for the context. See shell_theme_context_set_theme()
|
||||
*
|
||||
* Return value: (transfer none): the default theme for the context
|
||||
*/
|
||||
ShellTheme *
|
||||
shell_theme_context_get_theme (ShellThemeContext *context)
|
||||
{
|
||||
g_return_val_if_fail (SHELL_IS_THEME_CONTEXT (context), NULL);
|
||||
|
||||
return context->theme;
|
||||
}
|
||||
|
||||
void
|
||||
shell_theme_context_set_resolution (ShellThemeContext *context,
|
||||
double resolution)
|
||||
{
|
||||
g_return_if_fail (SHELL_IS_THEME_CONTEXT (context));
|
||||
|
||||
context->resolution = resolution;
|
||||
}
|
||||
|
||||
double
|
||||
shell_theme_context_get_resolution (ShellThemeContext *context)
|
||||
{
|
||||
g_return_val_if_fail (SHELL_IS_THEME_CONTEXT (context), 96.);
|
||||
|
||||
return context->resolution;
|
||||
}
|
||||
|
||||
void
|
||||
shell_theme_context_set_font (ShellThemeContext *context,
|
||||
const PangoFontDescription *font)
|
||||
{
|
||||
g_return_if_fail (SHELL_IS_THEME_CONTEXT (context));
|
||||
|
||||
if (context->font == font)
|
||||
return;
|
||||
|
||||
pango_font_description_free (context->font);
|
||||
context->font = pango_font_description_copy (font);
|
||||
}
|
||||
|
||||
const PangoFontDescription *
|
||||
shell_theme_context_get_font (ShellThemeContext *context)
|
||||
{
|
||||
g_return_val_if_fail (SHELL_IS_THEME_CONTEXT (context), NULL);
|
||||
|
||||
return context->font;
|
||||
}
|
||||
|
||||
/**
|
||||
* shell_theme_context_get_root_node:
|
||||
* @context: a #ShellThemeContext
|
||||
*
|
||||
* Gets the root node of the tree of theme style nodes that associated with this
|
||||
* context. For the node tree associated with a stage, this node represents
|
||||
* styles applied to the stage itself.
|
||||
*
|
||||
* Return value: (transfer none): the root node of the context's style tree
|
||||
*/
|
||||
ShellThemeNode *
|
||||
shell_theme_context_get_root_node (ShellThemeContext *context)
|
||||
{
|
||||
if (context->root_node == NULL)
|
||||
context->root_node = shell_theme_node_new (context, NULL, context->theme,
|
||||
G_TYPE_NONE, NULL, NULL, NULL);
|
||||
|
||||
return context->root_node;
|
||||
}
|
40
src/toolkit/shell-theme-context.h
Normal file
40
src/toolkit/shell-theme-context.h
Normal file
@ -0,0 +1,40 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
#ifndef __SHELL_THEME_CONTEXT_H__
|
||||
#define __SHELL_THEME_CONTEXT_H__
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <pango/pango.h>
|
||||
#include "shell-theme-node.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _ShellThemeContextClass ShellThemeContextClass;
|
||||
|
||||
#define SHELL_TYPE_THEME_CONTEXT (shell_theme_context_get_type ())
|
||||
#define SHELL_THEME_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SHELL_TYPE_THEME_CONTEXT, ShellThemeContext))
|
||||
#define SHELL_THEME_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_THEME_CONTEXT, ShellThemeContextClass))
|
||||
#define SHELL_IS_THEME_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SHELL_TYPE_THEME_CONTEXT))
|
||||
#define SHELL_IS_THEME_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_THEME_CONTEXT))
|
||||
#define SHELL_THEME_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_THEME_CONTEXT, ShellThemeContextClass))
|
||||
|
||||
GType shell_theme_context_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ShellThemeContext *shell_theme_context_new (void);
|
||||
ShellThemeContext *shell_theme_context_get_for_stage (ClutterStage *stage);
|
||||
|
||||
void shell_theme_context_set_theme (ShellThemeContext *context,
|
||||
ShellTheme *theme);
|
||||
ShellTheme * shell_theme_context_get_theme (ShellThemeContext *context);
|
||||
|
||||
void shell_theme_context_set_resolution (ShellThemeContext *context,
|
||||
gdouble resolution);
|
||||
double shell_theme_context_get_resolution (ShellThemeContext *context);
|
||||
void shell_theme_context_set_font (ShellThemeContext *context,
|
||||
const PangoFontDescription *font);
|
||||
const PangoFontDescription *shell_theme_context_get_font (ShellThemeContext *context);
|
||||
|
||||
ShellThemeNode * shell_theme_context_get_root_node (ShellThemeContext *context);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __SHELL_THEME_CONTEXT_H__ */
|
92
src/toolkit/shell-theme-image.c
Normal file
92
src/toolkit/shell-theme-image.c
Normal file
@ -0,0 +1,92 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "shell-theme-image.h"
|
||||
|
||||
struct _ShellThemeImage {
|
||||
GObject parent;
|
||||
|
||||
char *filename;
|
||||
int border_top;
|
||||
int border_right;
|
||||
int border_bottom;
|
||||
int border_left;
|
||||
};
|
||||
|
||||
struct _ShellThemeImageClass {
|
||||
GObjectClass parent_class;
|
||||
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (ShellThemeImage, shell_theme_image, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
shell_theme_image_finalize (GObject *object)
|
||||
{
|
||||
ShellThemeImage *image = SHELL_THEME_IMAGE (object);
|
||||
|
||||
g_free (image->filename);
|
||||
|
||||
G_OBJECT_CLASS (shell_theme_image_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
shell_theme_image_class_init (ShellThemeImageClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = shell_theme_image_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
shell_theme_image_init (ShellThemeImage *image)
|
||||
{
|
||||
}
|
||||
|
||||
ShellThemeImage *
|
||||
shell_theme_image_new (const char *filename,
|
||||
int border_top,
|
||||
int border_right,
|
||||
int border_bottom,
|
||||
int border_left)
|
||||
{
|
||||
ShellThemeImage *image;
|
||||
|
||||
image = g_object_new (SHELL_TYPE_THEME_IMAGE, NULL);
|
||||
|
||||
image->filename = g_strdup (filename);
|
||||
image->border_top = border_top;
|
||||
image->border_right = border_right;
|
||||
image->border_bottom = border_bottom;
|
||||
image->border_left = border_left;
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
const char *
|
||||
shell_theme_image_get_filename (ShellThemeImage *image)
|
||||
{
|
||||
g_return_val_if_fail (SHELL_IS_THEME_IMAGE (image), NULL);
|
||||
|
||||
return image->filename;
|
||||
}
|
||||
|
||||
void
|
||||
shell_theme_image_get_borders (ShellThemeImage *image,
|
||||
int *border_top,
|
||||
int *border_right,
|
||||
int *border_bottom,
|
||||
int *border_left)
|
||||
{
|
||||
g_return_if_fail (SHELL_IS_THEME_IMAGE (image));
|
||||
|
||||
if (border_top)
|
||||
*border_top = image->border_top;
|
||||
if (border_right)
|
||||
*border_right = image->border_right;
|
||||
if (border_bottom)
|
||||
*border_bottom = image->border_bottom;
|
||||
if (border_left)
|
||||
*border_left = image->border_left;
|
||||
}
|
38
src/toolkit/shell-theme-image.h
Normal file
38
src/toolkit/shell-theme-image.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
#ifndef __SHELL_THEME_IMAGE_H__
|
||||
#define __SHELL_THEME_IMAGE_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* A ShellThemeImage encapsulates an image with specified unscaled borders on each edge.
|
||||
*/
|
||||
typedef struct _ShellThemeImage ShellThemeImage;
|
||||
typedef struct _ShellThemeImageClass ShellThemeImageClass;
|
||||
|
||||
#define SHELL_TYPE_THEME_IMAGE (shell_theme_image_get_type ())
|
||||
#define SHELL_THEME_IMAGE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SHELL_TYPE_THEME_IMAGE, ShellThemeImage))
|
||||
#define SHELL_THEME_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_THEME_IMAGE, ShellThemeImageClass))
|
||||
#define SHELL_IS_THEME_IMAGE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SHELL_TYPE_THEME_IMAGE))
|
||||
#define SHELL_IS_THEME_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_THEME_IMAGE))
|
||||
#define SHELL_THEME_IMAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_THEME_IMAGE, ShellThemeImageClass))
|
||||
|
||||
GType shell_theme_image_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ShellThemeImage *shell_theme_image_new (const char *filename,
|
||||
int border_top,
|
||||
int border_right,
|
||||
int border_bottom,
|
||||
int border_left);
|
||||
|
||||
const char *shell_theme_image_get_filename (ShellThemeImage *image);
|
||||
void shell_theme_image_get_borders (ShellThemeImage *image,
|
||||
int *border_top,
|
||||
int *border_right,
|
||||
int *border_bottom,
|
||||
int *border_left);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __SHELL_THEME_IMAGE_H__ */
|
1777
src/toolkit/shell-theme-node.c
Normal file
1777
src/toolkit/shell-theme-node.c
Normal file
File diff suppressed because it is too large
Load Diff
115
src/toolkit/shell-theme-node.h
Normal file
115
src/toolkit/shell-theme-node.h
Normal file
@ -0,0 +1,115 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
#ifndef __SHELL_THEME_NODE_H__
|
||||
#define __SHELL_THEME_NODE_H__
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include "shell-theme-image.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _ShellTheme ShellTheme;
|
||||
typedef struct _ShellThemeContext ShellThemeContext;
|
||||
|
||||
typedef struct _ShellThemeNode ShellThemeNode;
|
||||
typedef struct _ShellThemeNodeClass ShellThemeNodeClass;
|
||||
|
||||
#define SHELL_TYPE_THEME_NODE (shell_theme_node_get_type ())
|
||||
#define SHELL_THEME_NODE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SHELL_TYPE_THEME_NODE, ShellThemeNode))
|
||||
#define SHELL_THEME_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_THEME_NODE, ShellThemeNodeClass))
|
||||
#define SHELL_IS_THEME_NODE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SHELL_TYPE_THEME_NODE))
|
||||
#define SHELL_IS_THEME_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_THEME_NODE))
|
||||
#define SHELL_THEME_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_THEME_NODE, ShellThemeNodeClass))
|
||||
|
||||
typedef enum {
|
||||
SHELL_SIDE_LEFT,
|
||||
SHELL_SIDE_RIGHT,
|
||||
SHELL_SIDE_TOP,
|
||||
SHELL_SIDE_BOTTOM
|
||||
} ShellSide;
|
||||
|
||||
/* These are the CSS values; that doesn't mean we have to implement blink... */
|
||||
typedef enum {
|
||||
SHELL_TEXT_DECORATION_UNDERLINE = 1 << 0,
|
||||
SHELL_TEXT_DECORATION_OVERLINE = 1 << 1,
|
||||
SHELL_TEXT_DECORATION_LINE_THROUGH = 1 << 2,
|
||||
SHELL_TEXT_DECORATION_BLINK = 1 << 3
|
||||
} ShellTextDecoration;
|
||||
|
||||
GType shell_theme_node_get_type (void) G_GNUC_CONST;
|
||||
|
||||
/* An element_type of G_TYPE_NONE means this style was created for the stage
|
||||
* actor and matches a selector element name of 'stage'
|
||||
*/
|
||||
ShellThemeNode *shell_theme_node_new (ShellThemeContext *context,
|
||||
ShellThemeNode *parent_node, /* can be null */
|
||||
ShellTheme *theme, /* can be null */
|
||||
GType element_type,
|
||||
const char *element_id,
|
||||
const char *element_class,
|
||||
const char *pseudo_class);
|
||||
|
||||
ShellThemeNode *shell_theme_node_get_parent (ShellThemeNode *node);
|
||||
|
||||
ShellTheme *shell_theme_node_get_theme (ShellThemeNode *node);
|
||||
|
||||
GType shell_theme_node_get_element_type (ShellThemeNode *node);
|
||||
const char *shell_theme_node_get_element_id (ShellThemeNode *node);
|
||||
const char *shell_theme_node_get_element_class (ShellThemeNode *node);
|
||||
const char *shell_theme_node_get_pseudo_class (ShellThemeNode *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 shell_theme_node_get_color (ShellThemeNode *node,
|
||||
const char *property_name,
|
||||
gboolean inherit,
|
||||
ClutterColor *color);
|
||||
|
||||
gboolean shell_theme_node_get_double (ShellThemeNode *node,
|
||||
const char *property_name,
|
||||
gboolean inherit,
|
||||
double *value);
|
||||
|
||||
/* The length here is already resolved to pixels
|
||||
*/
|
||||
gboolean shell_theme_node_get_length (ShellThemeNode *node,
|
||||
const char *property_name,
|
||||
gboolean inherit,
|
||||
gdouble *length);
|
||||
|
||||
/* Specific getters for particular properties: cached
|
||||
*/
|
||||
void shell_theme_node_get_background_color (ShellThemeNode *node,
|
||||
ClutterColor *color);
|
||||
void shell_theme_node_get_foreground_color (ShellThemeNode *node,
|
||||
ClutterColor *color);
|
||||
|
||||
const char *shell_theme_node_get_background_image (ShellThemeNode *node);
|
||||
|
||||
double shell_theme_node_get_border_width (ShellThemeNode *node,
|
||||
ShellSide side);
|
||||
void shell_theme_node_get_border_color (ShellThemeNode *node,
|
||||
ShellSide side,
|
||||
ClutterColor *color);
|
||||
double shell_theme_node_get_padding (ShellThemeNode *node,
|
||||
ShellSide side);
|
||||
|
||||
ShellTextDecoration shell_theme_node_get_text_decoration (ShellThemeNode *node);
|
||||
|
||||
/* Font rule processing is pretty complicated, so we just hardcode it
|
||||
* under the standard font/font-family/font-size/etc names. This means
|
||||
* you can't have multiple separate styled fonts for a single item,
|
||||
* but that should be OK.
|
||||
*/
|
||||
const PangoFontDescription *shell_theme_node_get_font (ShellThemeNode *node);
|
||||
|
||||
/* This is the getter for -shell-background-image, which is different from
|
||||
* background-image in having provisions for unscaled borders.
|
||||
*/
|
||||
ShellThemeImage *shell_theme_node_get_background_theme_image (ShellThemeNode *node);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __SHELL_THEME_NODE_H__ */
|
22
src/toolkit/shell-theme-private.h
Normal file
22
src/toolkit/shell-theme-private.h
Normal file
@ -0,0 +1,22 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
#ifndef __SHELL_THEME_PRIVATE_H__
|
||||
#define __SHELL_THEME_PRIVATE_H__
|
||||
|
||||
#include <libcroco/libcroco.h>
|
||||
#include "shell-theme.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void _shell_theme_get_matched_properties (ShellTheme *theme,
|
||||
ShellThemeNode *node,
|
||||
CRDeclaration ***properties,
|
||||
int *n_properties);
|
||||
|
||||
/* Resolve an URL from the stylesheet to a filename */
|
||||
char *_shell_theme_resolve_url (ShellTheme *theme,
|
||||
CRStyleSheet *base_stylesheet,
|
||||
const char *url);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __SHELL_THEME_PRIVATE_H__ */
|
1032
src/toolkit/shell-theme.c
Normal file
1032
src/toolkit/shell-theme.c
Normal file
File diff suppressed because it is too large
Load Diff
28
src/toolkit/shell-theme.h
Normal file
28
src/toolkit/shell-theme.h
Normal file
@ -0,0 +1,28 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
#ifndef __SHELL_THEME_H__
|
||||
#define __SHELL_THEME_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "shell-theme-node.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _ShellThemeClass ShellThemeClass;
|
||||
|
||||
#define SHELL_TYPE_THEME (shell_theme_get_type ())
|
||||
#define SHELL_THEME(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SHELL_TYPE_THEME, ShellTheme))
|
||||
#define SHELL_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_THEME, ShellThemeClass))
|
||||
#define SHELL_IS_THEME(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SHELL_TYPE_THEME))
|
||||
#define SHELL_IS_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_THEME))
|
||||
#define SHELL_THEME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_THEME, ShellThemeClass))
|
||||
|
||||
GType shell_theme_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ShellTheme *shell_theme_new (const char *application_stylesheet,
|
||||
const char *theme_stylesheet,
|
||||
const char *default_stylesheet);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __SHELL_THEME_H__ */
|
292
src/toolkit/test-theme.c
Normal file
292
src/toolkit/test-theme.c
Normal file
@ -0,0 +1,292 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include "shell-theme.h"
|
||||
#include "shell-theme-context.h"
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
static ShellThemeNode *root;
|
||||
static ShellThemeNode *group1;
|
||||
static ShellThemeNode *text1;
|
||||
static ShellThemeNode *text2;
|
||||
static ShellThemeNode *group2;
|
||||
static ShellThemeNode *text3;
|
||||
static ShellThemeNode *text4;
|
||||
static ShellThemeNode *group3;
|
||||
static ShellThemeNode *cairo_texture;
|
||||
static gboolean fail;
|
||||
|
||||
static const char *test;
|
||||
|
||||
static void
|
||||
assert_font (ShellThemeNode *node,
|
||||
const char *node_description,
|
||||
const char *expected)
|
||||
{
|
||||
char *value = pango_font_description_to_string (shell_theme_node_get_font (node));
|
||||
|
||||
if (strcmp (expected, value) != 0)
|
||||
{
|
||||
g_print ("%s: %s.font: expected: %s, got: %s\n",
|
||||
test, node_description, expected, value);
|
||||
fail = TRUE;
|
||||
}
|
||||
|
||||
g_free (value);
|
||||
}
|
||||
|
||||
static char *
|
||||
text_decoration_to_string (ShellTextDecoration decoration)
|
||||
{
|
||||
GString *result = g_string_new (NULL);
|
||||
|
||||
if (decoration & SHELL_TEXT_DECORATION_UNDERLINE)
|
||||
g_string_append(result, " underline");
|
||||
if (decoration & SHELL_TEXT_DECORATION_OVERLINE)
|
||||
g_string_append(result, " overline");
|
||||
if (decoration & SHELL_TEXT_DECORATION_LINE_THROUGH)
|
||||
g_string_append(result, " line_through");
|
||||
if (decoration & SHELL_TEXT_DECORATION_BLINK)
|
||||
g_string_append(result, " blink");
|
||||
|
||||
if (result->len > 0)
|
||||
g_string_erase (result, 0, 1);
|
||||
else
|
||||
g_string_append(result, "none");
|
||||
|
||||
return g_string_free (result, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
assert_text_decoration (ShellThemeNode *node,
|
||||
const char *node_description,
|
||||
ShellTextDecoration expected)
|
||||
{
|
||||
ShellTextDecoration value = shell_theme_node_get_text_decoration (node);
|
||||
if (expected != value)
|
||||
{
|
||||
char *es = text_decoration_to_string (expected);
|
||||
char *vs = text_decoration_to_string (value);
|
||||
|
||||
g_print ("%s: %s.text-decoration: expected: %s, got: %s\n",
|
||||
test, node_description, es, vs);
|
||||
fail = TRUE;
|
||||
|
||||
g_free (es);
|
||||
g_free (vs);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
assert_foreground_color (ShellThemeNode *node,
|
||||
const char *node_description,
|
||||
guint32 expected)
|
||||
{
|
||||
ClutterColor color;
|
||||
shell_theme_node_get_foreground_color (node, &color);
|
||||
guint32 value = clutter_color_to_pixel (&color);
|
||||
|
||||
if (expected != value)
|
||||
{
|
||||
g_print ("%s: %s.color: expected: #%08x, got: #%08x\n",
|
||||
test, node_description, expected, value);
|
||||
fail = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
assert_background_color (ShellThemeNode *node,
|
||||
const char *node_description,
|
||||
guint32 expected)
|
||||
{
|
||||
ClutterColor color;
|
||||
shell_theme_node_get_background_color (node, &color);
|
||||
guint32 value = clutter_color_to_pixel (&color);
|
||||
|
||||
if (expected != value)
|
||||
{
|
||||
g_print ("%s: %s.background-color: expected: #%08x, got: #%08x\n",
|
||||
test, node_description, expected, value);
|
||||
fail = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
assert_background_image (ShellThemeNode *node,
|
||||
const char *node_description,
|
||||
const char *expected)
|
||||
{
|
||||
const char *value = shell_theme_node_get_background_image (node);
|
||||
if (expected == NULL)
|
||||
expected = "(null)";
|
||||
if (value == NULL)
|
||||
value = "(null)";
|
||||
|
||||
if (strcmp (expected, value) != 0)
|
||||
{
|
||||
g_print ("%s: %s.background-image: expected: %s, got: %s\n",
|
||||
test, node_description, expected, value);
|
||||
fail = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
#define LENGTH_EPSILON 0.001
|
||||
|
||||
static void
|
||||
assert_length (const char *node_description,
|
||||
const char *property_description,
|
||||
double expected,
|
||||
double value)
|
||||
{
|
||||
if (fabs (expected - value) > LENGTH_EPSILON)
|
||||
{
|
||||
g_print ("%s %s.%s: expected: %3f, got: %3f\n",
|
||||
test, node_description, property_description, expected, value);
|
||||
fail = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_defaults (void)
|
||||
{
|
||||
test = "defaults";
|
||||
/* font comes from context */
|
||||
assert_font (root, "stage", "sans-serif 12");
|
||||
/* black is the default foreground color */
|
||||
assert_foreground_color (root, "stage", 0x00000ff);
|
||||
}
|
||||
|
||||
static void
|
||||
test_lengths (void)
|
||||
{
|
||||
test = "lengths";
|
||||
/* 12pt == 16px at 96dpi */
|
||||
assert_length ("group1", "padding-top", 16.,
|
||||
shell_theme_node_get_padding (group1, SHELL_SIDE_TOP));
|
||||
/* 12px == 12px */
|
||||
assert_length ("group1", "padding-right", 12.,
|
||||
shell_theme_node_get_padding (group1, SHELL_SIDE_RIGHT));
|
||||
/* 2em == 32px (with a 12pt font) */
|
||||
assert_length ("group1", "padding-bottom", 32.,
|
||||
shell_theme_node_get_padding (group1, SHELL_SIDE_BOTTOM));
|
||||
/* 1in == 72pt == 96px, at 96dpi */
|
||||
assert_length ("group1", "padding-left", 96.,
|
||||
shell_theme_node_get_padding (group1, SHELL_SIDE_LEFT));
|
||||
}
|
||||
|
||||
static void
|
||||
test_classes (void)
|
||||
{
|
||||
test = "classes";
|
||||
/* .special-text class overrides size and style;
|
||||
* the ClutterTexture.special-text selector doesn't match */
|
||||
assert_font (text1, "text1", "sans-serif Italic 32px");
|
||||
}
|
||||
|
||||
static void
|
||||
test_type_inheritance (void)
|
||||
{
|
||||
test = "type_inheritance";
|
||||
/* From ClutterTexture element selector */
|
||||
assert_length ("cairoTexture", "padding-top", 10.,
|
||||
shell_theme_node_get_padding (cairo_texture, SHELL_SIDE_TOP));
|
||||
/* From ClutterCairoTexture element selector */
|
||||
assert_length ("cairoTexture", "padding-right", 20.,
|
||||
shell_theme_node_get_padding (cairo_texture, SHELL_SIDE_RIGHT));
|
||||
}
|
||||
|
||||
static void
|
||||
test_adjacent_selector (void)
|
||||
{
|
||||
test = "adjacent_selector";
|
||||
/* #group1 > #text1 matches text1 */
|
||||
assert_foreground_color (text1, "text1", 0x00ff00ff);
|
||||
/* stage > #text2 doesn't match text2 */
|
||||
assert_foreground_color (text2, "text2", 0x000000ff);
|
||||
}
|
||||
|
||||
static void
|
||||
test_background (void)
|
||||
{
|
||||
test = "background";
|
||||
/* group1 has a background: shortcut property setting color and image */
|
||||
assert_background_color (group1, "group1", 0xff0000ff);
|
||||
assert_background_image (group1, "group1", "toolkit/some-background.png");
|
||||
/* text1 inherits the background image but not the color */
|
||||
assert_background_color (text1, "text1", 0x00000000);
|
||||
assert_background_image (text1, "text1", "toolkit/some-background.png");
|
||||
/* text1 inherits inherits both, but then background: none overrides both */
|
||||
assert_background_color (text2, "text2", 0x00000000);
|
||||
assert_background_image (text2, "text2", NULL);
|
||||
/* background-image property */
|
||||
assert_background_image (group2, "group2", "toolkit/other-background.png");
|
||||
}
|
||||
|
||||
static void
|
||||
test_font (void)
|
||||
{
|
||||
test = "font";
|
||||
/* font specified with font: */
|
||||
assert_font (group2, "group2", "serif Italic 12px");
|
||||
/* text3 inherits and overrides individually properties */
|
||||
assert_font (text3, "text3", "serif Bold Oblique Small-Caps 24px");
|
||||
}
|
||||
|
||||
static void
|
||||
test_pseudo_class (void)
|
||||
{
|
||||
test = "pseudo_class";
|
||||
/* text4 has :visited and :hover pseudo-classes, so should pick up both of these */
|
||||
assert_foreground_color (text4, "text4", 0x888888ff);
|
||||
assert_text_decoration (text4, "text4", SHELL_TEXT_DECORATION_UNDERLINE);
|
||||
/* :hover pseudo-class matches, but class doesn't match */
|
||||
assert_text_decoration (group3, "group3", 0);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
ShellTheme *theme;
|
||||
ShellThemeContext *context;
|
||||
|
||||
clutter_init (&argc, &argv);
|
||||
|
||||
theme = shell_theme_new ("toolkit/test-theme.css",
|
||||
NULL, NULL);
|
||||
|
||||
context = shell_theme_context_new ();
|
||||
shell_theme_context_set_theme (context, theme);
|
||||
shell_theme_context_set_resolution (context, 96.);
|
||||
shell_theme_context_set_font (context,
|
||||
pango_font_description_from_string ("sans-serif 12"));
|
||||
|
||||
root = shell_theme_context_get_root_node (context);
|
||||
group1 = shell_theme_node_new (context, root, NULL,
|
||||
CLUTTER_TYPE_GROUP, "group1", NULL, NULL);
|
||||
text1 = shell_theme_node_new (context, group1, NULL,
|
||||
CLUTTER_TYPE_TEXT, "text1", "special-text", NULL);
|
||||
text2 = shell_theme_node_new (context, group1, NULL,
|
||||
CLUTTER_TYPE_TEXT, "text2", NULL, NULL);
|
||||
group2 = shell_theme_node_new (context, root, NULL,
|
||||
CLUTTER_TYPE_GROUP, "group2", NULL, NULL);
|
||||
text3 = shell_theme_node_new (context, group2, NULL,
|
||||
CLUTTER_TYPE_TEXT, "text3", NULL, NULL);
|
||||
text4 = shell_theme_node_new (context, group2, NULL,
|
||||
CLUTTER_TYPE_TEXT, "text4", NULL, "visited hover");
|
||||
group3 = shell_theme_node_new (context, group2, NULL,
|
||||
CLUTTER_TYPE_GROUP, "group3", NULL, "hover");
|
||||
cairo_texture = shell_theme_node_new (context, root, NULL,
|
||||
CLUTTER_TYPE_CAIRO_TEXTURE, "cairoTexture", NULL, NULL);
|
||||
|
||||
test_defaults ();
|
||||
test_lengths ();
|
||||
test_classes ();
|
||||
test_type_inheritance ();
|
||||
test_adjacent_selector ();
|
||||
test_background ();
|
||||
test_font ();
|
||||
test_pseudo_class ();
|
||||
|
||||
return fail ? 1 : 0;
|
||||
}
|
68
src/toolkit/test-theme.css
Normal file
68
src/toolkit/test-theme.css
Normal file
@ -0,0 +1,68 @@
|
||||
stage {
|
||||
}
|
||||
|
||||
#group1 {
|
||||
padding: 12pt;
|
||||
padding-right: 12px;
|
||||
padding-bottom: 2em;
|
||||
padding-left: 1in;
|
||||
|
||||
background: #ff0000 url('some-background.png');
|
||||
}
|
||||
|
||||
#text1 {
|
||||
background-image: inherit;
|
||||
}
|
||||
|
||||
.special-text {
|
||||
font-size: 24pt;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
ClutterTexture.special-text {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#text2 {
|
||||
background: inherit;
|
||||
background: none; /* also overrides the color */
|
||||
}
|
||||
|
||||
#group2 {
|
||||
font: italic 12px serif;
|
||||
}
|
||||
|
||||
#text3 {
|
||||
font-variant: small-caps;
|
||||
font-weight: bold;
|
||||
font-style: oblique;
|
||||
font-size: 200%;
|
||||
}
|
||||
|
||||
ClutterTexture {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
ClutterCairoTexture {
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
#group1 > #text1 {
|
||||
color: #00ff00;
|
||||
}
|
||||
|
||||
stage > #text2 {
|
||||
color: #ff0000;
|
||||
}
|
||||
|
||||
#group2 {
|
||||
background-image: url('other-background.png');
|
||||
}
|
||||
|
||||
ClutterText:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
ClutterText:visited {
|
||||
color: #888888;
|
||||
}
|
Loading…
Reference in New Issue
Block a user