From e158c4832aa1d5dc8603fb9c33cac3f7cc19abc9 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Wed, 21 Jun 2017 14:25:13 +0200 Subject: added the widget and the composite widget classes --- src/gui/composite_widget.c | 137 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 src/gui/composite_widget.c (limited to 'src/gui/composite_widget.c') diff --git a/src/gui/composite_widget.c b/src/gui/composite_widget.c new file mode 100644 index 0000000..e9cc166 --- /dev/null +++ b/src/gui/composite_widget.c @@ -0,0 +1,137 @@ +#include "composite_widget.h" + +#include "string.h" +#include "stddef.h" + +static composite_widget_vtable_t composite_widget_vtable = { + { + composite_widget_draw, + composite_widget_get_focus, + widget_model_to_screen, + widget_contains_coordinate, + composite_widget_on_mouse_down, + composite_widget_on_mouse_up, + composite_widget_on_mouse_move, + composite_widget_on_key_down, + composite_widget_on_key_up + }, + composite_widget_add_child +}; + +void composite_widget_init( composite_widget_t *widget, widget_t *parent, const int x, const int y, const int w, const int h ) +{ + memset( widget, 0, sizeof( composite_widget_t ) ); + + widget_init( &widget->base, parent, x, y, w, h ); + + widget->nof_children = 0; + widget->focused_child = NULL; + memset( widget->children, 0, MAX_NOF_WIDGET_CHILDREN * sizeof( widget_t * ) ); + + widget->vtable = &composite_widget_vtable; +} + +void composite_widget_draw( void *obj, graphics_context_t *context ) +{ + composite_widget_t *widget = obj; + + widget->base.vtable->draw( obj, context ); + + for( int i = widget->nof_children - 1; i >= 0; i-- ) { + widget_t *child = widget->children[i]; + child->vtable->draw( child, context ); + } +} + +void composite_widget_get_focus( void *obj, widget_t *widget ) +{ + composite_widget_t *o = obj; + + o->focused_child = widget; + + o->base.vtable->get_focus( o, widget ); +} + +void composite_widget_add_child( void *obj, widget_t *child ) +{ + composite_widget_t *widget = obj; + + if( widget->nof_children >= MAX_NOF_WIDGET_CHILDREN ) { + // TODO: kernel_panic, but in an indirect way because + // the GUI framework should not depend on the kernel. + // Maybe something like a runtime context similar to + // the graphics context? + return; + } + + widget->children[widget->nof_children++] = child; +} + +void composite_widget_on_mouse_down( void *obj, const int x, const int y ) +{ + composite_widget_t *widget = obj; + + for( int i = 0; i < widget->nof_children; i++ ) { + widget_t *child = widget->children[i]; + if( child->vtable->contains_coordinate( child, x - widget->base.x, y - widget->base.y ) ) { + child->vtable->on_mouse_down( child, x - widget->base.x, y - widget->base.y ); + break; + } + } +} + +void composite_widget_on_mouse_up( void *obj, const int x, const int y ) +{ + composite_widget_t *widget = obj; + + for( int i = 0; i < widget->nof_children; i++ ) { + widget_t *child = widget->children[i]; + if( child->vtable->contains_coordinate( child, x - widget->base.x, y - widget->base.y ) ) { + child->vtable->on_mouse_up( child, x - widget->base.x, y - widget->base.y ); + break; + } + } +} + +void composite_widget_on_mouse_move( void *obj, const int old_x, const int old_y, const int x, const int y ) +{ + composite_widget_t *widget = obj; + widget_t *moved_out_from = NULL; + + for( int i = 0; i < widget->nof_children; i++ ) { + widget_t *child = widget->children[i]; + if( child->vtable->contains_coordinate( child, old_x - widget->base.x, old_y - widget->base.y ) ) { + child->vtable->on_mouse_move( child, old_x - widget->base.x, old_y - widget->base.y, x - widget->base.x, y - widget->base.y ); + moved_out_from = child; + break; + } + } + + for( int i = 0; i < widget->nof_children; i++ ) { + widget_t *child = widget->children[i]; + if( child->vtable->contains_coordinate( child, x - widget->base.x, y - widget->base.y ) ) { + if( moved_out_from != NULL ) { + child->vtable->on_mouse_move( child, old_x - widget->base.x, old_y - widget->base.y, x - widget->base.x, y - widget->base.y ); + break; + } + } + } +} + +void composite_widget_on_key_down( void *obj, char c ) +{ + composite_widget_t *widget = obj; + + if( widget->focused_child != NULL ) { + widget->focused_child->vtable->on_key_down( widget->focused_child, c ); + } +} + +void composite_widget_on_key_up( void *obj, char c ) +{ + composite_widget_t *widget = obj; + + if( widget->focused_child != NULL ) { + widget->focused_child->vtable->on_key_up( widget->focused_child, c ); + } +} -- cgit v1.2.3-54-g00ecf