diff options
author | Keith Packard <keithp@keithp.com> | 2004-10-26 19:56:19 +0000 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2004-10-26 19:56:19 +0000 |
commit | 89ad67caa2f0e8454ccacb8efa2bd1eee94c0566 (patch) | |
tree | 8592d14fbe37f3ebcc825e8ea4b5bf92bf30986d | |
parent | c29f62fcb77cd79f4a4739e0cdc241aed539ed4c (diff) |
Add button widget
Grab button down inside client area. Add button widget
Test button widget
Permit subclassing; add offset to make text shift in button
Add _twin_widget_contains to test inclusion
Grab button down inside client area
Make hello window larger
-rw-r--r-- | ChangeLog | 30 | ||||
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | twin.h | 37 | ||||
-rw-r--r-- | twin_button.c | 155 | ||||
-rw-r--r-- | twin_hello.c | 9 | ||||
-rw-r--r-- | twin_hello.h | 33 | ||||
-rw-r--r-- | twin_label.c | 28 | ||||
-rw-r--r-- | twin_widget.c | 9 | ||||
-rw-r--r-- | twin_window.c | 44 | ||||
-rw-r--r-- | twinint.h | 30 | ||||
-rw-r--r-- | xtwin.c | 3 |
11 files changed, 341 insertions, 38 deletions
@@ -1,3 +1,33 @@ +2004-10-26 Keith Packard <keithp@keithp.com> + + * Makefile.am: + * twin_button.c: (_twin_button_paint), + (_twin_button_set_label_offset), (_twin_button_dispatch), + (_twin_button_init), (twin_button_create): + Add button widget + + * twin.h: + * twinint.h: + Grab button down inside client area. + Add button widget + + * twin_hello.c: (twin_hello_start): + * twin_hello.h: + Test button widget + + * twin_label.c: (_twin_label_paint), (_twin_label_init), + (twin_label_create): + Permit subclassing; add offset to make text shift in button + + * twin_widget.c: (_twin_widget_contains): + Add _twin_widget_contains to test inclusion + + * twin_window.c: (twin_window_create), (twin_window_dispatch): + Grab button down inside client area + + * xtwin.c: (main): + Make hello window larger + 2004-10-25 Keith Packard <keithp@keithp.com> * Makefile.am: diff --git a/Makefile.am b/Makefile.am index 936b076..78b41b7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -16,6 +16,7 @@ bin_PROGRAMS = xtwin xtwin_SOURCES = \ twin.h \ twin_box.c \ + twin_button.c \ twin_convolve.c \ twin_dispatch.c \ twin_draw.c \ @@ -312,6 +312,8 @@ struct _twin_window { twin_window_style_t style; twin_rect_t client; twin_rect_t damage; + twin_bool_t client_grab; + twin_bool_t want_focus; void *client_data; char *name; @@ -364,12 +366,11 @@ typedef struct _twin_file twin_file_t; typedef struct _twin_widget twin_widget_t; typedef struct _twin_box twin_box_t; -typedef enum _twin_widget_kind_t { - TwinWidgetToplevel, - TwinWidgetBox, - TwinWidgetLabel, - TwinWidgetGlue, -} twin_widget_kind_t; +#define _twin_widget_width(w) (((twin_widget_t *)(w))->extents.right - \ + ((twin_widget_t *)(w))->extents.left) + +#define _twin_widget_height(w) (((twin_widget_t *)(w))->extents.bottom - \ + ((twin_widget_t *)(w))->extents.top) typedef enum _twin_dispatch_result { TwinDispatchNone, @@ -417,11 +418,18 @@ typedef struct _twin_label { twin_argb32_t foreground; twin_fixed_t font_size; twin_style_t font_style; + twin_point_t offset; } twin_label_t; -typedef struct _twin_glue { - twin_widget_t widget; -} twin_glue_t; +typedef void (*twin_callback_t) (twin_widget_t *widget, void *closure); + +typedef struct _twin_button { + twin_label_t label; + twin_bool_t pressed; + twin_bool_t active; + twin_callback_t callback; + void *closure; +} twin_button_t; /* * twin_box.c @@ -432,6 +440,17 @@ twin_box_create (twin_box_t *parent, twin_layout_t layout); /* + * twin_button.c + */ + +twin_button_t * +twin_button_create (twin_box_t *parent, + const char *value, + twin_argb32_t foreground, + twin_fixed_t font_size, + twin_style_t font_style); + +/* * twin_convolve.c */ void diff --git a/twin_button.c b/twin_button.c new file mode 100644 index 0000000..2cfa67d --- /dev/null +++ b/twin_button.c @@ -0,0 +1,155 @@ +/* + * $Id$ + * + * Copyright © 2004 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "twinint.h" + +#define _twin_button_bw(button) ((button)->label.font_size / 5) + +static void +_twin_button_paint (twin_button_t *button) +{ + twin_path_t *path = twin_path_create (); + twin_coord_t w = button->label.widget.extents.right - button->label.widget.extents.left; + twin_coord_t h = button->label.widget.extents.bottom - button->label.widget.extents.top; + twin_fixed_t wf = twin_int_to_fixed (w); + twin_fixed_t hf = twin_int_to_fixed (h); + twin_fixed_t bf = _twin_button_bw (button); + twin_fixed_t bh = bf / 2; + twin_argb32_t top_color, bot_color; + twin_pixmap_t *pixmap = button->label.widget.window->pixmap; + + if (path) + { + if (button->active) + { + top_color = 0x80000000; + bot_color = 0x80808080; + } + else + { + top_color = 0x80808080; + bot_color = 0x80000000; + } + twin_path_move (path, bh, hf-bh); + twin_path_draw (path, bh, bh); + twin_path_draw (path, wf-bh, bh); + twin_paint_stroke (pixmap, top_color, path, bf); + twin_path_empty (path); + twin_path_move (path, bh, hf-bh); + twin_path_draw (path, wf-bh, hf-bh); + twin_path_draw (path, wf-bh, bh); + twin_paint_stroke (pixmap, bot_color, path, bf); + twin_path_destroy (path); + } +} + +static void +_twin_button_set_label_offset (twin_button_t *button) +{ + twin_fixed_t bf = _twin_button_bw (button); + twin_fixed_t bh = bf / 2; + + if (button->active) + button->label.offset.y = button->label.offset.x = 0; + else + button->label.offset.y = button->label.offset.x = -bh; + _twin_widget_queue_paint (&button->label.widget); +} + +twin_dispatch_result_t +_twin_button_dispatch (twin_widget_t *widget, twin_event_t *event) +{ + twin_button_t *button = (twin_button_t *) widget; + + _twin_label_dispatch (widget, event); + switch (event->kind) { + case TwinEventPaint: + _twin_button_paint (button); + return TWIN_TRUE; + case TwinEventButtonDown: + button->pressed = TWIN_TRUE; + button->active = TWIN_TRUE; + _twin_button_set_label_offset (button); + return TWIN_TRUE; + case TwinEventMotion: + if (button->pressed) + { + twin_bool_t active = _twin_widget_contains (&button->label.widget, + event->u.pointer.x, + event->u.pointer.y); + if (active != button->active) + { + button->active = active; + _twin_button_set_label_offset (button); + } + } + return TWIN_TRUE; + case TwinEventButtonUp: + button->pressed = TWIN_FALSE; + if (button->active) + { + if (button->callback) + (*button->callback) (&button->label.widget, button->closure); + button->active = TWIN_FALSE; + _twin_button_set_label_offset (button); + } + return TWIN_TRUE; + default: + break; + } + return TwinDispatchNone; +} + +void +_twin_button_init (twin_button_t *button, + twin_box_t *parent, + const char *value, + twin_argb32_t foreground, + twin_fixed_t font_size, + twin_style_t font_style, + twin_dispatch_proc_t dispatch) +{ + _twin_label_init (&button->label, parent, value, + foreground, font_size, font_style, dispatch); + button->pressed = TWIN_FALSE; + _twin_button_set_label_offset (button); +} + + +twin_button_t * +twin_button_create (twin_box_t *parent, + const char *value, + twin_argb32_t foreground, + twin_fixed_t font_size, + twin_style_t font_style) +{ + twin_button_t *button = malloc (sizeof (twin_button_t)); + + if (!button) + return 0; + _twin_button_init (button, parent, value, foreground, + font_size, font_style, _twin_button_dispatch); + return button; +} + diff --git a/twin_hello.c b/twin_hello.c index c04ef08..08b9e0a 100644 --- a/twin_hello.c +++ b/twin_hello.c @@ -22,7 +22,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include <twin.h> +#include "twin_hello.h" #include <time.h> static twin_time_t @@ -58,8 +58,15 @@ twin_hello_start (twin_screen_t *screen, const char *name, int x, int y, int w, 0xff008000, twin_int_to_fixed (12), TWIN_TEXT_OBLIQUE); + twin_button_t *button = twin_button_create (&top->box, + "Button", + 0xff800000, + twin_int_to_fixed (18), + TWIN_TEXT_BOLD); twin_widget_set (&labela->widget, 0xc0c0c0c0); + (void) widget; twin_widget_set (&labelb->widget, 0xc0c0c0c0); + twin_widget_set (&button->label.widget, 0xc0808080); twin_toplevel_show (top); twin_set_timeout (_twin_hello_timeout, 1000, labelb); } diff --git a/twin_hello.h b/twin_hello.h new file mode 100644 index 0000000..810b182 --- /dev/null +++ b/twin_hello.h @@ -0,0 +1,33 @@ +/* + * $Id$ + * + * Copyright © 2004 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _TWIN_HELLO_H_ +#define _TWIN_HELLO_H_ + +#include <twin.h> + +void +twin_hello_start (twin_screen_t *screen, const char *name, int x, int y, int w, int h); + +#endif /* _TWIN_HELLO_H_ */ diff --git a/twin_label.c b/twin_label.c index 1414ed9..6d013ee 100644 --- a/twin_label.c +++ b/twin_label.c @@ -49,8 +49,8 @@ _twin_label_paint (twin_label_t *label) { twin_path_t *path = twin_path_create (); twin_text_metrics_t m; - twin_coord_t w = label->widget.extents.right - label->widget.extents.left; - twin_coord_t h = label->widget.extents.bottom - label->widget.extents.top; + twin_coord_t w = _twin_widget_width(label); + twin_coord_t h = _twin_widget_height(label); if (path) { @@ -60,8 +60,8 @@ _twin_label_paint (twin_label_t *label) twin_path_set_font_size (path, label->font_size); twin_path_set_font_style (path, label->font_style); twin_text_metrics_utf8 (path, label->label, &m); - twin_path_move (path, (wf - m.width) / 2, - (hf - (m.font_ascent + m.font_descent)) / 2 + m.font_ascent); + twin_path_move (path, (wf - m.width) / 2 + label->offset.x, + (hf - (m.ascent + m.descent)) / 2 + m.ascent + label->offset.y); twin_path_utf8 (path, label->label); twin_paint_path (label->widget.window->pixmap, label->foreground, path); @@ -114,17 +114,20 @@ twin_label_set (twin_label_t *label, } void -_twin_label_init (twin_label_t *label, - twin_box_t *parent, - const char *value, - twin_argb32_t foreground, - twin_fixed_t font_size, - twin_style_t font_style) +_twin_label_init (twin_label_t *label, + twin_box_t *parent, + const char *value, + twin_argb32_t foreground, + twin_fixed_t font_size, + twin_style_t font_style, + twin_dispatch_proc_t dispatch) { static const twin_rect_t empty = { 0, 0, 0, 0 }; _twin_widget_init (&label->widget, parent, 0, - empty, 1, 1, _twin_label_dispatch); + empty, 1, 1, dispatch); label->label = NULL; + label->offset.x = 0; + label->offset.y = 0; twin_label_set (label, value, foreground, font_size, font_style); } @@ -140,7 +143,8 @@ twin_label_create (twin_box_t *parent, if (!label) return 0; - _twin_label_init (label, parent, value, foreground, font_size, font_style); + _twin_label_init (label, parent, value, foreground, + font_size, font_style, _twin_label_dispatch); return label; } diff --git a/twin_widget.c b/twin_widget.c index cc73876..4d5cd4e 100644 --- a/twin_widget.c +++ b/twin_widget.c @@ -113,6 +113,15 @@ _twin_widget_queue_layout (twin_widget_t *widget) _twin_toplevel_queue_layout (widget); } +twin_bool_t +_twin_widget_contains (twin_widget_t *widget, + twin_coord_t x, + twin_coord_t y) +{ + return (0 <= x && x < _twin_widget_width(widget) && + 0 <= y && y < _twin_widget_height(widget)); +} + twin_widget_t * twin_widget_create (twin_box_t *parent, twin_argb32_t background, diff --git a/twin_window.c b/twin_window.c index 464d850..0f489f5 100644 --- a/twin_window.c +++ b/twin_window.c @@ -77,6 +77,8 @@ twin_window_create (twin_screen_t *screen, twin_pixmap_move (window->pixmap, x, y); window->damage.left = window->damage.right = 0; window->damage.top = window->damage.bottom = 0; + window->client_grab = TWIN_FALSE; + window->want_focus = TWIN_FALSE; window->client_data = 0; window->name = 0; @@ -337,19 +339,43 @@ twin_window_dispatch (twin_window_t *window, twin_event_t *event) switch (ev.kind) { case TwinEventButtonDown: - if (ev.u.pointer.x < window->client.left || - window->client.right <= ev.u.pointer.x || - ev.u.pointer.y < window->client.top || - window->client.bottom <= ev.u.pointer.y) + if (window->client.left <= ev.u.pointer.x && + ev.u.pointer.x < window->client.right && + window->client.top <= ev.u.pointer.y && + ev.u.pointer.y < window->client.bottom) { - delegate = TWIN_FALSE; - break; + delegate = TWIN_TRUE; + window->client_grab = TWIN_TRUE; + ev.u.pointer.x -= window->client.left; + ev.u.pointer.y -= window->client.top; } - /* fall through... */ + else + delegate = TWIN_FALSE; + break; case TwinEventButtonUp: + if (window->client_grab) + { + delegate = TWIN_TRUE; + window->client_grab = TWIN_FALSE; + ev.u.pointer.x -= window->client.left; + ev.u.pointer.y -= window->client.top; + } + else + delegate = TWIN_FALSE; + break; case TwinEventMotion: - ev.u.pointer.x -= window->client.left; - ev.u.pointer.y -= window->client.top; + if (window->client_grab || + (window->client.left <= ev.u.pointer.x && + ev.u.pointer.x < window->client.right && + window->client.top <= ev.u.pointer.y && + ev.u.pointer.y < window->client.bottom)) + { + delegate = TWIN_TRUE; + ev.u.pointer.x -= window->client.left; + ev.u.pointer.y -= window->client.top; + } + else + delegate = TWIN_FALSE; break; default: break; @@ -479,13 +479,19 @@ _twin_widget_queue_paint (twin_widget_t *widget); void _twin_widget_queue_layout (twin_widget_t *widget); +twin_bool_t +_twin_widget_contains (twin_widget_t *widget, + twin_coord_t x, + twin_coord_t y); + void -_twin_label_init (twin_label_t *label, - twin_box_t *parent, - const char *value, - twin_argb32_t foreground, - twin_fixed_t font_size, - twin_style_t font_style); +_twin_label_init (twin_label_t *label, + twin_box_t *parent, + const char *value, + twin_argb32_t foreground, + twin_fixed_t font_size, + twin_style_t font_style, + twin_dispatch_proc_t dispatch); twin_dispatch_result_t _twin_label_dispatch (twin_widget_t *widget, twin_event_t *event); @@ -505,4 +511,16 @@ _twin_toplevel_queue_paint (twin_widget_t *widget); void _twin_toplevel_queue_layout (twin_widget_t *widget); +twin_dispatch_result_t +_twin_button_dispatch (twin_widget_t *widget, twin_event_t *event); + +void +_twin_button_init (twin_button_t *button, + twin_box_t *parent, + const char *value, + twin_argb32_t foreground, + twin_fixed_t font_size, + twin_style_t font_style, + twin_dispatch_proc_t dispatch); + #endif /* _TWININT_H_ */ @@ -32,6 +32,7 @@ #include <twin_clock.h> #include <twin_text.h> #include <twin_demo.h> +#include <twin_hello.h> #define WIDTH 512 #define HEIGHT 512 @@ -50,7 +51,7 @@ main (int argc, char **argv) 0, 0, 300, 300); #endif twin_hello_start (x11->screen, "Hello, World", - 0, 0, 100, 100); + 0, 0, 200, 200); twin_dispatch (); return 0; } |