From 1219ec1563c9831c3431658747cdabbd33e41c32 Mon Sep 17 00:00:00 2001 From: DanyLE Date: Mon, 22 Apr 2024 00:31:57 +0200 Subject: [PATCH] add more widgets (WIP) --- meson.build | 1 + src/base.c | 4 +- src/launcher.c | 5 +- src/main.c | 3 + src/session.c | 90 +++++++++++++ src/wayland.c | 2 +- src/widgets/cairo-box.c | 217 +++++++++++++++++++++++++++++- src/widgets/cairo-box.h | 4 +- src/widgets/cairo-image.c | 263 +++++++++++++++++++++++++++++++++++++ src/widgets/cairo-image.h | 9 ++ src/widgets/cairo-widget.c | 203 ++++++++++++++-------------- src/widgets/cairo-widget.h | 41 ++++-- src/widgets/cairo-window.c | 56 +++++++- src/widgets/cairo-window.h | 1 + 14 files changed, 767 insertions(+), 132 deletions(-) create mode 100644 src/widgets/cairo-image.c create mode 100644 src/widgets/cairo-image.h diff --git a/meson.build b/meson.build index 63e4f96..06ac974 100644 --- a/meson.build +++ b/meson.build @@ -59,6 +59,7 @@ src = [ 'src/widgets/cairo-widget.c', 'src/widgets/cairo-box.c', 'src/widgets/cairo-window.c', + 'src/widgets/cairo-image.c', 'src/main.c', wayland_targets] diff --git a/src/base.c b/src/base.c index ef726f5..5dace5f 100644 --- a/src/base.c +++ b/src/base.c @@ -6,7 +6,7 @@ G_DEFINE_ABSTRACT_TYPE(DiyaObject, diya_object, G_TYPE_OBJECT) static void diya_object_dispose(GObject* object) { - g_debug("diya_object_dispose"); + g_debug("diya_object_dispose: %s", diya_object_to_string(object)); G_OBJECT_CLASS (diya_object_parent_class)->dispose(object); } @@ -40,7 +40,7 @@ G_DEFINE_TYPE_WITH_PRIVATE(DiyaShellObject, diya_shell_object, DIYA_TYPE_OBJECT) static void diya_shell_object_dispose(GObject* object) { - g_debug("diya_shell_object_dispose"); + g_debug("diya_shell_object_dispose: %s", diya_object_to_string(object)); G_OBJECT_CLASS(diya_shell_object_parent_class)->dispose(object); } diff --git a/src/launcher.c b/src/launcher.c index 3c9051b..8c604a7 100644 --- a/src/launcher.c +++ b/src/launcher.c @@ -83,10 +83,11 @@ void diya_shell_launcher_init(DiyaShell * shell) for (l = apps; l != NULL; l = l->next) { gpointer element_data = l->data; - g_warning("%s", g_app_info_get_display_name(element_data)); /*print out all of the display names of the .desktop files */ + + /*g_warning("%s", g_app_info_get_display_name(element_data)); g_warning("%s", g_app_info_get_id(element_data)); g_warning("%s", g_app_info_get_name(element_data)); - //g_warning("%s", g_app_info_get_icon(element_data)); + //g_warning("%s", g_app_info_get_icon(element_data));*/ } g_list_free_full(apps, g_object_unref); } \ No newline at end of file diff --git a/src/main.c b/src/main.c index 693f58c..ceef9fb 100644 --- a/src/main.c +++ b/src/main.c @@ -11,6 +11,9 @@ static void activate(GtkApplication *app, void *data) { (void)app; (void)data; + + DiyaShell *shell = data; + diya_shell_lock(shell); } static gboolean restart(gpointer d) diff --git a/src/session.c b/src/session.c index e84d6c7..47aad67 100644 --- a/src/session.c +++ b/src/session.c @@ -11,6 +11,8 @@ #include "session.h" #include "wayland.h" #include "widgets/cairo-window.h" +#include "widgets/cairo-box.h" +#include "widgets/cairo-image.h" #define DEF_SURF_W 600 #define DEF_SURF_H 400 @@ -239,6 +241,7 @@ static void lock_surface_configure(void *data, self->surface_height = height; session_lock_realloc_surface(self); diya_cairo_widget_set_size(self->window, width, height); + g_warning("update and damaged window"); diya_cairo_window_update(self->window); } ext_session_lock_surface_v1_ack_configure(lock_surface, serial); @@ -264,6 +267,90 @@ static void lock_surface_frame_done(void *data, struct wl_callback *cb, uint32_t lock_session_draw_frame(lock); } +static void diya_lock_session_ui(DiyaCairoWindow * window) +{ + diya_stroke_t stroke = { + 2.0, + { 1.0, 0.0, 1.0, 1.0 } + }; + + diya_stroke_t stroke1 = { + 2.0, + { 0.0, 0.0, 1.0, 1.0 } + }; + + diya_offset_t margin = {10,20,10,20}; + diya_offset_t padding = {20, 10, 20, 10}; + + g_object_set(window, "margin", &margin, "padding", &padding, NULL); + + DiyaCairoBox * root = g_object_new( + DIYA_TYPE_CAIRO_BOX, + "mode", DIYA_CAIRO_BOX_HORIZONTAL, + "stroke", &stroke, + NULL); + + diya_cairo_window_set_background_image(window, "/etc/xdg/labwc/wpp.jpg", TRUE); + diya_cairo_window_set_root(window, root); + + DiyaCairoBox * box = g_object_new(DIYA_TYPE_CAIRO_BOX, + "mode", DIYA_CAIRO_BOX_HORIZONTAL, + "stroke", &stroke1, + NULL); + diya_cairo_container_add(root, box); + + box = g_object_new(DIYA_TYPE_CAIRO_BOX, + "mode", DIYA_CAIRO_BOX_VERTICAL, + "vspace", DIYA_CAIRO_WIDGET_FILL_CONTENT, + "hspace", DIYA_CAIRO_WIDGET_FILL_CONTENT, + "stroke", &stroke, + NULL); + diya_cairo_container_add(root, box); + + + DiyaCairoBox* hbox = g_object_new(DIYA_TYPE_CAIRO_BOX, + "mode", DIYA_CAIRO_BOX_HORIZONTAL, + "stroke", &stroke1, + NULL); + diya_cairo_container_add(box, hbox); + + + hbox = g_object_new(DIYA_TYPE_CAIRO_BOX, + "mode", DIYA_CAIRO_BOX_HORIZONTAL, + "vspace", DIYA_CAIRO_WIDGET_FILL_CONTENT, + "hspace", DIYA_CAIRO_WIDGET_FILL_CONTENT, + "stroke", &stroke, + "padding", &padding, + NULL); + diya_cairo_container_add(box, hbox); + + diya_stroke_t stroke_img = { + 2.0, + { 0.0, 0.0, 1.0, 1.0 } + }; + DiyaCairoImage * image = g_object_new(DIYA_TYPE_CAIRO_IMAGE, + "file", + "/home/diya/test.jpg", + "stroke", + &stroke_img, + "vspace", DIYA_CAIRO_WIDGET_FILL_NONE, + "hspace", DIYA_CAIRO_WIDGET_FILL_NONE, + NULL); + diya_cairo_container_add(hbox, image); + + hbox = g_object_new(DIYA_TYPE_CAIRO_BOX, + "mode", DIYA_CAIRO_BOX_HORIZONTAL, + "stroke", &stroke1, + NULL); + diya_cairo_container_add(box, hbox); + + box = g_object_new(DIYA_TYPE_CAIRO_BOX, + "mode", DIYA_CAIRO_BOX_HORIZONTAL, + "stroke", &stroke1, + NULL); + diya_cairo_container_add(root, box); +} + static void diya_lock_session_init(DiyaLockSession *self) { self->session_lock = ext_session_lock_manager_v1_lock(g_session_lock_manager); @@ -282,8 +369,11 @@ static void diya_lock_session_init(DiyaLockSession *self) self->wl_surface = NULL; self->wl_buffer = NULL; + self->window = g_object_new(DIYA_TYPE_CAIRO_WINDOW,NULL); + diya_lock_session_ui(self->window); + self->cairo_surface = NULL; self->raw_shared_buffer = NULL; self->raw_shared_buffer_size = 0; diff --git a/src/wayland.c b/src/wayland.c index c70f640..e9054ad 100644 --- a/src/wayland.c +++ b/src/wayland.c @@ -56,7 +56,7 @@ static void handle_global(void *data, struct wl_registry *registry, uint32_t nam DiyaWayland * wayland; g_object_get(shell, "wayland", &wayland, NULL); assert(DIYA_IS_WAYLAND(wayland)); - g_warning("GLOBAL: %s", interface); + g_debug("WAYLAND GLOBAL: %s", interface); if (!g_strcmp0(interface, zwlr_foreign_toplevel_manager_v1_interface.name)) { diya_shell_foreign_toplevel_register(registry, name, data); diff --git a/src/widgets/cairo-box.c b/src/widgets/cairo-box.c index e5f0098..2df189b 100644 --- a/src/widgets/cairo-box.c +++ b/src/widgets/cairo-box.c @@ -1,3 +1,5 @@ +#include +#include #include "cairo-box.h" enum @@ -24,7 +26,7 @@ static void diya_cairo_box_dispose(GObject * object) static void diya_cairo_box_init(DiyaCairoBox* self) { - self->mode = DIYA_CAIRO_HORIZONTAL_BOX; + self->mode = DIYA_CAIRO_BOX_HORIZONTAL; } static void diya_cairo_box_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) @@ -55,13 +57,224 @@ static void diya_cairo_box_get_property(GObject *object, guint property_id, GVal } } +static gboolean cairo_box_draw(gpointer object, cairo_t * cairo) +{ + DIYA_CAIRO_WIDGET_CLASS(diya_cairo_box_parent_class)->draw(object, cairo); + GList * children = DIYA_CAIRO_CONTAINER_GET_CLASS(object)->children(object); + gpointer item; + G_LIST_FOREACH(item, children) + { + DIYA_CAIRO_WIDGET_GET_CLASS(DIYA_CAIRO_WIDGET(item))->draw(item, cairo); + } + return TRUE; +} + +static void cairo_box_update(gpointer object) +{ + diya_offset_t margin = {0}; + g_object_set( + object, + "halign", DIYA_CAIRO_WIDGET_ALIGN_START, + "valign", DIYA_CAIRO_WIDGET_ALIGN_START, + "margin", &margin, + NULL + ); + DIYA_CAIRO_WIDGET_CLASS(diya_cairo_box_parent_class)->update(object); + + assert(DIYA_IS_CAIRO_BOX(object)); + DiyaCairoBox * self = DIYA_CAIRO_BOX(object); + GList * children = DIYA_CAIRO_CONTAINER_GET_CLASS(object)->children(object); + if(!children) + { + return; + } + + diya_rect_t space = diya_cairo_widget_get_extent(object); + diya_offset_t * padding; + diya_stroke_t * stroke; + g_object_get(object,"padding", &padding, "stroke", &stroke, NULL); + gint stroke_size = ceil(stroke->size); + gpointer item; + guint n_extended = 0; + gint occupied_space = 2*stroke_size; + guint vspace, hspace; + guint cwidth, cheight; + // explore all other children + if(self->mode == DIYA_CAIRO_BOX_HORIZONTAL) + { + occupied_space += padding->left + padding->right; + } + else + { + occupied_space += padding->right + padding->bottom; + } + G_LIST_FOREACH(item, children) + { + g_object_get(item, "vspace", &vspace, "hspace", &hspace, NULL); + DIYA_CAIRO_WIDGET_GET_CLASS(item)->content_size(item, &cwidth, &cheight); + if(self->mode == DIYA_CAIRO_BOX_HORIZONTAL) + { + switch (hspace) + { + case DIYA_CAIRO_WIDGET_FILL_EXTEND: + n_extended++; + break; + case DIYA_CAIRO_WIDGET_FILL_CONTENT: + case DIYA_CAIRO_WIDGET_FILL_NONE: + occupied_space += cwidth; + break; + default: + break; + } + } + else + { + switch (vspace) + { + case DIYA_CAIRO_WIDGET_FILL_EXTEND: + n_extended++; + break; + case DIYA_CAIRO_WIDGET_FILL_CONTENT: + case DIYA_CAIRO_WIDGET_FILL_NONE: + occupied_space += cheight; + break; + default: + break; + } + } + } + + gint off_x = padding->left + stroke_size; + gint off_y = padding->top + stroke_size; + + G_LIST_FOREACH(item, children) + { + g_object_get(item, "vspace", &vspace, "hspace", &hspace, NULL); + DIYA_CAIRO_WIDGET_GET_CLASS(item)->content_size(item, &cwidth, &cheight); + + diya_rect_t rect = {0}; + rect.x = off_x; + rect.y = off_y; + if(self->mode == DIYA_CAIRO_BOX_HORIZONTAL) + { + rect.height = space.height - padding->top - padding->bottom - stroke_size*2; + + switch (hspace) + { + case DIYA_CAIRO_WIDGET_FILL_EXTEND: + rect.width = (occupied_space >= space.width)?0:(space.width - occupied_space) / n_extended; + off_x += rect.width; + break; + case DIYA_CAIRO_WIDGET_FILL_CONTENT: + case DIYA_CAIRO_WIDGET_FILL_NONE: + rect.width = cwidth; + if(!DIYA_IS_CAIRO_BOX(item)) + { + rect.height = cheight; + } + off_x += cwidth; + break; + default: + break; + } + } + else + { + rect.width = space.width - padding->left - padding->right - stroke_size*2; + switch (vspace) + { + case DIYA_CAIRO_WIDGET_FILL_EXTEND: + rect.height = (occupied_space >= space.height)?0:(space.height - occupied_space) / n_extended; + off_y += rect.height; + break; + case DIYA_CAIRO_WIDGET_FILL_CONTENT: + case DIYA_CAIRO_WIDGET_FILL_NONE: + rect.height = cheight; + if(!DIYA_IS_CAIRO_BOX(item)) + { + rect.width = cwidth; + } + off_y += cheight; + break; + default: + break; + } + } + diya_rect_t * item_extent = DIYA_CAIRO_WIDGET_GET_CLASS(item)->extent(item); + memcpy(item_extent, &rect, sizeof(rect)); + } + + G_LIST_FOREACH(item, children) + { + // back up vspace hspace + g_object_get(item, "vspace", &vspace, "hspace", &hspace, NULL); + g_object_set(item, + "vspace", DIYA_CAIRO_WIDGET_FILL_EXTEND, + "hspace", DIYA_CAIRO_WIDGET_FILL_EXTEND, + NULL); + DIYA_CAIRO_WIDGET_GET_CLASS(DIYA_CAIRO_WIDGET(item))->update(item); + g_object_set(item, + "vspace", vspace, + "hspace", hspace, + NULL); + } +} + +static diya_rect_t cairo_box_allocate_space(gpointer object, gpointer child) +{ + (void) object; + return diya_cairo_widget_get_extent(child); +} + +static void cairo_box_content_size(gpointer object, gint* width, gint * height) +{ + DiyaCairoBox * self = DIYA_CAIRO_BOX(object); + *width = 0; + *height = 0; + gpointer item; + GList * children = DIYA_CAIRO_CONTAINER_GET_CLASS(object)->children(object); + diya_stroke_t * stroke; + diya_offset_t * padding; + g_object_get(object, "stroke", &stroke,"padding", &padding, NULL); + gint stroke_size = ceil(stroke->size) * 2; + G_LIST_FOREACH(item, children) + { + gint cw,ch; + DIYA_CAIRO_WIDGET_GET_CLASS(item)->content_size(item,&cw,&ch); + if(self->mode == DIYA_CAIRO_BOX_HORIZONTAL) + { + *width += cw; + *height = MAX(*height,ch); + } + else + { + *height += ch; + *width = MAX(*width,cw); + } + } + *height += stroke_size + padding->bottom + padding->top; + *width += stroke_size + padding->left + padding->right; +} + static void diya_cairo_box_class_init(DiyaCairoBoxClass * class) { GObjectClass *gobject_class = G_OBJECT_CLASS(class); DIYA_CAIRO_WIDGET_SET_NAME(class, "DiyaCairoBox"); + + DiyaCairoWidgetClass *wclass = DIYA_CAIRO_WIDGET_CLASS(class); + + wclass->draw = cairo_box_draw; + wclass->update = cairo_box_update; + wclass->alloc_space = cairo_box_allocate_space; + wclass->content_size = cairo_box_content_size; + 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_prop[BOX_MODE] = g_param_spec_uint( + "mode", NULL, + "Box mode", DIYA_CAIRO_BOX_HORIZONTAL, + DIYA_CAIRO_BOX_VERTICAL, DIYA_CAIRO_BOX_HORIZONTAL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_properties (gobject_class, N_PROPERTIES, g_prop); } \ No newline at end of file diff --git a/src/widgets/cairo-box.h b/src/widgets/cairo-box.h index cdf098e..a59ad76 100644 --- a/src/widgets/cairo-box.h +++ b/src/widgets/cairo-box.h @@ -4,8 +4,8 @@ #include "cairo-widget.h" enum { - DIYA_CAIRO_HORIZONTAL_BOX, - DIYA_CAIRO_VERTICAL_BOX + DIYA_CAIRO_BOX_HORIZONTAL, + DIYA_CAIRO_BOX_VERTICAL }; #define DIYA_TYPE_CAIRO_BOX (diya_cairo_box_get_type ()) diff --git a/src/widgets/cairo-image.c b/src/widgets/cairo-image.c new file mode 100644 index 0000000..1ea0b17 --- /dev/null +++ b/src/widgets/cairo-image.c @@ -0,0 +1,263 @@ +#include +#include +#include "cairo-image.h" + +enum +{ + NO_PROP, + IMG_FILE, + IMG_ALPHA, + IMG_PIXBUF, + IMG_FIT, + N_PROPERTIES +}; +static GParamSpec *g_prop[N_PROPERTIES] = {0}; + +struct _DiyaCairoImage +{ + DiyaCairoWidget parent_object; + gchar * file; + GdkPixbuf * buffer; + gdouble alpha; + + gboolean fit; +}; + +G_DEFINE_FINAL_TYPE(DiyaCairoImage, diya_cairo_image, DIYA_TYPE_CAIRO_WIDGET) + +static void diya_cairo_image_dispose(GObject * object) +{ + g_debug("diya_cairo_image_dispose: %s", diya_object_to_string(object)); + DiyaCairoImage * self = DIYA_CAIRO_IMAGE(object); + if(self->file) + { + g_free(self->file); + } + if(self->buffer) + { + g_debug("diya_cairo_image_dispose: release image buffer"); + g_object_unref(self->buffer); + } + G_OBJECT_CLASS(diya_cairo_image_parent_class)->dispose(object); +} + +static void diya_cairo_set_pixbuf(DiyaCairoImage* self, GdkPixbuf * buf) +{ + if(self->buffer) + { + g_object_unref(self->buffer); + self->buffer = NULL; + } + self->buffer = buf; + diya_cairo_widget_set_size(self, + gdk_pixbuf_get_width(self->buffer), + gdk_pixbuf_get_height(self->buffer) + ); + diya_cairo_widget_damage(self); +} +static void diya_cairo_load_image_from_file(DiyaCairoImage* self, const gchar* path) +{ + if(self->file) + { + g_free(self->file); + } + self->file = g_strdup(path); + GError *error = NULL; + GdkPixbuf * buf = gdk_pixbuf_new_from_file(self->file,&error); + if(!buf) + { + g_error("diya_cairo_load_image_from_file: [%s] %s", self->file, error->message); + return; + } + diya_cairo_set_pixbuf(self,buf); +} + +static void diya_cairo_image_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + DiyaCairoImage * self = DIYA_CAIRO_IMAGE(object); + switch (property_id) + { + case IMG_FILE: + diya_cairo_load_image_from_file(self, g_value_get_pointer(value)); + break; + case IMG_ALPHA: + self->alpha = g_value_get_double(value); + break; + case IMG_FIT: + self->fit = g_value_get_boolean(value); + break; + case IMG_PIXBUF: + if(self->file) + { + g_free(self->file); + self->file = NULL; + } + diya_cairo_set_pixbuf(self,g_value_get_pointer(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void diya_cairo_image_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + DiyaCairoImage * self = DIYA_CAIRO_IMAGE(object); + switch (property_id) + { + case IMG_FILE: + g_value_set_pointer(value, self->file); + break; + case IMG_ALPHA: + g_value_set_double(value, self->alpha); + break; + case IMG_FIT: + g_value_set_boolean(value, self->fit); + break; + case IMG_PIXBUF: + g_value_set_pointer(value, self->buffer); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void diya_cairo_image_init(DiyaCairoImage * self) +{ + self->file = NULL; + self->buffer = NULL; + self->alpha = 1.0; + + self->fit = FALSE; +} + +static gboolean diya_cairo_image_draw(gpointer object, cairo_t * context) +{ + DiyaCairoImage * self = DIYA_CAIRO_IMAGE(object); + if(!self->buffer || !diya_cairo_widget_is_damaged(self) || !diya_cairo_widget_is_visible(self)) + { + return FALSE; + } + diya_rect_t view_port = diya_cairo_widget_get_view_port(object); + diya_rect_dump("view port: ", &view_port); + + if(diya_rect_is_empty(&view_port)) + { + return FALSE; + } + cairo_save(context); + cairo_rectangle(context, view_port.x, view_port.y, view_port.width, view_port.height); + cairo_clip(context); + + diya_color_t * color; + diya_stroke_t * stroke; + diya_point_t gpos = diya_cairo_widget_get_global_position(object); + diya_rect_t * default_extent; + guint halign, valign; + diya_offset_t * margin; + diya_rect_t extent = diya_cairo_widget_get_extent(object); + diya_rect_dump("extent: ", &extent); + g_object_get(object, + "fill", &color, + "stroke", &stroke, + "halign", &halign, + "valign", &valign, + "margin", &margin, + "default-extent", &default_extent, + NULL); + + gint img_width = default_extent->width; + gint img_height = default_extent->height; + gint stroke_size = ceil(stroke->size); + GdkPixbuf * buf = NULL; + if(self->fit) + { + img_width = extent.width; + img_height = extent.height; + buf = gdk_pixbuf_scale_simple(self->buffer,img_width, img_height, GDK_INTERP_BILINEAR); + } + else + { + buf = g_object_ref(self->buffer); + } + gint off_x = margin->left + stroke->size / 2.0; + gint off_y = margin->top + stroke->size / 2.0; + + switch (halign) + { + case DIYA_CAIRO_WIDGET_ALIGN_MIDDLE: + off_x += (extent.width - img_width) / 2; + break; + case DIYA_CAIRO_WIDGET_ALIGN_END: + off_x += extent.width - img_width; + break; + default: + break; + } + + switch (valign) + { + case DIYA_CAIRO_WIDGET_ALIGN_MIDDLE: + off_y += (extent.height - img_height) / 2; + break; + case DIYA_CAIRO_WIDGET_ALIGN_END: + off_y += extent.height - img_height; + break; + default: + break; + } + + g_warning("Global position %d %d offset %d %d", gpos.x, gpos.y, off_x, off_y); + + if(color->a > 0) + { + //cairo_move_to(context, (double)gpos.x, (double)gpos.y); + cairo_rectangle(context, + gpos.x + margin->left + stroke_size, + gpos.y + margin->top + stroke_size, + extent.width - margin->left - margin->right - 2*stroke_size, + extent.height - margin->bottom - margin->top - 2*stroke_size); + cairo_set_source_rgba(context, color->r, color->g, color->b, color->a); + cairo_fill(context); + } + // draw image + gdk_cairo_set_source_pixbuf(context, buf, (double)(gpos.x + off_x), (double)(gpos.y + off_y)); + cairo_paint_with_alpha(context, self->alpha); + + if(stroke->size > 0 && stroke->color.a != 0) + { + //cairo_move_to(context, (double)gpos.x, (double)gpos.y); + cairo_rectangle(context, + gpos.x + margin->left + stroke_size, + gpos.y + margin->top + stroke_size, + extent.width - margin->left - margin->right - 2*stroke_size, + extent.height - margin->bottom - margin->top - 2*stroke_size); + cairo_set_source_rgba(context, stroke->color.r, stroke->color.g, stroke->color.b, stroke->color.a); + cairo_set_line_width(context,stroke->size); + cairo_stroke(context); + } + + g_object_unref(buf); + cairo_restore(context); + return TRUE; +} + +static void diya_cairo_image_class_init(DiyaCairoImageClass* class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(class); + DiyaCairoWidgetClass *wclass = DIYA_CAIRO_WIDGET_CLASS(class); + + wclass->draw = diya_cairo_image_draw; + + DIYA_CAIRO_WIDGET_SET_NAME(class, "DiyaCairoImage"); + gobject_class->dispose = diya_cairo_image_dispose; + + gobject_class->set_property = diya_cairo_image_set_property; + gobject_class->get_property = diya_cairo_image_get_property; + g_prop[IMG_FILE] = g_param_spec_pointer("file", NULL, "Image file", G_PARAM_READWRITE ); + g_prop[IMG_ALPHA] = g_param_spec_pointer("alpha", NULL, "Image alpha", G_PARAM_READWRITE ); + g_prop[IMG_PIXBUF] = g_param_spec_pointer("pixbuf", NULL, "Image data from gdk_pixbuf", G_PARAM_READWRITE ); + g_prop[IMG_FIT] = g_param_spec_boolean("scale-to-fit", NULL, "Scale image to fit space", FALSE, G_PARAM_READWRITE ); + g_object_class_install_properties (gobject_class, N_PROPERTIES, g_prop); +} \ No newline at end of file diff --git a/src/widgets/cairo-image.h b/src/widgets/cairo-image.h new file mode 100644 index 0000000..5196505 --- /dev/null +++ b/src/widgets/cairo-image.h @@ -0,0 +1,9 @@ +#ifndef CAIRO_IMAGE_H +#define CAIRO_IMAGE_H + +#include "cairo-widget.h" + +#define DIYA_TYPE_CAIRO_IMAGE (diya_cairo_image_get_type ()) +G_DECLARE_FINAL_TYPE (DiyaCairoImage, diya_cairo_image, DIYA, CAIRO_IMAGE, DiyaCairoWidget) + +#endif \ No newline at end of file diff --git a/src/widgets/cairo-widget.c b/src/widgets/cairo-widget.c index e8e67d5..bdf494d 100644 --- a/src/widgets/cairo-widget.c +++ b/src/widgets/cairo-widget.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "cairo-widget.h" /* #include @@ -56,7 +57,7 @@ static GParamSpec *g_cw_prop[CW_N_PROPERTIES] = {0}; typedef struct _DiyaCairoWidgetPrivate { - DiyaObject * parent_object; + DiyaObject parent_object; diya_rect_t extent; diya_rect_t default_extent; DiyaCairoWidget * parent_widget; @@ -248,33 +249,41 @@ static const gchar *diya_cairo_widget_to_string(DiyaObject *object) DiyaCairoWidgetClass *class = DIYA_CAIRO_WIDGET_GET_CLASS(object); DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self); + diya_point_t gpos = diya_cairo_widget_get_global_position(object); + g_snprintf(priv->string,sizeof(priv->string), - "%s (%dx%d) at %d@%d", + "%s (%dx%d) at %d@%d (local %d@%d)", class->name, - priv->extent.x, priv->extent.y, - priv->extent.width, priv->extent.height + priv->extent.width, priv->extent.height, + gpos.x, gpos.y, + priv->extent.x, priv->extent.y ); return priv->string; } -static diya_rect_t diya_cairo_widget_get_view_port(gpointer object) +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_offset_t * margin; + g_object_get(object,"margin", &margin, NULL); 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}; + diya_rect_t view = { + gpos.x + margin->left, + gpos.y + margin->top, + priv->extent.width - margin->left - margin->right, + priv->extent.height - margin->bottom - margin->top + }; 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.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); @@ -287,58 +296,72 @@ static diya_rect_t diya_cairo_widget_get_view_port(gpointer object) return view; } -static void diya_cairo_widget_draw(gpointer object, cairo_t* context) +static gboolean 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; + return FALSE; } if(priv->visibility != DIYA_CAIRO_WIDGET_VISIBLE_ON) { - return; + return FALSE; } + diya_rect_t view_port = diya_cairo_widget_get_view_port(object); + if(diya_rect_is_empty(&view_port)) { - return; + return FALSE; } + 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); + //cairo_move_to(context, (double)gpos.x +, (double)gpos.y); + guint stroke_size = ceil(priv->stroke.size); + guint half_stroke_size = ceil(priv->stroke.size / 2.0); + cairo_rectangle(context, + gpos.x + priv->margin.left + half_stroke_size, + gpos.y + priv->margin.top + half_stroke_size, + priv->extent.width - priv->margin.left - priv->margin.right - stroke_size, + priv->extent.height - priv->margin.bottom - priv->margin.top - stroke_size); 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); + cairo_fill_preserve(context); } if(priv->stroke.size > 0 && priv->stroke.color.a != 0) { + cairo_set_source_rgba(context, priv->stroke.color.r, priv->stroke.color.g, priv->stroke.color.b, priv->stroke.color.a); cairo_set_line_width(context,priv->stroke.size); cairo_stroke(context); } cairo_restore(context); priv->damaged = FALSE; + return TRUE; } -static void diya_cairo_widget_content_size(gpointer object, guint* width, guint* height) +static void diya_cairo_widget_content_size(gpointer object, gint* width, gint* 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 + + gint stroke_size = ceil(priv->stroke.size) *2; + *width = priv->default_extent.width + priv->margin.left + priv->margin.right + stroke_size; + *height = priv->default_extent.height + priv->margin.top + priv->margin.bottom + stroke_size; } -static void diya_cairo_widget_resize(gpointer object) + +static void diya_cairo_widget_update(gpointer object) { - // calculate effective size + assert(DIYA_IS_CAIRO_WIDGET(object)); DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object); DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self); + if(priv->visibility == DIYA_CAIRO_WIDGET_VISIBLE_HIDDEN) { /** @@ -355,49 +378,41 @@ static void diya_cairo_widget_resize(gpointer object) 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}; + 0, + 0, + priv->default_extent.width, + priv->default_extent.height }; if(priv->parent_widget) { - space = DIYA_CAIRO_WIDGET_GET_CLASS(self)->alloc_space(priv->parent_object, object); + space = DIYA_CAIRO_WIDGET_GET_CLASS(priv->parent_widget)->alloc_space(priv->parent_widget, 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); - } + gint width,height,cwidth = 0,cheight = 0; + 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: + case DIYA_CAIRO_WIDGET_FILL_NONE: width = cwidth; break; default: - width = priv->extent.width; + width = priv->default_extent.width + priv->margin.left + priv->margin.right; 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: + case DIYA_CAIRO_WIDGET_FILL_NONE: height = cheight; break; default: - height = priv->extent.height; + height = priv->default_extent.height + priv->margin.top + priv->margin.bottom; break; } @@ -407,79 +422,48 @@ static void diya_cairo_widget_resize(gpointer object) } priv->extent.width = width; priv->extent.height = height; - /*if(space.x != priv->extent.x || space.y != priv->extent.y) + 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) { + (void) 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); + diya_rect_t space = {0,0,priv->extent.width, priv->extent.height}; + guint stroke_size = ceil(priv->stroke.size); + space.x += priv->padding.left + priv->margin.left + stroke_size; + space.y += priv->padding.top + priv->margin.top + stroke_size; + space.width -= (priv->padding.right + priv->padding.left + priv->margin.left+ priv->margin.right + stroke_size*2); + space.height -= (priv->padding.bottom + priv->padding.top + priv->margin.top + priv->margin.bottom + stroke_size*2); return space; } +static diya_rect_t diya_cairo_widget_get_default_extent(gpointer object) +{ + DiyaCairoWidget * self = DIYA_CAIRO_WIDGET(object); + DiyaCairoWidgetPrivate* priv = diya_cairo_widget_get_instance_private(self); + return priv->default_extent; +} + +static diya_rect_t* diya_cairo_widget_get_extent_mut(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; +} + static void diya_cairo_widget_class_init(DiyaCairoWidgetClass *class) { GObjectClass *gobject_class = G_OBJECT_CLASS(class); @@ -491,9 +475,14 @@ static void diya_cairo_widget_class_init(DiyaCairoWidgetClass *class) 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; + class->parent = diya_cairo_widget_get_parent; + class->position = diya_cairo_widget_get_position; + class->global_position = diya_cairo_widget_get_global_position; + class->extent = diya_cairo_widget_get_extent_mut; + class->view_port = diya_cairo_widget_get_view_port; + class->damaged = diya_cairo_widget_is_damaged; + class->default_extent = diya_cairo_widget_get_default_extent; 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); @@ -529,7 +518,7 @@ static void diya_cairo_widget_class_init(DiyaCairoWidgetClass *class) G_PARAM_READWRITE); g_cw_prop[CW_VSPACE] = g_param_spec_uint( - "vpsace", NULL, "Widget vspace", + "vspace", NULL, "Widget vspace", DIYA_CAIRO_WIDGET_FILL_NONE, DIYA_CAIRO_WIDGET_FILL_MAX, DIYA_CAIRO_WIDGET_FILL_EXTEND, @@ -715,7 +704,7 @@ void diya_cairo_widget_damage(gpointer object) typedef struct _DiyaCairoContainerPrivate { - DiyaCairoWidget * parent_object; + DiyaCairoWidget parent_object; GList* children; } DiyaCairoContainerPrivate; @@ -736,12 +725,20 @@ static void diya_cairo_container_init(DiyaCairoContainer *self) DiyaCairoContainerPrivate* priv = diya_cairo_container_get_instance_private(self); priv->children = NULL; } + +static GList * diya_cairo_container_get_children(gpointer object) +{ + DiyaCairoContainerPrivate* priv = diya_cairo_container_get_instance_private(DIYA_CAIRO_CONTAINER(object)); + return priv->children; +} + static void diya_cairo_container_class_init(DiyaCairoContainerClass *class) { GObjectClass *gobject_class = G_OBJECT_CLASS(class); - //DiyaObjectClass *base_class = DIYA_OBJECT_CLASS(class); + //DiyaCairoWidgetClass *wclass = DIYA_CAIRO_WIDGET_CLASS(class); DIYA_CAIRO_WIDGET_SET_NAME(class, "DiyaCairoContainer"); gobject_class->dispose = diya_cairo_container_dispose; + class->children = diya_cairo_container_get_children; } void diya_cairo_container_add(gpointer object, gpointer child) diff --git a/src/widgets/cairo-widget.h b/src/widgets/cairo-widget.h index f0ffa18..d29510b 100644 --- a/src/widgets/cairo-widget.h +++ b/src/widgets/cairo-widget.h @@ -11,8 +11,8 @@ typedef struct { gint x; gint y; - guint width; - guint height; + gint width; + gint height; } diya_rect_t; typedef struct @@ -26,8 +26,8 @@ typedef struct { gint left; gint top; - gint bottom; gint right; + gint bottom; } diya_offset_t; @@ -46,13 +46,18 @@ typedef struct diya_color_t color; } diya_stroke_t; -#define BETWEEN(value,min,max) ((value > min) && (value < max)) +#define BETWEEN(value,min,max) ((value >= min) && (value <= max)) -#define diya_rect_is_empty(rect) (((rect)->width <= 0) && ((rect)->height <= 0)) +#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))) + (BETWEEN((a)->x, (b)->x, (b)->x + (b)->width) || BETWEEN((b)->x, (a)->x, (a)->x + (a)->width)) && \ + (BETWEEN((a)->y, (b)->y, (b)->y + (b)->height) || BETWEEN((b)->y, (a)->y, (a)->y + (a)->height))) + +#define diya_rect_dump(prefix, rect) (g_warning(prefix ": [%d@%d, %dx%d]", (rect)->x,(rect)->y, (rect)->width, (rect)->height)) + +#define G_LIST_FOREACH(item, list) for(GList *__glist = list; __glist && (item = __glist->data, TRUE); __glist = __glist->next) + void diya_offset_normalize(diya_offset_t * offset); @@ -66,6 +71,7 @@ enum DIYA_CAIRO_WIDGET_ALIGN_START, DIYA_CAIRO_WIDGET_ALIGN_MIDDLE, DIYA_CAIRO_WIDGET_ALIGN_END, + DIYA_CAIRO_WIDGET_ALIGN_DEFAULT, DIYA_CAIRO_WIDGET_ALIGN_MAX, // not used /*fill enum*/ DIYA_CAIRO_WIDGET_FILL_NONE, // using extent size @@ -84,13 +90,19 @@ enum struct _DiyaCairoWidgetClass { DiyaObjectClass parent_class; - void (*draw)(gpointer, cairo_t*); + gboolean (*draw)(gpointer, cairo_t*); void (*update)(gpointer); - void (*resize)(gpointer); - void (*align)(gpointer); - void (*content_size)(gpointer, guint*, guint*); + void (*content_size)(gpointer, gint*, gint*); diya_rect_t (*alloc_space)(gpointer, gpointer); + DiyaCairoWidget* (*parent)(gpointer); + diya_point_t (*position)(gpointer); + diya_point_t (*global_position)(gpointer); + diya_rect_t* (*extent)(gpointer); + diya_rect_t (*default_extent)(gpointer); + diya_rect_t (*view_port)(gpointer); + gboolean (*damaged)(gpointer); + const gchar* name; }; @@ -101,6 +113,7 @@ 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); +diya_rect_t diya_cairo_widget_get_view_port(gpointer object); void diya_cairo_widget_damage(gpointer object); @@ -110,15 +123,17 @@ 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; + DiyaCairoWidgetClass parent_class; + + GList* (*children)(gpointer); }; void diya_cairo_container_add(gpointer object, gpointer child); - #endif \ No newline at end of file diff --git a/src/widgets/cairo-window.c b/src/widgets/cairo-window.c index 9bd9d0a..cedfb6c 100644 --- a/src/widgets/cairo-window.c +++ b/src/widgets/cairo-window.c @@ -1,6 +1,6 @@ #include #include "cairo-window.h" - +#include "cairo-image.h" /* enum { @@ -12,8 +12,10 @@ static GParamSpec *g_prop[N_PROPERTIES] = {0}; */ struct _DiyaCairoWindow { - DiyaCairoWidget * parent_object; + DiyaCairoWidget parent_object; DiyaCairoWidget * root; + + gpointer background; }; G_DEFINE_FINAL_TYPE(DiyaCairoWindow, diya_cairo_window, DIYA_TYPE_CAIRO_WIDGET) @@ -26,32 +28,51 @@ static void diya_cairo_window_dispose(GObject * object) { g_object_unref(window->root); } + if(window->background) + { + g_object_unref(window->background); + } G_OBJECT_CLASS(diya_cairo_window_parent_class)->dispose(object); } static void diya_cairo_window_init(DiyaCairoWindow * window) { window->root = NULL; + window->background = NULL; } -static void cairo_window_draw(gpointer object, cairo_t * cairo) +static gboolean 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->background) + { + g_warning("drawing background"); + assert(DIYA_IS_CAIRO_IMAGE(window->background)); + DIYA_CAIRO_WIDGET_GET_CLASS(DIYA_CAIRO_WIDGET(window->background))->draw(window->background, cairo); + } if(window->root) { - DIYA_CAIRO_WIDGET_GET_CLASS(DIYA_CAIRO_WIDGET(window->root))->draw(object, cairo); + DIYA_CAIRO_WIDGET_GET_CLASS(DIYA_CAIRO_WIDGET(window->root))->draw(window->root, cairo); } + return TRUE; } static void cairo_window_update(gpointer object) { + g_warning("Updating cairo window"); DiyaCairoWindow * self = DIYA_CAIRO_WINDOW(object); DIYA_CAIRO_WIDGET_CLASS(diya_cairo_window_parent_class)->update(object); - + if(self->background) + { + g_warning("Updating cairo image"); + assert(DIYA_IS_CAIRO_IMAGE(self->background)); + DIYA_CAIRO_WIDGET_GET_CLASS(DIYA_CAIRO_WIDGET(self->background))->update(self->background); + } if(self->root) { - DIYA_CAIRO_WIDGET_CLASS(DIYA_CAIRO_WIDGET(self->root))->update(self->root); + g_warning("Updating root"); + DIYA_CAIRO_WIDGET_GET_CLASS(DIYA_CAIRO_WIDGET(self->root))->update(self->root); } } @@ -61,6 +82,7 @@ static void diya_cairo_window_class_init(DiyaCairoWindowClass* class) DiyaCairoWidgetClass *wclass = DIYA_CAIRO_WIDGET_CLASS(class); wclass->draw = cairo_window_draw; wclass->update = cairo_window_update; + // wclass->alloc_space = cairo_window_allocate_space; DIYA_CAIRO_WIDGET_SET_NAME(class, "DiyaCairoWindow"); gobject_class->dispose = diya_cairo_window_dispose; } @@ -93,5 +115,25 @@ void diya_cairo_window_render(gpointer object, cairo_surface_t * surface) void diya_cairo_window_update(gpointer object) { assert(DIYA_IS_CAIRO_WINDOW(object)); - DIYA_CAIRO_WIDGET_CLASS(DIYA_CAIRO_WIDGET(object))->update(object); + g_warning("update and damaged widget"); + DiyaCairoWidget * widget = DIYA_CAIRO_WIDGET(object); + assert(DIYA_IS_CAIRO_WIDGET(widget)); + DIYA_CAIRO_WIDGET_GET_CLASS(widget)->update(object); +} + +void diya_cairo_window_set_background_image(gpointer object, const char* path, gboolean scale_to_fit) +{ + assert(DIYA_IS_CAIRO_WINDOW(object)); + DiyaCairoWindow * self = DIYA_CAIRO_WINDOW(object); + + self->background = g_object_new(DIYA_TYPE_CAIRO_IMAGE, + "file",path, "parent", object, + "scale-to-fit", scale_to_fit, + "hspace", DIYA_CAIRO_WIDGET_FILL_EXTEND, + "vspace", DIYA_CAIRO_WIDGET_FILL_EXTEND, + "halign", DIYA_CAIRO_WIDGET_ALIGN_START, + "valign", DIYA_CAIRO_WIDGET_ALIGN_START, + NULL); + + } \ No newline at end of file diff --git a/src/widgets/cairo-window.h b/src/widgets/cairo-window.h index fe0d6ec..656067a 100644 --- a/src/widgets/cairo-window.h +++ b/src/widgets/cairo-window.h @@ -10,4 +10,5 @@ G_DECLARE_FINAL_TYPE (DiyaCairoWindow, diya_cairo_window, DIYA, CAIRO_WINDOW, Di 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); +void diya_cairo_window_set_background_image(gpointer object, const char * file, gboolean scale_to_fit); #endif \ No newline at end of file