| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- /*
- * m2gtkshim.c - small C support library for the m2-GTK4 Modula-2 bindings.
- *
- * GNU Modula-2 cannot register GObject subclasses (no class_init /
- * vfunc overrides), which blocks widgets and paintables that need a
- * custom snapshot. This shim provides two such types whose snapshot
- * vfuncs hand a Cairo context to a Modula-2 callback, so the drawing
- * itself reuses the existing Cairo binding:
- *
- * M2GtkWidget - a GtkWidget subclass; the M2 callback is
- * void draw(GtkWidget *w, cairo_t *cr,
- * int width, int height, gpointer user);
- * M2Paintable - a GdkPaintable implementation; the M2 callback is
- * void draw(cairo_t *cr, int width, int height,
- * gpointer user);
- *
- * The M2 callback addresses and user data are supplied at construction;
- * an optional destroy notify frees the user data.
- */
- #include <gtk/gtk.h>
- /* ------------------------------------------------------------------ */
- /* M2GtkWidget */
- /* ------------------------------------------------------------------ */
- typedef void (*M2WidgetDrawFunc) (GtkWidget *widget, cairo_t *cr,
- int width, int height, gpointer user_data);
- typedef struct _M2GtkWidget M2GtkWidget;
- typedef struct _M2GtkWidgetClass M2GtkWidgetClass;
- struct _M2GtkWidget
- {
- GtkWidget parent_instance;
- M2WidgetDrawFunc draw;
- gpointer user_data;
- GDestroyNotify destroy;
- };
- struct _M2GtkWidgetClass
- {
- GtkWidgetClass parent_class;
- };
- G_DEFINE_TYPE (M2GtkWidget, m2_gtk_widget, GTK_TYPE_WIDGET)
- static void
- m2_gtk_widget_snapshot (GtkWidget *widget, GtkSnapshot *snapshot)
- {
- M2GtkWidget *self = (M2GtkWidget *) widget;
- int width = gtk_widget_get_width (widget);
- int height = gtk_widget_get_height (widget);
- if (self->draw == NULL || width <= 0 || height <= 0)
- return;
- graphene_rect_t bounds = GRAPHENE_RECT_INIT (0.f, 0.f, width, height);
- cairo_t *cr = gtk_snapshot_append_cairo (snapshot, &bounds);
- self->draw (widget, cr, width, height, self->user_data);
- cairo_destroy (cr);
- }
- static void
- m2_gtk_widget_finalize (GObject *object)
- {
- M2GtkWidget *self = (M2GtkWidget *) object;
- if (self->destroy != NULL)
- self->destroy (self->user_data);
- G_OBJECT_CLASS (m2_gtk_widget_parent_class)->finalize (object);
- }
- static void
- m2_gtk_widget_class_init (M2GtkWidgetClass *klass)
- {
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
- object_class->finalize = m2_gtk_widget_finalize;
- widget_class->snapshot = m2_gtk_widget_snapshot;
- }
- static void
- m2_gtk_widget_init (M2GtkWidget *self)
- {
- self->draw = NULL;
- self->user_data = NULL;
- self->destroy = NULL;
- }
- GtkWidget *
- m2_gtk_widget_new (M2WidgetDrawFunc draw, gpointer user_data,
- GDestroyNotify destroy)
- {
- M2GtkWidget *self = g_object_new (m2_gtk_widget_get_type (), NULL);
- self->draw = draw;
- self->user_data = user_data;
- self->destroy = destroy;
- return GTK_WIDGET (self);
- }
- /* ------------------------------------------------------------------ */
- /* M2Paintable (implements GdkPaintable) */
- /* ------------------------------------------------------------------ */
- typedef void (*M2PaintableDrawFunc) (cairo_t *cr, int width, int height,
- gpointer user_data);
- typedef struct _M2Paintable M2Paintable;
- typedef struct _M2PaintableClass M2PaintableClass;
- struct _M2Paintable
- {
- GObject parent_instance;
- M2PaintableDrawFunc draw;
- gpointer user_data;
- GDestroyNotify destroy;
- int width;
- int height;
- };
- struct _M2PaintableClass
- {
- GObjectClass parent_class;
- };
- static void
- m2_paintable_snapshot (GdkPaintable *paintable, GtkSnapshot *snapshot,
- double width, double height)
- {
- M2Paintable *self = (M2Paintable *) paintable;
- graphene_rect_t bounds = GRAPHENE_RECT_INIT (0.f, 0.f, (float) width,
- (float) height);
- cairo_t *cr = gtk_snapshot_append_cairo (snapshot, &bounds);
- if (self->draw != NULL)
- self->draw (cr, (int) width, (int) height, self->user_data);
- cairo_destroy (cr);
- }
- static int
- m2_paintable_get_intrinsic_width (GdkPaintable *paintable)
- {
- return ((M2Paintable *) paintable)->width;
- }
- static int
- m2_paintable_get_intrinsic_height (GdkPaintable *paintable)
- {
- return ((M2Paintable *) paintable)->height;
- }
- static double
- m2_paintable_get_intrinsic_aspect_ratio (GdkPaintable *paintable)
- {
- M2Paintable *self = (M2Paintable *) paintable;
- return self->height > 0 ? (double) self->width / (double) self->height : 0.0;
- }
- static void
- m2_paintable_paintable_init (GdkPaintableInterface *iface)
- {
- iface->snapshot = m2_paintable_snapshot;
- iface->get_intrinsic_width = m2_paintable_get_intrinsic_width;
- iface->get_intrinsic_height = m2_paintable_get_intrinsic_height;
- iface->get_intrinsic_aspect_ratio = m2_paintable_get_intrinsic_aspect_ratio;
- }
- G_DEFINE_TYPE_WITH_CODE (M2Paintable, m2_paintable, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
- m2_paintable_paintable_init))
- static void
- m2_paintable_finalize (GObject *object)
- {
- M2Paintable *self = (M2Paintable *) object;
- if (self->destroy != NULL)
- self->destroy (self->user_data);
- G_OBJECT_CLASS (m2_paintable_parent_class)->finalize (object);
- }
- static void
- m2_paintable_class_init (M2PaintableClass *klass)
- {
- G_OBJECT_CLASS (klass)->finalize = m2_paintable_finalize;
- }
- static void
- m2_paintable_init (M2Paintable *self)
- {
- self->draw = NULL;
- self->user_data = NULL;
- self->destroy = NULL;
- self->width = 0;
- self->height = 0;
- }
- GdkPaintable *
- m2_paintable_new (M2PaintableDrawFunc draw, int width, int height,
- gpointer user_data, GDestroyNotify destroy)
- {
- M2Paintable *self = g_object_new (m2_paintable_get_type (), NULL);
- self->draw = draw;
- self->width = width;
- self->height = height;
- self->user_data = user_data;
- self->destroy = destroy;
- return GDK_PAINTABLE (self);
- }
- /* ------------------------------------------------------------------ */
- /* M2ListModel (implements GListModel) */
- /* ------------------------------------------------------------------ */
- typedef guint (*M2ListModelGetNItemsFunc) (gpointer user_data);
- typedef gpointer (*M2ListModelGetItemFunc) (guint position,
- gpointer user_data);
- typedef struct _M2ListModel M2ListModel;
- typedef struct _M2ListModelClass M2ListModelClass;
- struct _M2ListModel
- {
- GObject parent_instance;
- M2ListModelGetNItemsFunc get_n_items;
- M2ListModelGetItemFunc get_item;
- gpointer user_data;
- GDestroyNotify destroy;
- GType item_type;
- };
- struct _M2ListModelClass
- {
- GObjectClass parent_class;
- };
- static guint
- m2_list_model_get_n_items (GListModel *list)
- {
- M2ListModel *self = (M2ListModel *) list;
- return self->get_n_items != NULL ? self->get_n_items (self->user_data) : 0;
- }
- static GType
- m2_list_model_get_item_type (GListModel *list)
- {
- return ((M2ListModel *) list)->item_type;
- }
- static gpointer
- m2_list_model_get_item (GListModel *list, guint position)
- {
- M2ListModel *self = (M2ListModel *) list;
- return self->get_item != NULL ? self->get_item (position, self->user_data)
- : NULL;
- }
- static void
- m2_list_model_list_init (GListModelInterface *iface)
- {
- iface->get_n_items = m2_list_model_get_n_items;
- iface->get_item_type = m2_list_model_get_item_type;
- iface->get_item = m2_list_model_get_item;
- }
- G_DEFINE_TYPE_WITH_CODE (M2ListModel, m2_list_model, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL,
- m2_list_model_list_init))
- static void
- m2_list_model_finalize (GObject *object)
- {
- M2ListModel *self = (M2ListModel *) object;
- if (self->destroy != NULL)
- self->destroy (self->user_data);
- G_OBJECT_CLASS (m2_list_model_parent_class)->finalize (object);
- }
- static void
- m2_list_model_class_init (M2ListModelClass *klass)
- {
- G_OBJECT_CLASS (klass)->finalize = m2_list_model_finalize;
- }
- static void
- m2_list_model_init (M2ListModel *self)
- {
- self->get_n_items = NULL;
- self->get_item = NULL;
- self->user_data = NULL;
- self->destroy = NULL;
- self->item_type = G_TYPE_OBJECT;
- }
- GListModel *
- m2_list_model_new (M2ListModelGetNItemsFunc get_n_items,
- M2ListModelGetItemFunc get_item, GType item_type,
- gpointer user_data, GDestroyNotify destroy)
- {
- M2ListModel *self = g_object_new (m2_list_model_get_type (), NULL);
- self->get_n_items = get_n_items;
- self->get_item = get_item;
- self->item_type = item_type;
- self->user_data = user_data;
- self->destroy = destroy;
- return G_LIST_MODEL (self);
- }
- void
- m2_list_model_items_changed (GListModel *model, guint position,
- guint removed, guint added)
- {
- g_list_model_items_changed (model, position, removed, added);
- }
|