summaryrefslogtreecommitdiff
path: root/src/gui/composite_widget.c
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2017-06-21 14:25:13 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2017-06-21 14:25:13 +0200
commite158c4832aa1d5dc8603fb9c33cac3f7cc19abc9 (patch)
tree0055162852966fab10afb7a230744796007a9c2f /src/gui/composite_widget.c
parent32f14fa04237963d8b6016d8cc0c6d853e68d2fe (diff)
downloadabaos-e158c4832aa1d5dc8603fb9c33cac3f7cc19abc9.tar.gz
abaos-e158c4832aa1d5dc8603fb9c33cac3f7cc19abc9.tar.bz2
added the widget and the composite widget classes
Diffstat (limited to 'src/gui/composite_widget.c')
-rw-r--r--src/gui/composite_widget.c137
1 files changed, 137 insertions, 0 deletions
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 );
+ }
+}