2014-04-16 06:45:56 +04:00
|
|
|
|
2012-07-07 08:08:28 +04:00
|
|
|
/*
|
|
|
|
* draw
|
|
|
|
*
|
|
|
|
* Windowed graphical drawing tool.
|
|
|
|
* Simple painting application.
|
|
|
|
*
|
|
|
|
* This is also the playground for the work-in-progress
|
|
|
|
* ToaruToolKit GUI toolkit.
|
|
|
|
*/
|
2012-04-13 07:42:24 +04:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
2014-04-16 06:45:56 +04:00
|
|
|
#include "lib/yutani.h"
|
2013-04-08 03:21:00 +04:00
|
|
|
#include "gui/ttk/ttk.h"
|
2012-04-13 10:21:01 +04:00
|
|
|
#include "lib/list.h"
|
|
|
|
|
|
|
|
/* XXX TOOLKIT FUNCTIONS */
|
|
|
|
|
Context-based graphics library.
All graphics library commands now take a gfx_context_t pointer, which
points to a simple datastructure describing a rendering context (width,
height, depth, total size, front buffer, backbuffer; where backbuffer =
front buffer when not in double-buffering mode, thus we always render to
backbuffer except on a flip). This may have caused a minor speed
reduction, but I don't really care as it's far more important that we
support multiple graphics contexts.
TODO:
- Shared Memory Fonts library (there are a couple of apps that use these
so-called "shmem fonts" on their own; we need a dedicated library for
them)
- Break off "TTK" GUI toolkit into its own library. Since it's just a
callback-based button framework, this shouldn't be too hard right now.
Also, with the previous tick, I'll be able to put labels on controls
and start using text in more places.
2012-04-17 22:21:34 +04:00
|
|
|
gfx_context_t * ctx;
|
2014-04-16 06:45:56 +04:00
|
|
|
yutani_window_t * wina;
|
|
|
|
yutani_t * yctx;
|
Context-based graphics library.
All graphics library commands now take a gfx_context_t pointer, which
points to a simple datastructure describing a rendering context (width,
height, depth, total size, front buffer, backbuffer; where backbuffer =
front buffer when not in double-buffering mode, thus we always render to
backbuffer except on a flip). This may have caused a minor speed
reduction, but I don't really care as it's far more important that we
support multiple graphics contexts.
TODO:
- Shared Memory Fonts library (there are a couple of apps that use these
so-called "shmem fonts" on their own; we need a dedicated library for
them)
- Break off "TTK" GUI toolkit into its own library. Since it's just a
callback-based button framework, this shouldn't be too hard right now.
Also, with the previous tick, I'll be able to put labels on controls
and start using text in more places.
2012-04-17 22:21:34 +04:00
|
|
|
|
2012-04-14 07:20:36 +04:00
|
|
|
/* Active TTK window XXX */
|
2014-04-16 08:16:46 +04:00
|
|
|
static yutani_window_t * ttk_window = NULL;
|
2012-04-14 07:20:36 +04:00
|
|
|
|
|
|
|
/* TTK Window's objects XXX */
|
2012-04-13 10:21:01 +04:00
|
|
|
static list_t * ttk_objects = NULL;
|
|
|
|
|
2013-04-08 03:21:00 +04:00
|
|
|
#define TTK_BUTTON_TYPE 0x00000001
|
|
|
|
#define TTK_RAW_SURFACE_TYPE 0x00000002
|
|
|
|
|
|
|
|
#define TTK_BUTTON_STATE_NORMAL 0
|
|
|
|
#define TTK_BUTTON_STATE_DOWN 1
|
2012-04-14 07:20:36 +04:00
|
|
|
|
2014-04-16 06:45:56 +04:00
|
|
|
cairo_surface_t * internal_surface;
|
|
|
|
|
2012-04-14 07:20:36 +04:00
|
|
|
/*
|
|
|
|
* Core TTK GUI object
|
|
|
|
*/
|
2012-04-13 10:21:01 +04:00
|
|
|
typedef struct {
|
2012-04-14 07:20:36 +04:00
|
|
|
uint32_t type; /* Object type indicator (for introspection) */
|
|
|
|
int32_t x; /* Coordinates */
|
2012-04-13 10:21:01 +04:00
|
|
|
int32_t y;
|
2012-04-14 07:20:36 +04:00
|
|
|
int32_t width; /* Sizes */
|
2012-04-13 10:21:01 +04:00
|
|
|
int32_t height;
|
2013-04-08 03:21:00 +04:00
|
|
|
void (*render_func)(void *, cairo_t * cr); /* (Internal) function to render the object */
|
2014-04-16 06:45:56 +04:00
|
|
|
void (*click_callback)(void *, struct yutani_msg_window_mouse_event *); /* Callback function for clicking */
|
2012-04-13 10:21:01 +04:00
|
|
|
} ttk_object;
|
|
|
|
|
2012-04-14 07:20:36 +04:00
|
|
|
/* TTK Button */
|
2012-04-13 10:21:01 +04:00
|
|
|
typedef struct {
|
2012-04-14 07:20:36 +04:00
|
|
|
ttk_object _super; /* Parent type (Object -> Button) */
|
|
|
|
char * title; /* Button text */
|
|
|
|
uint32_t fill_color; /* Fill color */
|
2012-04-17 22:46:46 +04:00
|
|
|
uint32_t fore_color; /* Text color */
|
2013-04-08 03:21:00 +04:00
|
|
|
int button_state;
|
2012-04-13 10:21:01 +04:00
|
|
|
} ttk_button;
|
|
|
|
|
2013-04-08 03:21:00 +04:00
|
|
|
typedef struct {
|
|
|
|
ttk_object _super;
|
|
|
|
gfx_context_t * surface;
|
|
|
|
} ttk_raw_surface;
|
|
|
|
|
|
|
|
void ttk_render_button(void * s, cairo_t * cr) {
|
2012-04-13 10:21:01 +04:00
|
|
|
ttk_object * self = (ttk_object *)s;
|
2013-04-08 03:21:00 +04:00
|
|
|
|
|
|
|
if (((ttk_button *)self)->button_state == TTK_BUTTON_STATE_DOWN) {
|
|
|
|
_ttk_draw_button_select(cr, self->x, self->y, self->width, self->height, ((ttk_button *)self)->title);
|
|
|
|
} else {
|
|
|
|
_ttk_draw_button(cr, self->x, self->y, self->width, self->height, ((ttk_button *)self)->title);
|
|
|
|
}
|
|
|
|
#if 0
|
2012-04-14 07:20:36 +04:00
|
|
|
/* Fill the button */
|
2012-04-13 10:21:01 +04:00
|
|
|
for (uint16_t y = self->y + 1; y < self->y + self->height; y++) {
|
Context-based graphics library.
All graphics library commands now take a gfx_context_t pointer, which
points to a simple datastructure describing a rendering context (width,
height, depth, total size, front buffer, backbuffer; where backbuffer =
front buffer when not in double-buffering mode, thus we always render to
backbuffer except on a flip). This may have caused a minor speed
reduction, but I don't really care as it's far more important that we
support multiple graphics contexts.
TODO:
- Shared Memory Fonts library (there are a couple of apps that use these
so-called "shmem fonts" on their own; we need a dedicated library for
them)
- Break off "TTK" GUI toolkit into its own library. Since it's just a
callback-based button framework, this shouldn't be too hard right now.
Also, with the previous tick, I'll be able to put labels on controls
and start using text in more places.
2012-04-17 22:21:34 +04:00
|
|
|
draw_line(ctx, self->x, self->x + self->width, y, y, ((ttk_button *)self)->fill_color);
|
2012-04-13 10:21:01 +04:00
|
|
|
}
|
2012-04-14 07:20:36 +04:00
|
|
|
/* Then draw the border */
|
2012-04-13 10:21:01 +04:00
|
|
|
uint32_t border_color = rgb(0,0,0);
|
Context-based graphics library.
All graphics library commands now take a gfx_context_t pointer, which
points to a simple datastructure describing a rendering context (width,
height, depth, total size, front buffer, backbuffer; where backbuffer =
front buffer when not in double-buffering mode, thus we always render to
backbuffer except on a flip). This may have caused a minor speed
reduction, but I don't really care as it's far more important that we
support multiple graphics contexts.
TODO:
- Shared Memory Fonts library (there are a couple of apps that use these
so-called "shmem fonts" on their own; we need a dedicated library for
them)
- Break off "TTK" GUI toolkit into its own library. Since it's just a
callback-based button framework, this shouldn't be too hard right now.
Also, with the previous tick, I'll be able to put labels on controls
and start using text in more places.
2012-04-17 22:21:34 +04:00
|
|
|
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);
|
2012-04-17 22:46:46 +04:00
|
|
|
/* button-specific stuff */
|
2012-04-17 22:55:54 +04:00
|
|
|
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);
|
2013-04-08 03:21:00 +04:00
|
|
|
#endif
|
2012-04-13 10:21:01 +04:00
|
|
|
}
|
|
|
|
|
2013-04-08 03:21:00 +04:00
|
|
|
void ttk_render_raw_surface(void * s, cairo_t * cr) {
|
|
|
|
ttk_object * self = (ttk_object *)s;
|
|
|
|
|
|
|
|
gfx_context_t * surface = ((ttk_raw_surface *)self)->surface;
|
|
|
|
|
|
|
|
{
|
|
|
|
cairo_save(cr);
|
|
|
|
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, surface->width);
|
|
|
|
cairo_surface_t * internal_surface = cairo_image_surface_create_for_data(surface->backbuffer, CAIRO_FORMAT_ARGB32, surface->width, surface->height, stride);
|
|
|
|
|
|
|
|
cairo_set_source_surface(cr, internal_surface, self->x, self->y);
|
|
|
|
cairo_paint(cr);
|
|
|
|
|
|
|
|
cairo_surface_destroy(internal_surface);
|
|
|
|
cairo_restore(cr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-16 06:45:56 +04:00
|
|
|
ttk_button * ttk_button_new(char * title, void (*callback)(void *, struct yutani_msg_window_mouse_event *)) {
|
2012-04-13 10:21:01 +04:00
|
|
|
ttk_button * out = malloc(sizeof(ttk_button));
|
|
|
|
out->title = title;
|
|
|
|
out->fill_color = rgb(100,100,100);
|
2013-04-08 03:21:00 +04:00
|
|
|
out->button_state = TTK_BUTTON_STATE_NORMAL;
|
2012-04-13 10:21:01 +04:00
|
|
|
|
|
|
|
/* Standard */
|
|
|
|
ttk_object * obj = (ttk_object *)out;
|
2013-04-09 07:44:42 +04:00
|
|
|
obj->click_callback = callback;
|
2012-04-13 10:21:01 +04:00
|
|
|
obj->render_func = ttk_render_button;
|
2012-04-14 07:20:36 +04:00
|
|
|
obj->type = TTK_BUTTON_TYPE;
|
|
|
|
obj->x = 0;
|
|
|
|
obj->y = 0;
|
|
|
|
obj->width = 20;
|
|
|
|
obj->height = 20;
|
2012-04-13 10:21:01 +04:00
|
|
|
|
|
|
|
list_insert(ttk_objects, obj);
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2013-04-09 07:44:42 +04:00
|
|
|
static cairo_surface_t * close_button_sprite;
|
|
|
|
void ttk_render_decor_button_close(void * s, cairo_t * cr) {
|
|
|
|
cairo_save(cr);
|
|
|
|
cairo_set_source_rgb(cr, 244.0, 244.0, 244.0);
|
|
|
|
|
|
|
|
double x = ((ttk_object *)s)->x;
|
|
|
|
double y = ((ttk_object *)s)->y;
|
|
|
|
|
|
|
|
cairo_set_source_surface(cr, close_button_sprite, x + 1, y + 1);
|
|
|
|
cairo_paint(cr);
|
|
|
|
|
|
|
|
cairo_restore(cr);
|
|
|
|
}
|
|
|
|
|
2014-04-16 06:45:56 +04:00
|
|
|
ttk_button * ttk_decor_button_close(void (*callback)(void *, struct yutani_msg_window_mouse_event *)) {
|
2013-04-09 07:44:42 +04:00
|
|
|
if (!close_button_sprite) {
|
|
|
|
close_button_sprite = cairo_image_surface_create_from_png("/usr/share/ttk/common/button-close.png"); /* TTK_PATH ? something less dumb? */
|
|
|
|
}
|
|
|
|
ttk_button * out = ttk_button_new("Close" /* For future tooltips */, callback);
|
|
|
|
((ttk_object *)out)->render_func = ttk_render_decor_button_close;
|
|
|
|
((ttk_object *)out)->width = 10;
|
|
|
|
((ttk_object *)out)->height = 10;
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2013-04-08 03:21:00 +04:00
|
|
|
ttk_raw_surface * ttk_raw_surface_new(int width, int height) {
|
|
|
|
ttk_raw_surface * out = malloc(sizeof(ttk_raw_surface));
|
|
|
|
|
|
|
|
ttk_object * obj = (ttk_object *)out;
|
|
|
|
|
|
|
|
out->surface = malloc(sizeof(gfx_context_t));
|
|
|
|
out->surface->width = width;
|
|
|
|
out->surface->height = height;
|
|
|
|
out->surface->depth = 32;
|
|
|
|
out->surface->buffer = malloc(sizeof(uint32_t) * width * height);
|
|
|
|
out->surface->backbuffer = out->surface->buffer;
|
|
|
|
|
|
|
|
draw_fill(out->surface, rgb(255,255,255));
|
|
|
|
|
|
|
|
obj->width = width;
|
|
|
|
obj->height = height;
|
|
|
|
obj->x = 10;
|
|
|
|
obj->y = 10;
|
|
|
|
|
|
|
|
obj->click_callback = NULL;
|
|
|
|
obj->type = TTK_RAW_SURFACE_TYPE;
|
|
|
|
|
|
|
|
obj->render_func = ttk_render_raw_surface;
|
|
|
|
|
|
|
|
list_insert(ttk_objects, obj);
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2012-04-14 07:20:36 +04:00
|
|
|
/*
|
|
|
|
* Reposition a TTK object
|
|
|
|
*/
|
2012-04-13 10:21:01 +04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-04-16 06:45:56 +04:00
|
|
|
int ttk_within(ttk_object * obj, struct yutani_msg_window_mouse_event * evt) {
|
2012-04-13 10:21:01 +04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-04-16 06:45:56 +04:00
|
|
|
void ttk_check_click(struct yutani_msg_window_mouse_event * evt) {
|
|
|
|
if (evt->command == YUTANI_MOUSE_EVENT_CLICK) {
|
2012-04-13 10:21:01 +04:00
|
|
|
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() {
|
2013-04-08 03:21:00 +04:00
|
|
|
/* XXX */
|
|
|
|
ttk_window_t _window;
|
|
|
|
ttk_window_t * window = &_window;
|
2014-04-16 06:45:56 +04:00
|
|
|
|
2013-04-08 03:21:00 +04:00
|
|
|
window->core_context = ctx;
|
2014-04-25 09:38:27 +04:00
|
|
|
window->core_window = ttk_window;
|
2013-04-08 03:21:00 +04:00
|
|
|
window->width = ctx->width; // - decor_width();
|
|
|
|
window->height = ctx->height; //- decor_height();
|
|
|
|
window->off_x = 0; //decor_left_width;
|
|
|
|
window->off_y = 0; //decor_top_height;
|
|
|
|
window->title = "Draw!";
|
|
|
|
|
|
|
|
draw_fill(ctx, rgb(TTK_BACKGROUND_DEFAULT));
|
|
|
|
ttk_redraw_borders(window);
|
|
|
|
|
|
|
|
{
|
|
|
|
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, window->core_window->width);
|
|
|
|
cairo_surface_t * core_surface = cairo_image_surface_create_for_data(window->core_context->backbuffer, CAIRO_FORMAT_ARGB32, window->core_window->width, window->core_window->height, stride);
|
|
|
|
cairo_t * cr_main = cairo_create(core_surface);
|
|
|
|
|
|
|
|
/* TODO move this surface to a ttk_frame_t or something; GUIs man, go look at some Qt or GTK APIs! */
|
|
|
|
cairo_surface_t * internal_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, window->width, window->height);
|
|
|
|
cairo_t * cr = cairo_create(internal_surface);
|
|
|
|
|
|
|
|
foreach(node, ttk_objects) {
|
|
|
|
ttk_object * obj = (ttk_object *)node->value;
|
|
|
|
if (obj->render_func) {
|
|
|
|
obj->render_func(obj, cr);
|
|
|
|
}
|
2012-04-13 10:21:01 +04:00
|
|
|
}
|
2013-04-08 03:21:00 +04:00
|
|
|
|
|
|
|
/* Paint the window's internal surface onto the backbuffer */
|
|
|
|
cairo_set_source_surface(cr_main, internal_surface, (double)window->off_x, (double)window->off_y);
|
|
|
|
cairo_paint(cr_main);
|
|
|
|
cairo_surface_flush(internal_surface);
|
|
|
|
cairo_destroy(cr);
|
|
|
|
cairo_surface_destroy(internal_surface);
|
|
|
|
|
|
|
|
/* In theory, we don't actually want to destroy much of any of this; maybe the cairo_t */
|
|
|
|
cairo_surface_flush(core_surface);
|
|
|
|
cairo_destroy(cr_main);
|
|
|
|
cairo_surface_destroy(core_surface);
|
2012-04-13 10:21:01 +04:00
|
|
|
}
|
2013-04-08 03:21:00 +04:00
|
|
|
|
|
|
|
flip(window->core_context);
|
2014-04-16 06:45:56 +04:00
|
|
|
yutani_flip(yctx, wina);
|
2012-04-13 10:21:01 +04:00
|
|
|
}
|
|
|
|
|
2014-04-16 08:16:46 +04:00
|
|
|
void setup_ttk(yutani_window_t * window) {
|
2012-04-13 10:21:01 +04:00
|
|
|
ttk_window = window;
|
|
|
|
ttk_objects = list_create();
|
2012-04-17 22:46:46 +04:00
|
|
|
init_shmemfonts();
|
2012-04-13 10:21:01 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t drawing_color = 0;
|
2012-04-14 07:20:36 +04:00
|
|
|
uint16_t quit = 0;
|
2012-04-13 10:21:01 +04:00
|
|
|
|
2013-04-08 03:21:00 +04:00
|
|
|
ttk_button * button_red;
|
|
|
|
ttk_button * button_green;
|
|
|
|
ttk_button * button_blue;
|
2014-04-17 10:50:57 +04:00
|
|
|
ttk_button * close_button;
|
2013-04-08 03:21:00 +04:00
|
|
|
|
|
|
|
ttk_button * button_thick;
|
|
|
|
ttk_button * button_thin;
|
|
|
|
ttk_raw_surface * drawing_surface;
|
|
|
|
int thick = 0;
|
|
|
|
|
2014-04-16 06:45:56 +04:00
|
|
|
static void set_color(void * button, struct yutani_msg_window_mouse_event * event) {
|
2012-04-13 10:21:01 +04:00
|
|
|
ttk_button * self = (ttk_button *)button;
|
2013-04-08 03:21:00 +04:00
|
|
|
|
|
|
|
if (button_blue != self) button_blue->button_state = TTK_BUTTON_STATE_NORMAL;
|
|
|
|
if (button_red != self) button_red->button_state = TTK_BUTTON_STATE_NORMAL;
|
|
|
|
if (button_green != self) button_green->button_state = TTK_BUTTON_STATE_NORMAL;
|
|
|
|
|
|
|
|
self->button_state = TTK_BUTTON_STATE_DOWN;
|
2012-04-13 10:21:01 +04:00
|
|
|
drawing_color = self->fill_color;
|
2013-04-08 03:21:00 +04:00
|
|
|
|
|
|
|
ttk_render();
|
2012-04-13 10:21:01 +04:00
|
|
|
}
|
2012-04-13 07:42:24 +04:00
|
|
|
|
2014-04-16 06:45:56 +04:00
|
|
|
static void quit_app(void * button, struct yutani_msg_window_mouse_event * event) {
|
2012-04-14 07:20:36 +04:00
|
|
|
quit = 1;
|
|
|
|
}
|
|
|
|
|
2014-04-16 06:45:56 +04:00
|
|
|
static void set_thickness_thick(void * button, struct yutani_msg_window_mouse_event * event) {
|
2013-04-08 03:21:00 +04:00
|
|
|
#if 0
|
2012-04-18 01:06:44 +04:00
|
|
|
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);
|
2013-04-08 03:21:00 +04:00
|
|
|
#endif
|
|
|
|
button_thick->button_state = TTK_BUTTON_STATE_DOWN;
|
|
|
|
button_thin->button_state = TTK_BUTTON_STATE_NORMAL;
|
2012-04-18 01:06:44 +04:00
|
|
|
thick = 1;
|
|
|
|
ttk_render();
|
|
|
|
}
|
|
|
|
|
2014-04-16 06:45:56 +04:00
|
|
|
static void set_thickness_thin(void * button, struct yutani_msg_window_mouse_event * event) {
|
2013-04-08 03:21:00 +04:00
|
|
|
#if 0
|
2012-04-18 01:06:44 +04:00
|
|
|
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);
|
2013-04-08 03:21:00 +04:00
|
|
|
#endif
|
|
|
|
button_thin->button_state = TTK_BUTTON_STATE_DOWN;
|
|
|
|
button_thick->button_state = TTK_BUTTON_STATE_NORMAL;
|
2012-04-18 01:06:44 +04:00
|
|
|
thick = 0;
|
|
|
|
ttk_render();
|
|
|
|
}
|
|
|
|
|
2014-04-17 11:24:54 +04:00
|
|
|
static void resize_finish(int width, int height) {
|
|
|
|
yutani_window_resize_accept(yctx, wina, width, height);
|
2014-04-17 10:50:57 +04:00
|
|
|
reinit_graphics_yutani(ctx, wina);
|
|
|
|
((ttk_object *)close_button)->x = wina->width - 28;
|
|
|
|
ttk_render();
|
|
|
|
yutani_window_resize_done(yctx, wina);
|
|
|
|
yutani_flip(yctx, wina);
|
|
|
|
}
|
|
|
|
|
2014-04-17 11:24:54 +04:00
|
|
|
static void resize_button(void * button, struct yutani_msg_window_mouse_event * event) {
|
|
|
|
yutani_window_resize(yctx, wina, 600, 600);
|
|
|
|
yutani_msg_t * m = yutani_wait_for(yctx, YUTANI_MSG_RESIZE_OFFER);
|
|
|
|
struct yutani_msg_window_resize * wr = (void*)m->data;
|
|
|
|
resize_finish(wr->width, wr->height);
|
|
|
|
free(m);
|
|
|
|
}
|
|
|
|
|
2014-04-16 06:45:56 +04:00
|
|
|
void keep_drawing(struct yutani_msg_window_mouse_event * mouse) {
|
2013-04-08 03:21:00 +04:00
|
|
|
double thickness = thick ? 2.0 : 0.5;;
|
|
|
|
|
|
|
|
int old_x = mouse->old_x - ((ttk_object *)drawing_surface)->x;
|
|
|
|
int old_y = mouse->old_y - ((ttk_object *)drawing_surface)->y;
|
|
|
|
|
|
|
|
int new_x = mouse->new_x - ((ttk_object *)drawing_surface)->x;
|
|
|
|
int new_y = mouse->new_y - ((ttk_object *)drawing_surface)->y;
|
|
|
|
|
|
|
|
{
|
|
|
|
cairo_t * cr = cairo_create(internal_surface);
|
|
|
|
|
|
|
|
cairo_set_source_rgb(cr, _RED(drawing_color) / 255.0, _GRE(drawing_color) / 255.0, _BLU(drawing_color) / 255.0);
|
|
|
|
cairo_set_line_width(cr, thickness);
|
|
|
|
|
|
|
|
cairo_move_to(cr, old_x, old_y);
|
|
|
|
cairo_line_to(cr, new_x, new_y);
|
|
|
|
|
|
|
|
cairo_stroke(cr);
|
|
|
|
|
|
|
|
cairo_destroy(cr);
|
2014-04-16 06:45:56 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, wina->width);
|
|
|
|
cairo_surface_t * core_surface = cairo_image_surface_create_for_data(ctx->backbuffer, CAIRO_FORMAT_ARGB32, wina->width, wina->height, stride);
|
|
|
|
cairo_t * cr = cairo_create(core_surface);
|
|
|
|
|
|
|
|
cairo_rectangle(cr, ((ttk_object*)drawing_surface)->x, ((ttk_object*)drawing_surface)->y, ((ttk_object*)drawing_surface)->width, ((ttk_object*)drawing_surface)->height);
|
|
|
|
cairo_clip(cr);
|
|
|
|
|
|
|
|
cairo_set_source_rgb(cr, _RED(drawing_color) / 255.0, _GRE(drawing_color) / 255.0, _BLU(drawing_color) / 255.0);
|
|
|
|
cairo_set_line_width(cr, thickness);
|
|
|
|
|
|
|
|
cairo_move_to(cr, old_x + ((ttk_object*)drawing_surface)->x, old_y + ((ttk_object*)drawing_surface)->y);
|
|
|
|
cairo_line_to(cr, new_x + ((ttk_object*)drawing_surface)->x, new_y + ((ttk_object*)drawing_surface)->y);
|
|
|
|
|
|
|
|
cairo_stroke(cr);
|
|
|
|
cairo_destroy(cr);
|
|
|
|
cairo_surface_destroy(core_surface);
|
|
|
|
|
|
|
|
flip(ctx);
|
2013-04-08 03:21:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-04-13 07:42:24 +04:00
|
|
|
int main (int argc, char ** argv) {
|
|
|
|
int left = 30;
|
|
|
|
int top = 30;
|
|
|
|
|
|
|
|
int width = 450;
|
|
|
|
int height = 450;
|
|
|
|
|
2014-04-16 06:45:56 +04:00
|
|
|
yctx = yutani_init();
|
2012-10-14 07:44:59 +04:00
|
|
|
|
2012-04-13 07:42:24 +04:00
|
|
|
/* Do something with a window */
|
2014-04-16 06:45:56 +04:00
|
|
|
wina = yutani_window_create(yctx, width, height);
|
|
|
|
|
|
|
|
ctx = init_graphics_yutani_double_buffer(wina);
|
2014-04-25 09:38:27 +04:00
|
|
|
draw_fill(ctx, rgba(0,0,0,0));
|
|
|
|
|
2012-04-18 00:34:34 +04:00
|
|
|
init_decorations();
|
2012-04-13 07:42:24 +04:00
|
|
|
|
2014-05-04 00:20:16 +04:00
|
|
|
yutani_window_advertise_icon(yctx, wina, "Draw!", "applications-painting");
|
2012-04-13 07:42:24 +04:00
|
|
|
|
2014-04-18 11:18:19 +04:00
|
|
|
setup_ttk(wina);
|
2013-04-09 07:44:42 +04:00
|
|
|
|
2014-04-25 09:38:27 +04:00
|
|
|
|
2014-04-17 10:50:57 +04:00
|
|
|
close_button = ttk_decor_button_close(quit_app);
|
2013-04-09 07:44:42 +04:00
|
|
|
|
|
|
|
((ttk_object *)close_button)->x = width - 28;
|
|
|
|
((ttk_object *)close_button)->y = 16;
|
|
|
|
|
2013-04-08 03:21:00 +04:00
|
|
|
button_blue = ttk_button_new("Blue", set_color);
|
2012-04-18 00:34:34 +04:00
|
|
|
ttk_position((ttk_object *)button_blue, decor_left_width + 3, decor_top_height + 3, 100, 20);
|
2012-04-13 10:21:01 +04:00
|
|
|
button_blue->fill_color = rgb(0,0,255);
|
2012-04-17 22:46:46 +04:00
|
|
|
button_blue->fore_color = rgb(255,255,255);
|
2012-04-13 10:21:01 +04:00
|
|
|
|
2013-04-08 03:21:00 +04:00
|
|
|
button_green = ttk_button_new("Green", set_color);
|
2012-04-18 00:34:34 +04:00
|
|
|
ttk_position((ttk_object *)button_green, decor_left_width + 106, decor_top_height + 3, 100, 20);
|
2012-04-13 10:21:01 +04:00
|
|
|
button_green->fill_color = rgb(0,255,0);
|
2012-04-17 22:46:46 +04:00
|
|
|
button_green->fore_color = rgb(0,0,0);
|
2012-04-13 10:21:01 +04:00
|
|
|
|
2013-04-08 03:21:00 +04:00
|
|
|
button_red = ttk_button_new("Red", set_color);
|
2012-04-18 00:34:34 +04:00
|
|
|
ttk_position((ttk_object *)button_red, decor_left_width + 209, decor_top_height + 3, 100, 20);
|
2012-04-13 10:21:01 +04:00
|
|
|
button_red->fill_color = rgb(255,0,0);
|
2012-04-17 22:46:46 +04:00
|
|
|
button_red->fore_color = rgb(255,255,255);
|
2012-04-13 10:21:01 +04:00
|
|
|
|
2013-04-08 03:21:00 +04:00
|
|
|
button_thick = ttk_button_new("Thick", set_thickness_thick);
|
2012-04-18 01:06:44 +04:00
|
|
|
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);
|
|
|
|
|
2013-04-08 03:21:00 +04:00
|
|
|
button_thin = ttk_button_new("Thin", set_thickness_thin);
|
2012-04-18 01:06:44 +04:00
|
|
|
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);
|
|
|
|
|
2014-04-17 11:24:54 +04:00
|
|
|
ttk_button * button_resize = ttk_button_new("*", resize_button);
|
|
|
|
ttk_position((ttk_object *)button_resize, decor_left_width + 410, decor_top_height + 3, 20, 20);
|
|
|
|
button_resize->fill_color = rgb(127,127,127);
|
|
|
|
button_resize->fore_color = rgb(255,255,255);
|
2012-04-14 07:20:36 +04:00
|
|
|
|
2013-04-08 03:21:00 +04:00
|
|
|
drawing_surface = ttk_raw_surface_new(width - 30, height - 70);
|
|
|
|
((ttk_object *)drawing_surface)->y = 60;
|
|
|
|
|
2014-04-16 06:45:56 +04:00
|
|
|
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, drawing_surface->surface->width);
|
|
|
|
internal_surface = cairo_image_surface_create_for_data(drawing_surface->surface->backbuffer, CAIRO_FORMAT_ARGB32, drawing_surface->surface->width, drawing_surface->surface->height, stride);
|
|
|
|
|
2012-04-13 10:21:01 +04:00
|
|
|
drawing_color = rgb(255,0,0);
|
|
|
|
|
|
|
|
ttk_render();
|
|
|
|
|
2012-04-14 07:20:36 +04:00
|
|
|
while (!quit) {
|
2014-04-16 06:45:56 +04:00
|
|
|
yutani_msg_t * m = yutani_poll(yctx);
|
|
|
|
if (m) {
|
|
|
|
switch (m->type) {
|
|
|
|
case YUTANI_MSG_KEY_EVENT:
|
|
|
|
{
|
|
|
|
struct yutani_msg_key_event * ke = (void*)m->data;
|
|
|
|
if (ke->event.action == KEY_ACTION_DOWN && ke->event.keycode == 'q') {
|
|
|
|
quit = 1;
|
|
|
|
break;
|
2013-04-08 03:21:00 +04:00
|
|
|
}
|
2014-04-16 06:45:56 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case YUTANI_MSG_WINDOW_FOCUS_CHANGE:
|
|
|
|
{
|
|
|
|
struct yutani_msg_window_focus_change * wf = (void*)m->data;
|
|
|
|
yutani_window_t * win = hashmap_get(yctx->windows, (void*)wf->wid);
|
|
|
|
if (win) {
|
|
|
|
win->focused = wf->focused;
|
|
|
|
ttk_render();
|
2013-04-08 03:21:00 +04:00
|
|
|
}
|
2014-04-16 06:45:56 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case YUTANI_MSG_WINDOW_MOUSE_EVENT:
|
|
|
|
{
|
|
|
|
struct yutani_msg_window_mouse_event * me = (void*)m->data;
|
|
|
|
if (me->command == YUTANI_MOUSE_EVENT_DRAG && me->buttons & YUTANI_MOUSE_BUTTON_LEFT) {
|
|
|
|
keep_drawing(me);
|
|
|
|
yutani_flip(yctx, wina);
|
|
|
|
} else if (me->command == YUTANI_MOUSE_EVENT_RAISE) {
|
|
|
|
ttk_render();
|
|
|
|
} else {
|
|
|
|
ttk_check_click(me);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2014-04-17 11:24:54 +04:00
|
|
|
case YUTANI_MSG_RESIZE_OFFER:
|
|
|
|
{
|
|
|
|
struct yutani_msg_window_resize * wr = (void*)m->data;
|
|
|
|
resize_finish(wr->width, wr->height);
|
|
|
|
}
|
|
|
|
break;
|
2014-04-19 06:23:45 +04:00
|
|
|
case YUTANI_MSG_SESSION_END:
|
|
|
|
quit = 1;
|
|
|
|
break;
|
2014-04-16 06:45:56 +04:00
|
|
|
default:
|
|
|
|
break;
|
2012-04-13 07:42:24 +04:00
|
|
|
}
|
2014-04-16 06:45:56 +04:00
|
|
|
free(m);
|
2012-04-13 07:42:24 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-16 06:45:56 +04:00
|
|
|
yutani_close(yctx, wina);
|
2012-04-13 07:42:24 +04:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|