summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2004-10-27 20:09:36 +0000
committerKeith Packard <keithp@keithp.com>2004-10-27 20:09:36 +0000
commit143d1a70aab4e551bccece0fe8845f7be77fb8d9 (patch)
tree0803b77840d76b90a401a83e24b275917fd09765
parent4e67aeb9a6aaf0852ab9b6aba46c21cb483cdf54 (diff)
Add calculator and missing header files
Change type name from twin_layout_t to twin_box_dir_t Create new twin_widget_layout_t holding layout preferences. Add copy_geom field to widget to make widgets look the same Add button signals and signal proc. Fix box layout to sum stretch along axis and minimize normal Add calculator demo
-rw-r--r--ChangeLog28
-rw-r--r--Makefile.am7
-rw-r--r--twin.h72
-rw-r--r--twin_box.c133
-rw-r--r--twin_button.c22
-rw-r--r--twin_calc.c239
-rw-r--r--twin_calc.h35
-rw-r--r--twin_label.c20
-rw-r--r--twin_toplevel.c2
-rw-r--r--twin_widget.c47
-rw-r--r--twinint.h6
-rw-r--r--xtwin.c5
12 files changed, 494 insertions, 122 deletions
diff --git a/ChangeLog b/ChangeLog
index 3992356..e20625d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+2004-10-27 Keith Packard <keithp@keithp.com>
+
+ * Makefile.am:
+ Add calculator and missing header files
+
+ * twin.h:
+ * twin_box.c: (_twin_box_init), (_twin_box_query_geometry),
+ (_twin_box_configure), (_twin_box_dispatch), (twin_box_create):
+ * twin_button.c: (_twin_button_dispatch), (_twin_button_init):
+ * twin_toplevel.c: (_twin_toplevel_init):
+ * twin_widget.c: (_twin_widget_dispatch), (_twin_widget_init),
+ * twin_label.c: (_twin_label_query_geometry),
+ (_twin_label_dispatch), (_twin_label_init):
+ * twinint.h:
+ (twin_widget_create):
+ Change type name from twin_layout_t to twin_box_dir_t
+ Create new twin_widget_layout_t holding layout preferences.
+ Add copy_geom field to widget to make widgets look the same
+ Add button signals and signal proc.
+ Fix box layout to sum stretch along axis and minimize normal
+
+ * twin_calc.c: (_twin_calc_button_to_id),
+ (_twin_calc_update_value), (_twin_calc_push), (_twin_calc_pop),
+ (_twin_calc_digit), (_twin_calc_button_signal), (twin_calc_start):
+ * twin_calc.h:
+ * xtwin.c: (main):
+ Add calculator demo
+
2004-10-26 Keith Packard <keithp@keithp.com>
* twin_button.c: (_twin_button_paint):
diff --git a/Makefile.am b/Makefile.am
index 78b41b7..547a2f9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -44,11 +44,18 @@ xtwin_SOURCES = \
twin_window.c \
twin_work.c \
twin_x11.c \
+ twin_x11.h \
twinint.h \
twin_clock.c \
+ twin_clock.h \
+ twin_calc.c \
+ twin_calc.h \
twin_text.c \
+ twin_text.h \
twin_demo.c \
+ twin_demo.h \
twin_hello.c \
+ twin_hello.h \
xtwin.c
xtwin_LDADD = @X_LIBS@ -lm
diff --git a/twin.h b/twin.h
index 3f71940..f425c5f 100644
--- a/twin.h
+++ b/twin.h
@@ -372,37 +372,42 @@ typedef struct _twin_box twin_box_t;
#define _twin_widget_height(w) (((twin_widget_t *)(w))->extents.bottom - \
((twin_widget_t *)(w))->extents.top)
+typedef enum _twin_box_dir {
+ TwinBoxHorz, TwinBoxVert
+} twin_box_dir_t;
+
typedef enum _twin_dispatch_result {
- TwinDispatchNone,
- TwinDispatchPaint,
- TwinDispatchConfigure,
+ TwinDispatchDone,
+ TwinDispatchContinue
} twin_dispatch_result_t;
-typedef enum _twin_layout {
- TwinLayoutHorz, TwinLayoutVert
-} twin_layout_t;
-
typedef twin_dispatch_result_t (*twin_dispatch_proc_t) (twin_widget_t *widget,
twin_event_t *event);
+typedef struct _twin_widget_layout {
+ twin_coord_t width;
+ twin_coord_t height;
+ twin_stretch_t stretch_width;
+ twin_stretch_t stretch_height;
+} twin_widget_layout_t;
+
struct _twin_widget {
twin_window_t *window;
twin_widget_t *next;
twin_box_t *parent;
+ twin_widget_t *copy_geom;
twin_bool_t paint;
twin_bool_t layout;
twin_bool_t want_focus;
twin_argb32_t background;
twin_rect_t extents; /* current geometry */
- twin_rect_t preferred; /* desired geometry */
- twin_stretch_t hstretch; /* stretch ratio in horizontal dir */
- twin_stretch_t vstretch; /* stretch ratio in vertical dir */
+ twin_widget_layout_t preferred;
twin_dispatch_proc_t dispatch;
};
struct _twin_box {
twin_widget_t widget;
- twin_layout_t layout;
+ twin_box_dir_t dir;
twin_widget_t *children;
twin_widget_t *button_down;
twin_widget_t *focus;
@@ -421,15 +426,42 @@ typedef struct _twin_label {
twin_point_t offset;
} twin_label_t;
-typedef void (*twin_callback_t) (twin_widget_t *widget, void *closure);
+typedef enum _twin_button_signal {
+ TwinButtonSignalDown, /* sent when button pressed */
+ TwinButtonSignalUp, /* send when button released inside widget */
+} twin_button_signal_t;
-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;
+typedef struct _twin_button twin_button_t;
+
+typedef void (*twin_button_signal_proc_t) (twin_button_t *button,
+ twin_button_signal_t signal,
+ void *closure);
+
+struct _twin_button {
+ twin_label_t label;
+ twin_bool_t pressed;
+ twin_bool_t active;
+ twin_button_signal_proc_t signal;
+ void *closure;
+};
+
+typedef enum _twin_scroll_signal {
+ TwinScrollSignalUpArrow,
+ TwinScrollSignalDownArrow,
+ TwinScrollSignalThumb,
+ TwinScrollSignalAboveThumb,
+ TwinScrollSignalBelowThumb,
+} twin_scroll_signal_t;
+
+typedef struct _twin_scroll twin_scroll_t;
+
+typedef void (*twin_scroll_signal_proc_t) (twin_scroll_t *scroll,
+ twin_scroll_signal_t signal,
+ void *closure);
+
+struct _twin_scroll {
+ twin_widget_t widget;
+};
/*
* twin_box.c
@@ -437,7 +469,7 @@ typedef struct _twin_button {
twin_box_t *
twin_box_create (twin_box_t *parent,
- twin_layout_t layout);
+ twin_box_dir_t dir);
/*
* twin_button.c
diff --git a/twin_box.c b/twin_box.c
index 85df058..9a1e043 100644
--- a/twin_box.c
+++ b/twin_box.c
@@ -28,58 +28,74 @@ void
_twin_box_init (twin_box_t *box,
twin_box_t *parent,
twin_window_t *window,
- twin_layout_t layout,
+ twin_box_dir_t dir,
twin_dispatch_proc_t dispatch)
{
- static twin_rect_t preferred = { 0, 0, 0, 0 };
- _twin_widget_init (&box->widget, parent, window, preferred, 0, 0, dispatch);
- box->layout = layout;
- box->children = 0;
+ static twin_widget_layout_t preferred = { 0, 0, 0, 0 };
+ _twin_widget_init (&box->widget, parent, window, preferred, dispatch);
+ box->dir = dir;
+ box->children = NULL;
+ box->button_down = NULL;
+ box->focus = NULL;
}
static twin_dispatch_result_t
_twin_box_query_geometry (twin_box_t *box)
{
- twin_widget_t *widget;
- twin_event_t ev;
- twin_coord_t w, h;
- twin_coord_t c_w, c_h;
+ twin_widget_t *child;
+ twin_event_t ev;
+ twin_widget_layout_t preferred;
- w = 0; h = 0;
+ preferred.width = 0;
+ preferred.height = 0;
+ if (box->dir == TwinBoxHorz)
+ {
+ preferred.stretch_width = 0;
+ preferred.stretch_height = 10000;
+ }
+ else
+ {
+ preferred.stretch_width = 10000;
+ preferred.stretch_height = 0;
+ }
/*
* Find preferred geometry
*/
- for (widget = box->children; widget; widget = widget->next)
+ for (child = box->children; child; child = child->next)
{
- ev.kind = TwinEventQueryGeometry;
- (*widget->dispatch) (widget, &ev);
- c_w = widget->preferred.right - widget->preferred.left;
- c_h = widget->preferred.bottom - widget->preferred.top;
- if (box->layout == TwinLayoutHorz)
+ if (child->layout)
+ {
+ ev.kind = TwinEventQueryGeometry;
+ (*child->dispatch) (child, &ev);
+ }
+ if (box->dir == TwinBoxHorz)
{
- w += c_w;
- if (c_h > h)
- h = c_h;
+ preferred.width += child->preferred.width;
+ preferred.stretch_width += child->preferred.stretch_width;
+ if (child->preferred.height > preferred.height)
+ preferred.height = child->preferred.height;
+ if (child->preferred.stretch_height < preferred.stretch_height)
+ preferred.stretch_height = child->preferred.stretch_height;
}
else
{
- h += c_h;
- if (c_w > w)
- w = c_w;
+ preferred.height += child->preferred.height;
+ preferred.stretch_height += child->preferred.stretch_height;
+ if (child->preferred.width > preferred.width)
+ preferred.width = child->preferred.width;
+ if (child->preferred.stretch_width < preferred.stretch_width)
+ preferred.stretch_width = child->preferred.stretch_width;
}
}
- box->widget.preferred.left = 0;
- box->widget.preferred.top = 0;
- box->widget.preferred.right = w;
- box->widget.preferred.bottom = h;
- return TwinDispatchNone;
+ box->widget.preferred = preferred;
+ return TwinDispatchContinue;
}
static twin_dispatch_result_t
_twin_box_configure (twin_box_t *box)
{
- twin_coord_t w = box->widget.extents.right - box->widget.extents.left;
- twin_coord_t h = box->widget.extents.bottom - box->widget.extents.top;
+ twin_coord_t width = _twin_widget_width (box);
+ twin_coord_t height = _twin_widget_height (box);
twin_coord_t actual;
twin_coord_t pref;
twin_coord_t delta;
@@ -87,21 +103,18 @@ _twin_box_configure (twin_box_t *box)
twin_coord_t stretch = 0;
twin_coord_t pos = 0;
twin_widget_t *child;
- twin_dispatch_result_t result = TwinDispatchNone;
- if (box->layout == TwinLayoutHorz)
+ if (box->dir == TwinBoxHorz)
{
- for (child = box->children; child; child = child->next)
- stretch += child->hstretch;
- actual = w;
- pref = box->widget.preferred.right - box->widget.preferred.left;
+ stretch = box->widget.preferred.stretch_width;
+ actual = width;
+ pref = box->widget.preferred.width;
}
else
{
- for (child = box->children; child; child = child->next)
- stretch += child->vstretch;
- actual = h;
- pref = box->widget.preferred.bottom - box->widget.preferred.top;
+ stretch = box->widget.preferred.stretch_height;
+ actual = height;
+ pref = box->widget.preferred.height;
}
if (!stretch) stretch = 1;
delta = delta_remain = actual - pref;
@@ -116,10 +129,10 @@ _twin_box_configure (twin_box_t *box)
delta_this = delta_remain;
else
{
- if (box->layout == TwinLayoutHorz)
- stretch_this = child->hstretch;
+ if (box->dir == TwinBoxHorz)
+ stretch_this = child->preferred.stretch_width;
else
- stretch_this = child->vstretch;
+ stretch_this = child->preferred.stretch_height;
delta_this = delta * stretch_this / stretch;
}
if (delta_remain < 0)
@@ -133,30 +146,33 @@ _twin_box_configure (twin_box_t *box)
delta_this = delta_remain;
}
delta_remain -= delta_this;
- if (box->layout == TwinLayoutHorz)
+ if (box->dir == TwinBoxHorz)
{
- twin_coord_t child_w = (child->preferred.right -
- child->preferred.left);
+ twin_coord_t child_w = child->preferred.width;
extents.top = 0;
- extents.bottom = h;
+ extents.bottom = height;
extents.left = pos;
pos = extents.right = pos + child_w + delta_this;
}
else
{
- twin_coord_t child_h = (child->preferred.bottom -
- child->preferred.top);
+ twin_coord_t child_h = child->preferred.height;
extents.left = 0;
- extents.right = w;
+ extents.right = width;
extents.top = pos;
pos = extents.bottom = pos + child_h + delta_this;
}
- ev.kind = TwinEventConfigure;
- ev.u.configure.extents = extents;
- (*child->dispatch) (child, &ev);
- result = TwinDispatchPaint;
+ if (extents.left != ev.u.configure.extents.left ||
+ extents.top != ev.u.configure.extents.top ||
+ extents.right != ev.u.configure.extents.right ||
+ extents.bottom != ev.u.configure.extents.bottom)
+ {
+ ev.kind = TwinEventConfigure;
+ ev.u.configure.extents = extents;
+ (*child->dispatch) (child, &ev);
+ }
}
- return result;
+ return TwinDispatchContinue;
}
static twin_widget_t *
@@ -180,11 +196,12 @@ _twin_box_dispatch (twin_widget_t *widget, twin_event_t *event)
twin_event_t ev;
twin_widget_t *child;
+ if (_twin_widget_dispatch (widget, event) == TwinDispatchDone)
+ return TwinDispatchDone;
switch (event->kind) {
case TwinEventQueryGeometry:
return _twin_box_query_geometry (box);
case TwinEventConfigure:
- _twin_widget_dispatch (widget, event);
return _twin_box_configure (box);
case TwinEventButtonDown:
box->button_down = _twin_box_xy_to_widget (box,
@@ -227,17 +244,17 @@ _twin_box_dispatch (twin_widget_t *widget, twin_event_t *event)
default:
break;
}
- return TwinDispatchNone;
+ return TwinDispatchContinue;
}
twin_box_t *
twin_box_create (twin_box_t *parent,
- twin_layout_t layout)
+ twin_box_dir_t dir)
{
twin_box_t *box = malloc (sizeof (twin_box_t));
if (!box)
return 0;
- _twin_box_init (box, parent, 0, layout, _twin_box_dispatch);
+ _twin_box_init (box, parent, 0, dir, _twin_box_dispatch);
return box;
}
diff --git a/twin_button.c b/twin_button.c
index a308abb..b340f10 100644
--- a/twin_button.c
+++ b/twin_button.c
@@ -52,16 +52,19 @@ _twin_button_dispatch (twin_widget_t *widget, twin_event_t *event)
{
twin_button_t *button = (twin_button_t *) widget;
- _twin_label_dispatch (widget, event);
+ if (_twin_label_dispatch (widget, event) == TwinDispatchDone)
+ return TwinDispatchDone;
switch (event->kind) {
case TwinEventPaint:
_twin_button_paint (button);
- return TWIN_TRUE;
+ break;
case TwinEventButtonDown:
button->pressed = TWIN_TRUE;
button->active = TWIN_TRUE;
_twin_button_set_label_offset (button);
- return TWIN_TRUE;
+ if (button->signal)
+ (*button->signal) (button, TwinButtonSignalDown, button->closure);
+ break;
case TwinEventMotion:
if (button->pressed)
{
@@ -74,21 +77,21 @@ _twin_button_dispatch (twin_widget_t *widget, twin_event_t *event)
_twin_button_set_label_offset (button);
}
}
- return TWIN_TRUE;
+ break;
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);
+ if (button->signal)
+ (*button->signal) (button, TwinButtonSignalUp, button->closure);
}
- return TWIN_TRUE;
+ break;
default:
break;
}
- return TwinDispatchNone;
+ return TwinDispatchContinue;
}
void
@@ -103,6 +106,9 @@ _twin_button_init (twin_button_t *button,
_twin_label_init (&button->label, parent, value,
foreground, font_size, font_style, dispatch);
button->pressed = TWIN_FALSE;
+ button->active = TWIN_FALSE;
+ button->signal = NULL;
+ button->closure = NULL;
_twin_button_set_label_offset (button);
}
diff --git a/twin_calc.c b/twin_calc.c
new file mode 100644
index 0000000..56af91c
--- /dev/null
+++ b/twin_calc.c
@@ -0,0 +1,239 @@
+/*
+ * $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 "twin_calc.h"
+#include <stdio.h>
+
+#define TWIN_CALC_STACK 5
+#define TWIN_CALC_ZERO 0
+#define TWIN_CALC_ONE 1
+#define TWIN_CALC_TWO 2
+#define TWIN_CALC_THREE 3
+#define TWIN_CALC_FOUR 4
+#define TWIN_CALC_FIVE 5
+#define TWIN_CALC_SIX 6
+#define TWIN_CALC_SEVEN 7
+#define TWIN_CALC_EIGHT 8
+#define TWIN_CALC_NINE 9
+#define TWIN_CALC_PLUS 10
+#define TWIN_CALC_MINUS 11
+#define TWIN_CALC_TIMES 12
+#define TWIN_CALC_DIVIDE 13
+#define TWIN_CALC_EQUAL 14
+#define TWIN_CALC_CLEAR 15
+#define TWIN_CALC_NBUTTON 16
+
+/*
+ * Layout:
+ *
+ * display
+ *
+ * 7 8 9 +
+ * 4 5 6 -
+ * 1 2 3 *
+ * 0 clr = ÷
+ */
+#define TWIN_CALC_COLS 4
+#define TWIN_CALC_ROWS 4
+
+const static int calc_layout[TWIN_CALC_ROWS][TWIN_CALC_COLS] = {
+ { TWIN_CALC_SEVEN, TWIN_CALC_EIGHT, TWIN_CALC_NINE, TWIN_CALC_PLUS },
+ { TWIN_CALC_FOUR, TWIN_CALC_FIVE, TWIN_CALC_SIX, TWIN_CALC_MINUS },
+ { TWIN_CALC_ONE, TWIN_CALC_TWO, TWIN_CALC_THREE, TWIN_CALC_TIMES },
+ { TWIN_CALC_ZERO, TWIN_CALC_CLEAR, TWIN_CALC_EQUAL, TWIN_CALC_DIVIDE },
+};
+
+typedef struct _twin_calc {
+ int stack[TWIN_CALC_STACK];
+ int pending_op;
+ twin_bool_t pending_delete;
+ twin_window_t *window;
+ twin_toplevel_t *toplevel;
+ twin_box_t *keys;
+ twin_box_t *cols[4];
+ twin_label_t *display;
+ twin_button_t *buttons[TWIN_CALC_NBUTTON];
+} twin_calc_t;
+
+static const char *twin_calc_labels[] = {
+ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
+ "+", "-", "*", "/", "=", "CLR"
+};
+
+#define TWIN_CALC_VALUE_SIZE twin_int_to_fixed(24)
+#define TWIN_CALC_VALUE_STYLE TWIN_TEXT_BOLD
+#define TWIN_CALC_VALUE_FG 0xff000000
+#define TWIN_CALC_VALUE_BG 0xc0c0c0c0
+#define TWIN_CALC_BUTTON_SIZE twin_int_to_fixed(15)
+#define TWIN_CALC_BUTTON_STYLE TWIN_TEXT_BOLD
+#define TWIN_CALC_BUTTON_FG 0xff000000
+#define TWIN_CALC_BUTTON_BG 0xc0808080
+
+static int
+_twin_calc_button_to_id (twin_calc_t *calc, twin_button_t *button)
+{
+ int i;
+
+ for (i = 0; i < TWIN_CALC_NBUTTON; i++)
+ if (calc->buttons[i] == button)
+ return i;
+ return -1;
+}
+
+static void
+_twin_calc_update_value (twin_calc_t *calc)
+{
+ char v[20];
+
+ sprintf (v, "%d", calc->stack[0]);
+ twin_label_set (calc->display, v, TWIN_CALC_VALUE_FG,
+ TWIN_CALC_VALUE_SIZE, TWIN_CALC_VALUE_STYLE);
+}
+
+static void
+_twin_calc_push (twin_calc_t *calc)
+{
+ int i;
+
+ for (i = 0; i < TWIN_CALC_STACK - 1; i++)
+ calc->stack[i+1] = calc->stack[i];
+ calc->pending_delete = TWIN_TRUE;
+}
+
+static int
+_twin_calc_pop (twin_calc_t *calc)
+{
+ int i;
+ int v = calc->stack[0];
+ for (i = 0; i < TWIN_CALC_STACK - 1; i++)
+ calc->stack[i] = calc->stack[i+1];
+ return v;
+}
+
+static void
+_twin_calc_digit (twin_calc_t *calc, int digit)
+{
+ if (calc->pending_delete)
+ {
+ calc->stack[0] = 0;
+ calc->pending_delete = TWIN_FALSE;
+ }
+ calc->stack[0] = calc->stack[0] * 10 + digit;
+ _twin_calc_update_value (calc);
+}
+
+static void
+_twin_calc_button_signal (twin_button_t *button,
+ twin_button_signal_t signal,
+ void *closure)
+{
+ twin_calc_t *calc = closure;
+ int i;
+ int a, b;
+
+ if (signal != TwinButtonSignalDown) return;
+ i = _twin_calc_button_to_id (calc, button);
+ if (i < 0) return;
+ switch (i) {
+ case TWIN_CALC_PLUS:
+ case TWIN_CALC_MINUS:
+ case TWIN_CALC_TIMES:
+ case TWIN_CALC_DIVIDE:
+ calc->pending_op = i;
+ _twin_calc_push (calc);
+ break;
+ case TWIN_CALC_EQUAL:
+ if (calc->pending_op != 0)
+ {
+ b = _twin_calc_pop (calc);
+ a = _twin_calc_pop (calc);
+ switch (calc->pending_op) {
+ case TWIN_CALC_PLUS: a = a + b; break;
+ case TWIN_CALC_MINUS: a = a - b; break;
+ case TWIN_CALC_TIMES: a = a * b; break;
+ case TWIN_CALC_DIVIDE: if (!b) a = 0; else a = a / b; break;
+ }
+ _twin_calc_push (calc);
+ calc->stack[0] = a;
+ _twin_calc_update_value (calc);
+ calc->pending_op = 0;
+ }
+ calc->pending_delete = TWIN_TRUE;
+ break;
+ case TWIN_CALC_CLEAR:
+ for (i = 0; i < TWIN_CALC_STACK; i++)
+ calc->stack[i] = 0;
+ calc->pending_op = 0;
+ calc->pending_delete = TWIN_TRUE;
+ _twin_calc_update_value (calc);
+ break;
+ default:
+ _twin_calc_digit (calc, i);
+ break;
+ }
+}
+
+void
+twin_calc_start (twin_screen_t *screen, const char *name, int x, int y, int w, int h)
+{
+ twin_calc_t *calc = malloc (sizeof (twin_calc_t));
+ int i, j;
+
+ calc->toplevel = twin_toplevel_create (screen,
+ TWIN_ARGB32,
+ TwinWindowApplication,
+ x, y, w, h, name);
+ calc->display = twin_label_create (&calc->toplevel->box,
+ "0",
+ TWIN_CALC_VALUE_FG,
+ TWIN_CALC_VALUE_SIZE,
+ TWIN_CALC_VALUE_STYLE);
+ twin_widget_set (&calc->display->widget, TWIN_CALC_VALUE_BG);
+ calc->keys = twin_box_create (&calc->toplevel->box, TwinBoxHorz);
+ for (i = 0; i < TWIN_CALC_COLS; i++)
+ {
+ calc->cols[i] = twin_box_create (calc->keys, TwinBoxVert);
+ for (j = 0; j < TWIN_CALC_ROWS; j++)
+ {
+ int b = calc_layout[j][i];
+ calc->buttons[b] = twin_button_create (calc->cols[i],
+ twin_calc_labels[b],
+ TWIN_CALC_BUTTON_FG,
+ TWIN_CALC_BUTTON_SIZE,
+ TWIN_CALC_BUTTON_STYLE);
+ twin_widget_set (&calc->buttons[b]->label.widget,
+ TWIN_CALC_BUTTON_BG);
+ calc->buttons[b]->signal = _twin_calc_button_signal;
+ calc->buttons[b]->closure = calc;
+ if (i || j)
+ calc->buttons[b]->label.widget.copy_geom = &calc->buttons[calc_layout[0][0]]->label.widget;
+ }
+ }
+
+ for (i = 0; i < TWIN_CALC_STACK; i++)
+ calc->stack[i] = 0;
+ calc->pending_delete = TWIN_TRUE;
+ calc->pending_op = 0;
+ twin_toplevel_show (calc->toplevel);
+}
diff --git a/twin_calc.h b/twin_calc.h
new file mode 100644
index 0000000..0d3df7d
--- /dev/null
+++ b/twin_calc.h
@@ -0,0 +1,35 @@
+/*
+ * $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 <twin.h>
+
+#ifndef _TWIN_CALC_H_
+#define _TWIN_CALC_H_
+
+#include <twin.h>
+
+void
+twin_calc_start (twin_screen_t *screen, const char *name, int x, int y, int w, int h);
+
+#endif /* _TWIN_CALC_H_ */
diff --git a/twin_label.c b/twin_label.c
index 6d013ee..6d74160 100644
--- a/twin_label.c
+++ b/twin_label.c
@@ -30,16 +30,14 @@ _twin_label_query_geometry (twin_label_t *label)
twin_path_t *path = twin_path_create ();
twin_text_metrics_t m;
- label->widget.preferred.left = 0;
- label->widget.preferred.top = 0;
- label->widget.preferred.right = twin_fixed_to_int (label->font_size);
- label->widget.preferred.bottom = twin_fixed_to_int (label->font_size) * 2;
+ label->widget.preferred.width = twin_fixed_to_int (label->font_size) * 2;
+ label->widget.preferred.height = twin_fixed_to_int (label->font_size) * 2;
if (path)
{
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);
- label->widget.preferred.right += twin_fixed_to_int (m.width);
+ label->widget.preferred.width += twin_fixed_to_int (m.width);
twin_path_destroy (path);
}
}
@@ -74,18 +72,19 @@ _twin_label_dispatch (twin_widget_t *widget, twin_event_t *event)
{
twin_label_t *label = (twin_label_t *) widget;
- _twin_widget_dispatch (widget, event);
+ if (_twin_widget_dispatch (widget, event) == TwinDispatchDone)
+ return TwinDispatchDone;
switch (event->kind) {
case TwinEventPaint:
_twin_label_paint (label);
- return TwinDispatchNone;
+ break;
case TwinEventQueryGeometry:
_twin_label_query_geometry (label);
break;
default:
break;
}
- return TwinDispatchNone;
+ return TwinDispatchContinue;
}
void
@@ -122,9 +121,8 @@ _twin_label_init (twin_label_t *label,
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, dispatch);
+ static const twin_widget_layout_t preferred = { 0, 0, 1, 1 };
+ _twin_widget_init (&label->widget, parent, 0, preferred, dispatch);
label->label = NULL;
label->offset.x = 0;
label->offset.y = 0;
diff --git a/twin_toplevel.c b/twin_toplevel.c
index 5527a1e..42de014 100644
--- a/twin_toplevel.c
+++ b/twin_toplevel.c
@@ -91,7 +91,7 @@ _twin_toplevel_init (twin_toplevel_t *toplevel,
window->destroy = _twin_toplevel_destroy;
window->event = _twin_toplevel_event;
window->client_data = toplevel;
- _twin_box_init (&toplevel->box, 0, window, TwinLayoutVert, dispatch);
+ _twin_box_init (&toplevel->box, 0, window, TwinBoxVert, dispatch);
}
twin_toplevel_t *
diff --git a/twin_widget.c b/twin_widget.c
index cc0e12a..c9b0ed9 100644
--- a/twin_widget.c
+++ b/twin_widget.c
@@ -41,9 +41,19 @@ twin_dispatch_result_t
_twin_widget_dispatch (twin_widget_t *widget, twin_event_t *event)
{
switch (event->kind) {
+ case TwinEventQueryGeometry:
+ widget->layout = TWIN_FALSE;
+ if (widget->copy_geom)
+ {
+ twin_widget_t *copy = widget->copy_geom;
+ if (copy->layout)
+ (*copy->dispatch) (copy, event);
+ widget->preferred = copy->preferred;
+ return TwinDispatchDone;
+ }
+ break;
case TwinEventConfigure:
widget->extents = event->u.configure.extents;
- widget->layout = TWIN_FALSE;
break;
case TwinEventPaint:
_twin_widget_paint (widget);
@@ -52,16 +62,14 @@ _twin_widget_dispatch (twin_widget_t *widget, twin_event_t *event)
default:
break;
}
- return TwinDispatchNone;
+ return TwinDispatchContinue;
}
void
_twin_widget_init (twin_widget_t *widget,
twin_box_t *parent,
twin_window_t *window,
- twin_rect_t preferred,
- twin_stretch_t hstretch,
- twin_stretch_t vstretch,
+ twin_widget_layout_t preferred,
twin_dispatch_proc_t dispatch)
{
if (parent)
@@ -77,13 +85,15 @@ _twin_widget_init (twin_widget_t *widget,
widget->next = NULL;
widget->window = window;
widget->parent = parent;
+ widget->copy_geom = NULL;
widget->paint = TWIN_TRUE;
+ widget->layout = TWIN_TRUE;
+ widget->want_focus = TWIN_FALSE;
+ widget->background = 0x00000000;
+ widget->extents.left = widget->extents.top = 0;
+ widget->extents.right = widget->extents.bottom = 0;
widget->preferred = preferred;
- widget->extents = preferred;
- widget->hstretch = hstretch;
- widget->vstretch = vstretch;
widget->dispatch = dispatch;
- widget->background = 0x00000000;
}
void
@@ -171,20 +181,19 @@ twin_widget_create (twin_box_t *parent,
twin_argb32_t background,
twin_coord_t width,
twin_coord_t height,
- twin_stretch_t hstretch,
- twin_stretch_t vstretch)
+ twin_stretch_t stretch_width,
+ twin_stretch_t stretch_height)
{
- twin_widget_t *widget = malloc (sizeof (twin_widget_t));
- twin_rect_t extents;
+ twin_widget_t *widget = malloc (sizeof (twin_widget_t));
+ twin_widget_layout_t preferred;
if (!widget)
return NULL;
- extents.left = 0;
- extents.top = 0;
- extents.right = width;
- extents.bottom = height;
- _twin_widget_init (widget, parent, 0, extents, hstretch, vstretch,
- _twin_widget_dispatch);
+ preferred.width = width;
+ preferred.height = height;
+ preferred.stretch_width = stretch_width;
+ preferred.stretch_height = stretch_height;
+ _twin_widget_init (widget, parent, 0, preferred, _twin_widget_dispatch);
widget->background = background;
return widget;
}
diff --git a/twinint.h b/twinint.h
index 4063948..c970d0b 100644
--- a/twinint.h
+++ b/twinint.h
@@ -455,7 +455,7 @@ void
_twin_box_init (twin_box_t *box,
twin_box_t *parent,
twin_window_t *window,
- twin_layout_t layout,
+ twin_box_dir_t dir,
twin_dispatch_proc_t dispatch);
twin_dispatch_result_t
@@ -465,9 +465,7 @@ void
_twin_widget_init (twin_widget_t *widget,
twin_box_t *parent,
twin_window_t *window,
- twin_rect_t preferred,
- twin_stretch_t hstretch,
- twin_stretch_t vstretch,
+ twin_widget_layout_t preferred,
twin_dispatch_proc_t dispatch);
twin_dispatch_result_t
diff --git a/xtwin.c b/xtwin.c
index 5a544d4..e656019 100644
--- a/xtwin.c
+++ b/xtwin.c
@@ -33,6 +33,7 @@
#include <twin_text.h>
#include <twin_demo.h>
#include <twin_hello.h>
+#include <twin_calc.h>
#define WIDTH 512
#define HEIGHT 512
@@ -49,9 +50,11 @@ main (int argc, char **argv)
twin_clock_start (x11->screen, "Clock", 10, 10, 200, 200);
twin_text_start (x11->screen, "Gettysburg Address",
0, 0, 300, 300);
-#endif
twin_hello_start (x11->screen, "Hello, World",
0, 0, 200, 200);
+#endif
+ twin_calc_start (x11->screen, "Calculator",
+ 100, 100, 200, 200);
twin_dispatch ();
return 0;
}