view examples/calculator/main.c @ 88:dd813dcc232c

New example, calculator.
author Thinker K.F. Li <thinker@branda.to>
date Sat, 23 Aug 2008 15:26:47 +0800
parents
children 90428161fc61
line wrap: on
line source

#include <stdio.h>
#include <mb_types.h>
#include <X_supp.h>
#include <shapes.h>
#include <tools.h>
#include "calculator_scr.h"

typedef struct _ex_rt ex_rt_t;
struct _ex_rt {
    X_MB_runtime_t *rt;
    calculator_scr_t *code;
};

static struct {
    int c;
    int off;
} tgt_list[] = {
    { 0, OFFSET(calculator_scr_t, but_0) },
    { 1, OFFSET(calculator_scr_t, but_1) },
    { 2, OFFSET(calculator_scr_t, but_2) },
    { 3, OFFSET(calculator_scr_t, but_3) },
    { 4, OFFSET(calculator_scr_t, but_4) },
    { 5, OFFSET(calculator_scr_t, but_5) },
    { 6, OFFSET(calculator_scr_t, but_6) },
    { 7, OFFSET(calculator_scr_t, but_7) },
    { 8, OFFSET(calculator_scr_t, but_8) },
    { 9, OFFSET(calculator_scr_t, but_9) },
    { '+', OFFSET(calculator_scr_t, but_add) },
    { '-', OFFSET(calculator_scr_t, but_minus) },
    { '*', OFFSET(calculator_scr_t, but_mul) },
    { '/', OFFSET(calculator_scr_t, but_div) },
    { '=', OFFSET(calculator_scr_t, but_eq) },
    { 'c', OFFSET(calculator_scr_t, but_clr) }
};

static int real_compute(int op, int v1, int v2) {
    int r = v2;

    switch(op) {
    case '+':
	r = v1 + v2;
	break;
    case '-':
	r = v1 - v2;
	break;
    case '*':
	r = v1 * v2;
	break;
    case '/':
	r = v1 / v2;
	break;
    }

    return r;
}

static void show_text(ex_rt_t *ex_rt, int num) {
    char buf[20];

    sprintf(buf, "%d", num);
    sh_text_set_text(ex_rt->code->screen_text, buf);
    rdman_shape_changed(ex_rt->rt->rdman, ex_rt->code->screen_text);
}

static void compute(ex_rt_t *ex_rt, coord_t *tgt) {
    int i;
    coord_t **coord_p;
    static int num = 0;
    static int saved = 0;
    static int op = 0;

    for(i = 0; i < 16; i++) {
	coord_p = (coord_t **)((void *)ex_rt->code + tgt_list[i].off);
	if(*coord_p == (void *)tgt)
	    break;
    }
    if(i >= 16) return;

    if(i < 10) {
	num = num * 10 + i;
	show_text(ex_rt, num);
    } else {
	switch(tgt_list[i].c) {
	case 'c':
	    saved = num = 0;
	    show_text(ex_rt, 0);
	    break;

	case '+':
	    saved = real_compute(op, saved, num);
	    show_text(ex_rt, saved);
	    op = '+';
	    num = 0;
	    break;

	case '-':
	    saved = real_compute(op, saved, num);
	    show_text(ex_rt, saved);
	    op = '-';
	    num = 0;
	    break;

	case '*':
	    saved = real_compute(op, saved, num);
	    show_text(ex_rt, saved);
	    op = '*';
	    num = 0;
	    break;

	case '/':
	    saved = real_compute(op, saved, num);
	    show_text(ex_rt, saved);
	    op = '/';
	    num = 0;
	    break;

	case '=':
	    saved = real_compute(op, saved, num);
	    show_text(ex_rt, saved);
	    num = 0;
	    break;
	}
    }
    rdman_redraw_changed(ex_rt->rt->rdman);
}

static void buttons_handler(event_t *evt, void *arg) {
    ex_rt_t *ex_rt = (ex_rt_t *)arg;

    switch(evt->type) {
    case EVT_MOUSE_BUT_PRESS:
	compute(ex_rt, (coord_t *)evt->cur_tgt);
	break;
    }
}

static void setup_observers(ex_rt_t *ex_rt) {
    calculator_scr_t *calculator_scr;
    ob_factory_t *factory;
    subject_t *subject;

    calculator_scr = ex_rt->code;
    factory = rdman_get_ob_factory(ex_rt->rt->rdman);

    subject = coord_get_mouse_event(calculator_scr->but_0);
    subject_add_observer(factory, subject, buttons_handler, ex_rt);
    subject = coord_get_mouse_event(calculator_scr->but_1);
    subject_add_observer(factory, subject, buttons_handler, ex_rt);
    subject = coord_get_mouse_event(calculator_scr->but_2);
    subject_add_observer(factory, subject, buttons_handler, ex_rt);
    subject = coord_get_mouse_event(calculator_scr->but_3);
    subject_add_observer(factory, subject, buttons_handler, ex_rt);
    subject = coord_get_mouse_event(calculator_scr->but_4);
    subject_add_observer(factory, subject, buttons_handler, ex_rt);
    subject = coord_get_mouse_event(calculator_scr->but_5);
    subject_add_observer(factory, subject, buttons_handler, ex_rt);
    subject = coord_get_mouse_event(calculator_scr->but_6);
    subject_add_observer(factory, subject, buttons_handler, ex_rt);
    subject = coord_get_mouse_event(calculator_scr->but_7);
    subject_add_observer(factory, subject, buttons_handler, ex_rt);
    subject = coord_get_mouse_event(calculator_scr->but_8);
    subject_add_observer(factory, subject, buttons_handler, ex_rt);
    subject = coord_get_mouse_event(calculator_scr->but_9);
    subject_add_observer(factory, subject, buttons_handler, ex_rt);
    subject = coord_get_mouse_event(calculator_scr->but_add);
    subject_add_observer(factory, subject, buttons_handler, ex_rt);
    subject = coord_get_mouse_event(calculator_scr->but_minus);
    subject_add_observer(factory, subject, buttons_handler, ex_rt);
    subject = coord_get_mouse_event(calculator_scr->but_mul);
    subject_add_observer(factory, subject, buttons_handler, ex_rt);
    subject = coord_get_mouse_event(calculator_scr->but_div);
    subject_add_observer(factory, subject, buttons_handler, ex_rt);
    subject = coord_get_mouse_event(calculator_scr->but_eq);
    subject_add_observer(factory, subject, buttons_handler, ex_rt);
    subject = coord_get_mouse_event(calculator_scr->but_clr);
    subject_add_observer(factory, subject, buttons_handler, ex_rt);
}

int main(int argc, char * const argv[]) {
    X_MB_runtime_t rt;
    calculator_scr_t *calculator_scr;
    ex_rt_t ex_rt;
    int r;

    r = X_MB_init(":0.0", 300, 400, &rt);

    calculator_scr = calculator_scr_new(rt.rdman);

    ex_rt.rt = &rt;
    ex_rt.code = calculator_scr;
    setup_observers(&ex_rt);

    X_MB_handle_connection(&rt);

    calculator_scr_free(calculator_scr);
    X_MB_destroy(&rt);

    return 0;
}