summaryrefslogtreecommitdiff
path: root/src/gui
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
parent32f14fa04237963d8b6016d8cc0c6d853e68d2fe (diff)
downloadabaos-e158c4832aa1d5dc8603fb9c33cac3f7cc19abc9.tar.gz
abaos-e158c4832aa1d5dc8603fb9c33cac3f7cc19abc9.tar.bz2
added the widget and the composite widget classes
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/composite_widget.c137
-rw-r--r--src/gui/composite_widget.h32
-rw-r--r--src/gui/widget.c74
-rw-r--r--src/gui/widget.h19
4 files changed, 253 insertions, 9 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 );
+ }
+}
diff --git a/src/gui/composite_widget.h b/src/gui/composite_widget.h
new file mode 100644
index 0000000..d3ba90a
--- /dev/null
+++ b/src/gui/composite_widget.h
@@ -0,0 +1,32 @@
+#ifndef COMPOSITE_WIDGET_H
+#define COMPOSITE_WIDGET_H
+
+#include "widget.h"
+
+#define MAX_NOF_WIDGET_CHILDREN 100
+
+typedef struct {
+ widget_vtable_t base;
+ void (*add_child)( void *obj, widget_t *child );
+} composite_widget_vtable_t;
+
+typedef struct {
+ widget_t base;
+ composite_widget_vtable_t *vtable;
+ widget_t *children[MAX_NOF_WIDGET_CHILDREN];
+ int nof_children;
+ widget_t *focused_child;
+} composite_widget_t;
+
+void composite_widget_init( composite_widget_t *widget, widget_t *parent, const int x, const int y, const int w, const int h );
+
+void composite_widget_draw( void *obj, graphics_context_t *context );
+void composite_widget_get_focus( void *obj, widget_t *widget );
+void composite_widget_on_mouse_down( void *obj, const int x, const int y );
+void composite_widget_on_mouse_up( void *obj, const int x, const int y );
+void composite_widget_on_mouse_move( void *obj, const int old_x, const int old_y, const int x, const int y );
+void composite_widget_on_key_down( void *obj, char c );
+void composite_widget_on_key_up( void *obj, char c );
+void composite_widget_add_child( void *obj, widget_t *child );
+
+#endif // COMPOSITE_WIDGET_H
diff --git a/src/gui/widget.c b/src/gui/widget.c
index 313fd49..cd77d03 100644
--- a/src/gui/widget.c
+++ b/src/gui/widget.c
@@ -5,12 +5,14 @@
static widget_vtable_t widget_vtable = {
widget_draw,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
+ widget_get_focus,
+ widget_model_to_screen,
+ widget_contains_coordinate,
+ widget_on_mouse_down,
+ widget_on_mouse_up,
+ widget_on_mouse_move,
+ widget_on_key_down,
+ widget_on_key_up
};
void widget_init( widget_t *widget, widget_t *parent, const int x, const int y, const int w, const int h )
@@ -29,7 +31,65 @@ void widget_init( widget_t *widget, widget_t *parent, const int x, const int y,
void widget_draw( void *obj, graphics_context_t *context )
{
widget_t *widget = obj;
+ int x = 0;
+ int y = 0;
- vga_draw_rectangle( context, widget->x, widget->y, widget->w, widget->h,
+ widget->vtable->model_to_screen( widget, &x, &y );
+
+ vga_draw_rectangle( context, x, y, widget->w, widget->h,
vga_make_RGB( 0xFF, 0xFF, 0xFF ) );
}
+
+void widget_get_focus( void *obj, widget_t *widget )
+{
+ widget_t *o = obj;
+
+ if( o->parent != NULL ) {
+ o->parent->vtable->get_focus( widget->parent, widget );
+ }
+}
+
+void widget_model_to_screen( void *obj, int *x, int *y )
+{
+ widget_t *widget = obj;
+
+ if( widget->parent != NULL ) {
+ widget->parent->vtable->model_to_screen( widget->parent, x, y );
+ }
+
+ *x += widget->x;
+ *y += widget->y;
+}
+
+bool widget_contains_coordinate( void *obj, const int x, const int y )
+{
+ widget_t *widget = obj;
+
+ return widget->x <= x && x < widget->x + widget->w &&
+ widget->y <= y && y < widget->y + widget->h;
+}
+
+void widget_on_mouse_down( void *obj, const int x, const int y )
+{
+ widget_t *widget = obj;
+
+ if( widget->focusable ) {
+ widget->vtable->get_focus( widget, widget );
+ }
+}
+
+void widget_on_mouse_up( void *obj, const int x, const int y )
+{
+}
+
+void widget_on_mouse_move( void *obj, const int old_x, const int old_y, const int x, const int y )
+{
+}
+
+void widget_on_key_down( void *obj, char c )
+{
+}
+
+void widget_on_key_up( void *obj, char c )
+{
+}
diff --git a/src/gui/widget.h b/src/gui/widget.h
index a1e9a21..1fd23ac 100644
--- a/src/gui/widget.h
+++ b/src/gui/widget.h
@@ -3,14 +3,20 @@
#include "graphics_context.h"
+#include <stdbool.h>
+
+struct widget_t;
+
typedef struct {
void (*draw)( void *obj, graphics_context_t *context );
- void (*get_focus)( void *obj );
- void (*widget_model_to_screen)( void *obj, int *x, int *y );
+ void (*get_focus)( void *obj, struct widget_t *widget );
+ void (*model_to_screen)( void *obj, int *x, int *y );
+ bool (*contains_coordinate)( void *obj, const int x, const int y );
void (*on_mouse_down)( void *obj, const int x, const int y );
void (*on_mouse_up)( void *obj, const int x, const int y );
void (*on_mouse_move)( void *obj, const int old_x, const int old_y, const int x, const int y );
void (*on_key_down)( void *obj, char c );
+ void (*on_key_up)( void *obj, char c );
} widget_vtable_t;
typedef struct widget_t {
@@ -18,6 +24,7 @@ typedef struct widget_t {
int y;
int w;
int h;
+ bool focusable;
struct widget_t *parent;
widget_vtable_t *vtable;
} widget_t;
@@ -25,5 +32,13 @@ typedef struct widget_t {
void widget_init( widget_t *widget, widget_t *parent, const int x, const int y, const int w, const int h );
void widget_draw( void *obj, graphics_context_t *context );
+void widget_get_focus( void *obj, widget_t *widget );
+void widget_model_to_screen( void *obj, int *x, int *y );
+bool widget_contains_coordinate( void *obj, const int x, const int y );
+void widget_on_mouse_down( void *obj, const int x, const int y );
+void widget_on_mouse_up( void *obj, const int x, const int y );
+void widget_on_mouse_move( void *obj, const int old_x, const int old_y, const int x, const int y );
+void widget_on_key_down( void *obj, char c );
+void widget_on_key_up( void *obj, char c );
#endif // WIDGET_H