add cairo-based widgets for wl_surface (WIP)
This commit is contained in:
parent
f8deb67a5a
commit
eba7d34476
@ -57,6 +57,8 @@ src = [
|
|||||||
'src/foreign.c',
|
'src/foreign.c',
|
||||||
'src/session.c',
|
'src/session.c',
|
||||||
'src/widgets/cairo-widget.c',
|
'src/widgets/cairo-widget.c',
|
||||||
|
'src/widgets/cairo-box.c',
|
||||||
|
'src/widgets/cairo-window.c',
|
||||||
'src/main.c',
|
'src/main.c',
|
||||||
wayland_targets]
|
wayland_targets]
|
||||||
|
|
||||||
|
11
src/base.h
11
src/base.h
@ -3,14 +3,6 @@
|
|||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
gint x;
|
|
||||||
gint y;
|
|
||||||
gint width;
|
|
||||||
gint height;
|
|
||||||
} diya_rect_t;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class object
|
* Base class object
|
||||||
*
|
*
|
||||||
@ -23,9 +15,8 @@ struct _DiyaObjectClass
|
|||||||
GObjectClass parent_class;
|
GObjectClass parent_class;
|
||||||
const gchar *(*to_string)(DiyaObject *self);
|
const gchar *(*to_string)(DiyaObject *self);
|
||||||
/**
|
/**
|
||||||
* @brief reserve for futur use to
|
* @brief reserve for future use to
|
||||||
* define common API for descendants
|
* define common API for descendants
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include "session.h"
|
#include "session.h"
|
||||||
#include "wayland.h"
|
#include "wayland.h"
|
||||||
|
#include "widgets/cairo-window.h"
|
||||||
|
|
||||||
#define DEF_SURF_W 600
|
#define DEF_SURF_W 600
|
||||||
#define DEF_SURF_H 400
|
#define DEF_SURF_H 400
|
||||||
@ -30,6 +31,8 @@ struct _DiyaLockSession
|
|||||||
guint32 raw_shared_buffer_size;
|
guint32 raw_shared_buffer_size;
|
||||||
cairo_surface_t *cairo_surface;
|
cairo_surface_t *cairo_surface;
|
||||||
|
|
||||||
|
DiyaCairoWindow * window;
|
||||||
|
|
||||||
guint surface_width;
|
guint surface_width;
|
||||||
guint surface_height;
|
guint surface_height;
|
||||||
|
|
||||||
@ -59,6 +62,11 @@ static void diya_lock_session_dispose(GObject *object)
|
|||||||
cairo_surface_destroy(self->cairo_surface);
|
cairo_surface_destroy(self->cairo_surface);
|
||||||
self->cairo_surface = NULL;
|
self->cairo_surface = NULL;
|
||||||
}
|
}
|
||||||
|
if(self->window)
|
||||||
|
{
|
||||||
|
g_object_unref(self->window);
|
||||||
|
self->window = NULL;
|
||||||
|
}
|
||||||
G_OBJECT_CLASS(diya_lock_session_parent_class)->dispose(object);
|
G_OBJECT_CLASS(diya_lock_session_parent_class)->dispose(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,9 +103,7 @@ static void handle_session_lock_finished(void *data, struct ext_session_lock_v1
|
|||||||
}
|
}
|
||||||
static void randname(char *buf)
|
static void randname(char *buf)
|
||||||
{
|
{
|
||||||
struct timespec ts;
|
long r = g_get_real_time() / 1000000;
|
||||||
clock_gettime(CLOCK_REALTIME, &ts);
|
|
||||||
long r = ts.tv_nsec;
|
|
||||||
for (int i = 0; i < 6; ++i)
|
for (int i = 0; i < 6; ++i)
|
||||||
{
|
{
|
||||||
buf[i] = 'A' + (r & 15) + (r & 16) * 2;
|
buf[i] = 'A' + (r & 15) + (r & 16) * 2;
|
||||||
@ -122,7 +128,7 @@ static int create_shm_file(void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int allocate_shm_file(size_t size)
|
static int allocate_shm_file(guint size)
|
||||||
{
|
{
|
||||||
int fd = create_shm_file();
|
int fd = create_shm_file();
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
@ -176,7 +182,7 @@ static void session_lock_realloc_surface(DiyaLockSession *self)
|
|||||||
self->cairo_surface = NULL;
|
self->cairo_surface = NULL;
|
||||||
}
|
}
|
||||||
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, self->surface_width);
|
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, self->surface_width);
|
||||||
int size = stride * self->surface_height;
|
guint size = stride * self->surface_height;
|
||||||
|
|
||||||
int fd = allocate_shm_file(size);
|
int fd = allocate_shm_file(size);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
@ -214,32 +220,7 @@ static void lock_session_draw_frame(DiyaLockSession *self)
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cairo_t *cr = cairo_create(self->cairo_surface);
|
diya_cairo_window_render(self->window, self->cairo_surface);
|
||||||
// Start of example
|
|
||||||
double xc = 128.0;
|
|
||||||
double yc = 128.0;
|
|
||||||
double radius = 100.0;
|
|
||||||
double angle1 = (double)(self->last_frame_time % 180) * (M_PI / 180.0); /* angles are specified */
|
|
||||||
double angle2 = 180.0 * (M_PI / 180.0); /* in radians */
|
|
||||||
|
|
||||||
cairo_set_line_width(cr, 10.0);
|
|
||||||
cairo_arc(cr, xc, yc, radius, angle1, angle2);
|
|
||||||
cairo_stroke(cr);
|
|
||||||
|
|
||||||
/* draw helping lines */
|
|
||||||
cairo_set_source_rgba(cr, 1, 0.2, 0.2, 0.6);
|
|
||||||
cairo_set_line_width(cr, 6.0);
|
|
||||||
|
|
||||||
cairo_arc(cr, xc, yc, 10.0, 0, 2 * M_PI);
|
|
||||||
cairo_fill(cr);
|
|
||||||
|
|
||||||
cairo_arc(cr, xc, yc, radius, angle1, angle1);
|
|
||||||
cairo_line_to(cr, xc, yc);
|
|
||||||
cairo_arc(cr, xc, yc, radius, angle2, angle2);
|
|
||||||
cairo_line_to(cr, xc, yc);
|
|
||||||
cairo_stroke(cr);
|
|
||||||
// End of example
|
|
||||||
cairo_destroy(cr);
|
|
||||||
|
|
||||||
wl_surface_attach(self->wl_surface, self->wl_buffer, 0, 0);
|
wl_surface_attach(self->wl_surface, self->wl_buffer, 0, 0);
|
||||||
wl_surface_damage_buffer(self->wl_surface, 0, 0, self->surface_width, self->surface_height);
|
wl_surface_damage_buffer(self->wl_surface, 0, 0, self->surface_width, self->surface_height);
|
||||||
@ -257,6 +238,8 @@ static void lock_surface_configure(void *data,
|
|||||||
self->surface_width = width;
|
self->surface_width = width;
|
||||||
self->surface_height = height;
|
self->surface_height = height;
|
||||||
session_lock_realloc_surface(self);
|
session_lock_realloc_surface(self);
|
||||||
|
diya_cairo_widget_set_size(self->window, width, height);
|
||||||
|
diya_cairo_window_update(self->window);
|
||||||
}
|
}
|
||||||
ext_session_lock_surface_v1_ack_configure(lock_surface, serial);
|
ext_session_lock_surface_v1_ack_configure(lock_surface, serial);
|
||||||
|
|
||||||
@ -273,7 +256,7 @@ static void lock_surface_frame_done(void *data, struct wl_callback *cb, uint32_t
|
|||||||
cb = wl_surface_frame(lock->wl_surface);
|
cb = wl_surface_frame(lock->wl_surface);
|
||||||
wl_callback_add_listener(cb, &lock->frame_listener, data);
|
wl_callback_add_listener(cb, &lock->frame_listener, data);
|
||||||
|
|
||||||
if (!lock->cairo_surface || !lock->wl_buffer)
|
if (!lock->cairo_surface || !lock->wl_buffer || lock->window)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -299,6 +282,7 @@ static void diya_lock_session_init(DiyaLockSession *self)
|
|||||||
|
|
||||||
self->wl_surface = NULL;
|
self->wl_surface = NULL;
|
||||||
self->wl_buffer = NULL;
|
self->wl_buffer = NULL;
|
||||||
|
self->window = g_object_new(DIYA_TYPE_CAIRO_WINDOW,NULL);
|
||||||
|
|
||||||
self->cairo_surface = NULL;
|
self->cairo_surface = NULL;
|
||||||
self->raw_shared_buffer = NULL;
|
self->raw_shared_buffer = NULL;
|
||||||
|
67
src/widgets/cairo-box.c
Normal file
67
src/widgets/cairo-box.c
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#include "cairo-box.h"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
NO_PROP,
|
||||||
|
BOX_MODE,
|
||||||
|
N_PROPERTIES
|
||||||
|
};
|
||||||
|
static GParamSpec *g_prop[N_PROPERTIES] = {0};
|
||||||
|
|
||||||
|
struct _DiyaCairoBox
|
||||||
|
{
|
||||||
|
DiyaCairoContainer parent_object;
|
||||||
|
guint mode;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_FINAL_TYPE(DiyaCairoBox, diya_cairo_box, DIYA_TYPE_CAIRO_CONTAINER)
|
||||||
|
|
||||||
|
static void diya_cairo_box_dispose(GObject * object)
|
||||||
|
{
|
||||||
|
g_debug("diya_cairo_box_dispose: %s", diya_object_to_string(object));
|
||||||
|
G_OBJECT_CLASS(diya_cairo_box_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_cairo_box_init(DiyaCairoBox* self)
|
||||||
|
{
|
||||||
|
self->mode = DIYA_CAIRO_HORIZONTAL_BOX;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_cairo_box_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
DiyaCairoBox * self = DIYA_CAIRO_BOX(object);
|
||||||
|
switch (property_id)
|
||||||
|
{
|
||||||
|
case BOX_MODE:
|
||||||
|
self->mode = g_value_get_uint(value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_cairo_box_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
DiyaCairoBox * self = DIYA_CAIRO_BOX(object);
|
||||||
|
switch (property_id)
|
||||||
|
{
|
||||||
|
case BOX_MODE:
|
||||||
|
g_value_set_uint(value, self->mode);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_cairo_box_class_init(DiyaCairoBoxClass * class)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||||
|
DIYA_CAIRO_WIDGET_SET_NAME(class, "DiyaCairoBox");
|
||||||
|
gobject_class->dispose = diya_cairo_box_dispose;
|
||||||
|
gobject_class->set_property = diya_cairo_box_set_property;
|
||||||
|
gobject_class->get_property = diya_cairo_box_get_property;
|
||||||
|
g_prop[BOX_MODE] = g_param_spec_pointer("mode", NULL, "Box mode", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||||
|
g_object_class_install_properties (gobject_class, N_PROPERTIES, g_prop);
|
||||||
|
}
|
14
src/widgets/cairo-box.h
Normal file
14
src/widgets/cairo-box.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef CAIRO_BOX_H
|
||||||
|
#define CAIRO_BOX_H
|
||||||
|
|
||||||
|
#include "cairo-widget.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
DIYA_CAIRO_HORIZONTAL_BOX,
|
||||||
|
DIYA_CAIRO_VERTICAL_BOX
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DIYA_TYPE_CAIRO_BOX (diya_cairo_box_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (DiyaCairoBox, diya_cairo_box, DIYA, CAIRO_BOX, DiyaCairoContainer)
|
||||||
|
|
||||||
|
#endif
|
@ -1,13 +1,55 @@
|
|||||||
#include <cairo/cairo.h>
|
#include <cairo/cairo.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <limits.h>
|
||||||
#include "cairo-widget.h"
|
#include "cairo-widget.h"
|
||||||
|
/*
|
||||||
|
#include <cairo.h>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 150, 50);
|
||||||
|
cairo_t *cr = cairo_create(s);
|
||||||
|
|
||||||
|
cairo_set_source_rgb(cr, 1, 0, 0);
|
||||||
|
cairo_paint(cr);
|
||||||
|
|
||||||
|
cairo_rectangle(cr, 0, 0, 100, 100);
|
||||||
|
cairo_clip(cr);
|
||||||
|
cairo_move_to(cr, 50, 25);
|
||||||
|
cairo_set_source_rgb(cr, 0, 0, 0);
|
||||||
|
cairo_show_text(cr, "pretend that this string is > 100px wide");
|
||||||
|
|
||||||
|
cairo_destroy(cr);
|
||||||
|
cairo_surface_write_to_png(s, "out.png");
|
||||||
|
cairo_surface_destroy(s);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*/
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
CW_NO_PROP,
|
CW_NO_PROP,
|
||||||
|
CW_EXTENT_DEF,
|
||||||
CW_EXTENT,
|
CW_EXTENT,
|
||||||
CW_PARENT,
|
CW_PARENT,
|
||||||
|
CW_VISIBILITY,
|
||||||
|
CW_HALIGN,
|
||||||
|
CW_VALIGN,
|
||||||
|
CW_HSPACE,
|
||||||
|
CW_VSPACE,
|
||||||
|
CW_PADDING,
|
||||||
|
CW_PADDING_LEFT,
|
||||||
|
CW_PADDING_TOP,
|
||||||
|
CW_PADDING_BOTTOM,
|
||||||
|
CW_PADDING_RIGHT,
|
||||||
|
CW_MARGIN_LEFT,
|
||||||
|
CW_MARGIN_RIGHT,
|
||||||
|
CW_MARGIN_TOP,
|
||||||
|
CW_MARGIN_BOTTOM,
|
||||||
|
CW_MARGIN,
|
||||||
|
CW_FILL,
|
||||||
|
CW_STROKE,
|
||||||
CW_N_PROPERTIES
|
CW_N_PROPERTIES
|
||||||
};
|
};
|
||||||
static GParamSpec *g_cw_prop[CW_N_PROPERTIES] = {0};
|
static GParamSpec *g_cw_prop[CW_N_PROPERTIES] = {0};
|
||||||
@ -16,9 +58,25 @@ typedef struct _DiyaCairoWidgetPrivate
|
|||||||
{
|
{
|
||||||
DiyaObject * parent_object;
|
DiyaObject * parent_object;
|
||||||
diya_rect_t extent;
|
diya_rect_t extent;
|
||||||
|
diya_rect_t default_extent;
|
||||||
DiyaCairoWidget * parent_widget;
|
DiyaCairoWidget * parent_widget;
|
||||||
// TODO list of children
|
|
||||||
gchar string[64];
|
gchar string[64];
|
||||||
|
|
||||||
|
guint16 visibility;
|
||||||
|
guint16 halign;
|
||||||
|
guint16 valign;
|
||||||
|
guint16 hspace;
|
||||||
|
guint16 vspace;
|
||||||
|
|
||||||
|
diya_offset_t margin;
|
||||||
|
diya_offset_t padding;
|
||||||
|
|
||||||
|
diya_color_t fill;
|
||||||
|
|
||||||
|
diya_stroke_t stroke;
|
||||||
|
|
||||||
|
gboolean damaged;
|
||||||
} DiyaCairoWidgetPrivate;
|
} DiyaCairoWidgetPrivate;
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_PRIVATE(DiyaCairoWidget, diya_cairo_widget, DIYA_TYPE_OBJECT);
|
G_DEFINE_TYPE_WITH_PRIVATE(DiyaCairoWidget, diya_cairo_widget, DIYA_TYPE_OBJECT);
|
||||||
@ -26,7 +84,7 @@ G_DEFINE_TYPE_WITH_PRIVATE(DiyaCairoWidget, diya_cairo_widget, DIYA_TYPE_OBJECT)
|
|||||||
|
|
||||||
static void diya_cairo_widget_dispose(GObject* object)
|
static void diya_cairo_widget_dispose(GObject* object)
|
||||||
{
|
{
|
||||||
g_debug("diya_cairo_widget_dispose");
|
g_debug("diya_cairo_widget_dispose: %s", diya_object_to_string(object));
|
||||||
G_OBJECT_CLASS(diya_cairo_widget_parent_class)->dispose(object);
|
G_OBJECT_CLASS(diya_cairo_widget_parent_class)->dispose(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,16 +92,78 @@ static void diya_cairo_widget_set_property(GObject *object, guint property_id, c
|
|||||||
{
|
{
|
||||||
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
|
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
|
||||||
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
||||||
diya_rect_t * rect;
|
gpointer ptr;
|
||||||
switch (property_id)
|
switch (property_id)
|
||||||
{
|
{
|
||||||
case CW_PARENT:
|
case CW_PARENT:
|
||||||
priv->parent_widget = g_value_get_pointer(value);
|
priv->parent_widget = g_value_get_pointer(value);
|
||||||
|
assert(DIYA_IS_CAIRO_WIDGET(priv->parent_widget));
|
||||||
|
break;
|
||||||
|
case CW_EXTENT_DEF:
|
||||||
|
ptr = g_value_get_pointer(value);
|
||||||
|
assert(ptr);
|
||||||
|
priv->default_extent = *(diya_rect_t*)ptr;
|
||||||
break;
|
break;
|
||||||
case CW_EXTENT:
|
case CW_EXTENT:
|
||||||
rect = g_value_get_pointer(value);
|
break;
|
||||||
assert(rect);
|
case CW_VISIBILITY:
|
||||||
memcpy(&priv->extent,rect, sizeof(priv->extent));
|
priv->visibility = (guint16) g_value_get_uint(value);
|
||||||
|
break;
|
||||||
|
case CW_HALIGN:
|
||||||
|
priv->halign = (guint16)g_value_get_uint(value);
|
||||||
|
break;
|
||||||
|
case CW_VALIGN:
|
||||||
|
priv->valign = (guint16)g_value_get_uint(value);
|
||||||
|
break;
|
||||||
|
case CW_HSPACE:
|
||||||
|
priv->hspace = (guint16)g_value_get_uint(value);
|
||||||
|
break;
|
||||||
|
case CW_VSPACE:
|
||||||
|
priv->vspace = (guint16)g_value_get_uint(value);
|
||||||
|
break;
|
||||||
|
case CW_PADDING:
|
||||||
|
ptr = g_value_get_pointer(value);
|
||||||
|
assert(ptr);
|
||||||
|
priv->padding = *(diya_offset_t*)ptr;
|
||||||
|
break;
|
||||||
|
case CW_PADDING_LEFT:
|
||||||
|
priv->padding.left = g_value_get_int(value);
|
||||||
|
break;
|
||||||
|
case CW_PADDING_RIGHT:
|
||||||
|
priv->padding.right = g_value_get_int(value);
|
||||||
|
break;
|
||||||
|
case CW_PADDING_BOTTOM:
|
||||||
|
priv->padding.bottom = g_value_get_int(value);
|
||||||
|
break;
|
||||||
|
case CW_PADDING_TOP:
|
||||||
|
priv->padding.top = g_value_get_int(value);
|
||||||
|
break;
|
||||||
|
case CW_MARGIN:
|
||||||
|
ptr = g_value_get_pointer(value);
|
||||||
|
assert(ptr);
|
||||||
|
priv->margin = *(diya_offset_t*)ptr;
|
||||||
|
break;
|
||||||
|
case CW_MARGIN_LEFT:
|
||||||
|
priv->margin.left = g_value_get_int(value);
|
||||||
|
break;
|
||||||
|
case CW_MARGIN_RIGHT:
|
||||||
|
priv->margin.right = g_value_get_int(value);
|
||||||
|
break;
|
||||||
|
case CW_MARGIN_BOTTOM:
|
||||||
|
priv->margin.bottom = g_value_get_int(value);
|
||||||
|
break;
|
||||||
|
case CW_MARGIN_TOP:
|
||||||
|
priv->margin.top = g_value_get_int(value);
|
||||||
|
break;
|
||||||
|
case CW_FILL:
|
||||||
|
ptr = g_value_get_pointer(value);
|
||||||
|
assert(ptr);
|
||||||
|
priv->fill = *(diya_color_t*)ptr;
|
||||||
|
break;
|
||||||
|
case CW_STROKE:
|
||||||
|
ptr = g_value_get_pointer(value);
|
||||||
|
assert(ptr);
|
||||||
|
priv->stroke = *(diya_stroke_t*) ptr;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
@ -60,22 +180,66 @@ static void diya_cairo_widget_get_property(GObject *object, guint property_id, G
|
|||||||
case CW_PARENT:
|
case CW_PARENT:
|
||||||
g_value_set_pointer(value, priv->parent_widget);
|
g_value_set_pointer(value, priv->parent_widget);
|
||||||
break;
|
break;
|
||||||
|
case CW_EXTENT_DEF:
|
||||||
|
g_value_set_pointer(value, &priv->default_extent);
|
||||||
|
break;
|
||||||
case CW_EXTENT:
|
case CW_EXTENT:
|
||||||
g_value_set_pointer(value, &priv->extent);
|
g_value_set_pointer(value, &priv->extent);
|
||||||
break;
|
break;
|
||||||
|
case CW_VISIBILITY:
|
||||||
|
g_value_set_uint(value, priv->visibility);
|
||||||
|
break;
|
||||||
|
case CW_HALIGN:
|
||||||
|
g_value_set_uint(value, priv->halign);
|
||||||
|
break;
|
||||||
|
case CW_VALIGN:
|
||||||
|
g_value_set_uint(value, priv->valign);
|
||||||
|
break;
|
||||||
|
case CW_HSPACE:
|
||||||
|
g_value_set_uint(value, priv->hspace);
|
||||||
|
break;
|
||||||
|
case CW_VSPACE:
|
||||||
|
g_value_set_uint(value, priv->vspace);
|
||||||
|
break;
|
||||||
|
case CW_PADDING:
|
||||||
|
g_value_set_pointer(value, &priv->padding);
|
||||||
|
break;
|
||||||
|
case CW_MARGIN:
|
||||||
|
g_value_set_pointer(value, &priv->margin);
|
||||||
|
break;
|
||||||
|
case CW_FILL:
|
||||||
|
g_value_set_pointer(value, &priv->fill);
|
||||||
|
break;
|
||||||
|
case CW_STROKE:
|
||||||
|
g_value_set_pointer(value, &priv->stroke);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void diya_cairo_widget_init(DiyaCairoWidget *self)
|
static void diya_cairo_widget_init(DiyaCairoWidget *self)
|
||||||
{
|
{
|
||||||
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
||||||
memset(&priv->extent,0,sizeof(priv->extent));
|
memset(&priv->extent,0,sizeof(priv->extent));
|
||||||
|
memset(&priv->extent,0,sizeof(priv->default_extent));
|
||||||
priv->parent_widget = NULL;
|
priv->parent_widget = NULL;
|
||||||
priv->string[0] = '\0';
|
priv->string[0] = '\0';
|
||||||
|
|
||||||
|
priv->visibility = DIYA_CAIRO_WIDGET_VISIBLE_ON;
|
||||||
|
|
||||||
|
priv->hspace = DIYA_CAIRO_WIDGET_FILL_EXTEND;
|
||||||
|
priv->vspace = DIYA_CAIRO_WIDGET_FILL_EXTEND;
|
||||||
|
|
||||||
|
priv->halign = DIYA_CAIRO_WIDGET_ALIGN_MIDDLE;
|
||||||
|
priv->valign = DIYA_CAIRO_WIDGET_ALIGN_MIDDLE;
|
||||||
|
|
||||||
|
memset(&priv->padding,0,sizeof(priv->padding));
|
||||||
|
memset(&priv->margin,0,sizeof(priv->margin));
|
||||||
|
memset(&priv->fill, 0, sizeof(priv->fill));
|
||||||
|
|
||||||
|
priv->damaged = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const gchar *diya_cairo_widget_to_string(DiyaObject *object)
|
static const gchar *diya_cairo_widget_to_string(DiyaObject *object)
|
||||||
@ -93,18 +257,519 @@ static const gchar *diya_cairo_widget_to_string(DiyaObject *object)
|
|||||||
return priv->string;
|
return priv->string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static diya_rect_t diya_cairo_widget_get_view_port(gpointer object)
|
||||||
|
{
|
||||||
|
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
|
||||||
|
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
||||||
|
|
||||||
|
diya_point_t gpos = diya_cairo_widget_get_global_position(object);
|
||||||
|
diya_rect_t view = {gpos.x, gpos.y, priv->extent.width, priv->extent.height};
|
||||||
|
if(priv->parent_widget)
|
||||||
|
{
|
||||||
|
diya_rect_t parent_view = diya_cairo_widget_get_view_port(priv->parent_widget);
|
||||||
|
|
||||||
|
if(!diya_rect_overlap(&view, &parent_view))
|
||||||
|
{
|
||||||
|
view.x = view.y = view.width = view.height = 0;
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
view.width = MIN(view.x + view.width, parent_view.x + parent_view.width);
|
||||||
|
view.height = MIN(view.y + view.height, parent_view.y + parent_view.height);
|
||||||
|
|
||||||
|
view.x = MAX(view.x, parent_view.x);
|
||||||
|
view.y = MAX(view.y, parent_view.y);
|
||||||
|
|
||||||
|
view.width -= view.x;
|
||||||
|
view.height -= view.y;
|
||||||
|
|
||||||
|
}
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_cairo_widget_draw(gpointer object, cairo_t* context)
|
||||||
|
{
|
||||||
|
(void) context;
|
||||||
|
|
||||||
|
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
|
||||||
|
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
||||||
|
|
||||||
|
if(!priv->damaged)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(priv->visibility != DIYA_CAIRO_WIDGET_VISIBLE_ON)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
diya_rect_t view_port = diya_cairo_widget_get_view_port(object);
|
||||||
|
if(diya_rect_is_empty(&view_port))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cairo_save(context);
|
||||||
|
cairo_rectangle(context, view_port.x, view_port.y, view_port.width, view_port.height);
|
||||||
|
cairo_clip(context);
|
||||||
|
diya_point_t gpos = diya_cairo_widget_get_global_position(object);
|
||||||
|
cairo_move_to(context, (double)gpos.x, (double)gpos.y);
|
||||||
|
if(priv->fill.a > 0)
|
||||||
|
{
|
||||||
|
cairo_set_source_rgba(context, priv->fill.r, priv->fill.g, priv->fill.b, priv->fill.a);
|
||||||
|
cairo_fill(context);
|
||||||
|
}
|
||||||
|
if(priv->stroke.size > 0 && priv->stroke.color.a != 0)
|
||||||
|
{
|
||||||
|
cairo_set_line_width(context,priv->stroke.size);
|
||||||
|
cairo_stroke(context);
|
||||||
|
}
|
||||||
|
cairo_restore(context);
|
||||||
|
priv->damaged = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_cairo_widget_content_size(gpointer object, guint* width, guint* height)
|
||||||
|
{
|
||||||
|
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
|
||||||
|
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
||||||
|
*width = priv->extent.width;
|
||||||
|
*height = priv->extent.height;
|
||||||
|
// take into account margin
|
||||||
|
}
|
||||||
|
static void diya_cairo_widget_resize(gpointer object)
|
||||||
|
{
|
||||||
|
// calculate effective size
|
||||||
|
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
|
||||||
|
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
||||||
|
if(priv->visibility == DIYA_CAIRO_WIDGET_VISIBLE_HIDDEN)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Item is hidden, set extent to empty
|
||||||
|
*/
|
||||||
|
if(!diya_rect_is_empty(&priv->extent))
|
||||||
|
{
|
||||||
|
priv->damaged = TRUE;
|
||||||
|
}
|
||||||
|
priv->extent.width = 0;
|
||||||
|
priv->extent.height = 0;
|
||||||
|
priv->extent.x = 0;
|
||||||
|
priv->extent.y = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
diya_rect_t space = {
|
||||||
|
priv->margin.left,
|
||||||
|
priv->margin.top,
|
||||||
|
priv->extent.width - priv->margin.left - priv->margin.right,
|
||||||
|
priv->extent.height - priv->margin.top - priv->margin.bottom};
|
||||||
|
if(priv->parent_widget)
|
||||||
|
{
|
||||||
|
space = DIYA_CAIRO_WIDGET_GET_CLASS(self)->alloc_space(priv->parent_object, object);
|
||||||
|
}
|
||||||
|
guint width,height,cwidth = 0,cheight = 0;
|
||||||
|
if(priv->hspace == DIYA_CAIRO_WIDGET_FILL_CONTENT ||
|
||||||
|
priv->vspace == DIYA_CAIRO_WIDGET_FILL_CONTENT)
|
||||||
|
{
|
||||||
|
DIYA_CAIRO_WIDGET_GET_CLASS(self)->content_size(object, &cwidth, &cheight);
|
||||||
|
}
|
||||||
|
switch(priv->hspace)
|
||||||
|
{
|
||||||
|
case DIYA_CAIRO_WIDGET_FILL_NONE:
|
||||||
|
width = priv->default_extent.width;
|
||||||
|
break;
|
||||||
|
case DIYA_CAIRO_WIDGET_FILL_EXTEND:
|
||||||
|
width = space.width;
|
||||||
|
break;
|
||||||
|
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
|
||||||
|
width = cwidth;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
width = priv->extent.width;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(priv->vspace)
|
||||||
|
{
|
||||||
|
case DIYA_CAIRO_WIDGET_FILL_NONE:
|
||||||
|
height = priv->default_extent.height;
|
||||||
|
break;
|
||||||
|
case DIYA_CAIRO_WIDGET_FILL_EXTEND:
|
||||||
|
height = space.height;
|
||||||
|
break;
|
||||||
|
case DIYA_CAIRO_WIDGET_FILL_CONTENT:
|
||||||
|
height = cheight;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
height = priv->extent.height;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(width != priv->extent.width || height != priv->extent.height)
|
||||||
|
{
|
||||||
|
priv->damaged = TRUE;
|
||||||
|
}
|
||||||
|
priv->extent.width = width;
|
||||||
|
priv->extent.height = height;
|
||||||
|
/*if(space.x != priv->extent.x || space.y != priv->extent.y)
|
||||||
|
{
|
||||||
|
priv->damaged = TRUE;
|
||||||
|
}*/
|
||||||
|
priv->extent.x = space.x;
|
||||||
|
priv->extent.y = space.y;
|
||||||
|
}
|
||||||
|
static void diya_cairo_widget_align(gpointer object)
|
||||||
|
{
|
||||||
|
guint cwidth, cheight;
|
||||||
|
// calculate widget position
|
||||||
|
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
|
||||||
|
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
||||||
|
DIYA_CAIRO_WIDGET_GET_CLASS(self)->content_size(object, &cwidth, &cheight);
|
||||||
|
if(diya_rect_is_empty(&priv->extent))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int x = priv->extent.x, y = priv->extent.y;
|
||||||
|
switch(priv->halign)
|
||||||
|
{
|
||||||
|
case DIYA_CAIRO_WIDGET_ALIGN_MIDDLE:
|
||||||
|
x += (priv->extent.width - cwidth ) / 2;
|
||||||
|
break;
|
||||||
|
case DIYA_CAIRO_WIDGET_ALIGN_END:
|
||||||
|
x += priv->extent.width - cwidth;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(priv->valign)
|
||||||
|
{
|
||||||
|
case DIYA_CAIRO_WIDGET_ALIGN_MIDDLE:
|
||||||
|
y += (priv->extent.height - cheight ) / 2;
|
||||||
|
break;
|
||||||
|
case DIYA_CAIRO_WIDGET_ALIGN_END:
|
||||||
|
y += priv->extent.height - cheight;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(x != priv->extent.x || y != priv->extent.y)
|
||||||
|
{
|
||||||
|
priv->damaged = TRUE;
|
||||||
|
}
|
||||||
|
priv->extent.x = x;
|
||||||
|
priv->extent.y = y;
|
||||||
|
}
|
||||||
|
static void diya_cairo_widget_update(gpointer object)
|
||||||
|
{
|
||||||
|
|
||||||
|
DIYA_CAIRO_WIDGET_GET_CLASS(DIYA_CAIRO_WIDGET(object))->resize(object);
|
||||||
|
DIYA_CAIRO_WIDGET_GET_CLASS(DIYA_CAIRO_WIDGET(object))->align(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static diya_rect_t diya_cairo_widget_alloc_space(gpointer object, gpointer child)
|
||||||
|
{
|
||||||
|
assert(object);
|
||||||
|
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
|
||||||
|
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
||||||
|
diya_rect_t space = {0,0,priv->extent.width, priv->extent.height};
|
||||||
|
diya_offset_t * margin = NULL;
|
||||||
|
g_object_get(child,"margin", &margin, NULL);
|
||||||
|
|
||||||
|
space.x += priv->padding.left + margin->left;
|
||||||
|
space.y += priv->padding.top + margin->top;
|
||||||
|
space.width -= (priv->padding.right + priv->padding.left + margin->right + margin->left);
|
||||||
|
space.height -= (priv->padding.bottom + priv->padding.top + margin->bottom + margin->top);
|
||||||
|
|
||||||
|
return space;
|
||||||
|
}
|
||||||
|
|
||||||
static void diya_cairo_widget_class_init(DiyaCairoWidgetClass *class)
|
static void diya_cairo_widget_class_init(DiyaCairoWidgetClass *class)
|
||||||
{
|
{
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||||
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
|
DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
|
||||||
DIYA_CAIRO_WIDGET_SET_NAME(class, "");
|
DIYA_CAIRO_WIDGET_SET_NAME(class, "DiyaCairoWidget");
|
||||||
gobject_class->dispose = diya_cairo_widget_dispose;
|
gobject_class->dispose = diya_cairo_widget_dispose;
|
||||||
gobject_class->set_property = diya_cairo_widget_set_property;
|
gobject_class->set_property = diya_cairo_widget_set_property;
|
||||||
gobject_class->get_property = diya_cairo_widget_get_property;
|
gobject_class->get_property = diya_cairo_widget_get_property;
|
||||||
g_cw_prop[CW_EXTENT] = g_param_spec_pointer("extent", NULL, "Widget extent relative to its parent", G_PARAM_READWRITE); //
|
class->draw = diya_cairo_widget_draw;
|
||||||
|
class->update = diya_cairo_widget_update;
|
||||||
|
class->alloc_space = diya_cairo_widget_alloc_space;
|
||||||
|
class->resize = diya_cairo_widget_resize;
|
||||||
|
class->align = diya_cairo_widget_align;
|
||||||
|
class->content_size = diya_cairo_widget_content_size;
|
||||||
|
|
||||||
|
g_cw_prop[CW_EXTENT_DEF] = g_param_spec_pointer("default-extent", NULL, "Widget actual extent relative to its parent", G_PARAM_READWRITE); //
|
||||||
|
g_cw_prop[CW_EXTENT] = g_param_spec_pointer("extent", NULL, "Widget default extent", G_PARAM_READABLE);
|
||||||
g_cw_prop[CW_PARENT] = g_param_spec_pointer("parent", NULL, "Parent widget", G_PARAM_READWRITE); //
|
g_cw_prop[CW_PARENT] = g_param_spec_pointer("parent", NULL, "Parent widget", G_PARAM_READWRITE); //
|
||||||
|
g_cw_prop[CW_FILL] = g_param_spec_pointer("fill", NULL, "Fill color", G_PARAM_READWRITE);
|
||||||
|
g_cw_prop[CW_STROKE] = g_param_spec_pointer("stroke", NULL, "Border size and color", G_PARAM_READWRITE);
|
||||||
|
g_cw_prop[CW_VISIBILITY] = g_param_spec_uint(
|
||||||
|
"visibility", NULL, "Widget visibility",
|
||||||
|
DIYA_CAIRO_WIDGET_VISIBLE_ON,
|
||||||
|
DIYA_CAIRO_WIDGET_VISIBLE_MAX,
|
||||||
|
DIYA_CAIRO_WIDGET_VISIBLE_ON,
|
||||||
|
G_PARAM_READWRITE);
|
||||||
|
|
||||||
|
g_cw_prop[CW_HALIGN] = g_param_spec_uint(
|
||||||
|
"halign", NULL, "Widget halign",
|
||||||
|
DIYA_CAIRO_WIDGET_ALIGN_START,
|
||||||
|
DIYA_CAIRO_WIDGET_ALIGN_MAX,
|
||||||
|
DIYA_CAIRO_WIDGET_ALIGN_MIDDLE,
|
||||||
|
G_PARAM_READWRITE);
|
||||||
|
|
||||||
|
g_cw_prop[CW_VALIGN] = g_param_spec_uint(
|
||||||
|
"valign", NULL, "Widget valign",
|
||||||
|
DIYA_CAIRO_WIDGET_ALIGN_START,
|
||||||
|
DIYA_CAIRO_WIDGET_ALIGN_MAX,
|
||||||
|
DIYA_CAIRO_WIDGET_ALIGN_MIDDLE,
|
||||||
|
G_PARAM_READWRITE);
|
||||||
|
|
||||||
|
g_cw_prop[CW_HSPACE] = g_param_spec_uint(
|
||||||
|
"hspace", NULL, "Widget hspace",
|
||||||
|
DIYA_CAIRO_WIDGET_FILL_NONE,
|
||||||
|
DIYA_CAIRO_WIDGET_FILL_MAX,
|
||||||
|
DIYA_CAIRO_WIDGET_FILL_EXTEND,
|
||||||
|
G_PARAM_READWRITE);
|
||||||
|
|
||||||
|
g_cw_prop[CW_VSPACE] = g_param_spec_uint(
|
||||||
|
"vpsace", NULL, "Widget vspace",
|
||||||
|
DIYA_CAIRO_WIDGET_FILL_NONE,
|
||||||
|
DIYA_CAIRO_WIDGET_FILL_MAX,
|
||||||
|
DIYA_CAIRO_WIDGET_FILL_EXTEND,
|
||||||
|
G_PARAM_READWRITE);
|
||||||
|
|
||||||
|
g_cw_prop[CW_PADDING] = g_param_spec_pointer("padding", NULL, "Widget padding", G_PARAM_READWRITE);
|
||||||
|
g_cw_prop[CW_MARGIN] = g_param_spec_pointer("margin", NULL, "Widget margin", G_PARAM_READWRITE);
|
||||||
|
|
||||||
|
g_cw_prop[CW_PADDING_LEFT] = g_param_spec_int(
|
||||||
|
"padding-left", NULL, "Widget padding-left",
|
||||||
|
G_MININT,
|
||||||
|
G_MAXINT,
|
||||||
|
0,
|
||||||
|
G_PARAM_WRITABLE);
|
||||||
|
g_cw_prop[CW_PADDING_RIGHT] = g_param_spec_int(
|
||||||
|
"padding-right", NULL, "Widget padding-right",
|
||||||
|
INT_MIN,
|
||||||
|
INT_MAX,
|
||||||
|
0,
|
||||||
|
G_PARAM_WRITABLE);
|
||||||
|
g_cw_prop[CW_PADDING_TOP] = g_param_spec_int(
|
||||||
|
"padding-top", NULL, "Widget padding-top",
|
||||||
|
INT_MIN,
|
||||||
|
INT_MAX,
|
||||||
|
0,
|
||||||
|
G_PARAM_WRITABLE);
|
||||||
|
g_cw_prop[CW_PADDING_BOTTOM] = g_param_spec_int(
|
||||||
|
"padding-bottom", NULL, "Widget padding-bottom",
|
||||||
|
INT_MIN,
|
||||||
|
INT_MAX,
|
||||||
|
0,
|
||||||
|
G_PARAM_WRITABLE);
|
||||||
|
|
||||||
|
g_cw_prop[CW_MARGIN_LEFT] = g_param_spec_int(
|
||||||
|
"margin-left", NULL, "Widget margin-left",
|
||||||
|
INT_MIN,
|
||||||
|
INT_MAX,
|
||||||
|
0,
|
||||||
|
G_PARAM_WRITABLE);
|
||||||
|
g_cw_prop[CW_MARGIN_RIGHT] = g_param_spec_int(
|
||||||
|
"margin-right", NULL, "Widget margin-right",
|
||||||
|
INT_MIN,
|
||||||
|
INT_MAX,
|
||||||
|
0,
|
||||||
|
G_PARAM_WRITABLE);
|
||||||
|
g_cw_prop[CW_MARGIN_TOP] = g_param_spec_int(
|
||||||
|
"margin-top", NULL, "Widget margin-top",
|
||||||
|
INT_MIN,
|
||||||
|
INT_MAX,
|
||||||
|
0,
|
||||||
|
G_PARAM_WRITABLE);
|
||||||
|
g_cw_prop[CW_MARGIN_BOTTOM] = g_param_spec_int(
|
||||||
|
"margin-bottom", NULL, "Widget margin-bottom",
|
||||||
|
INT_MIN,
|
||||||
|
INT_MAX,
|
||||||
|
0,
|
||||||
|
G_PARAM_WRITABLE);
|
||||||
|
|
||||||
base_class->to_string = diya_cairo_widget_to_string;
|
base_class->to_string = diya_cairo_widget_to_string;
|
||||||
|
|
||||||
g_object_class_install_properties (gobject_class, CW_N_PROPERTIES, g_cw_prop);
|
g_object_class_install_properties (gobject_class, CW_N_PROPERTIES, g_cw_prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
diya_point_t diya_cairo_widget_get_position(gpointer object)
|
||||||
|
{
|
||||||
|
diya_point_t p = {0};
|
||||||
|
assert(DIYA_IS_CAIRO_WIDGET(object));
|
||||||
|
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
|
||||||
|
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
||||||
|
p.x = priv->extent.x;
|
||||||
|
p.y = priv->extent.y;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
diya_point_t diya_cairo_widget_get_global_position(gpointer object)
|
||||||
|
{
|
||||||
|
assert(DIYA_IS_CAIRO_WIDGET(object));
|
||||||
|
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
|
||||||
|
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
||||||
|
diya_point_t p = {priv->extent.x, priv->extent.y};
|
||||||
|
if(priv->parent_widget)
|
||||||
|
{
|
||||||
|
|
||||||
|
diya_point_t parent_pos = diya_cairo_widget_get_global_position(priv->parent_widget);
|
||||||
|
p.x += parent_pos.x;
|
||||||
|
p.y += parent_pos.y;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
DiyaCairoWidget* diya_cairo_widget_get_parent(gpointer object)
|
||||||
|
{
|
||||||
|
assert(DIYA_IS_CAIRO_WIDGET(object));
|
||||||
|
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
|
||||||
|
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
||||||
|
return priv->parent_widget;
|
||||||
|
}
|
||||||
|
diya_rect_t diya_cairo_widget_get_extent(gpointer object)
|
||||||
|
{
|
||||||
|
assert(DIYA_IS_CAIRO_WIDGET(object));
|
||||||
|
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
|
||||||
|
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
||||||
|
|
||||||
|
return priv->extent;
|
||||||
|
}
|
||||||
|
gboolean diya_cairo_widget_is_visible(gpointer object)
|
||||||
|
{
|
||||||
|
assert(DIYA_IS_CAIRO_WIDGET(object));
|
||||||
|
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
|
||||||
|
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
||||||
|
return priv->visibility == DIYA_CAIRO_WIDGET_VISIBLE_ON;
|
||||||
|
}
|
||||||
|
gboolean diya_cairo_widget_is_hidden(gpointer object)
|
||||||
|
{
|
||||||
|
assert(DIYA_IS_CAIRO_WIDGET(object));
|
||||||
|
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
|
||||||
|
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
||||||
|
return priv->visibility == DIYA_CAIRO_WIDGET_VISIBLE_HIDDEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
void diya_cairo_widget_set_size(gpointer object, guint width, guint height)
|
||||||
|
{
|
||||||
|
assert(DIYA_IS_CAIRO_WIDGET(object));
|
||||||
|
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
|
||||||
|
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
||||||
|
|
||||||
|
priv->default_extent.width = width;
|
||||||
|
priv->default_extent.height = height;
|
||||||
|
|
||||||
|
}
|
||||||
|
void diya_cairo_widget_set_position(gpointer object, gint x, gint y)
|
||||||
|
{
|
||||||
|
assert(DIYA_IS_CAIRO_WIDGET(object));
|
||||||
|
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
|
||||||
|
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
||||||
|
|
||||||
|
priv->default_extent.x = x;
|
||||||
|
priv->default_extent.y = y;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void diya_cairo_widget_fill(gpointer object, diya_color_t * color)
|
||||||
|
{
|
||||||
|
assert(DIYA_IS_CAIRO_WIDGET(object));
|
||||||
|
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
|
||||||
|
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
||||||
|
priv->fill = *color;
|
||||||
|
}
|
||||||
|
void diya_cairo_widget_set_stroke_size(gpointer object, gdouble size)
|
||||||
|
{
|
||||||
|
assert(DIYA_IS_CAIRO_WIDGET(object));
|
||||||
|
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
|
||||||
|
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
||||||
|
|
||||||
|
priv->stroke.size = size;
|
||||||
|
}
|
||||||
|
void diya_cairo_widget_set_stroke_color(gpointer object, diya_color_t * color)
|
||||||
|
{
|
||||||
|
assert(DIYA_IS_CAIRO_WIDGET(object));
|
||||||
|
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
|
||||||
|
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
||||||
|
|
||||||
|
priv->stroke.color = *color;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean diya_cairo_widget_is_damaged(gpointer object)
|
||||||
|
{
|
||||||
|
assert(DIYA_IS_CAIRO_WIDGET(object));
|
||||||
|
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
|
||||||
|
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
||||||
|
|
||||||
|
return priv->damaged;
|
||||||
|
}
|
||||||
|
|
||||||
|
void diya_cairo_widget_damage(gpointer object)
|
||||||
|
{
|
||||||
|
assert(DIYA_IS_CAIRO_WIDGET(object));
|
||||||
|
DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object);
|
||||||
|
DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self);
|
||||||
|
|
||||||
|
priv->damaged = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Container API*/
|
||||||
|
|
||||||
|
typedef struct _DiyaCairoContainerPrivate
|
||||||
|
{
|
||||||
|
DiyaCairoWidget * parent_object;
|
||||||
|
GList* children;
|
||||||
|
|
||||||
|
} DiyaCairoContainerPrivate;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_PRIVATE(DiyaCairoContainer, diya_cairo_container, DIYA_TYPE_CAIRO_WIDGET)
|
||||||
|
|
||||||
|
static void diya_cairo_container_dispose(GObject* object)
|
||||||
|
{
|
||||||
|
DiyaCairoContainer * self = DIYA_CAIRO_CONTAINER(object);
|
||||||
|
DiyaCairoContainerPrivate* priv = diya_cairo_container_get_instance_private(self);
|
||||||
|
g_debug("diya_cairo_container_dispose: %s", diya_object_to_string(object));
|
||||||
|
g_list_free_full(priv->children, g_object_unref);
|
||||||
|
G_OBJECT_CLASS(diya_cairo_widget_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_cairo_container_init(DiyaCairoContainer *self)
|
||||||
|
{
|
||||||
|
DiyaCairoContainerPrivate* priv = diya_cairo_container_get_instance_private(self);
|
||||||
|
priv->children = NULL;
|
||||||
|
}
|
||||||
|
static void diya_cairo_container_class_init(DiyaCairoContainerClass *class)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||||
|
//DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class);
|
||||||
|
DIYA_CAIRO_WIDGET_SET_NAME(class, "DiyaCairoContainer");
|
||||||
|
gobject_class->dispose = diya_cairo_container_dispose;
|
||||||
|
}
|
||||||
|
|
||||||
|
void diya_cairo_container_add(gpointer object, gpointer child)
|
||||||
|
{
|
||||||
|
assert(DIYA_IS_CAIRO_WIDGET(child));
|
||||||
|
assert(DIYA_IS_CAIRO_CONTAINER(object));
|
||||||
|
DiyaCairoContainerPrivate* priv = diya_cairo_container_get_instance_private(DIYA_CAIRO_CONTAINER(object));
|
||||||
|
g_object_set(child,"parent", object, NULL);
|
||||||
|
if(g_list_find (priv->children,child))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
priv->children = g_list_append(priv->children, child);
|
||||||
|
}
|
||||||
|
|
||||||
|
void diya_offset_normalize(diya_offset_t * offset)
|
||||||
|
{
|
||||||
|
gint tmp;
|
||||||
|
if(offset->left > offset->right)
|
||||||
|
{
|
||||||
|
tmp = offset->left;
|
||||||
|
offset->left = offset->right;
|
||||||
|
offset->right = tmp;
|
||||||
|
}
|
||||||
|
if(offset->top > offset->bottom)
|
||||||
|
{
|
||||||
|
tmp = offset->top;
|
||||||
|
offset->top = offset->bottom;
|
||||||
|
offset->bottom = tmp;
|
||||||
|
}
|
||||||
|
}
|
@ -1,20 +1,124 @@
|
|||||||
#ifndef CAIRO_WIDGET_H
|
#ifndef CAIRO_WIDGET_H
|
||||||
#define CAIRO_WIDGET_H
|
#define CAIRO_WIDGET_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <cairo/cairo.h>
|
||||||
#include "../base.h"
|
#include "../base.h"
|
||||||
|
|
||||||
#define DIYA_CAIRO_WIDGET_SET_NAME(c, n) (DIYA_CAIRO_WIDGET_CLASS(c)->name = n)
|
// basic type
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
gint x;
|
||||||
|
gint y;
|
||||||
|
guint width;
|
||||||
|
guint height;
|
||||||
|
} diya_rect_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
gint x;
|
||||||
|
gint y;
|
||||||
|
}
|
||||||
|
diya_point_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
gint left;
|
||||||
|
gint top;
|
||||||
|
gint bottom;
|
||||||
|
gint right;
|
||||||
|
}
|
||||||
|
diya_offset_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
gdouble r;
|
||||||
|
gdouble g;
|
||||||
|
gdouble b;
|
||||||
|
gdouble a;
|
||||||
|
}
|
||||||
|
diya_color_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
gdouble size;
|
||||||
|
diya_color_t color;
|
||||||
|
} diya_stroke_t;
|
||||||
|
|
||||||
|
#define BETWEEN(value,min,max) ((value > min) && (value < max))
|
||||||
|
|
||||||
|
#define diya_rect_is_empty(rect) (((rect)->width <= 0) && ((rect)->height <= 0))
|
||||||
|
#define diya_rect_to_offset(rect) ({(rect)->x,(rect)->y,(rect)->y+(rect)->height, (rect)->x + (rect)->width})
|
||||||
|
#define diya_rect_overlap(a,b) ( \
|
||||||
|
(BETWEEN((a)->x, (b)->x, (b)->x + (gint)(b)->width) || BETWEEN((b)->x, (a)->x, (a)->x + (gint)(a)->width)) && \
|
||||||
|
(BETWEEN((a)->y, (b)->y, (b)->y + (gint)(b)->height) || BETWEEN((b)->y, (a)->y, (a)->y + (gint)(a)->height)))
|
||||||
|
|
||||||
|
void diya_offset_normalize(diya_offset_t * offset);
|
||||||
|
|
||||||
|
#define DIYA_CAIRO_WIDGET_SET_NAME(c, n) (DIYA_CAIRO_WIDGET_CLASS(c)->name = n)
|
||||||
#define DIYA_TYPE_CAIRO_WIDGET (diya_cairo_widget_get_type ())
|
#define DIYA_TYPE_CAIRO_WIDGET (diya_cairo_widget_get_type ())
|
||||||
G_DECLARE_DERIVABLE_TYPE (DiyaCairoWidget, diya_cairo_widget, DIYA, CAIRO_WIDGET, DiyaObject)
|
G_DECLARE_DERIVABLE_TYPE (DiyaCairoWidget, diya_cairo_widget, DIYA, CAIRO_WIDGET, DiyaObject)
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
/*Align enum*/
|
||||||
|
DIYA_CAIRO_WIDGET_ALIGN_START,
|
||||||
|
DIYA_CAIRO_WIDGET_ALIGN_MIDDLE,
|
||||||
|
DIYA_CAIRO_WIDGET_ALIGN_END,
|
||||||
|
DIYA_CAIRO_WIDGET_ALIGN_MAX, // not used
|
||||||
|
/*fill enum*/
|
||||||
|
DIYA_CAIRO_WIDGET_FILL_NONE, // using extent size
|
||||||
|
DIYA_CAIRO_WIDGET_FILL_CONTENT, // extent calculated by its content
|
||||||
|
DIYA_CAIRO_WIDGET_FILL_EXTEND, // extend to the entire free space of the parent
|
||||||
|
DIYA_CAIRO_WIDGET_FILL_MAX, //not used
|
||||||
|
|
||||||
|
/* Visibility enum*/
|
||||||
|
DIYA_CAIRO_WIDGET_VISIBLE_ON,
|
||||||
|
DIYA_CAIRO_WIDGET_VISIBLE_OFF, // not show but take space
|
||||||
|
DIYA_CAIRO_WIDGET_VISIBLE_HIDDEN, // not show and does not take space
|
||||||
|
DIYA_CAIRO_WIDGET_VISIBLE_MAX, // not used
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
struct _DiyaCairoWidgetClass
|
struct _DiyaCairoWidgetClass
|
||||||
{
|
{
|
||||||
DiyaObjectClass parent_class;
|
DiyaObjectClass parent_class;
|
||||||
|
void (*draw)(gpointer, cairo_t*);
|
||||||
|
void (*update)(gpointer);
|
||||||
|
void (*resize)(gpointer);
|
||||||
|
void (*align)(gpointer);
|
||||||
|
void (*content_size)(gpointer, guint*, guint*);
|
||||||
|
diya_rect_t (*alloc_space)(gpointer, gpointer);
|
||||||
|
|
||||||
const gchar* name;
|
const gchar* name;
|
||||||
/**
|
|
||||||
* @brief TODO define more API function
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
diya_point_t diya_cairo_widget_get_position(gpointer object);
|
||||||
|
diya_point_t diya_cairo_widget_get_global_position(gpointer object);
|
||||||
|
DiyaCairoWidget* diya_cairo_widget_get_parent(gpointer object);
|
||||||
|
diya_rect_t diya_cairo_widget_get_extent(gpointer object);
|
||||||
|
gboolean diya_cairo_widget_is_visible(gpointer object);
|
||||||
|
gboolean diya_cairo_widget_is_hidden(gpointer object);
|
||||||
|
gboolean diya_cairo_widget_is_damaged(gpointer object);
|
||||||
|
|
||||||
|
void diya_cairo_widget_damage(gpointer object);
|
||||||
|
|
||||||
|
void diya_cairo_widget_set_size(gpointer object, guint width, guint height);
|
||||||
|
void diya_cairo_widget_set_position(gpointer object, gint x, gint y);
|
||||||
|
void diya_cairo_widget_fill(gpointer object, diya_color_t * color);
|
||||||
|
void diya_cairo_widget_set_stroke_size(gpointer object, gdouble size);
|
||||||
|
void diya_cairo_widget_set_stroke_color(gpointer object, diya_color_t * color);
|
||||||
|
|
||||||
|
#define DIYA_TYPE_CAIRO_CONTAINER (diya_cairo_container_get_type ())
|
||||||
|
G_DECLARE_DERIVABLE_TYPE (DiyaCairoContainer, diya_cairo_container, DIYA, CAIRO_CONTAINER, DiyaCairoWidget)
|
||||||
|
|
||||||
|
|
||||||
|
struct _DiyaCairoContainerClass
|
||||||
|
{
|
||||||
|
DiyaCairoWidget parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
void diya_cairo_container_add(gpointer object, gpointer child);
|
||||||
|
|
||||||
#endif
|
#endif
|
97
src/widgets/cairo-window.c
Normal file
97
src/widgets/cairo-window.c
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include "cairo-window.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
NO_PROP,
|
||||||
|
BOX_MODE,
|
||||||
|
N_PROPERTIES
|
||||||
|
};
|
||||||
|
static GParamSpec *g_prop[N_PROPERTIES] = {0};
|
||||||
|
*/
|
||||||
|
struct _DiyaCairoWindow
|
||||||
|
{
|
||||||
|
DiyaCairoWidget * parent_object;
|
||||||
|
DiyaCairoWidget * root;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_FINAL_TYPE(DiyaCairoWindow, diya_cairo_window, DIYA_TYPE_CAIRO_WIDGET)
|
||||||
|
|
||||||
|
static void diya_cairo_window_dispose(GObject * object)
|
||||||
|
{
|
||||||
|
g_debug("diya_cairo_window_dispose: %s", diya_object_to_string(object));
|
||||||
|
DiyaCairoWindow * window = DIYA_CAIRO_WINDOW(object);
|
||||||
|
if(window->root)
|
||||||
|
{
|
||||||
|
g_object_unref(window->root);
|
||||||
|
}
|
||||||
|
G_OBJECT_CLASS(diya_cairo_window_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_cairo_window_init(DiyaCairoWindow * window)
|
||||||
|
{
|
||||||
|
window->root = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cairo_window_draw(gpointer object, cairo_t * cairo)
|
||||||
|
{
|
||||||
|
DiyaCairoWindow * window = DIYA_CAIRO_WINDOW(object);
|
||||||
|
DIYA_CAIRO_WIDGET_CLASS(diya_cairo_window_parent_class)->draw(object, cairo);
|
||||||
|
if(window->root)
|
||||||
|
{
|
||||||
|
DIYA_CAIRO_WIDGET_GET_CLASS(DIYA_CAIRO_WIDGET(window->root))->draw(object, cairo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cairo_window_update(gpointer object)
|
||||||
|
{
|
||||||
|
DiyaCairoWindow * self = DIYA_CAIRO_WINDOW(object);
|
||||||
|
DIYA_CAIRO_WIDGET_CLASS(diya_cairo_window_parent_class)->update(object);
|
||||||
|
|
||||||
|
if(self->root)
|
||||||
|
{
|
||||||
|
DIYA_CAIRO_WIDGET_CLASS(DIYA_CAIRO_WIDGET(self->root))->update(self->root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void diya_cairo_window_class_init(DiyaCairoWindowClass* class)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
|
||||||
|
DiyaCairoWidgetClass *wclass = DIYA_CAIRO_WIDGET_CLASS(class);
|
||||||
|
wclass->draw = cairo_window_draw;
|
||||||
|
wclass->update = cairo_window_update;
|
||||||
|
DIYA_CAIRO_WIDGET_SET_NAME(class, "DiyaCairoWindow");
|
||||||
|
gobject_class->dispose = diya_cairo_window_dispose;
|
||||||
|
}
|
||||||
|
|
||||||
|
void diya_cairo_window_set_root(gpointer object, gpointer root)
|
||||||
|
{
|
||||||
|
assert(DIYA_IS_CAIRO_WINDOW(object));
|
||||||
|
assert(DIYA_IS_CAIRO_WIDGET(root));
|
||||||
|
DiyaCairoWindow * window = DIYA_CAIRO_WINDOW(object);
|
||||||
|
window->root = DIYA_CAIRO_WIDGET(root);
|
||||||
|
diya_rect_t extent = diya_cairo_widget_get_extent(window);
|
||||||
|
g_object_set(root,
|
||||||
|
"parent", window,
|
||||||
|
"default-extent", &extent,
|
||||||
|
"vspace", DIYA_CAIRO_WIDGET_FILL_EXTEND,
|
||||||
|
"hspace", DIYA_CAIRO_WIDGET_FILL_EXTEND,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void diya_cairo_window_render(gpointer object, cairo_surface_t * surface)
|
||||||
|
{
|
||||||
|
assert(DIYA_IS_CAIRO_WINDOW(object));
|
||||||
|
DiyaCairoWidget * widget = DIYA_CAIRO_WIDGET(object);
|
||||||
|
cairo_t *cr = cairo_create(surface);
|
||||||
|
DIYA_CAIRO_WIDGET_GET_CLASS(widget)->draw(object,cr);
|
||||||
|
cairo_destroy(cr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void diya_cairo_window_update(gpointer object)
|
||||||
|
{
|
||||||
|
assert(DIYA_IS_CAIRO_WINDOW(object));
|
||||||
|
DIYA_CAIRO_WIDGET_CLASS(DIYA_CAIRO_WIDGET(object))->update(object);
|
||||||
|
}
|
13
src/widgets/cairo-window.h
Normal file
13
src/widgets/cairo-window.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef DIYA_CAIRO_WINDOW_H
|
||||||
|
#define DIYA_CAIRO_WINDOW_H
|
||||||
|
|
||||||
|
#include "cairo-widget.h"
|
||||||
|
|
||||||
|
#define DIYA_TYPE_CAIRO_WINDOW (diya_cairo_window_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (DiyaCairoWindow, diya_cairo_window, DIYA, CAIRO_WINDOW, DiyaCairoWidget)
|
||||||
|
|
||||||
|
|
||||||
|
void diya_cairo_window_set_root(gpointer object, gpointer root);
|
||||||
|
void diya_cairo_window_render(gpointer object, cairo_surface_t * surface);
|
||||||
|
void diya_cairo_window_update(gpointer object);
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user