diff options
Diffstat (limited to 'fw/fe310/eos/eve/screen')
-rw-r--r-- | fw/fe310/eos/eve/screen/Makefile | 17 | ||||
-rw-r--r-- | fw/fe310/eos/eve/screen/form.c | 165 | ||||
-rw-r--r-- | fw/fe310/eos/eve/screen/form.h | 23 | ||||
-rw-r--r-- | fw/fe310/eos/eve/screen/page.c | 349 | ||||
-rw-r--r-- | fw/fe310/eos/eve/screen/page.h | 56 | ||||
-rw-r--r-- | fw/fe310/eos/eve/screen/uievt.h | 14 | ||||
-rw-r--r-- | fw/fe310/eos/eve/screen/view.c | 94 | ||||
-rw-r--r-- | fw/fe310/eos/eve/screen/view.h | 42 | ||||
-rw-r--r-- | fw/fe310/eos/eve/screen/window.c | 300 | ||||
-rw-r--r-- | fw/fe310/eos/eve/screen/window.h | 60 |
10 files changed, 1120 insertions, 0 deletions
diff --git a/fw/fe310/eos/eve/screen/Makefile b/fw/fe310/eos/eve/screen/Makefile new file mode 100644 index 0000000..cc4a81d --- /dev/null +++ b/fw/fe310/eos/eve/screen/Makefile @@ -0,0 +1,17 @@ +include ../../../common.mk + +CFLAGS += -I.. -I../.. + +obj = window.o view.o page.o form.o + + +%.o: %.c %.h + $(CC) $(CFLAGS) -c $< + +%.o: %.S + $(CC) $(CFLAGS) -c $< + +all: $(obj) + +clean: + rm -f *.o diff --git a/fw/fe310/eos/eve/screen/form.c b/fw/fe310/eos/eve/screen/form.c new file mode 100644 index 0000000..8555158 --- /dev/null +++ b/fw/fe310/eos/eve/screen/form.c @@ -0,0 +1,165 @@ +#include <stdlib.h> +#include <string.h> + +#include "eve.h" +#include "eve_kbd.h" +#include "eve_font.h" + +#include "window.h" +#include "page.h" +#include "form.h" + +#include "widget/widgets.h" + +#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) +#define MAX(X, Y) (((X) > (Y)) ? (X) : (Y)) + +static void form_update_g(EVEForm *form, EVEWidget *_widget) { + EVEPage *page = &form->p; + EVEWidget *widget = page->widget; + int i; + uint16_t w = 0; + uint16_t h = 0; + uint16_t l_h = 0; + + for (i=0; i<page->widget_size; i++) { + if (widget->label) { + h += l_h; + w = widget->label->g.w; + l_h = widget->label->g.h; + widget->label->g.x = 0; + widget->label->g.y = h; + } + if (w + widget->g.w > form->p.v.window->g.w) { + h += l_h; + w = 0; + l_h = 0; + } + widget->g.x = w; + widget->g.y = h; + + w += widget->g.w; + l_h = MAX(l_h, widget->g.h); + + widget = eve_widget_next(widget); + } + page->g.w = page->v.window->g.w; + page->g.h = h + l_h; +} + +static void widgets_destroy(EVEWidget *widget, uint16_t widget_size) { + int i; + + for (i=0; i<widget_size; i++) { + if (widget->label) eve_free(widget->label); + eve_widget_destroy(widget); + widget = eve_widget_next(widget); + } +} + +EVEForm *eve_form_create(EVEWindow *window, EVEViewStack *stack, EVEWidgetSpec spec[], uint16_t spec_size, eve_form_uievt_t uievt, eve_form_action_t action, eve_form_destructor_t destructor) { + EVEWidget *widgets; + EVEWidget *widget; + EVELabel *label; + EVEForm *form; + int w_size = 0; + int i, r; + + for (i=0; i<spec_size; i++) { + w_size += eve_widget_size(spec[i].widget.type); + } + form = eve_malloc(sizeof(EVEForm)); + if (form == NULL) { + return NULL; + } + if (uievt == NULL) uievt = eve_form_uievt; + if (destructor == NULL) destructor = eve_form_destroy; + eve_form_init(form, window, stack, NULL, 0, uievt, action, destructor); + + widgets = eve_malloc(w_size); + if (widgets == NULL) { + eve_free(form); + return NULL; + } + + widget = widgets; + for (i=0; i<spec_size; i++) { + r = eve_widget_create(widget, spec[i].widget.type, &spec[i].widget.g, (EVEPage *)form, &spec[i].widget.spec); + if (r) { + widgets_destroy(widgets, i); + eve_free(widgets); + eve_free(form); + return NULL; + } + if (spec[i].label.title) { + EVEFont *font = spec[i].label.font ? spec[i].label.font : eve_window_font(window); + label = eve_malloc(sizeof(EVELabel)); + if (label == NULL) { + eve_widget_destroy(widget); + widgets_destroy(widgets, i); + eve_free(widgets); + eve_free(form); + return NULL; + } + eve_label_init(label, &spec[i].label.g, font, spec[i].label.title); + eve_widget_set_label(widget, label); + if (label->g.w == 0) label->g.w = eve_font_str_w(font, label->title); + } + if (widget->label && (widget->label->g.w == 0)) eve_font_str_w(label->font, label->title) + EVE_FORM_LABEL_MARGIN; + if (widget->g.w == 0) widget->g.w = window->g.w - (widget->label ? widget->label->g.w : 0); + widget = eve_widget_next(widget); + } + eve_form_update(form, widgets, spec_size); + + return form; +} + +void eve_form_init(EVEForm *form, EVEWindow *window, EVEViewStack *stack, EVEWidget *widget, uint16_t widget_size, eve_form_uievt_t uievt, eve_form_action_t action, eve_form_destructor_t destructor) { + memset(form, 0, sizeof(EVEForm)); + eve_page_init(&form->p, window, stack, NULL, 0, EVE_PAGE_OPT_SCROLL_Y | EVE_PAGE_OPT_SCROLL_BACK | EVE_PAGE_OPT_TRACK_EXT_Y, eve_page_draw, eve_page_touch, (eve_view_uievt_t)uievt, (eve_page_destructor_t)destructor); + form->action = action; + eve_form_update(form, widget, widget_size); +} + +void eve_form_update(EVEForm *form, EVEWidget *widget, uint16_t widget_size) { + eve_page_update((EVEPage *)form, widget, widget_size); + form_update_g(form, NULL); +} + +void eve_form_destroy(EVEForm *form) { + widgets_destroy(form->p.widget, form->p.widget_size); + eve_free(form->p.widget); + eve_free(form); +} + +int eve_form_uievt(EVEForm *form, uint16_t evt, void *param) { + switch (evt) { + case EVE_UIEVT_WIDGET_UPDATE_G: + form_update_g(form, (EVEWidget *)param); + break; + + case EVE_UIEVT_PAGE_SCROLL_START: + break; + + case EVE_UIEVT_PAGE_SCROLL_STOP: + break; + + case EVE_UIEVT_PAGE_TRACK_START: + break; + + case EVE_UIEVT_PAGE_TRACK_STOP: { + EVEUIEvtTouch *touch_p = (EVEUIEvtTouch *)param; + if (touch_p->evt & EVE_TOUCH_ETYPE_TRACK_STOP) { + if (touch_p->touch->eevt & EVE_TOUCH_EETYPE_TRACK_RIGHT) { + eve_page_close((EVEPage *)form); + return 1; + } + if (touch_p->touch->eevt & EVE_TOUCH_EETYPE_TRACK_LEFT) { + if (form->action) form->action(form); + } + } + break; + } + } + return 0; +} diff --git a/fw/fe310/eos/eve/screen/form.h b/fw/fe310/eos/eve/screen/form.h new file mode 100644 index 0000000..272b6ed --- /dev/null +++ b/fw/fe310/eos/eve/screen/form.h @@ -0,0 +1,23 @@ +#include <stdint.h> + +#define EVE_FORM_LABEL_MARGIN 10 + +struct EVEWidget; +struct EVEWidgetSpec; +struct EVEForm; + +typedef int (*eve_form_uievt_t) (struct EVEForm *, uint16_t, void *); +typedef void (*eve_form_action_t) (struct EVEForm *); +typedef void (*eve_form_destructor_t) (struct EVEForm *); + +typedef struct EVEForm { + EVEPage p; + eve_form_action_t action; +} EVEForm; + +EVEForm *eve_form_create(EVEWindow *window, EVEViewStack *stack, struct EVEWidgetSpec *spec, uint16_t spec_size, eve_form_uievt_t uievt, eve_form_action_t action, eve_form_destructor_t destructor); +void eve_form_init(EVEForm *form, EVEWindow *window, EVEViewStack *stack, struct EVEWidget *widget, uint16_t widget_size, eve_form_uievt_t uievt, eve_form_action_t action, eve_form_destructor_t destructor); +void eve_form_update(EVEForm *form, struct EVEWidget *widget, uint16_t widget_size); +void eve_form_destroy(EVEForm *form); + +int eve_form_uievt(EVEForm *form, uint16_t evt, void *param); diff --git a/fw/fe310/eos/eve/screen/page.c b/fw/fe310/eos/eve/screen/page.c new file mode 100644 index 0000000..65dd534 --- /dev/null +++ b/fw/fe310/eos/eve/screen/page.c @@ -0,0 +1,349 @@ +#include <stdlib.h> +#include <string.h> + +#include "eve.h" +#include "eve_kbd.h" +#include "eve_font.h" + +#include "window.h" +#include "page.h" + +#include "widget/label.h" +#include "widget/widget.h" + +#define PAGE_TMODE_NONE 0 +#define PAGE_TMODE_TRACK 1 +#define PAGE_TMODE_SCROLL 2 + +void eve_page_init(EVEPage *page, EVEWindow *window, EVEViewStack *stack, EVEWidget *widget, uint16_t widget_size, uint8_t opt, eve_view_draw_t draw, eve_view_touch_t touch, eve_view_uievt_t uievt, eve_page_destructor_t destructor) { + memset(page, 0, sizeof(EVEPage)); + eve_view_init(&page->v, window, draw, touch, uievt, NULL); + page->stack = stack; + page->opt = opt; + page->destructor = destructor; + eve_page_update(page, widget, widget_size); +} + +void eve_page_update(EVEPage *page, EVEWidget *widget, uint16_t widget_size) { + page->widget = widget; + page->widget_size = widget_size; +} + +void eve_page_open(EVEPage *parent, eve_view_constructor_t constructor) { + EVEWindow *window = parent->v.window; + EVEViewStack *stack = parent->stack; + eve_page_destructor_t destructor = parent->destructor; + + if (destructor) destructor(parent); + eve_view_create(window, stack, constructor); +} + +void eve_page_close(EVEPage *page) { + EVEWindow *window = page->v.window; + EVEViewStack *stack = page->stack; + eve_page_destructor_t destructor = page->destructor; + + if (stack->level <= 1) return; + + if (page->lho_t0) { + page->lho_t0 = 0; + eve_touch_timer_stop(); + } + if (eve_window_scroll(window->root, NULL) == window) { + eve_window_scroll_stop(window); + } + + if (destructor) destructor(page); + eve_window_kbd_detach(window); + eve_view_destroy(window, stack); +} + +/* Screen to page coordinates */ +int16_t eve_page_x(EVEPage *page, int16_t x) { + return x + page->g.x - page->v.window->g.x; +} + +int16_t eve_page_y(EVEPage *page, int16_t y) { + return y + page->g.y - page->v.window->g.y; +} + +/* Page to window coordinates */ +int16_t eve_page_win_x(EVEPage *page, int16_t x) { + return x - page->g.x; +} + +int16_t eve_page_win_y(EVEPage *page, int16_t y) { + return y - page->g.y; +} + +/* Page to screen coordinates */ +int16_t eve_page_scr_x(EVEPage *page, int16_t x) { + return eve_page_win_x(page, x) + page->v.window->g.x; +} + +int16_t eve_page_scr_y(EVEPage *page, int16_t y) { + return eve_page_win_y(page, y) + page->v.window->g.y; +} + +int eve_page_rect_visible(EVEPage *page, EVERect *g) { + uint16_t w = page->v.window->g.w; + uint16_t h = page->v.window->g.h; + + if (((g->x + g->w) >= page->g.x) && ((g->y + g->h) >= page->g.y) && (g->x <= (page->g.x + w)) && (g->y <= (page->g.y + h))) return 1; + return 0; +} + +void eve_page_focus(EVEPage *page, EVERect *rect) { + if (rect) { + EVERect g; + + eve_window_visible_g(page->v.window, &g); + g.x -= page->v.window->g.x; + g.y -= page->v.window->g.y; + + if (rect->x < page->g.x + g.x) { + page->g.x = rect->x - g.x; + } + if (rect->y < page->g.y + g.y) { + page->g.y = rect->y - g.y; + } + if ((rect->x + rect->w) > (page->g.x + g.x + g.w)) { + page->g.x = (rect->x + rect->w) - (g.x + g.w); + } + if ((rect->y + rect->h) > (page->g.y + g.y + g.h)) { + page->g.y = (rect->y + rect->h) - (g.y + g.h); + } + } +} + +void eve_page_focus_widget(EVEPage *page, EVEWidget *widget, EVERect *rect) { + if (page->widget_f != widget) { + EVEWindow *window = page->v.window; + EVEWidget *widget_f = page->widget_f; + + if (widget_f && widget_f->putc) { + widget_f->putc(widget_f, EVE_PAGE_KBDCH_CLOSE); + if (!(widget && widget->putc)) eve_window_kbd_detach(window); + } + if (widget && widget->putc) { + EVEKbd *kbd = eve_window_kbd(window); + + if (kbd) eve_kbd_set_handler(kbd, widget->putc, widget); + if (!(widget_f && widget_f->putc)) eve_window_kbd_attach(window); + } + page->widget_f = widget; + } + if (rect) eve_page_focus(page, rect); +} + +EVEWidget *eve_page_focus_widget_get(EVEPage *page) { + return page->widget_f; +} + +EVEWidget *eve_page_widget(EVEPage *page, uint16_t idx) { + EVEWidget *w = page->widget; + int i; + + if (idx >= page->widget_size) return NULL; + + for (i=0; i<idx; i++) { + w = eve_widget_next(w); + } + return w; +} + +static int page_touch(EVEPage *page, EVETouch *touch, uint16_t evt, uint8_t tag0) { + EVEView *view = &page->v; + EVEWindow *window = view->window; + int scroll, scroll_x, scroll_y; + int ret = 0; + + scroll_x = page->opt & (EVE_PAGE_OPT_SCROLL_X | EVE_PAGE_OPT_SCROLL_XY); + if (scroll_x && touch) scroll_x = touch->eevt & ((page->opt & EVE_PAGE_OPT_SCROLL_XY) ? EVE_TOUCH_EETYPE_TRACK_XY : EVE_TOUCH_EETYPE_TRACK_X); + + scroll_y = page->opt & (EVE_PAGE_OPT_SCROLL_Y | EVE_PAGE_OPT_SCROLL_XY); + if (scroll_y && touch) scroll_y = touch->eevt & ((page->opt & EVE_PAGE_OPT_SCROLL_XY) ? EVE_TOUCH_EETYPE_TRACK_XY : EVE_TOUCH_EETYPE_TRACK_Y); + + scroll = scroll_x || scroll_y; + + if ((evt & EVE_TOUCH_ETYPE_POINT_UP) && !(touch->eevt & (EVE_TOUCH_EETYPE_TRACK_XY | EVE_TOUCH_EETYPE_ABORT))) { + int _ret = 0; + + if (page->widget_f) eve_page_focus_widget(page, NULL, NULL); + _ret = eve_view_uievt_pusht(view, EVE_UIEVT_PAGE_TOUCH, touch, evt, tag0); + if (_ret) return _ret; + ret = 1; + } + + /* Scroll start */ + if ((evt & EVE_TOUCH_ETYPE_TRACK_START) && !(touch->eevt & EVE_TOUCH_EETYPE_ABORT)) { + int _ret = 0; + + if (scroll) { + page->track_mode = PAGE_TMODE_SCROLL; + eve_window_scroll_start(window, touch->tracker.tag); + _ret = eve_view_uievt_pusht(view, EVE_UIEVT_PAGE_SCROLL_START, touch, evt, tag0); + } else { + page->track_mode = PAGE_TMODE_TRACK; + _ret = eve_view_uievt_pusht(view, EVE_UIEVT_PAGE_TRACK_START, touch, evt, tag0); + } + if (_ret) return _ret; + ret = 1; + } + + /* Scroll stop */ + if (((evt & EVE_TOUCH_ETYPE_TRACK_STOP) && !(evt & EVE_TOUCH_ETYPE_TRACK_ABORT)) || + ((evt & EVE_TOUCH_ETYPE_POINT_UP) && (touch->eevt & EVE_TOUCH_EETYPE_ABORT) && !(touch->eevt & EVE_TOUCH_EETYPE_TRACK_XY))) { + if ((page->track_mode == PAGE_TMODE_SCROLL) && (page->opt & EVE_PAGE_OPT_SCROLL_BACK)) { + int wmax_x, wmax_y; + int lho_x, lho_y; + EVERect vg; + + eve_window_visible_g(page->v.window, &vg); + wmax_x = page->g.w > vg.w ? page->g.w - vg.w : 0; + wmax_y = page->g.h > vg.h ? page->g.h - vg.h : 0; + lho_x = page->g.x < 0 ? 0 : wmax_x; + lho_y = page->g.y < 0 ? 0 : wmax_y; + if ((page->g.x < 0) || (page->g.x > wmax_x) || + (page->g.y < 0) || (page->g.y > wmax_y)) { + EVEPhyLHO *lho = &page->lho; + uint8_t _tag; + + eve_window_scroll(window->root, &_tag); + + eve_phy_lho_init(lho, lho_x, lho_y, 1000, 0.5, 0); + eve_phy_lho_start(lho, page->g.x, page->g.y); + page->lho_t0 = eve_time_get_tick(); + eve_touch_timer_start(_tag, 20); + } + } + + if (!page->lho_t0) { + int _ret = 0; + + if (page->track_mode == PAGE_TMODE_SCROLL) { + page->track_mode = PAGE_TMODE_NONE; + eve_window_scroll_stop(window); + _ret = eve_view_uievt_pusht(view, EVE_UIEVT_PAGE_SCROLL_STOP, touch, evt, tag0); + } else if (!(touch->eevt & EVE_TOUCH_EETYPE_ABORT)) { + page->track_mode = PAGE_TMODE_NONE; + _ret = eve_view_uievt_pusht(view, EVE_UIEVT_PAGE_TRACK_STOP, touch, evt, tag0); + } + if (_ret) return _ret; + ret = 1; + } + } + + if (page->track_mode == PAGE_TMODE_SCROLL) { + if (evt & EVE_TOUCH_ETYPE_TRACK_START) { + if (scroll_x) { + page->x0 = page->g.x; + } + if (scroll_y) { + page->y0 = page->g.y; + } + } + if (evt & EVE_TOUCH_ETYPE_TRACK) { + if (scroll_x) { + page->g.x = page->x0 + touch->x0 - touch->x; + } + if (scroll_y) { + page->g.y = page->y0 + touch->y0 - touch->y; + } + ret = 1; + } + if ((evt & EVE_TOUCH_ETYPE_TIMER) && (page->opt & EVE_PAGE_OPT_SCROLL_BACK)) { + EVEPhyLHO *lho = &page->lho; + int x, y, more; + + more = eve_phy_lho_tick(lho, eve_time_get_tick() - page->lho_t0, scroll_x ? &x : NULL, scroll_y ? &y : NULL); + if (scroll_x) page->g.x = x; + if (scroll_y) page->g.y = y; + if (!more) { + int _ret = 0; + + page->lho_t0 = 0; + eve_touch_timer_stop(); + page->track_mode = PAGE_TMODE_NONE; + eve_window_scroll_stop(window); + _ret = eve_view_uievt_pusht(view, EVE_UIEVT_PAGE_SCROLL_STOP, touch, evt, tag0); + if (_ret) return _ret; + } + ret = 1; + } + if (evt & EVE_TOUCH_EETYPE_TIMER_ABORT) { + page->lho_t0 = 0; + } + } + + return ret; +} + +uint8_t eve_page_draw(EVEView *view, uint8_t tag0) { + EVEPage *page = (EVEPage *)view; + EVEWidget *widget = page->widget; + int i; + uint8_t tagN = tag0; + uint8_t tag_opt; + + tag_opt = EVE_TOUCH_OPT_TRACK | EVE_TOUCH_OPT_TRACK_XY; + if (page->opt & EVE_PAGE_OPT_TRACK_EXT_X) tag_opt |= EVE_TOUCH_OPT_TRACK_EXT_X; + if (page->opt & EVE_PAGE_OPT_TRACK_EXT_Y) tag_opt |= EVE_TOUCH_OPT_TRACK_EXT_Y; + + tag0 = eve_view_clear(view, tag0, tag_opt); + tagN = tag0; + eve_cmd_dl(SAVE_CONTEXT()); + eve_cmd_dl(VERTEX_FORMAT(0)); + eve_cmd_dl(VERTEX_TRANSLATE_X(eve_page_scr_x(page, 0) * 16)); + eve_cmd_dl(VERTEX_TRANSLATE_Y(eve_page_scr_y(page, 0) * 16)); + for (i=0; i<page->widget_size; i++) { + if (widget->label && eve_page_rect_visible(page, &widget->label->g)) { + eve_cmd_dl(TAG_MASK(0)); + eve_label_draw(widget->label); + eve_cmd_dl(TAG_MASK(1)); + } + if (eve_page_rect_visible(page, &widget->g)) { + tagN = widget->draw(widget, tagN); + } + widget = eve_widget_next(widget); + } + eve_cmd_dl(RESTORE_CONTEXT()); + + for (i=tag0; i<tagN; i++) { + if (i != EVE_NOTAG) eve_touch_set_opt(i, eve_touch_get_opt(i) | tag_opt); + } + + return tagN; +} + +int eve_page_touch(EVEView *view, EVETouch *touch, uint16_t evt, uint8_t tag0) { + EVEPage *page = (EVEPage *)view; + EVEWidget *widget = page->widget; + int8_t touch_idx = eve_touch_get_idx(touch); + uint16_t _evt; + int i, ret; + + if (touch_idx > 0) return 0; + + _evt = eve_touch_evt(touch, evt, tag0, page->v.tag, 1); + if (_evt) { + ret = page_touch(page, touch, _evt, tag0); + if (ret) return 1; + } + for (i=0; i<page->widget_size; i++) { + if (eve_page_rect_visible(page, &widget->g)) { + _evt = eve_touch_evt(touch, evt, tag0, widget->tag0, widget->tagN - widget->tag0); + if (_evt) { + if (page->track_mode == PAGE_TMODE_NONE) { + ret = widget->touch(widget, touch, _evt); + if (ret) return 1; + } + ret = page_touch(page, touch, _evt, tag0); + if (ret) return 1; + } + } + widget = eve_widget_next(widget); + } + + return 0; +} diff --git a/fw/fe310/eos/eve/screen/page.h b/fw/fe310/eos/eve/screen/page.h new file mode 100644 index 0000000..26c33c5 --- /dev/null +++ b/fw/fe310/eos/eve/screen/page.h @@ -0,0 +1,56 @@ +#include <stdint.h> + +#define EVE_PAGE_KBDCH_CLOSE 0x1a + +#define EVE_PAGE_OPT_SCROLL_X 0x01 +#define EVE_PAGE_OPT_SCROLL_Y 0x02 +#define EVE_PAGE_OPT_SCROLL_BACK 0x04 +#define EVE_PAGE_OPT_SCROLL_XY 0x08 +#define EVE_PAGE_OPT_TRACK_EXT_X 0x10 +#define EVE_PAGE_OPT_TRACK_EXT_Y 0x20 +#define EVE_PAGE_OPT_TRACK_EXT_XY (EVE_PAGE_OPT_TRACK_EXT_X | EVE_PAGE_OPT_TRACK_EXT_Y) + +struct EVEWidget; +struct EVEPage; + +typedef void (*eve_page_destructor_t) (struct EVEPage *); + +typedef struct EVEPage { + EVEView v; + EVERect g; + int16_t x0; + int16_t y0; + EVEViewStack *stack; + eve_page_destructor_t destructor; + struct EVEWidget *widget; + uint16_t widget_size; + struct EVEWidget *widget_f; + EVEPhyLHO lho; + uint64_t lho_t0; + uint8_t track_mode; + uint8_t opt; +} EVEPage; + +void eve_page_init(EVEPage *page, EVEWindow *window, EVEViewStack *stack, struct EVEWidget *widget, uint16_t widget_size, uint8_t opt,eve_view_draw_t draw, eve_view_touch_t touch, eve_view_uievt_t uievt, eve_page_destructor_t destructor); +void eve_page_update(EVEPage *page, struct EVEWidget *widget, uint16_t widget_size); +void eve_page_open(EVEPage *parent, eve_view_constructor_t constructor); +void eve_page_close(EVEPage *page); + +/* Screen to page coordinates */ +int16_t eve_page_x(EVEPage *page, int16_t x); +int16_t eve_page_y(EVEPage *page, int16_t y); +/* Page to window coordinates */ +int16_t eve_page_win_x(EVEPage *page, int16_t x); +int16_t eve_page_win_y(EVEPage *page, int16_t y); +/* Page to screen coordinates */ +int16_t eve_page_scr_x(EVEPage *page, int16_t x); +int16_t eve_page_scr_y(EVEPage *page, int16_t y); +int eve_page_rect_visible(EVEPage *page, EVERect *g); + +void eve_page_focus(EVEPage *page, EVERect *rect); +void eve_page_focus_widget(EVEPage *page, struct EVEWidget *widget, EVERect *rect); +struct EVEWidget *eve_page_focus_widget_get(EVEPage *page); +struct EVEWidget *eve_page_widget(EVEPage *page, uint16_t idx); + +uint8_t eve_page_draw(EVEView *view, uint8_t tag0); +int eve_page_touch(EVEView *view, EVETouch *touch, uint16_t evt, uint8_t tag0); diff --git a/fw/fe310/eos/eve/screen/uievt.h b/fw/fe310/eos/eve/screen/uievt.h new file mode 100644 index 0000000..98f0d95 --- /dev/null +++ b/fw/fe310/eos/eve/screen/uievt.h @@ -0,0 +1,14 @@ +#define EVE_UIEVT_WIN_UPDATE_G 1 +#define EVE_UIEVT_PAGE_UPDATE_G 2 +#define EVE_UIEVT_PAGE_TOUCH 3 +#define EVE_UIEVT_PAGE_SCROLL_START 4 +#define EVE_UIEVT_PAGE_SCROLL_STOP 5 +#define EVE_UIEVT_PAGE_TRACK_START 6 +#define EVE_UIEVT_PAGE_TRACK_STOP 7 +#define EVE_UIEVT_WIDGET_UPDATE_G 8 + +typedef struct EVEUIEvtTouch { + EVETouch *touch; + uint16_t evt; + uint8_t tag0; +} EVEUIEvtTouch; diff --git a/fw/fe310/eos/eve/screen/view.c b/fw/fe310/eos/eve/screen/view.c new file mode 100644 index 0000000..ac9aef4 --- /dev/null +++ b/fw/fe310/eos/eve/screen/view.c @@ -0,0 +1,94 @@ +#include <stdlib.h> +#include <string.h> + +#include "eve.h" +#include "eve_kbd.h" +#include "eve_font.h" + +#include "window.h" + +void eve_view_init(EVEView *view, EVEWindow *window, eve_view_draw_t draw, eve_view_touch_t touch, eve_view_uievt_t uievt, void *param) { + view->draw = draw; + view->touch = touch; + view->uievt = uievt; + view->param = param; + view->window = window; + view->color_bg = 0x000000; + view->color_fg = 0xffffff; + window->view = view; +} + +void eve_view_set_color_bg(EVEView *view, uint8_t r, uint8_t g, uint8_t b) { + view->color_bg = (r << 16) | (g << 8) | b; +} + +void eve_view_set_color_fg(EVEView *view, uint8_t r, uint8_t g, uint8_t b) { + view->color_fg = (r << 16) | (g << 8) | b; +} + +uint8_t eve_view_clear(EVEView *view, uint8_t tag0, uint8_t tag_opt) { + EVEWindow *win_scroll = NULL; + EVEWindow *window = view->window; + uint8_t _tag; + + win_scroll = eve_window_scroll(window->root, &_tag); + eve_cmd_dl(CLEAR_COLOR_RGBC(view->color_bg)); + eve_cmd_dl(COLOR_RGBC(view->color_fg)); + if (win_scroll == window) { + view->tag = _tag; + eve_touch_set_opt(view->tag, tag_opt); + eve_cmd_dl(TAG(view->tag)); + eve_cmd_dl(CLEAR_TAG(view->tag)); + } else if (win_scroll) { + view->tag = EVE_NOTAG; + eve_cmd_dl(TAG(view->tag)); + eve_cmd_dl(CLEAR_TAG(view->tag)); + } else { + view->tag = tag0; + if (tag0 != EVE_NOTAG) { + eve_touch_set_opt(tag0, tag_opt); + eve_cmd_dl(CLEAR_TAG(tag0)); + tag0++; + } + } + eve_cmd_dl(CLEAR(1,1,1)); + return tag0; +} + +void eve_view_stack_init(EVEViewStack *stack) { + memset(stack, 0, sizeof(EVEViewStack)); +} + +void eve_view_create(EVEWindow *window, EVEViewStack *stack, eve_view_constructor_t constructor) { + if (stack->level < EVE_VIEW_SIZE_STACK - 1) { + stack->constructor[stack->level] = constructor; + stack->level++; + constructor(window, stack); + } +} + +void eve_view_destroy(EVEWindow *window, EVEViewStack *stack) { + if (stack->level > 1) { + eve_view_constructor_t constructor; + + stack->level--; + constructor = stack->constructor[stack->level - 1]; + constructor(window, stack); + } +} + +void eve_view_uievt_push(EVEView *view, uint16_t evt, void *param) { + if (view->uievt) view->uievt(view, evt, param); +} + +int eve_view_uievt_pusht(EVEView *view, uint16_t evt, EVETouch *touch, uint16_t t_evt, uint8_t tag0) { + if (view->uievt) { + EVEUIEvtTouch param; + + param.touch = touch; + param.evt = t_evt; + param.tag0 = tag0; + view->uievt(view, evt, ¶m); + } + return 0; +} diff --git a/fw/fe310/eos/eve/screen/view.h b/fw/fe310/eos/eve/screen/view.h new file mode 100644 index 0000000..65999d7 --- /dev/null +++ b/fw/fe310/eos/eve/screen/view.h @@ -0,0 +1,42 @@ +#include <stdint.h> + +#include "uievt.h" + +#define EVE_VIEW_SIZE_STACK 16 + +struct EVEView; +struct EVEViewStack; +struct EVEWindow; + +typedef uint8_t (*eve_view_draw_t) (struct EVEView *, uint8_t); +typedef int (*eve_view_touch_t) (struct EVEView *, EVETouch *, uint16_t, uint8_t); +typedef int (*eve_view_uievt_t) (struct EVEView *, uint16_t, void *); +typedef void (*eve_view_constructor_t) (struct EVEWindow *window, struct EVEViewStack *); + +typedef struct EVEView { + eve_view_draw_t draw; + eve_view_touch_t touch; + eve_view_uievt_t uievt; + struct EVEWindow *window; + void *param; + uint32_t color_bg; + uint32_t color_fg; + uint8_t tag; +} EVEView; + +typedef struct EVEViewStack { + eve_view_constructor_t constructor[EVE_VIEW_SIZE_STACK]; + uint8_t level; +} EVEViewStack; + +void eve_view_init(EVEView *view, struct EVEWindow *window, eve_view_draw_t draw, eve_view_touch_t touch, eve_view_uievt_t uievt, void *param); +void eve_view_set_color_bg(EVEView *view, uint8_t r, uint8_t g, uint8_t b); +void eve_view_set_color_fg(EVEView *view, uint8_t r, uint8_t g, uint8_t b); +uint8_t eve_view_clear(EVEView *view, uint8_t tag0, uint8_t tag_opt); + +void eve_view_stack_init(EVEViewStack *stack); +void eve_view_create(struct EVEWindow *window, EVEViewStack *stack, eve_view_constructor_t constructor); +void eve_view_destroy(struct EVEWindow *window, EVEViewStack *stack); + +void eve_view_uievt_push(EVEView *view, uint16_t evt, void *param); +int eve_view_uievt_pusht(EVEView *view, uint16_t evt, EVETouch *touch, uint16_t t_evt, uint8_t tag0); diff --git a/fw/fe310/eos/eve/screen/window.c b/fw/fe310/eos/eve/screen/window.c new file mode 100644 index 0000000..c259b19 --- /dev/null +++ b/fw/fe310/eos/eve/screen/window.c @@ -0,0 +1,300 @@ +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#include "eve.h" +#include "eve_kbd.h" +#include "eve_font.h" + +#include "window.h" + +#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) + +void eve_window_init(EVEWindow *window, EVERect *g, EVEWindow *parent, char *name) { + memset(window, 0, sizeof(EVEWindow)); + + if (g) window->g = *g; + window->root = parent ? parent->root : NULL; + window->parent = parent; + window->name = name; +} + +void eve_window_init_root(EVEWindowRoot *root, EVERect *g, char *name, EVEFont *font) { + EVEWindow *_window = &root->w; + + eve_window_init(_window, g, NULL, name); + _window->root = root; + root->mem_next = EVE_RAM_G; + root->font = font; + root->win_kbd = NULL; + root->tag0 = EVE_NOTAG; + eve_touch_set_handler(eve_window_root_touch, root); +} + +static uint8_t kbd_draw(EVEView *view, uint8_t tag0) { + EVEKbd *kbd = view->param; + + tag0 = eve_view_clear(view, tag0, 0); + + eve_kbd_draw(kbd); + return tag0; +} + +static int kbd_touch(EVEView *view, EVETouch *touch, uint16_t evt, uint8_t tag0) { + EVEKbd *kbd = view->param; + + return eve_kbd_touch(kbd, touch, evt, tag0); +} + +void eve_window_init_kbd(EVEWindowKbd *win_kbd, EVERect *g, EVEWindowRoot *root, char *name, EVEKbd *kbd) { + EVEWindow *_window = &win_kbd->w; + + eve_window_init(_window, g, NULL, name); + _window->root = root; + win_kbd->kbd = kbd; + root->win_kbd = win_kbd; + eve_view_init(&win_kbd->v, _window, kbd_draw, kbd_touch, NULL, kbd); +} + +void eve_window_set_parent(EVEWindow *window, EVEWindow *parent) { + window->parent = parent; + window->root = parent->root; +} + +int eve_window_visible(EVEWindow *window) { + if (window->g.x >= window->root->w.g.w) return 0; + if (window->g.y >= window->root->w.g.h) return 0; + if ((window->g.x + window->g.w) <= 0) return 0; + if ((window->g.y + window->g.h) <= 0) return 0; + return 1; +} + +static void window_visible_g(EVEWindow *w, EVERect *g) { + while (w) { + if (eve_window_visible(w)) { + if (w->g.x > g->x) g->w = MIN(g->w, w->g.x - g->x); + if (w->g.y > g->y) g->h = MIN(g->h, w->g.y - g->y); + if (w->g.x + w->g.w < g->x + g->w) { + uint16_t x0 = g->w - MIN(g->w, (g->x + g->w) - (w->g.x + w->g.w)); + g->x += x0; + g->w -= x0; + } + if (w->g.y + w->g.h < g->y + g->h) { + uint16_t y0 = g->h - MIN(g->h, (g->y + g->h) - (w->g.y + w->g.h)); + g->y += y0; + g->h -= y0; + } + } + if (w->child_head) window_visible_g(w->child_head, g); + w = w->next; + } +} + +void eve_window_visible_g(EVEWindow *window, EVERect *g) { + *g = window->g; + if (window->child_head) window_visible_g(window->child_head, g); + window_visible_g(window->next, g); +} + +void eve_window_append(EVEWindow *window) { + EVEWindow *parent = window->parent; + + window->prev = parent->child_tail; + window->next = NULL; + if (parent->child_tail) { + parent->child_tail->next = window; + } else { + parent->child_head = window; + } + parent->child_tail = window; +} + +void eve_window_insert_above(EVEWindow *window, EVEWindow *win_prev) { + EVEWindow *parent = window->parent; + + window->prev = win_prev; + window->next = win_prev->next; + + if (window->next) { + window->next->prev = window; + } else { + parent->child_tail = window; + } + win_prev->next = window; +} + +void eve_window_insert_below(EVEWindow *window, EVEWindow *win_next) { + EVEWindow *parent = window->parent; + + window->prev = win_next->prev; + window->next = win_next; + + win_next->prev = window; + if (window->prev) { + window->prev->next = window; + } else { + parent->child_head = window; + } +} + +void eve_window_remove(EVEWindow *window) { + EVEWindow *parent = window->parent; + + if (window->prev) { + window->prev->next = window->next; + } else { + parent->child_head = window->next; + } + if (window->next) { + window->next->prev = window->prev; + } else { + parent->child_tail = window->prev; + } + window->parent = NULL; + window->prev = NULL; + window->next = NULL; +} + +EVEWindow *eve_window_search(EVEWindow *window, char *name) { + while (window) { + if (window->name && (strcmp(name, window->name) == 0)) return window; + if (window->child_head) { + EVEWindow *ret = eve_window_search(window->child_head, name); + if (ret) return ret; + } + window = window->next; + } + + return NULL; +} + +uint8_t eve_window_draw(EVEWindow *window, uint8_t tag0) { + while (window) { + if (eve_window_visible(window) && window->view) { + int16_t s_x = window->g.x; + int16_t s_y = window->g.y; + uint16_t s_w = window->g.w; + uint16_t s_h = window->g.h; + + if (s_x < 0) { + s_w += s_x; + s_x = 0; + } + if (s_y < 0) { + s_h += s_y; + s_y = 0; + } + if (s_x + s_w > window->root->w.g.w) s_w = window->root->w.g.w - s_x; + if (s_y + s_h > window->root->w.g.h) s_h = window->root->w.g.h - s_y; + eve_cmd_dl(SCISSOR_XY(s_x, s_y)); + eve_cmd_dl(SCISSOR_SIZE(s_w, s_h)); + tag0 = window->view->draw(window->view, tag0); + } + if (window->child_head) tag0 = eve_window_draw(window->child_head, tag0); + window = window->next; + } + + return tag0; +} + +int eve_window_touch(EVEWindow *window, EVETouch *touch, uint16_t evt, uint8_t tag0) { + int ret = 0; + + while (window) { + if (window->child_tail) { + ret = eve_window_touch(window->child_tail, touch, evt, tag0); + if (ret) return 1; + } + if (eve_window_visible(window) && window->view) { + ret = window->view->touch(window->view, touch, evt, tag0); + if (ret) return 1; + } + window = window->prev; + } + + return 0; +} + +void eve_window_root_draw(EVEWindowRoot *root) { + uint8_t tag0 = 0x80; + int rv; + + eve_cmd_burst_start(); + eve_cmd_dl(CMD_DLSTART); + + if (root->tag0 != EVE_NOTAG) tag0 = EVE_NOTAG; + eve_window_draw(&root->w, tag0); + + eve_cmd_dl(DISPLAY()); + eve_cmd_dl(CMD_SWAP); + eve_cmd_burst_end(); + rv = eve_cmd_exec(1); + if (rv) printf("EVE EXEC ERR\n"); +} + +void eve_window_root_touch(EVETouch *touch, uint16_t evt, uint8_t tag0, void *win) { + EVEWindowRoot *root = (EVEWindowRoot *)win; + int ret; + + if (root->tag0 != EVE_NOTAG) tag0 = root->tag0; + ret = eve_window_touch(&root->w, touch, evt, tag0); + if (ret) { + eve_touch_clear_opt(); + eve_window_root_draw(root); + } +} + +EVEKbd *eve_window_kbd(EVEWindow *window) { + EVEWindowRoot *root = window->root; + EVEWindowKbd *win_kbd = root->win_kbd; + + if (win_kbd) return win_kbd->kbd; + return NULL; +} + +void eve_window_kbd_attach(EVEWindow *window) { + EVEWindowRoot *root = window->root; + EVEWindowKbd *win_kbd = root->win_kbd; + EVEKbd *kbd = win_kbd ? win_kbd->kbd : NULL; + + if (kbd) { + eve_window_set_parent(&win_kbd->w, window); + eve_window_append(&win_kbd->w); + } +} + +void eve_window_kbd_detach(EVEWindow *window) { + EVEWindowRoot *root = window->root; + EVEWindowKbd *win_kbd = root->win_kbd; + EVEKbd *kbd = win_kbd ? win_kbd->kbd : NULL; + + if (kbd && win_kbd->w.parent) { + eve_window_remove(&win_kbd->w); + eve_kbd_close(kbd); + } +} + +EVEFont *eve_window_font(EVEWindow *window) { + EVEWindowRoot *root = window->root; + + return root->font; +} + +EVEWindow *eve_window_scroll(EVEWindowRoot *root, uint8_t *tag) { + if (tag) *tag = root->tag0; + return root->win_scroll; +} + +void eve_window_scroll_start(EVEWindow *window, uint8_t tag) { + EVEWindowRoot *root = window->root; + + root->win_scroll = window; + root->tag0 = tag; +} + +void eve_window_scroll_stop(EVEWindow *window) { + EVEWindowRoot *root = window->root; + + root->win_scroll = NULL; + root->tag0 = EVE_NOTAG; +} diff --git a/fw/fe310/eos/eve/screen/window.h b/fw/fe310/eos/eve/screen/window.h new file mode 100644 index 0000000..27465c4 --- /dev/null +++ b/fw/fe310/eos/eve/screen/window.h @@ -0,0 +1,60 @@ +#include <stdint.h> + +#include "view.h" + +struct EVEWindowRoot; + +typedef struct EVEWindow { + EVERect g; + char *name; + EVEView *view; + struct EVEWindowRoot *root; + struct EVEWindow *parent; + struct EVEWindow *next; + struct EVEWindow *prev; + struct EVEWindow *child_head; + struct EVEWindow *child_tail; +} EVEWindow; + +typedef struct EVEWindowKbd { + EVEWindow w; + EVEView v; + EVEKbd *kbd; +} EVEWindowKbd; + +typedef struct EVEWindowRoot { + EVEWindow w; + uint32_t mem_next; + EVEFont *font; + EVEWindowKbd *win_kbd; + EVEWindow *win_scroll; + uint8_t tag0; +} EVEWindowRoot; + +void eve_window_init(EVEWindow *window, EVERect *g, EVEWindow *parent, char *name); +void eve_window_init_root(EVEWindowRoot *root, EVERect *g, char *name, EVEFont *font); +void eve_window_init_kbd(EVEWindowKbd *win_kbd, EVERect *g, EVEWindowRoot *root, char *name, EVEKbd *kbd); +void eve_window_set_parent(EVEWindow *window, EVEWindow *parent); + +int eve_window_visible(EVEWindow *window); +void eve_window_visible_g(EVEWindow *window, EVERect *g); + +void eve_window_append(EVEWindow *window); +void eve_window_insert_above(EVEWindow *window, EVEWindow *win_prev); +void eve_window_insert_below(EVEWindow *window, EVEWindow *win_next); +void eve_window_remove(EVEWindow *window); +EVEWindow *eve_window_search(EVEWindow *window, char *name); + +uint8_t eve_window_draw(EVEWindow *window, uint8_t tag0); +int eve_window_touch(EVEWindow *window, EVETouch *touch, uint16_t evt, uint8_t tag0); +void eve_window_root_draw(EVEWindowRoot *root); +void eve_window_root_touch(EVETouch *touch, uint16_t evt, uint8_t tag0, void *win); + +EVEKbd *eve_window_kbd(EVEWindow *window); +void eve_window_kbd_attach(EVEWindow *window); +void eve_window_kbd_detach(EVEWindow *window); +EVEFont *eve_window_font(EVEWindow *window); + +EVEWindow *eve_window_scroll(EVEWindowRoot *root, uint8_t *tag); +void eve_window_scroll_start(EVEWindow *window, uint8_t tag); +void eve_window_scroll_stop(EVEWindow *window); |