/* * draw * * Windowed graphical drawing tool. * Simple painting application. * * This is also the playground for the work-in-progress * ToaruToolKit GUI toolkit. */ #include #include "lib/window.h" #include "lib/graphics.h" #include "lib/list.h" #include "lib/shmemfonts.h" #include "lib/decorations.h" /* XXX TOOLKIT FUNCTIONS */ gfx_context_t * ctx; window_t * wina; /* Active TTK window XXX */ static window_t * ttk_window = NULL; /* TTK Window's objects XXX */ static list_t * ttk_objects = NULL; #define TTK_BUTTON_TYPE 0x00000001 /* * Core TTK GUI object */ typedef struct { uint32_t type; /* Object type indicator (for introspection) */ int32_t x; /* Coordinates */ int32_t y; int32_t width; /* Sizes */ int32_t height; void (*render_func)(void *); /* (Internal) function to render the object */ void (*click_callback)(void *, w_mouse_t *); /* Callback function for clicking */ } ttk_object; /* TTK Button */ typedef struct { ttk_object _super; /* Parent type (Object -> Button) */ char * title; /* Button text */ uint32_t fill_color; /* Fill color */ uint32_t fore_color; /* Text color */ } ttk_button; void ttk_render_button(void * s) { ttk_object * self = (ttk_object *)s; /* Fill the button */ for (uint16_t y = self->y + 1; y < self->y + self->height; y++) { draw_line(ctx, self->x, self->x + self->width, y, y, ((ttk_button *)self)->fill_color); } /* Then draw the border */ uint32_t border_color = rgb(0,0,0); draw_line(ctx, self->x, self->x + self->width, self->y, self->y, border_color); draw_line(ctx, self->x, self->x, self->y, self->y + self->height, border_color); draw_line(ctx, self->x + self->width, self->x + self->width, self->y, self->y + self->height, border_color); draw_line(ctx, self->x, self->x + self->width, self->y + self->height, self->y + self->height, border_color); /* button-specific stuff */ uint32_t w = draw_string_width(((ttk_button * )self)->title); uint16_t offset = (self->width - w) / 2; draw_string(ctx, self->x + offset, self->y + self->height - 3, ((ttk_button *)self)->fore_color, ((ttk_button * )self)->title); } ttk_button * ttk_new_button(char * title, void (*callback)(void *, w_mouse_t *)) { ttk_button * out = malloc(sizeof(ttk_button)); out->title = title; out->fill_color = rgb(100,100,100); /* Standard */ ttk_object * obj = (ttk_object *)out; obj->click_callback = callback;; obj->render_func = ttk_render_button; obj->type = TTK_BUTTON_TYPE; obj->x = 0; obj->y = 0; obj->width = 20; obj->height = 20; list_insert(ttk_objects, obj); return out; } /* * Reposition a TTK object */ void ttk_position(ttk_object * obj, int x, int y, int width, int height) { obj->x = x; obj->y = y; obj->width = width; obj->height = height; } int ttk_within(ttk_object * obj, w_mouse_t * evt) { if (evt->new_x >= obj->x && evt->new_x < obj->x + obj->width && evt->new_y >= obj->y && evt->new_y < obj->y + obj->height) { return 1; } return 0; } void ttk_check_click(w_mouse_t * evt) { if (evt->command == WE_MOUSECLICK) { foreach(node, ttk_objects) { ttk_object * obj = (ttk_object *)node->value; if (ttk_within(obj, evt)) { if (obj->click_callback) { obj->click_callback(obj, evt); } } } } } void ttk_render() { foreach(node, ttk_objects) { ttk_object * obj = (ttk_object *)node->value; if (obj->render_func) { obj->render_func(obj); } } } void setup_ttk(window_t * window) { ttk_window = window; ttk_objects = list_create(); mouse_action_callback = ttk_check_click; init_shmemfonts(); } uint32_t drawing_color = 0; uint16_t quit = 0; static void set_color(void * button, w_mouse_t * event) { ttk_button * self = (ttk_button *)button; drawing_color = self->fill_color; } static void quit_app(void * button, w_mouse_t * event) { quit = 1; teardown_windowing(); exit(0); } ttk_button * button_thick; ttk_button * button_thin; int thick = 0; static void set_thickness_thick(void * button, w_mouse_t * event) { button_thick->fill_color = rgb(127,127,127); button_thick->fore_color = rgb(255,255,255); button_thin->fill_color = rgb(40,40,40); button_thin->fore_color = rgb(255,255,255); thick = 1; ttk_render(); } static void set_thickness_thin(void * button, w_mouse_t * event) { button_thin->fill_color = rgb(127,127,127); button_thin->fore_color = rgb(255,255,255); button_thick->fill_color = rgb(40,40,40); button_thick->fore_color = rgb(255,255,255); thick = 0; ttk_render(); } void decors(window_t * win) { render_decorations(win, win->buffer, "Draw!"); } void resize_callback(window_t * window) { reinit_graphics_window(ctx, wina); decors(wina); ttk_render(); } int main (int argc, char ** argv) { int left = 30; int top = 30; int width = 450; int height = 450; setup_windowing(); resize_window_callback = resize_callback; /* Do something with a window */ wina = window_create(left, top, width, height); ctx = init_graphics_window(wina); draw_fill(ctx, rgb(255,255,255)); init_decorations(); win_use_threaded_handler(); setup_ttk(wina); ttk_button * button_blue = ttk_new_button("Blue", set_color); ttk_position((ttk_object *)button_blue, decor_left_width + 3, decor_top_height + 3, 100, 20); button_blue->fill_color = rgb(0,0,255); button_blue->fore_color = rgb(255,255,255); ttk_button * button_green = ttk_new_button("Green", set_color); ttk_position((ttk_object *)button_green, decor_left_width + 106, decor_top_height + 3, 100, 20); button_green->fill_color = rgb(0,255,0); button_green->fore_color = rgb(0,0,0); ttk_button * button_red = ttk_new_button("Red", set_color); ttk_position((ttk_object *)button_red, decor_left_width + 209, decor_top_height + 3, 100, 20); button_red->fill_color = rgb(255,0,0); button_red->fore_color = rgb(255,255,255); button_thick = ttk_new_button("Thick", set_thickness_thick); ttk_position((ttk_object *)button_thick, decor_left_width + 312, decor_top_height + 3, 50, 20); button_thick->fill_color = rgb(40,40,40); button_thick->fore_color = rgb(255,255,255); button_thin = ttk_new_button("Thin", set_thickness_thin); ttk_position((ttk_object *)button_thin, decor_left_width + 362, decor_top_height + 3, 50, 20); button_thin->fill_color = rgb(127,127,127); button_thin->fore_color = rgb(255,255,255); ttk_button * button_quit = ttk_new_button("X", quit_app); ttk_position((ttk_object *)button_quit, width - 23, 2, 20, 20); button_quit->fill_color = rgb(255,0,0); button_quit->fore_color = rgb(255,255,255); drawing_color = rgb(255,0,0); decors(wina); ttk_render(); while (!quit) { w_keyboard_t * kbd = poll_keyboard(); if (kbd != NULL) { if (kbd->key == 'q') { break; } free(kbd); } w_mouse_t * mouse = poll_mouse(); if (mouse != NULL) { if (mouse->command == WE_MOUSEMOVE && mouse->buttons & MOUSE_BUTTON_LEFT) { if (thick) { draw_line_thick(ctx, mouse->old_x, mouse->new_x, mouse->old_y, mouse->new_y, drawing_color, 2); } else { draw_line(ctx, mouse->old_x, mouse->new_x, mouse->old_y, mouse->new_y, drawing_color); } decors(wina); ttk_render(); } free(mouse); } syscall_yield(); } teardown_windowing(); return 0; }