GtkStyleSet: Register the border-style and border-color properties

This is also implemented in the theming engine, although the default
CSS should be using it in order to theme buttons, troughs, sliders
and such.
This commit is contained in:
Carlos Garnacho 2010-10-22 10:38:21 +02:00
parent 8d4ffedbf1
commit 3a455ed8f9
3 changed files with 165 additions and 144 deletions

View File

@ -618,6 +618,12 @@ typedef enum {
GTK_JUNCTION_RIGHT = 1 << 3 GTK_JUNCTION_RIGHT = 1 << 3
} GtkJunctionSides; } GtkJunctionSides;
typedef enum {
GTK_BORDER_STYLE_NONE,
GTK_BORDER_STYLE_SOLID,
GTK_BORDER_STYLE_INSET,
GTK_BORDER_STYLE_OUTSET
} GtkBorderStyle;
G_END_DECLS G_END_DECLS

View File

@ -23,6 +23,7 @@
#include <gobject/gvaluecollector.h> #include <gobject/gvaluecollector.h>
#include <cairo/cairo-gobject.h> #include <cairo/cairo-gobject.h>
#include "gtktypebuiltins.h"
#include "gtkstyleprovider.h" #include "gtkstyleprovider.h"
#include "gtkstyleset.h" #include "gtkstyleset.h"
#include "gtkprivate.h" #include "gtkprivate.h"
@ -92,6 +93,8 @@ gtk_style_set_class_init (GtkStyleSetClass *klass)
gtk_style_set_register_property ("border-width", G_TYPE_INT, NULL, NULL); gtk_style_set_register_property ("border-width", G_TYPE_INT, NULL, NULL);
gtk_style_set_register_property ("border-radius", G_TYPE_INT, NULL, NULL); gtk_style_set_register_property ("border-radius", G_TYPE_INT, NULL, NULL);
gtk_style_set_register_property ("border-style", GTK_TYPE_BORDER_STYLE, NULL, NULL);
gtk_style_set_register_property ("border-color", GDK_TYPE_COLOR, NULL, NULL);
gtk_style_set_register_property ("background-image", CAIRO_GOBJECT_TYPE_PATTERN, NULL, NULL); gtk_style_set_register_property ("background-image", CAIRO_GOBJECT_TYPE_PATTERN, NULL, NULL);
gtk_style_set_register_property ("border-image", GTK_TYPE_9SLICE, NULL, NULL); gtk_style_set_register_property ("border-image", GTK_TYPE_9SLICE, NULL, NULL);

View File

@ -52,7 +52,8 @@ enum {
SIDE_LEFT = 1, SIDE_LEFT = 1,
SIDE_BOTTOM = 1 << 1, SIDE_BOTTOM = 1 << 1,
SIDE_RIGHT = 1 << 2, SIDE_RIGHT = 1 << 2,
SIDE_TOP = 1 << 3 SIDE_TOP = 1 << 3,
SIDE_ALL = 0xF
}; };
struct GtkThemingEnginePrivate struct GtkThemingEnginePrivate
@ -1139,25 +1140,97 @@ color_shade (const GdkColor *color,
} }
static void static void
_cairo_round_rectangle (cairo_t *cr, _cairo_round_rectangle_sides (cairo_t *cr,
gdouble radius, gdouble radius,
gdouble x, gdouble x,
gdouble y, gdouble y,
gdouble width, gdouble width,
gdouble height) gdouble height,
guint sides,
GtkJunctionSides junction)
{ {
radius = CLAMP (radius, 0, MIN (width / 2, height / 2)); radius = CLAMP (radius, 0, MIN (width / 2, height / 2));
if (radius == 0) if (sides & SIDE_RIGHT)
cairo_rectangle (cr, x, y, width, height);
else
{ {
cairo_new_sub_path (cr); if (radius == 0 ||
cairo_arc (cr, x + width - radius, y + radius, radius, - G_PI / 2, 0); (junction & GTK_JUNCTION_TOP) ||
cairo_arc (cr, x + width - radius, y + height - radius, radius, 0, G_PI / 2); (junction & GTK_JUNCTION_RIGHT))
cairo_arc (cr, x + radius, y + height - radius, radius, G_PI / 2, G_PI); cairo_move_to (cr, x + width, y);
cairo_arc (cr, x + radius, y + radius, radius, G_PI, 3 * (G_PI / 2)); else
cairo_close_path (cr); {
cairo_new_sub_path (cr);
cairo_arc (cr, x + width - radius, y + radius, radius, - G_PI / 4, 0);
}
if (radius == 0 ||
(junction & GTK_JUNCTION_BOTTOM) ||
(junction & GTK_JUNCTION_RIGHT))
cairo_line_to (cr, x + width, y + height);
else
cairo_arc (cr, x + width - radius, y + height - radius, radius, 0, G_PI / 4);
}
if (sides & SIDE_BOTTOM)
{
if (radius != 0 &&
! (junction & GTK_JUNCTION_RIGHT) &&
! (junction & GTK_JUNCTION_BOTTOM))
{
if ((sides & SIDE_RIGHT) == 0)
cairo_new_sub_path (cr);
cairo_arc (cr, x + width - radius, y + height - radius, radius, G_PI / 4, G_PI / 2);
}
if (radius == 0 ||
(junction & GTK_JUNCTION_BOTTOM) ||
(junction & GTK_JUNCTION_LEFT))
cairo_line_to (cr, x, y + height);
else
cairo_arc (cr, x + radius, y + height - radius, radius, G_PI / 2, 3 * (G_PI / 4));
}
else
cairo_move_to (cr, x, y + height);
if (sides & SIDE_LEFT)
{
if (radius != 0 &&
! (junction & GTK_JUNCTION_LEFT) &&
! (junction & GTK_JUNCTION_BOTTOM))
{
if ((sides & SIDE_BOTTOM) == 0)
cairo_new_sub_path (cr);
cairo_arc (cr, x + radius, y + height - radius, radius, 3 * (G_PI / 4), G_PI);
}
if (radius == 0 ||
(junction & GTK_JUNCTION_TOP) ||
(junction & GTK_JUNCTION_LEFT))
cairo_line_to (cr, x, y);
else
cairo_arc (cr, x + radius, y + radius, radius, G_PI, G_PI + G_PI / 4);
}
if (sides & SIDE_TOP)
{
if (radius != 0 &&
! (junction & GTK_JUNCTION_TOP) &&
! (junction & GTK_JUNCTION_LEFT))
{
if ((sides & SIDE_TOP) == 0)
cairo_new_sub_path (cr);
cairo_arc (cr, x + radius, y + radius, radius, 5 * (G_PI / 4), 3 * (G_PI / 2));
}
if (radius == 0 ||
(junction & GTK_JUNCTION_TOP) ||
(junction & GTK_JUNCTION_RIGHT))
cairo_line_to (cr, x + width, y);
else
cairo_arc (cr, x + width - radius, y + radius, radius, 3 * (G_PI / 2), - G_PI / 4);
} }
} }
@ -1174,9 +1247,11 @@ gtk_theming_engine_render_background (GtkThemingEngine *engine,
GtkStateFlags flags; GtkStateFlags flags;
gboolean running; gboolean running;
gdouble progress, alpha = 1; gdouble progress, alpha = 1;
GtkJunctionSides junction;
gint radius; gint radius;
flags = gtk_theming_engine_get_state (engine); flags = gtk_theming_engine_get_state (engine);
junction = gtk_theming_engine_get_junction_sides (engine);
cairo_save (cr); cairo_save (cr);
if (gtk_theming_engine_has_class (engine, "spinbutton") && if (gtk_theming_engine_has_class (engine, "spinbutton") &&
@ -1197,7 +1272,9 @@ gtk_theming_engine_render_background (GtkThemingEngine *engine,
running = gtk_theming_engine_state_is_running (engine, GTK_STATE_PRELIGHT, &progress); running = gtk_theming_engine_state_is_running (engine, GTK_STATE_PRELIGHT, &progress);
_cairo_round_rectangle (cr, (gdouble) radius, x, y, width, height); _cairo_round_rectangle_sides (cr, (gdouble) radius,
x, y, width, height,
SIDE_ALL, junction);
cairo_clip (cr); cairo_clip (cr);
cairo_translate (cr, x, y); cairo_translate (cr, x, y);
@ -1448,163 +1525,98 @@ gtk_theming_engine_render_frame (GtkThemingEngine *engine,
{ {
GtkStateFlags flags; GtkStateFlags flags;
GdkColor lighter, darker; GdkColor lighter, darker;
GdkColor *bg_color; GdkColor *border_color;
Gtk9Slice *slice; Gtk9Slice *slice;
GtkBorderStyle border_style;
gint border_width, radius;
GtkJunctionSides junction;
flags = gtk_theming_engine_get_state (engine); flags = gtk_theming_engine_get_state (engine);
junction = gtk_theming_engine_get_junction_sides (engine);
gtk_theming_engine_get (engine, flags, gtk_theming_engine_get (engine, flags,
"border-image", &slice, "border-image", &slice,
"background-color", &bg_color, "border-color", &border_color,
"border-style", &border_style,
"border-width", &border_width,
"border-radius", &radius,
NULL); NULL);
if (slice) if (slice)
{ {
gtk_9slice_render (slice, cr, x, y, width, height); gtk_9slice_render (slice, cr, x, y, width, height);
gtk_9slice_unref (slice); gtk_9slice_unref (slice);
gdk_color_free (bg_color);
return;
} }
else if (border_style != GTK_BORDER_STYLE_NONE)
cairo_save (cr);
cairo_set_line_width (cr, 1);
color_shade (bg_color, 0.7, &darker);
color_shade (bg_color, 1.3, &lighter);
if (gtk_theming_engine_has_class (engine, "entry") ||
gtk_theming_engine_has_class (engine, "scrolled-window") ||
gtk_theming_engine_has_class (engine, "viewport"))
{ {
gdk_cairo_set_source_color (cr, bg_color); cairo_save (cr);
add_path_rectangle_sides (cr, x + 1, y + 1, width - 2, height - 2,
SIDE_BOTTOM | SIDE_RIGHT);
cairo_stroke (cr);
cairo_set_source_rgb (cr, 0, 0, 0); color_shade (border_color, 0.7, &darker);
add_path_rectangle_sides (cr, x + 1, y + 1, width - 2, height - 2, color_shade (border_color, 1.3, &lighter);
SIDE_TOP | SIDE_LEFT);
cairo_stroke (cr);
cairo_set_source_rgb (cr, 1, 1, 1); switch (border_style)
add_path_rectangle_sides (cr, x, y, width, height,
SIDE_BOTTOM | SIDE_RIGHT);
cairo_stroke (cr);
gdk_cairo_set_source_color (cr, &darker);
add_path_rectangle_sides (cr, x, y, width, height,
SIDE_TOP | SIDE_LEFT);
cairo_stroke (cr);
}
else if (gtk_theming_engine_has_class (engine, "button") &&
gtk_theming_engine_has_class (engine, "default"))
{
cairo_set_source_rgb (cr, 0, 0, 0);
cairo_rectangle (cr, x + 0.5, x + 0.5, width - 1, height - 1);
cairo_stroke (cr);
}
else if (gtk_theming_engine_has_class (engine, "scrollbar") &&
gtk_theming_engine_has_class (engine, "trough"))
{
gdk_cairo_set_source_color (cr, &darker);
add_path_rectangle_sides (cr, x, y, width, height,
SIDE_TOP | SIDE_LEFT);
cairo_stroke (cr);
gdk_cairo_set_source_color (cr, &lighter);
add_path_rectangle_sides (cr, x, y, width, height,
SIDE_BOTTOM | SIDE_RIGHT);
cairo_stroke (cr);
}
else if (gtk_theming_engine_has_class (engine, "spinbutton"))
{
if (gtk_theming_engine_has_class (engine, "button"))
{ {
GtkJunctionSides sides; case GTK_BORDER_STYLE_NONE:
break;
case GTK_BORDER_STYLE_SOLID:
cairo_set_line_width (cr, border_width);
sides = gtk_theming_engine_get_junction_sides (engine); if (border_width > 1)
{
x += (gdouble) border_width / 2;
y += (gdouble) border_width / 2;
width -= border_width;
height -= border_width;
}
if (sides & GTK_JUNCTION_BOTTOM) _cairo_round_rectangle_sides (cr, (gdouble) radius, x, y, width, height,
y += 2; SIDE_ALL, junction);
gdk_cairo_set_source_color (cr, border_color);
cairo_stroke (cr);
width -= 3; break;
height -= 2; case GTK_BORDER_STYLE_INSET:
case GTK_BORDER_STYLE_OUTSET:
cairo_set_line_width (cr, border_width);
cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
if (gtk_theming_engine_get_direction (engine) == GTK_TEXT_DIR_RTL) if (border_width > 1)
x += 2; {
gint d;
d = border_width / 2;
x += d;
y += d;
width -= d * 2;
height -= d * 2;
}
if (border_style == GTK_BORDER_STYLE_INSET)
gdk_cairo_set_source_color (cr, border_color);
else else
x += 1; gdk_cairo_set_source_color (cr, &darker);
gdk_cairo_set_source_color (cr, &lighter); _cairo_round_rectangle_sides (cr, (gdouble) radius, x, y, width, height,
add_path_rectangle_sides (cr, x, y, width, height, SIDE_TOP); SIDE_BOTTOM | SIDE_RIGHT, junction);
cairo_stroke (cr); cairo_stroke (cr);
gdk_cairo_set_source_color (cr, &darker); if (border_style == GTK_BORDER_STYLE_INSET)
add_path_rectangle_sides (cr, x, y, width, height, SIDE_BOTTOM); gdk_cairo_set_source_color (cr, &darker);
else
gdk_cairo_set_source_color (cr, border_color);
_cairo_round_rectangle_sides (cr, (gdouble) radius, x, y, width, height,
SIDE_TOP | SIDE_LEFT, junction);
cairo_stroke (cr); cairo_stroke (cr);
break;
} }
else
{
gdk_cairo_set_source_color (cr, &lighter);
add_path_rectangle_sides (cr, x, y, width, height,
SIDE_BOTTOM | SIDE_RIGHT);
cairo_stroke (cr);
gdk_cairo_set_source_color (cr, &darker); cairo_restore (cr);
add_path_rectangle_sides (cr, x, y, width, height, SIDE_TOP);
cairo_stroke (cr);
gdk_cairo_set_source_color (cr, bg_color);
add_path_rectangle_sides (cr, x, y, width - 1, height - 1, SIDE_BOTTOM);
cairo_stroke (cr);
cairo_set_source_rgb (cr, 0, 0, 0);
add_path_rectangle_sides (cr, x, y + 1, width - 1, height - 3,
SIDE_TOP | SIDE_LEFT | SIDE_RIGHT);
cairo_stroke (cr);
}
}
else
{
if (flags & GTK_STATE_FLAG_ACTIVE)
{
cairo_set_source_rgb (cr, 0, 0, 0);
add_path_rectangle_sides (cr, x + 1, y + 1, width - 2, height - 2,
SIDE_TOP | SIDE_LEFT);
cairo_stroke (cr);
gdk_cairo_set_source_color (cr, &lighter);
add_path_rectangle_sides (cr, x, y, width, height,
SIDE_BOTTOM | SIDE_RIGHT);
cairo_stroke (cr);
gdk_cairo_set_source_color (cr, &darker);
add_path_rectangle_sides (cr, x, y, width, height,
SIDE_TOP | SIDE_LEFT);
cairo_stroke (cr);
}
else
{
gdk_cairo_set_source_color (cr, &darker);
add_path_rectangle_sides (cr, x, y, width - 1, height - 1,
SIDE_BOTTOM | SIDE_RIGHT);
cairo_stroke (cr);
gdk_cairo_set_source_color (cr, &lighter);
add_path_rectangle_sides (cr, x, y, width, height,
SIDE_TOP | SIDE_LEFT);
cairo_stroke (cr);
cairo_set_source_rgb (cr, 0, 0, 0);
add_path_rectangle_sides (cr, x, y, width, height,
SIDE_BOTTOM | SIDE_RIGHT);
cairo_stroke (cr);
}
} }
cairo_restore (cr); if (border_color)
gdk_color_free (border_color);
gdk_color_free (bg_color);
} }
static void static void