Re: RFC: Re-Design GtkStyle to only pass cairo-context?



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]