Re: RFC: Re-Design GtkStyle to only pass cairo-context?
- From: "Kalle Vahlman" <kalle vahlman gmail com>
- To: "Clemens Eisserer" <linuxhippy gmail com>
- Cc: gtk-devel-list gnome org
- Subject: Re: RFC: Re-Design GtkStyle to only pass cairo-context?
- Date: Tue, 8 Jan 2008 09:43:30 +0200
And here is the attachments too!
*sigh*
2008/1/8, Kalle Vahlman <kalle vahlman gmail com>:
> 2008/1/7, Clemens Eisserer <linuxhippy gmail com>:
> > Hello Kalle,
> >
> > > I guess it could work if one derives a GtkCairoStyle from GtkStyle and
> > > add the cairo-based API to that. That way casts to GtkStyle should
> > > work and engines could implement the old api with the wrapper
> > > approach.
> > >
> > > Or was that what you meant already?-)
> > Not really, because as far as I understand this would break existing
> > themes, wouldn't it? Would this tradeof be accepted, in favour of a
> > cleaner API?
>
> No, it won't break them since you can always use the derived class
> like you would use the parent.
>
> > The wrappers could be even implemented in GTK+ itself, removing legacy
> > code from the themes.
> >
> > My idea was to re-implement the whole group of gtk_paint functions
> > again as e.g. gtk_cairo_paint - and gtk calls still the old functions
> > which are by default only wrappers to the new gtk_cairo_paint if the
> > theme engine does not overwrite them (-> if it overwrites it, its an
> > old theme engine and we don't use cairo). However this would not allow
> > to pass cairo-contexts to the gtk_paint functions, to be honest your
> > approach sounds much cleaner and better.
>
> I've implemented a mockup of how this could go (attached):
>
> gtkcairostyle.h:
> gtkcairostyle.c:
> GtkCairoStyle class to replace GtkStyle, doubles also as an
> implementation for a cairo-using "theme" (implementing the
> paint_slider method).
>
> gtkcairostyle-test.c:
> A test application that draws the slider graphics with either the
> default style object or with the aforementioned cairo style, also
> doubles as GTK+ by implementing the gtk_cairo_paint_slider() method.
> The upper half is drawn in cairo way if possible and in old style if
> not. The lower half is drawn with the old API regardless of the style
> in use.
>
> Looks to work fine, remember to CC me when you submit the patch to bugzilla ;)
>
> Or is there a bug open for this?
>
> --
> Kalle Vahlman, zuh iki fi
> Powered by http://movial.fi
> Interesting stuff at http://syslog.movial.fi
>
--
Kalle Vahlman, zuh iki fi
Powered by http://movial.fi
Interesting stuff at http://syslog.movial.fi
#include <cairo.h>
#include <gtk/gtk.h>
#include <gtk/gtkstyle.h>
#include "gtkcairostyle.h"
G_DEFINE_TYPE(GtkCairoStyle, gtk_cairo_style, GTK_TYPE_STYLE);
/* Method declarations */
static void gtk_cairo_style_finalize(GObject *style);
static
void gtk_cairo_style_draw_slider (GtkCairoStyle *style,
cairo_t *cr,
GtkStateType state_type,
GtkShadowType shadow_type,
GdkRectangle *area,
GtkWidget *widget,
const gchar *detail,
gint x,
gint y,
gint width,
gint height,
GtkOrientation orientation);
static
void gtk_wrapper_style_draw_slider (GtkStyle *style,
GdkWindow *window,
GtkStateType state_type,
GtkShadowType shadow_type,
GdkRectangle *area,
GtkWidget *widget,
const gchar *detail,
gint x,
gint y,
gint width,
gint height,
GtkOrientation orientation);
static void
gtk_cairo_style_class_init(GtkCairoStyleClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
GtkStyleClass *style_class = GTK_STYLE_CLASS(klass);
gobject_class->finalize = gtk_cairo_style_finalize;
klass->draw_slider = gtk_cairo_style_draw_slider;
style_class->draw_slider = gtk_wrapper_style_draw_slider;
}
static void
gtk_cairo_style_init(GtkCairoStyle *style)
{
}
static void
gtk_cairo_style_finalize(GObject *style)
{
}
static
void gtk_wrapper_style_draw_slider (GtkStyle *style,
GdkWindow *window,
GtkStateType state_type,
GtkShadowType shadow_type,
GdkRectangle *area,
GtkWidget *widget,
const gchar *detail,
gint x,
gint y,
gint width,
gint height,
GtkOrientation orientation)
{
cairo_t *cr;
cr = gdk_cairo_create(window);
gtk_cairo_style_draw_slider(GTK_CAIRO_STYLE(style), cr,
state_type, shadow_type,
area, widget, detail,
x, y, width, height,
orientation);
cairo_destroy(cr);
}
static
void gtk_cairo_style_draw_slider (GtkCairoStyle *style,
cairo_t *cr,
GtkStateType state_type,
GtkShadowType shadow_type,
GdkRectangle *area,
GtkWidget *widget,
const gchar *detail,
gint x,
gint y,
gint width,
gint height,
GtkOrientation orientation)
{
cairo_save(cr);
cairo_set_source_rgba(cr, 1.0, 0.0, 0.0, 0.5);
cairo_rectangle(cr, x, y, width, height);
cairo_fill(cr);
cairo_set_source_rgba(cr, 1.0, 0.9, 0.9, 1.0);
cairo_move_to(cr, x+width*0.3, y+height*0.75);
cairo_line_to(cr, x+width*0.5, y+height*0.25);
cairo_move_to(cr, x+width*0.5, y+height*0.75);
cairo_line_to(cr, x+width*0.7, y+height*0.25);
cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
cairo_set_line_width(cr, 10.0);
cairo_stroke(cr);
cairo_restore(cr);
}
#ifndef __GTK_CAIRO_STYLE_H__
#define __GTK_CAIRO_STYLE_H__
#include <glib.h>
#include <cairo.h>
#include <gtk/gtk.h>
G_BEGIN_DECLS
typedef struct _GtkCairoStyleClass GtkCairoStyleClass;
typedef struct _GtkCairoStyle GtkCairoStyle;
struct _GtkCairoStyle
{
GtkStyle parent;
/*< private >*/
};
struct _GtkCairoStyleClass
{
GtkStyleClass parent_class;
void (*draw_slider) (GtkCairoStyle *style,
cairo_t *cr,
GtkStateType state_type,
GtkShadowType shadow_type,
GdkRectangle *area,
GtkWidget *widget,
const gchar *detail,
gint x,
gint y,
gint width,
gint height,
GtkOrientation orientation);
};
GType gtk_cairo_style_get_type ();
#define GTK_TYPE_CAIRO_STYLE (gtk_cairo_style_get_type ())
#define GTK_CAIRO_STYLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_CAIRO_STYLE, GtkCairoStyle))
#define GTK_CAIRO_STYLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_CAIRO_STYLE, GtkCairoStyleClass))
#define GTK_IS_CAIRO_STYLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_CAIRO_STYLE))
#define GTK_IS_CAIRO_STYLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_CAIRO_STYLE))
#define GTK_CAIRO_STYLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CAIRO_STYLE, GtkCairoStyleClass))
G_END_DECLS
#endif /* __GTK_CAIRO_STYLE_H__ */
#include <cairo.h>
#include <cairo-xlib.h>
#include <gdk/gdkx.h>
#include <gtk/gtk.h>
#include "gtkcairostyle.h"
static
void gtk_cairo_paint_slider (GtkCairoStyle *style,
cairo_t *cr,
GtkStateType state_type,
GtkShadowType shadow_type,
GdkRectangle *area,
GtkWidget *widget,
const gchar *detail,
gint x,
gint y,
gint width,
gint height,
GtkOrientation orientation)
{
g_debug("%p", style);
g_assert(GTK_IS_CAIRO_STYLE(style));
GTK_CAIRO_STYLE_GET_CLASS(style)->draw_slider(style, cr, state_type, shadow_type,
area, widget, detail,
x, y, width, height,
orientation);
}
gboolean expose (GtkWidget *widget, GdkEventExpose *expose, gpointer data)
{
if (GTK_IS_CAIRO_STYLE(widget->style))
{
cairo_t *cr;
g_debug("Painting with cairo style");
cr = gdk_cairo_create(widget->window);
gtk_cairo_paint_slider(GTK_CAIRO_STYLE(widget->style), cr,
GTK_WIDGET_STATE(widget),
GTK_SHADOW_NONE, &expose->area, NULL, "slider",
widget->allocation.x, widget->allocation.y,
widget->allocation.width, widget->allocation.height/2.0,
GTK_ORIENTATION_HORIZONTAL);
cairo_destroy(cr);
} else {
g_debug("Painting with normal style");
gtk_paint_slider(widget->style, widget->window, GTK_WIDGET_STATE(widget),
GTK_SHADOW_NONE, &expose->area, NULL, "slider",
widget->allocation.x, widget->allocation.y,
widget->allocation.width, widget->allocation.height/2.0,
GTK_ORIENTATION_HORIZONTAL);
}
g_debug("Painting with old call with whatever style is set");
gtk_paint_slider(widget->style, widget->window, GTK_WIDGET_STATE(widget),
GTK_SHADOW_NONE, &expose->area, NULL, "slider",
widget->allocation.x,
widget->allocation.y + widget->allocation.height/2.0,
widget->allocation.width, widget->allocation.height/2.0,
GTK_ORIENTATION_HORIZONTAL);
return TRUE;
}
GtkCairoStyle *style;
void switch_style(GtkWidget *button, GtkWidget *widget)
{
static gboolean cairo_style = FALSE;
if (!cairo_style)
{
gtk_widget_set_style(widget, GTK_STYLE(style));
cairo_style = TRUE;
} else {
gtk_widget_set_style(widget, NULL);
cairo_style = FALSE;
}
}
int main (int argc, char*argv[])
{
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *drawingarea;
GtkWidget *button;
gtk_init(&argc, &argv);
style = GTK_CAIRO_STYLE(g_object_new(GTK_TYPE_CAIRO_STYLE, NULL));
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
vbox = gtk_vbox_new(FALSE, 6);
drawingarea = gtk_drawing_area_new();
button = gtk_button_new_with_label("Switch!");
gtk_container_add (GTK_CONTAINER(vbox), drawingarea);
gtk_container_add (GTK_CONTAINER(vbox), button);
gtk_container_add (GTK_CONTAINER(window), vbox);
gtk_widget_set_size_request(drawingarea, 400, 80);
g_signal_connect(G_OBJECT(window), "delete-event",
G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(G_OBJECT(drawingarea), "expose-event",
G_CALLBACK(expose), NULL);
g_signal_connect(G_OBJECT(button), "clicked",
G_CALLBACK(switch_style), drawingarea);
gtk_widget_show_all(window);
gtk_widget_realize(drawingarea);
gtk_main();
return 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]