summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2004-10-26 19:56:19 +0000
committerKeith Packard <keithp@keithp.com>2004-10-26 19:56:19 +0000
commit89ad67caa2f0e8454ccacb8efa2bd1eee94c0566 (patch)
tree8592d14fbe37f3ebcc825e8ea4b5bf92bf30986d
parentc29f62fcb77cd79f4a4739e0cdc241aed539ed4c (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--ChangeLog30
-rw-r--r--Makefile.am1
-rw-r--r--twin.h37
-rw-r--r--twin_button.c155
-rw-r--r--twin_hello.c9
-rw-r--r--twin_hello.h33
-rw-r--r--twin_label.c28
-rw-r--r--twin_widget.c9
-rw-r--r--twin_window.c44
-rw-r--r--twinint.h30
-rw-r--r--xtwin.c3
11 files changed, 341 insertions, 38 deletions
diff --git a/ChangeLog b/ChangeLog
index 08af913..b192df2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 \
diff --git a/twin.h b/twin.h
index 01bac97..3f71940 100644
--- a/twin.h
+++ b/twin.h
@@ -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;
diff --git a/twinint.h b/twinint.h
index 7cd994a..30bb235 100644
--- a/twinint.h
+++ b/twinint.h
@@ -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_ */
diff --git a/xtwin.c b/xtwin.c
index 47ea4de..5a544d4 100644
--- a/xtwin.c
+++ b/xtwin.c
@@ -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;
}