diff options
author | Hanspeter Portner <dev@open-music-kontrollers.ch> | 2019-05-09 19:02:47 +0200 |
---|---|---|
committer | Hanspeter Portner <dev@open-music-kontrollers.ch> | 2019-05-09 19:02:47 +0200 |
commit | 964a2f450910180a3e3f04dedbdd81e0bd7f318c (patch) | |
tree | 3ae8256770efa703eaed9287eb04e31186e77732 /subprojects | |
parent | 491afc6346236b32e5ae49687fd4b159cadf9600 (diff) | |
parent | 847b1b8f2a1e8669b2e1e6e49fa0a8f66c44e2aa (diff) | |
download | tracker.lv2-964a2f450910180a3e3f04dedbdd81e0bd7f318c.tar.xz |
Merge commit '847b1b8f2a1e8669b2e1e6e49fa0a8f66c44e2aa'
Diffstat (limited to 'subprojects')
-rw-r--r-- | subprojects/d2tk/.gitlab-ci.yml | 23 | ||||
-rw-r--r-- | subprojects/d2tk/VERSION | 2 | ||||
-rw-r--r-- | subprojects/d2tk/d2tk/base.h | 17 | ||||
-rw-r--r-- | subprojects/d2tk/example/example.c | 88 | ||||
-rw-r--r-- | subprojects/d2tk/meson.build | 2 | ||||
-rw-r--r-- | subprojects/d2tk/pugl/pugl/pugl_x11.c | 3 | ||||
-rw-r--r-- | subprojects/d2tk/src/base.c | 84 | ||||
-rw-r--r-- | subprojects/d2tk/test/base.c | 1738 |
8 files changed, 1909 insertions, 48 deletions
diff --git a/subprojects/d2tk/.gitlab-ci.yml b/subprojects/d2tk/.gitlab-ci.yml index 48c411c..f8f8464 100644 --- a/subprojects/d2tk/.gitlab-ci.yml +++ b/subprojects/d2tk/.gitlab-ci.yml @@ -18,7 +18,7 @@ stages: .build_template: &build_definition <<: *common_definition script: - - meson --prefix="/" --libdir="lib" --cross-file "${CI_BUILD_NAME}" -Db_lto=false build + - meson --prefix="/" --libdir="lib" --cross-file "${CI_BUILD_NAME}" build - sed -i -e '/framework/s/-Wl,-O1//g' -e '/framework/s/-Wl,--start-group//g' -e '/framework/s/-Wl,--end-group//g' build/build.ninja - ninja -C build - DESTDIR="${CI_PROJECT_DIR}/${BASE_NAME}-$(cat VERSION)/${CI_BUILD_NAME}" ninja -C build install @@ -26,15 +26,32 @@ stages: .test_template: &test_definition <<: *common_definition script: - - meson --prefix="/" --libdir="lib" --cross-file "${CI_BUILD_NAME}" -Db_lto=false build + - meson --prefix="/" --libdir="lib" --cross-file "${CI_BUILD_NAME}" build - sed -i -e '/framework/s/-Wl,-O1//g' -e '/framework/s/-Wl,--start-group//g' -e '/framework/s/-Wl,--end-group//g' build/build.ninja - ninja -C build - DESTDIR="${CI_PROJECT_DIR}/${BASE_NAME}-$(cat VERSION)/${CI_BUILD_NAME}" ninja -C build install - ninja -C build test +.analyze_template: &analyze_definition + <<: *common_definition + script: + - meson --prefix="/" --libdir="lib" --cross-file "${CI_BUILD_NAME}" build + - sed -i -e '/framework/s/-Wl,-O1//g' -e '/framework/s/-Wl,--start-group//g' -e '/framework/s/-Wl,--end-group//g' build/build.ninja + - ninja -C build + - DESTDIR="${CI_PROJECT_DIR}/${BASE_NAME}-$(cat VERSION)/${CI_BUILD_NAME}" ninja -C build install + - ninja -C build test + + - CC=clang CXX=clang++ meson --prefix="/" --libdir="lib" --cross-file "${CI_BUILD_NAME}" clang + - ninja -C clang + - ninja -C clang test + + - scan-build --status-bugs meson --prefix="/" --libdir="lib" --cross-file "${CI_BUILD_NAME}" scanbuild + - scan-build --status-bugs ninja -C scanbuild + - scan-build --status-bugs ninja -C scanbuild test + .universal_linux_template: &universal_linux_definition image: ventosus/universal-linux-gnu - <<: *test_definition + <<: *analyze_definition .arm_linux_template: &arm_linux_definition image: ventosus/arm-linux-gnueabihf diff --git a/subprojects/d2tk/VERSION b/subprojects/d2tk/VERSION index 2ce9d83..0014166 100644 --- a/subprojects/d2tk/VERSION +++ b/subprojects/d2tk/VERSION @@ -1 +1 @@ -0.1.641 +0.1.713 diff --git a/subprojects/d2tk/d2tk/base.h b/subprojects/d2tk/d2tk/base.h index 26cea3b..2d4774f 100644 --- a/subprojects/d2tk/d2tk/base.h +++ b/subprojects/d2tk/d2tk/base.h @@ -268,6 +268,9 @@ d2tk_base_get_alt(d2tk_base_t *base); D2TK_API bool d2tk_base_get_mod(d2tk_base_t *base); +D2TK_API const char * +d2tk_state_dump(d2tk_state_t state); + D2TK_API bool d2tk_state_is_down(d2tk_state_t state); @@ -381,7 +384,7 @@ d2tk_base_toggle(d2tk_base_t *base, d2tk_id_t id, const d2tk_rect_t *rect, D2TK_API d2tk_state_t d2tk_base_meter(d2tk_base_t *base, d2tk_id_t id, const d2tk_rect_t *rect, - int32_t *value); + const int32_t *value); #define d2tk_base_meter_is_changed(...) \ d2tk_state_is_changed(d2tk_base_meter(__VA_ARGS__)) @@ -590,6 +593,18 @@ d2tk_base_set_up(d2tk_base_t *base, bool down); D2TK_API void d2tk_base_set_down(d2tk_base_t *base, bool down); +D2TK_API bool +d2tk_base_get_left(d2tk_base_t *base); + +D2TK_API bool +d2tk_base_get_right(d2tk_base_t *base); + +D2TK_API bool +d2tk_base_get_up(d2tk_base_t *base); + +D2TK_API bool +d2tk_base_get_down(d2tk_base_t *base); + D2TK_API void d2tk_base_set_dimensions(d2tk_base_t *base, d2tk_coord_t w, d2tk_coord_t h); diff --git a/subprojects/d2tk/example/example.c b/subprojects/d2tk/example/example.c index b2ccc06..caaea41 100644 --- a/subprojects/d2tk/example/example.c +++ b/subprojects/d2tk/example/example.c @@ -229,6 +229,9 @@ _render_c_seq(d2tk_base_t *base, const d2tk_rect_t *rect) #define NN (N*N) const unsigned M = N * rect->h / rect->w; static val_t value [N*N]; + static bool drag = false; + static d2tk_pos_t from_pos; + static d2tk_pos_t to_pos; d2tk_style_t style = *d2tk_base_get_default_style(); style.border_width = 1; @@ -239,8 +242,8 @@ _render_c_seq(d2tk_base_t *base, const d2tk_rect_t *rect) D2TK_BASE_TABLE(rect, N, M, tab) { const unsigned k = d2tk_table_get_index(tab); - const unsigned x = d2tk_table_get_index_x(tab); - const unsigned y = d2tk_table_get_index_y(tab); + const d2tk_coord_t x = d2tk_table_get_index_x(tab); + const d2tk_coord_t y = d2tk_table_get_index_y(tab); const d2tk_rect_t *bnd = d2tk_table_get_rect(tab); const d2tk_id_t id = D2TK_ID_IDX(k); @@ -268,9 +271,86 @@ _render_c_seq(d2tk_base_t *base, const d2tk_rect_t *rect) continue; } - if(d2tk_base_toggle_is_changed(base, id, bnd, &val->b)) + bool clone = val->b; + + const uint32_t col_active = style.fill_color[D2TK_TRIPLE_ACTIVE]; + + if(drag) + { + const d2tk_coord_t y0 = from_pos.y <= to_pos.y ? from_pos.y : to_pos.y; + const d2tk_coord_t y1 = from_pos.y > to_pos.y ? from_pos.y : to_pos.y; + const d2tk_coord_t x0 = from_pos.x <= to_pos.x ? from_pos.x : to_pos.x; + const d2tk_coord_t x1 = from_pos.x > to_pos.x ? from_pos.x : to_pos.x; + + for(d2tk_coord_t Y = y0; Y <= y1; Y++) + { + for(d2tk_coord_t X = x0; X <= x1; X++) + { + if( (y == from_pos.y) && (x == from_pos.x) ) + { + continue; + } + + if( (y != Y) || (x != X) ) + { + continue; + } + + clone = true; + + style.fill_color[D2TK_TRIPLE_ACTIVE] = 0x9f00cfff; + break; + } + } + } + + const d2tk_state_t state = d2tk_base_toggle(base, id, bnd, &clone); + + style.fill_color[D2TK_TRIPLE_ACTIVE] = col_active; + + if(d2tk_state_is_changed(state)) + { + val->b = clone; + } + + if(d2tk_state_is_down(state)) + { + drag = true; + + from_pos.x = to_pos.x = x; + from_pos.y = to_pos.y = y; + + fprintf(stdout, "toggle %016"PRIx64" DOWN\n", id); + } + + if(drag && d2tk_state_is_over(state)) + { + to_pos.x = x; + to_pos.y = y; + } + + if(d2tk_state_is_up(state)) { - fprintf(stdout, "toggle %016"PRIx64" %s\n", id, val->b ? "ON" : "OFF"); + drag = false; + + const d2tk_coord_t y0 = from_pos.y <= to_pos.y ? from_pos.y : to_pos.y; + const d2tk_coord_t y1 = from_pos.y > to_pos.y ? from_pos.y : to_pos.y; + const d2tk_coord_t x0 = from_pos.x <= to_pos.x ? from_pos.x : to_pos.x; + const d2tk_coord_t x1 = from_pos.x > to_pos.x ? from_pos.x : to_pos.x; + + for(d2tk_coord_t Y = y0; Y <= y1; Y++) + { + const d2tk_coord_t O = N*Y; + + for(d2tk_coord_t X = x0; X <= x1; X++) + { + const d2tk_coord_t K = O + X; + + value[K] = *val; + } + } + + fprintf(stdout, "toggle %016"PRIx64" UP\n", id); } } diff --git a/subprojects/d2tk/meson.build b/subprojects/d2tk/meson.build index f3cdf57..e2e5b73 100644 --- a/subprojects/d2tk/meson.build +++ b/subprojects/d2tk/meson.build @@ -2,7 +2,7 @@ project('d2tk', 'c', default_options : [ 'buildtype=release', 'warning_level=3', 'werror=false', - 'b_lto=true', + 'b_lto=false', 'c_std=c11']) static_link = false #meson.is_cross_build() diff --git a/subprojects/d2tk/pugl/pugl/pugl_x11.c b/subprojects/d2tk/pugl/pugl/pugl_x11.c index 5c20782..5afc880 100644 --- a/subprojects/d2tk/pugl/pugl/pugl_x11.c +++ b/subprojects/d2tk/pugl/pugl/pugl_x11.c @@ -522,8 +522,7 @@ translateEvent(PuglView* view, XEvent xevent) case 7: event.scroll.dx = 1.0f; break; } } - __attribute__((fallthrough)); - // nobreak + /* fall through */ case ButtonRelease: if (xevent.xbutton.button < 4 || xevent.xbutton.button > 7) { event.button.type = ((xevent.type == ButtonPress) diff --git a/subprojects/d2tk/src/base.c b/subprojects/d2tk/src/base.c index f2ecf34..0bbbb8a 100644 --- a/subprojects/d2tk/src/base.c +++ b/subprojects/d2tk/src/base.c @@ -82,6 +82,8 @@ struct _d2tk_base_t { d2tk_flip_t focusitem; d2tk_id_t lastitem; + bool not_first_time; + struct { d2tk_coord_t x; d2tk_coord_t y; @@ -222,7 +224,7 @@ const size_t d2tk_flowmatrix_arc_sz = sizeof(d2tk_flowmatrix_arc_t); const size_t d2tk_pane_sz = sizeof(d2tk_pane_t); static inline d2tk_id_t -_d2tk_flip_get(d2tk_flip_t *flip) +_d2tk_flip_get_cur(d2tk_flip_t *flip) { return flip->cur; } @@ -234,9 +236,9 @@ _d2tk_flip_get_old(d2tk_flip_t *flip) } static inline bool -_d2tk_flip_equal(d2tk_flip_t *flip, d2tk_id_t id) +_d2tk_flip_equal_cur(d2tk_flip_t *flip, d2tk_id_t id) { - return _d2tk_flip_get(flip) == id; + return _d2tk_flip_get_cur(flip) == id; } static inline bool @@ -248,7 +250,7 @@ _d2tk_flip_equal_old(d2tk_flip_t *flip, d2tk_id_t id) static inline bool _d2tk_flip_invalid(d2tk_flip_t *flip) { - return _d2tk_flip_equal(flip, 0); + return _d2tk_flip_equal_cur(flip, 0); } static inline bool @@ -646,6 +648,25 @@ d2tk_base_get_mod(d2tk_base_t *base) return base->keys.shift || base->keys.ctrl || base->keys.alt; } +D2TK_API const char * +d2tk_state_dump(d2tk_state_t state) +{ +#define LEN 16 + static char buf [LEN + 1]; + + for(unsigned i = 0; i < LEN; i++) + { + buf[LEN - 1 - i] = (1 << i) & state + ? '1' + : '.'; + } + + buf[LEN] = '\0'; + + return buf; +#undef LEN +} + D2TK_API bool d2tk_state_is_down(d2tk_state_t state) { @@ -832,19 +853,21 @@ d2tk_base_is_active_hot(d2tk_base_t *base, d2tk_id_t id, const d2tk_rect_t *rect, d2tk_flag_t flags) { d2tk_state_t state = D2TK_STATE_NONE; - bool is_active = _d2tk_flip_equal(&base->activeitem, id); + bool is_active = _d2tk_flip_equal_cur(&base->activeitem, id); bool is_hot = false; bool is_over = false; - bool is_focused = _d2tk_flip_equal(&base->focusitem, id); + bool curfocus = _d2tk_flip_equal_cur(&base->focusitem, id); + bool newfocus = curfocus; + const bool lastfocus = _d2tk_flip_equal_old(&base->focusitem, id); // handle forward focus - if(is_focused) + if(curfocus) { if(base->keys.ctrl) { if(base->keys.right) { - is_focused = false; + newfocus = false; // do NOT change curfocus base->focused = false; // clear focused flag base->keys.right = false; } @@ -895,7 +918,8 @@ d2tk_base_is_active_hot(d2tk_base_t *base, d2tk_id_t id, } else if(!base->focused) { - is_focused = _d2tk_base_set_focus(base, id); + curfocus = _d2tk_base_set_focus(base, id); + newfocus = curfocus; base->focused = true; // set focused flag } @@ -915,7 +939,8 @@ d2tk_base_is_active_hot(d2tk_base_t *base, d2tk_id_t id, { _d2tk_flip_set(&base->activeitem, id); is_active = true; - is_focused = _d2tk_base_set_focus(base, id); + curfocus = _d2tk_base_set_focus(base, id); + newfocus = curfocus; state |= D2TK_STATE_DOWN; } @@ -963,15 +988,12 @@ d2tk_base_is_active_hot(d2tk_base_t *base, d2tk_id_t id, state |= D2TK_STATE_OVER; } - if(is_focused) + if(newfocus) { state |= D2TK_STATE_FOCUS; } { - const bool lastfocus = _d2tk_flip_equal_old(&base->focusitem, id); - const bool curfocus = _d2tk_flip_equal(&base->focusitem, id); - if(lastfocus && !curfocus) { state |= D2TK_STATE_FOCUS_OUT; @@ -982,9 +1004,9 @@ d2tk_base_is_active_hot(d2tk_base_t *base, d2tk_id_t id, } else if(!lastfocus && curfocus) { - if(_d2tk_flip_invalid_old(&base->focusitem)) + if(_d2tk_flip_invalid_old(&base->focusitem) && base->not_first_time) { - _d2tk_flip_set(&base->focusitem, _d2tk_flip_get(&base->focusitem)); + _d2tk_flip_set(&base->focusitem, _d2tk_flip_get_cur(&base->focusitem)); } else { @@ -998,7 +1020,7 @@ d2tk_base_is_active_hot(d2tk_base_t *base, d2tk_id_t id, } // handle backwards focus - if(is_focused) + if(newfocus) { if(base->keys.ctrl) { @@ -1012,6 +1034,8 @@ d2tk_base_is_active_hot(d2tk_base_t *base, d2tk_id_t id, base->lastitem = id; + base->not_first_time = true; + return state; } @@ -2010,7 +2034,7 @@ _d2tk_base_draw_meter(d2tk_core_t *core, const d2tk_rect_t *rect, D2TK_API d2tk_state_t d2tk_base_meter(d2tk_base_t *base, d2tk_id_t id, const d2tk_rect_t *rect, - int32_t *value) + const int32_t *value) { const d2tk_style_t *style = d2tk_base_get_style(base); @@ -3798,6 +3822,30 @@ d2tk_base_set_down(d2tk_base_t *base, bool down) base->keys.down = down; } +D2TK_API bool +d2tk_base_get_left(d2tk_base_t *base) +{ + return base->keys.left; +} + +D2TK_API bool +d2tk_base_get_right(d2tk_base_t *base) +{ + return base->keys.right; +} + +D2TK_API bool +d2tk_base_get_up(d2tk_base_t *base) +{ + return base->keys.up; +} + +D2TK_API bool +d2tk_base_get_down(d2tk_base_t *base) +{ + return base->keys.down; +} + D2TK_API void d2tk_base_set_dimensions(d2tk_base_t *base, d2tk_coord_t w, d2tk_coord_t h) { diff --git a/subprojects/d2tk/test/base.c b/subprojects/d2tk/test/base.c index c711528..367c0af 100644 --- a/subprojects/d2tk/test/base.c +++ b/subprojects/d2tk/test/base.c @@ -25,9 +25,30 @@ #include <d2tk/hash.h> #include "mock.h" +#define N 4 static void _expose_hot(d2tk_base_t *base, const d2tk_rect_t *rect, unsigned n, unsigned p) { +#define hot_over (D2TK_STATE_HOT | D2TK_STATE_OVER) + static const d2tk_state_t states [N][N] = { + [0] = { + [0] = D2TK_STATE_FOCUS | D2TK_STATE_FOCUS_IN | hot_over + }, + [1] = { + [0] = D2TK_STATE_FOCUS, + [1] = hot_over + }, + [2] = { + [0] = D2TK_STATE_FOCUS, + [2] = hot_over + }, + [3] = { + [0] = D2TK_STATE_FOCUS, + [3] = hot_over + } + }; +#undef hot_over + D2TK_BASE_TABLE(rect, n, 1, tab) { const d2tk_rect_t *bnd = d2tk_table_get_rect(tab); @@ -36,32 +57,256 @@ _expose_hot(d2tk_base_t *base, const d2tk_rect_t *rect, unsigned n, unsigned p) const d2tk_state_t state = d2tk_base_button(base, id, bnd); - if(k == p) // this element must be of state OVER and HOT - { - if(p == 0) // first element additionally has FOCUS - { - assert(state == (D2TK_STATE_OVER | D2TK_STATE_FOCUS | D2TK_STATE_HOT) ); + assert(state == states[p][k]); + } +} + +static void +_test_hot() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + assert(base); + + d2tk_base_set_dimensions(base, DIM_W, DIM_H); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + + for(unsigned p = 0; p < N; p++) + { + const float p5 = p + 0.5f; + const d2tk_coord_t mx = DIM_W / N * p5; + const d2tk_coord_t my = DIM_H / 2; + + d2tk_base_set_mouse_pos(base, mx, my); + + d2tk_base_pre(base); + + _expose_hot(base, &rect, N, p); + + d2tk_base_post(base); + assert(!d2tk_base_get_again(base)); + } + + // trigger garbage collector + for(unsigned i = 0; i < 0x400; i++) + { + d2tk_base_pre(base); + d2tk_base_post(base); + assert(!d2tk_base_get_again(base)); + } + + d2tk_base_free(base); +} +#undef N + +#define N 4 +static void +_expose_mouse_fwd_focus(d2tk_base_t *base, const d2tk_rect_t *rect, unsigned n, + unsigned p, bool down) +{ +#define focus_down ( \ + D2TK_STATE_DOWN \ + | D2TK_STATE_ACTIVE \ + | D2TK_STATE_HOT \ + | D2TK_STATE_FOCUS \ + | D2TK_STATE_FOCUS_IN \ + | D2TK_STATE_MOTION \ + | D2TK_STATE_CHANGED \ + | D2TK_STATE_OVER ) +#define focus_up ( \ + D2TK_STATE_UP \ + | D2TK_STATE_HOT \ + | D2TK_STATE_FOCUS \ + | D2TK_STATE_OVER ) + static const d2tk_state_t states [N][2][N] = { + [0] = { + [true] = { + [0] = focus_down + }, + [false] = { + [0] = focus_up } - else - { - assert(state == (D2TK_STATE_OVER | D2TK_STATE_HOT) ); + }, + [1] = { + [true] = { + [0] = D2TK_STATE_FOCUS, + [1] = focus_down + }, + [false] = { + [0] = D2TK_STATE_FOCUS_OUT, + [1] = focus_up + } + }, + [2] = { + [true] = { + [1] = D2TK_STATE_FOCUS, + [2] = focus_down + }, + [false] = { + [1] = D2TK_STATE_FOCUS_OUT, + [2] = focus_up + } + }, + [3] = { + [true] = { + [2] = D2TK_STATE_FOCUS, + [3] = focus_down + }, + [false] = { + [2] = D2TK_STATE_FOCUS_OUT, + [3] = focus_up } } - else if(k == 0) // first element always has FOCUS + }; +#undef focus_up +#undef focus_down + + D2TK_BASE_TABLE(rect, n, 1, tab) + { + const d2tk_rect_t *bnd = d2tk_table_get_rect(tab); + const unsigned k = d2tk_table_get_index(tab); + const d2tk_id_t id = D2TK_ID_IDX(k); + + const d2tk_state_t state = d2tk_base_button(base, id, bnd); + + assert(state == states[p][down][k]); + } +} + +static void +_test_mouse_fwd_focus() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + assert(base); + + d2tk_base_set_dimensions(base, DIM_W, DIM_H); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + + for(unsigned p = 0; p < N; p++) + { + const float p5 = p + 0.5f; + const d2tk_coord_t mx = DIM_W / N * p5; + const d2tk_coord_t my = DIM_H / 2; + { - assert(state == D2TK_STATE_FOCUS); + d2tk_base_set_mouse_pos(base, mx, my); + d2tk_base_set_mouse_l(base, true); + + d2tk_base_pre(base); + + _expose_mouse_fwd_focus(base, &rect, N, p, true); + + d2tk_base_post(base); + assert(!d2tk_base_get_again(base)); } - else // all other elements have no state + { - assert(state == D2TK_STATE_NONE); + d2tk_base_set_mouse_l(base, false); + + d2tk_base_pre(base); + + _expose_mouse_fwd_focus(base, &rect, N, p, false); + + d2tk_base_post(base); + assert(!d2tk_base_get_again(base)); } } + + // trigger garbage collector + for(unsigned i = 0; i < 0x400; i++) + { + d2tk_base_pre(base); + d2tk_base_post(base); + assert(!d2tk_base_get_again(base)); + } + + d2tk_base_free(base); } +#undef N +#define N 4 static void -_test_hot() +_expose_mouse_bwd_focus(d2tk_base_t *base, const d2tk_rect_t *rect, unsigned n, + unsigned p, bool down) +{ +#define focus_down ( \ + D2TK_STATE_DOWN \ + | D2TK_STATE_ACTIVE \ + | D2TK_STATE_HOT \ + | D2TK_STATE_FOCUS \ + | D2TK_STATE_FOCUS_IN \ + | D2TK_STATE_MOTION \ + | D2TK_STATE_CHANGED \ + | D2TK_STATE_OVER ) +#define focus_up ( \ + D2TK_STATE_UP \ + | D2TK_STATE_HOT \ + | D2TK_STATE_FOCUS \ + | D2TK_STATE_OVER ) + static const d2tk_state_t states [N][2][N] = { + [0] = { + [true] = { + [0] = D2TK_STATE_FOCUS | D2TK_STATE_FOCUS_IN, + [3] = focus_down + }, + [false] = { + [0] = D2TK_STATE_FOCUS_OUT, + [3] = focus_up + } + }, + [1] = { + [true] = { + [2] = focus_down, + [3] = D2TK_STATE_FOCUS_OUT + }, + [false] = { + [2] = focus_up + } + }, + [2] = { + [true] = { + [1] = focus_down, + [2] = D2TK_STATE_FOCUS_OUT + }, + [false] = { + [1] = focus_up + } + }, + [3] = { + [true] = { + [0] = focus_down, + [1] = D2TK_STATE_FOCUS_OUT + }, + [false] = { + [0] = focus_up + } + } + }; +#undef focus_up +#undef focus_down + + D2TK_BASE_TABLE(rect, n, 1, tab) + { + const d2tk_rect_t *bnd = d2tk_table_get_rect(tab); + const unsigned k = d2tk_table_get_index(tab); + const d2tk_id_t id = D2TK_ID_IDX(k); + + const d2tk_state_t state = d2tk_base_button(base, id, bnd); + + assert(state == states[p][down][k]); + } +} + +static void +_test_mouse_bwd_focus() { -#define N 4 d2tk_mock_ctx_t ctx = { .check = NULL }; @@ -73,18 +318,253 @@ _test_hot() const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); for(unsigned p = 0; p < N; p++) - { + { const float p5 = p + 0.5f; - const d2tk_coord_t mx = DIM_W / N * p5; + const d2tk_coord_t mx = DIM_W - DIM_W / N * p5; const d2tk_coord_t my = DIM_H / 2; - d2tk_base_set_mouse_pos(base, mx, my); + { + d2tk_base_set_mouse_pos(base, mx, my); + d2tk_base_set_mouse_l(base, true); + d2tk_base_pre(base); + + _expose_mouse_bwd_focus(base, &rect, N, p, true); + + d2tk_base_post(base); + assert(!d2tk_base_get_again(base)); + } + + { + d2tk_base_set_mouse_l(base, false); + + d2tk_base_pre(base); + + _expose_mouse_bwd_focus(base, &rect, N, p, false); + + d2tk_base_post(base); + assert(!d2tk_base_get_again(base)); + } + } + + // trigger garbage collector + for(unsigned i = 0; i < 0x400; i++) + { d2tk_base_pre(base); + d2tk_base_post(base); + assert(!d2tk_base_get_again(base)); + } - _expose_hot(base, &rect, N, p); + d2tk_base_free(base); +} +#undef N +#define N 4 +static void +_expose_key_fwd_focus(d2tk_base_t *base, const d2tk_rect_t *rect, unsigned n, + unsigned p, bool down) +{ +#define invar D2TK_STATE_HOT | D2TK_STATE_OVER + static const d2tk_state_t states [N][2][N] = { + [0] = { + [true] = { + [0] = invar | D2TK_STATE_FOCUS | D2TK_STATE_FOCUS_IN + }, + [false] = { + [0] = invar | D2TK_STATE_FOCUS + } + }, + [1] = { + [true] = { + [0] = invar, + [1] = D2TK_STATE_FOCUS | D2TK_STATE_FOCUS_IN + }, + [false] = { + [0] = invar | D2TK_STATE_FOCUS_OUT, + [1] = D2TK_STATE_FOCUS + } + }, + [2] = { + [true] = { + [0] = invar, + [2] = D2TK_STATE_FOCUS | D2TK_STATE_FOCUS_IN + }, + [false] = { + [0] = invar, + [1] = D2TK_STATE_FOCUS_OUT, + [2] = D2TK_STATE_FOCUS + } + }, + [3] = { + [true] = { + [0] = invar, + [3] = D2TK_STATE_FOCUS | D2TK_STATE_FOCUS_IN + }, + [false] = { + [0] = invar, + [2] = D2TK_STATE_FOCUS_OUT, + [3] = D2TK_STATE_FOCUS + } + } + }; +#undef invar + + D2TK_BASE_TABLE(rect, n, 1, tab) + { + const d2tk_rect_t *bnd = d2tk_table_get_rect(tab); + const unsigned k = d2tk_table_get_index(tab); + const d2tk_id_t id = D2TK_ID_IDX(k); + + const d2tk_state_t state = d2tk_base_button(base, id, bnd); + + assert(state == states[p][down][k]); + } +} + +static void +_test_key_fwd_focus() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + assert(base); + + d2tk_base_set_dimensions(base, DIM_W, DIM_H); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + + for(unsigned p = 0; p < N; p++) + { + { + d2tk_base_set_ctrl(base, true); + d2tk_base_set_right(base, true); + + d2tk_base_pre(base); + + _expose_key_fwd_focus(base, &rect, N, p, true); + + d2tk_base_post(base); + assert(!d2tk_base_get_again(base)); + } + + { + d2tk_base_set_right(base, false); + d2tk_base_set_ctrl(base, false); + + d2tk_base_pre(base); + + _expose_key_fwd_focus(base, &rect, N, p, false); + + d2tk_base_post(base); + assert(!d2tk_base_get_again(base)); + } + } + + // trigger garbage collector + for(unsigned i = 0; i < 0x400; i++) + { + d2tk_base_pre(base); d2tk_base_post(base); + assert(!d2tk_base_get_again(base)); + } + + d2tk_base_free(base); +} +#undef N + +#define N 4 +static void +_expose_key_bwd_focus(d2tk_base_t *base, const d2tk_rect_t *rect, unsigned n, + unsigned p, bool down) +{ +#define invar D2TK_STATE_HOT | D2TK_STATE_OVER + static const d2tk_state_t states [N][2][N] = { + [0] = { + [true] = { + [0] = invar | D2TK_STATE_FOCUS | D2TK_STATE_FOCUS_IN + }, + [false] = { + [0] = invar | D2TK_STATE_FOCUS_OUT + } + }, + [1] = { //FIXME something's very wrong here, focus seems lost + [true] = { + [0] = invar + }, + [false] = { + [0] = invar + } + }, + [2] = { + [true] = { + [0] = invar + }, + [false] = { + [0] = invar + } + }, + [3] = { + [true] = { + [0] = invar + }, + [false] = { + [0] = invar + } + } + }; +#undef invar + + D2TK_BASE_TABLE(rect, n, 1, tab) + { + const d2tk_rect_t *bnd = d2tk_table_get_rect(tab); + const unsigned k = d2tk_table_get_index(tab); + const d2tk_id_t id = D2TK_ID_IDX(k); + + const d2tk_state_t state = d2tk_base_button(base, id, bnd); + + assert(state == states[p][down][k]); + } +} + +static void +_test_key_bwd_focus() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + assert(base); + + d2tk_base_set_dimensions(base, DIM_W, DIM_H); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + + for(unsigned p = 0; p < N; p++) + { + { + d2tk_base_set_ctrl(base, true); + d2tk_base_set_left(base, true); + + d2tk_base_pre(base); + + _expose_key_bwd_focus(base, &rect, N, p, true); + + d2tk_base_post(base); + assert(!d2tk_base_get_again(base)); + } + + { + d2tk_base_set_left(base, false); + d2tk_base_set_ctrl(base, false); + + d2tk_base_pre(base); + + _expose_key_bwd_focus(base, &rect, N, p, false); + + d2tk_base_post(base); + assert(!d2tk_base_get_again(base)); + } } // trigger garbage collector @@ -92,6 +572,1188 @@ _test_hot() { d2tk_base_pre(base); d2tk_base_post(base); + assert(!d2tk_base_get_again(base)); + } + + d2tk_base_free(base); +} +#undef N + +static void +_test_get_set() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + assert(base); + + { + d2tk_coord_t w = 0; + d2tk_coord_t h = 0; + + d2tk_base_set_dimensions(base, DIM_W, DIM_H); + d2tk_base_get_dimensions(base, &w, &h); + + assert(w == DIM_W); + assert(h == DIM_H); + } + + { + d2tk_base_set_ttls(base, 128, 128); + //FIXME add getter + } + + { + d2tk_base_clear_focus(base); + d2tk_base_set_again(base); + //FIXME add getter + } + + { + d2tk_base_set_mouse_l(base, true); + d2tk_base_set_mouse_m(base, true); + d2tk_base_set_mouse_r(base, true); + //FIXME add getter + } + + { + d2tk_coord_t x = 0; + d2tk_coord_t y = 0; + + d2tk_base_set_mouse_pos(base, 30, 40); + + d2tk_base_get_mouse_pos(base, &x, &y); + assert(x == 30); + assert(y == 40); + + x = 0; + y = 0; + d2tk_base_get_mouse_pos(base, NULL, NULL); + assert(x == 0); + assert(y == 0); + } + + { + d2tk_base_add_mouse_scroll(base, 2, 3); + //FIXME add getter + } + + { + d2tk_base_set_shift(base, false); + d2tk_base_set_ctrl(base, false); + d2tk_base_set_alt(base, false); + + assert(d2tk_base_get_shift(base) == false); + assert(d2tk_base_get_ctrl(base) == false); + assert(d2tk_base_get_alt(base) == false); + + d2tk_base_set_shift(base, true); + d2tk_base_set_ctrl(base, true); + d2tk_base_set_alt(base, true); + + assert(d2tk_base_get_shift(base) == true); + assert(d2tk_base_get_ctrl(base) == true); + assert(d2tk_base_get_alt(base) == true); + } + + { + d2tk_base_set_shift(base, false); + d2tk_base_set_ctrl(base, false); + d2tk_base_set_alt(base, false); + + assert(d2tk_base_get_mod(base) == false); + + d2tk_base_set_shift(base, true); + d2tk_base_set_ctrl(base, false); + d2tk_base_set_alt(base, false); + + assert(d2tk_base_get_mod(base) == true); + + d2tk_base_set_shift(base, false); + d2tk_base_set_ctrl(base, true); + d2tk_base_set_alt(base, false); + + assert(d2tk_base_get_mod(base) == true); + + d2tk_base_set_shift(base, false); + d2tk_base_set_ctrl(base, false); + d2tk_base_set_alt(base, true); + + assert(d2tk_base_get_mod(base) == true); + } + + { + d2tk_base_set_left(base, false); + d2tk_base_set_right(base, false); + d2tk_base_set_up(base, false); + d2tk_base_set_down(base, false); + + assert(d2tk_base_get_left(base) == false); + assert(d2tk_base_get_right(base) == false); + assert(d2tk_base_get_up(base) == false); + assert(d2tk_base_get_down(base) == false); + + d2tk_base_set_left(base, true); + d2tk_base_set_right(base, true); + d2tk_base_set_up(base, true); + d2tk_base_set_down(base, true); + + assert(d2tk_base_get_left(base) == true); + assert(d2tk_base_get_right(base) == true); + assert(d2tk_base_get_up(base) == true); + assert(d2tk_base_get_down(base) == true); + } + + d2tk_base_free(base); +} + +static void +_test_table() +{ +#define N 12 +#define M 8 + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + D2TK_BASE_TABLE(&rect, N, M, tab) + { + const d2tk_rect_t *bnd = d2tk_table_get_rect(tab); + const unsigned k = d2tk_table_get_index(tab); + const unsigned x = d2tk_table_get_index_x(tab); + const unsigned y = d2tk_table_get_index_y(tab); + + assert(bnd); + assert(bnd->x == rect.w / N * (d2tk_coord_t)x); + assert(bnd->y == rect.h / M * (d2tk_coord_t)y); + assert(bnd->w == rect.w / N); + assert(bnd->h == rect.h / M); + assert(y*N + x == k); + } + + d2tk_base_free(base); +#undef M +#undef N +} + +static void +_test_frame() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + D2TK_BASE_FRAME(base, &rect, -1, "label", frm) + { + const d2tk_rect_t *bnd = d2tk_frame_get_rect(frm); + + assert(bnd); + assert(bnd->x > rect.x); + assert(bnd->y > rect.y); + assert(bnd->w < rect.w); + assert(bnd->h < rect.h); + } + + d2tk_base_free(base); +} + +static void +_test_layout_relative_x() +{ +#define N 4 + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + const d2tk_coord_t frac [N] = { + 1, 2, 4, 0 + }; + unsigned i = 0; + D2TK_BASE_LAYOUT(&rect, N, frac, D2TK_FLAG_LAYOUT_X | D2TK_FLAG_LAYOUT_REL, lay) + { + const d2tk_rect_t *bnd = d2tk_layout_get_rect(lay); + const unsigned k = d2tk_layout_get_index(lay); + + assert(k == i++); + assert(bnd); + //FIXME bnd->x/y/w/h + } + + d2tk_base_free(base); +#undef N +} + +static void +_test_layout_relative_y() +{ +#define N 4 + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + const d2tk_coord_t frac [N] = { + 1, 2, 4, 0 + }; + unsigned i = 0; + D2TK_BASE_LAYOUT(&rect, N, frac, D2TK_FLAG_LAYOUT_Y | D2TK_FLAG_LAYOUT_REL, lay) + { + const d2tk_rect_t *bnd = d2tk_layout_get_rect(lay); + const unsigned k = d2tk_layout_get_index(lay); + + assert(k == i++); + assert(bnd); + //FIXME bnd->x/y/w/h + } + + d2tk_base_free(base); +#undef N +} + +static void +_test_layout_absolute_x() +{ +#define N 4 + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + const d2tk_coord_t frac [N] = { + DIM_W/4, 0, 0, 0 + }; + unsigned i = 0; + D2TK_BASE_LAYOUT(&rect, N, frac, D2TK_FLAG_LAYOUT_X | D2TK_FLAG_LAYOUT_ABS, lay) + { + const d2tk_rect_t *bnd = d2tk_layout_get_rect(lay); + const unsigned k = d2tk_layout_get_index(lay); + + assert(k == i++); + assert(bnd); + //FIXME bnd->x/y/w/h + } + + d2tk_base_free(base); +#undef N +} + +static void +_test_layout_absolute_y() +{ +#define N 4 + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + const d2tk_coord_t frac [N] = { + DIM_W/4, 0, 0, 0 + }; + unsigned i = 0; + D2TK_BASE_LAYOUT(&rect, N, frac, D2TK_FLAG_LAYOUT_Y | D2TK_FLAG_LAYOUT_ABS, lay) + { + const d2tk_rect_t *bnd = d2tk_layout_get_rect(lay); + const unsigned k = d2tk_layout_get_index(lay); + + assert(k == i++); + assert(bnd); + //FIXME bnd->x/y/w/h + } + + d2tk_base_free(base); +#undef N +} + +static void +_test_clip() +{ + { + const int32_t imin = 2; + const int32_t imax = 4; + + int32_t ival = 1; + d2tk_clip_int32(imin, &ival, imax); + assert(ival == imin); + + ival = 2; + d2tk_clip_int32(imin, &ival, imax); + assert(ival == imin); + + ival = 3; + d2tk_clip_int32(imin, &ival, imax); + assert(ival == 3); + + ival = 4; + d2tk_clip_int32(imin, &ival, imax); + assert(ival == imax); + + ival = 5; + d2tk_clip_int32(imin, &ival, imax); + assert(ival == imax); + } + + { + const int64_t imin = 2; + const int64_t imax = 4; + + int64_t ival = 1; + d2tk_clip_int64(imin, &ival, imax); + assert(ival == imin); + + ival = 2; + d2tk_clip_int64(imin, &ival, imax); + assert(ival == imin); + + ival = 3; + d2tk_clip_int64(imin, &ival, imax); + assert(ival == 3); + + ival = 4; + d2tk_clip_int64(imin, &ival, imax); + assert(ival == imax); + + ival = 5; + d2tk_clip_int64(imin, &ival, imax); + assert(ival == imax); + } + + { + const float imin = 2.f; + const float imax = 4.f; + + float ival = 1.f; + d2tk_clip_float(imin, &ival, imax); + assert(ival == imin); + + ival = 2.f; + d2tk_clip_float(imin, &ival, imax); + assert(ival == imin); + + ival = 3.f; + d2tk_clip_float(imin, &ival, imax); + assert(ival == 3); + + ival = 4.f; + d2tk_clip_float(imin, &ival, imax); + assert(ival == imax); + + ival = 5.f; + d2tk_clip_float(imin, &ival, imax); + assert(ival == imax); + } + + { + const double imin = 2.0; + const double imax = 4.0; + + double ival = 1.0; + d2tk_clip_double(imin, &ival, imax); + assert(ival == imin); + + ival = 2.0; + d2tk_clip_double(imin, &ival, imax); + assert(ival == imin); + + ival = 3.0; + d2tk_clip_double(imin, &ival, imax); + assert(ival == 3); + + ival = 4.0; + d2tk_clip_double(imin, &ival, imax); + assert(ival == imax); + + ival = 5.0; + d2tk_clip_double(imin, &ival, imax); + assert(ival == imax); + } +} + +static void +_test_state() +{ + assert(d2tk_state_is_down(D2TK_STATE_DOWN)); + assert(!d2tk_state_is_down(D2TK_STATE_NONE)); + + assert(d2tk_state_is_up(D2TK_STATE_UP)); + assert(!d2tk_state_is_up(D2TK_STATE_NONE)); + + assert(d2tk_state_is_motion(D2TK_STATE_MOTION)); + assert(!d2tk_state_is_motion(D2TK_STATE_NONE)); + + assert(d2tk_state_is_scroll_up(D2TK_STATE_SCROLL_UP)); + assert(!d2tk_state_is_scroll_up(D2TK_STATE_NONE)); + + assert(d2tk_state_is_scroll_down(D2TK_STATE_SCROLL_DOWN)); + assert(!d2tk_state_is_scroll_down(D2TK_STATE_NONE)); + + assert(d2tk_state_is_scroll_left(D2TK_STATE_SCROLL_LEFT)); + assert(!d2tk_state_is_scroll_left(D2TK_STATE_NONE)); + + assert(d2tk_state_is_scroll_right(D2TK_STATE_SCROLL_RIGHT)); + assert(!d2tk_state_is_scroll_right(D2TK_STATE_NONE)); + + assert(d2tk_state_is_active(D2TK_STATE_ACTIVE)); + assert(!d2tk_state_is_active(D2TK_STATE_NONE)); + + assert(d2tk_state_is_hot(D2TK_STATE_HOT)); + assert(!d2tk_state_is_hot(D2TK_STATE_NONE)); + + assert(d2tk_state_is_focused(D2TK_STATE_FOCUS)); + assert(!d2tk_state_is_focused(D2TK_STATE_NONE)); + + assert(d2tk_state_is_focus_in(D2TK_STATE_FOCUS_IN)); + assert(!d2tk_state_is_focus_in(D2TK_STATE_NONE)); + + assert(d2tk_state_is_focus_out(D2TK_STATE_FOCUS_OUT)); + assert(!d2tk_state_is_focus_out(D2TK_STATE_NONE)); + + assert(d2tk_state_is_changed(D2TK_STATE_CHANGED)); + assert(!d2tk_state_is_changed(D2TK_STATE_NONE)); + + assert(d2tk_state_is_enter(D2TK_STATE_ENTER)); + assert(!d2tk_state_is_enter(D2TK_STATE_NONE)); + + assert(d2tk_state_is_over(D2TK_STATE_OVER)); + assert(!d2tk_state_is_over(D2TK_STATE_NONE)); +} + +static void +_test_hit() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + assert(base); + + const d2tk_rect_t rect = D2TK_RECT(10, 10, 10, 10); + + d2tk_base_set_mouse_pos(base, 0, 0); + assert(!d2tk_base_is_hit(base, &rect)); + + d2tk_base_set_mouse_pos(base, 0, 10); + assert(!d2tk_base_is_hit(base, &rect)); + + d2tk_base_set_mouse_pos(base, 10, 0); + assert(!d2tk_base_is_hit(base, &rect)); + + d2tk_base_set_mouse_pos(base, 10, 10); + assert(d2tk_base_is_hit(base, &rect)); + + d2tk_base_set_mouse_pos(base, 15, 15); + assert(d2tk_base_is_hit(base, &rect)); + + d2tk_base_set_mouse_pos(base, 10, 20); + assert(!d2tk_base_is_hit(base, &rect)); + + d2tk_base_set_mouse_pos(base, 20, 10); + assert(!d2tk_base_is_hit(base, &rect)); + + d2tk_base_set_mouse_pos(base, 20, 20); + assert(!d2tk_base_is_hit(base, &rect)); + + d2tk_base_free(base); +} + +static void +_test_default_style() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + assert(base); + + const d2tk_style_t *default_style = d2tk_base_get_default_style(); + const d2tk_style_t *style = d2tk_base_get_style(base); + const d2tk_style_t custom_style = *default_style; + + assert(default_style); + assert(style); + assert(default_style == style); + + d2tk_base_set_style(base, &custom_style); + style = d2tk_base_get_style(base); + + assert(style); + assert(style == &custom_style); + + d2tk_base_set_default_style(base); + style = d2tk_base_get_style(base); + + assert(style); + assert(style == default_style); + + d2tk_base_free(base); +} + +static void +_test_scrollbar_x() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + +#define H 128 +#define h 32 + D2TK_BASE_SCROLLBAR(base, &rect, D2TK_ID, D2TK_FLAG_SCROLL_X, H, 0, h, 0, scroll) + { + const d2tk_rect_t *bnd = d2tk_scrollbar_get_rect(scroll); + const float xo = d2tk_scrollbar_get_offset_x(scroll); + const float yo = d2tk_scrollbar_get_offset_y(scroll); + + assert(bnd); + assert(xo == 0); + assert(yo == 0); + } + //FIXME test scrolling +#undef h +#undef H + + d2tk_base_free(base); +} + +static void +_test_scrollbar_y() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + +#define V 128 +#define v 32 + D2TK_BASE_SCROLLBAR(base, &rect, D2TK_ID, D2TK_FLAG_SCROLL_Y, 0, V, 0, v, scroll) + { + const d2tk_rect_t *bnd = d2tk_scrollbar_get_rect(scroll); + const float xo = d2tk_scrollbar_get_offset_x(scroll); + const float yo = d2tk_scrollbar_get_offset_y(scroll); + + assert(bnd); + assert(xo == 0); + assert(yo == 0); + } + //FIXME test scrolling +#undef v +#undef V + + d2tk_base_free(base); +} + +static void +_test_pane_x() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + +#define fmin 0.25f +#define fmax 0.75f + D2TK_BASE_PANE(base, &rect, D2TK_ID, D2TK_FLAG_PANE_X, fmin, fmax, pane) + { + const d2tk_rect_t *bnd = d2tk_pane_get_rect(pane); + const unsigned k = d2tk_pane_get_index(pane); + const float f = d2tk_pane_get_fraction(pane); + + assert(bnd); + switch(k) + { + case 0: + { + assert(f == fmin); + } break; + case 1: + { + assert(f == fmin); + } break; + } + } + //FIXME test panning +#undef fmin +#undef fmax + + d2tk_base_free(base); +} + +static void +_test_pane_y() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + +#define fmin 0.25f +#define fmax 0.75f + D2TK_BASE_PANE(base, &rect, D2TK_ID, D2TK_FLAG_PANE_Y, fmin, fmax, pane) + { + const d2tk_rect_t *bnd = d2tk_pane_get_rect(pane); + const unsigned k = d2tk_pane_get_index(pane); + const float f = d2tk_pane_get_fraction(pane); + + assert(bnd); + switch(k) + { + case 0: + { + assert(f == fmin); + } break; + case 1: + { + assert(f == fmin); + } break; + } + } + //FIXME test panning +#undef fmin +#undef fmax + + d2tk_base_free(base); +} + +static void +_test_cursor() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + d2tk_base_cursor(base, &rect); + + d2tk_base_free(base); +} + +static void +_test_button_label_image() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + const d2tk_state_t state = d2tk_base_button_label_image(base, D2TK_ID, + -1, "label", -1, "image.png", &rect); + assert(state == (D2TK_STATE_HOT | D2TK_STATE_FOCUS | D2TK_STATE_FOCUS_IN + |D2TK_STATE_OVER) ); + + d2tk_base_free(base); +} + +static void +_test_button_label() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + const d2tk_state_t state = d2tk_base_button_label(base, D2TK_ID, + -1, "label", &rect); + assert(state == (D2TK_STATE_HOT | D2TK_STATE_FOCUS | D2TK_STATE_FOCUS_IN + | D2TK_STATE_OVER) ); + + d2tk_base_free(base); +} + +static void +_test_button_image() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + const d2tk_state_t state = d2tk_base_button_image(base, D2TK_ID, + -1, "image.png", &rect); + assert(state == (D2TK_STATE_HOT | D2TK_STATE_FOCUS | D2TK_STATE_FOCUS_IN + | D2TK_STATE_OVER) ); + + d2tk_base_free(base); +} + +static void +_test_button() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + const d2tk_state_t state = d2tk_base_button(base, D2TK_ID, &rect); + assert(state == (D2TK_STATE_HOT | D2TK_STATE_FOCUS | D2TK_STATE_FOCUS_IN + | D2TK_STATE_OVER) ); + + d2tk_base_free(base); +} + +static void +_test_toggle_label() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + bool val = false; + const d2tk_state_t state = d2tk_base_toggle_label(base, D2TK_ID, + -1, "label", &rect, &val); + assert(state == (D2TK_STATE_HOT | D2TK_STATE_FOCUS | D2TK_STATE_FOCUS_IN + | D2TK_STATE_OVER) ); + assert(val == false); + + d2tk_base_free(base); +} + +static void +_test_toggle() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + bool val = false; + d2tk_base_set_mouse_l(base, true); + const d2tk_state_t state = d2tk_base_toggle(base, D2TK_ID, &rect, &val); + assert(state == (D2TK_STATE_DOWN | D2TK_STATE_ACTIVE | D2TK_STATE_HOT + | D2TK_STATE_FOCUS | D2TK_STATE_FOCUS_IN | D2TK_STATE_CHANGED + | D2TK_STATE_OVER) ); + assert(val == true); + + d2tk_base_free(base); +} + +static void +_test_meter() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + const int32_t val = -32; + const d2tk_state_t state = d2tk_base_meter(base, D2TK_ID, &rect, &val); + assert(state == (D2TK_STATE_HOT | D2TK_STATE_FOCUS | D2TK_STATE_FOCUS_IN + | D2TK_STATE_OVER) ); + + d2tk_base_free(base); +} + +static void +_test_combo() +{ +#define nitms 4 + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + const char *itms [nitms] = { + "1", "2", "3", "4" + }; + int32_t val = 0; + const d2tk_state_t state = d2tk_base_combo(base, D2TK_ID, nitms, itms, &rect, &val); + assert(state == (D2TK_STATE_HOT | D2TK_STATE_FOCUS | D2TK_STATE_FOCUS_IN + | D2TK_STATE_OVER) ); + assert(val == 0); + //FIXME test toggling + + d2tk_base_free(base); +#undef ntims +} + +static void +_test_combo_scroll_up() +{ +#define nitms 4 + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + d2tk_base_add_mouse_scroll(base, 0.f, 1.f); + + const char *itms [nitms] = { + "1", "2", "3", "4" + }; + int32_t val = 0; + const d2tk_state_t state = d2tk_base_combo(base, D2TK_ID, nitms, itms, &rect, &val); + assert(state == (D2TK_STATE_HOT | D2TK_STATE_FOCUS | D2TK_STATE_FOCUS_IN + |D2TK_STATE_SCROLL_UP | D2TK_STATE_CHANGED | D2TK_STATE_OVER) ); + assert(val == 1); + //FIXME test toggling + + d2tk_base_free(base); +#undef ntims +} + +static void +_test_combo_scroll_down() +{ +#define nitms 4 + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + d2tk_base_add_mouse_scroll(base, 0.f, -1.f); + + const char *itms [nitms] = { + "1", "2", "3", "4" + }; + int32_t val = 0; + const d2tk_state_t state = d2tk_base_combo(base, D2TK_ID, nitms, itms, &rect, &val); + assert(state == (D2TK_STATE_HOT | D2TK_STATE_FOCUS | D2TK_STATE_FOCUS_IN + | D2TK_STATE_SCROLL_DOWN | D2TK_STATE_OVER) ); + assert(val == 0); + //FIXME test toggling + + d2tk_base_free(base); +#undef ntims +} + +static void +_test_text_field() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + d2tk_base_append_char(base, 'h'); + d2tk_base_append_char(base, 'e'); + d2tk_base_append_char(base, 'l'); + d2tk_base_append_char(base, 'l'); + d2tk_base_append_char(base, 'o'); + + char txt [32] = "foo bar"; + const d2tk_state_t state = d2tk_base_text_field(base, D2TK_ID, &rect, + sizeof(txt), txt, D2TK_ALIGN_LEFT, "hello"); + assert(state == (D2TK_STATE_HOT | D2TK_STATE_FOCUS | D2TK_STATE_FOCUS_IN + | D2TK_STATE_OVER) ); + assert(!strcmp(txt, "foo bar")); + + d2tk_base_free(base); +} + +static void +_test_label() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + const char *lbl= "label"; + const d2tk_state_t state = d2tk_base_label(base, -1, lbl, 0.8f, &rect, + D2TK_ALIGN_LEFT); + assert(state == D2TK_STATE_NONE); + + d2tk_base_free(base); +} + +static void +_test_dial_bool() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + bool val = false; + const d2tk_state_t state = d2tk_base_dial_bool(base, D2TK_ID, &rect, &val); + assert(state == (D2TK_STATE_HOT | D2TK_STATE_FOCUS | D2TK_STATE_FOCUS_IN + | D2TK_STATE_OVER) ); + assert(val == false); + //FIXME toggling + + d2tk_base_free(base); +} + +static void +_test_dial_int32() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + int32_t val = 12; + const d2tk_state_t state = d2tk_base_dial_int32(base, D2TK_ID, &rect, + 0, &val, 20); + assert(state == (D2TK_STATE_HOT | D2TK_STATE_FOCUS | D2TK_STATE_FOCUS_IN + | D2TK_STATE_OVER) ); + assert(val == 12); + //FIXME toggling + + d2tk_base_free(base); +} + +static void +_test_dial_int64() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + int64_t val = 12; + const d2tk_state_t state = d2tk_base_dial_int64(base, D2TK_ID, &rect, + 0, &val, 20); + assert(state == (D2TK_STATE_HOT | D2TK_STATE_FOCUS | D2TK_STATE_FOCUS_IN + | D2TK_STATE_OVER) ); + assert(val == 12); + //FIXME toggling + + d2tk_base_free(base); +} + +static void +_test_dial_float() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + float val = 12.f; + const d2tk_state_t state = d2tk_base_dial_float(base, D2TK_ID, &rect, + 0.f, &val, 20.f); + assert(state == (D2TK_STATE_HOT | D2TK_STATE_FOCUS | D2TK_STATE_FOCUS_IN + | D2TK_STATE_OVER) ); + assert(val == 12.f); + //FIXME toggling + + d2tk_base_free(base); +} + +static void +_test_dial_double() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + double val = 12.0; + const d2tk_state_t state = d2tk_base_dial_double(base, D2TK_ID, &rect, + 0.0, &val, 20.0); + assert(state == (D2TK_STATE_HOT | D2TK_STATE_FOCUS | D2TK_STATE_FOCUS_IN + | D2TK_STATE_OVER) ); + assert(val == 12.0); + //FIXME toggling + + d2tk_base_free(base); +} + +static void +_test_prop_int32() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + int32_t val = 12; + const d2tk_state_t state = d2tk_base_prop_int32(base, D2TK_ID, &rect, + 0, &val, 20); + assert(state == (D2TK_STATE_HOT | D2TK_STATE_FOCUS | D2TK_STATE_FOCUS_IN + | D2TK_STATE_OVER) ); + assert(val == 12); + //FIXME toggling + + d2tk_base_free(base); +} + +static void +_test_prop_float() +{ + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + float val = 12.f; + const d2tk_state_t state = d2tk_base_prop_float(base, D2TK_ID, &rect, + 0.f, &val, 20.f); + assert(state == (D2TK_STATE_HOT | D2TK_STATE_FOCUS | D2TK_STATE_FOCUS_IN + | D2TK_STATE_OVER) ); + assert(val == 12.f); + //FIXME toggling + + d2tk_base_free(base); +} + +static void +_test_flowmatrix() +{ +#define N 4 + d2tk_mock_ctx_t ctx = { + .check = NULL + }; + static d2tk_pos_t pos_nodes [N]; + static d2tk_pos_t pos_arcs [N][N]; + + d2tk_base_t *base = d2tk_base_new(&d2tk_mock_driver_lazy, &ctx); + const d2tk_rect_t rect = D2TK_RECT(0, 0, DIM_W, DIM_H); + assert(base); + + D2TK_BASE_FLOWMATRIX(base, &rect, D2TK_ID, flowm) + { + // draw arcs + for(unsigned i = 0; i < N; i++) + { + const unsigned nin = i + 1; + + d2tk_flowmatrix_set_src(flowm, D2TK_ID, &pos_nodes[i]); + + for(unsigned j = 0; j < N; j++) + { + const unsigned nout = j + 1; + d2tk_state_t state = D2TK_STATE_NONE; + + d2tk_flowmatrix_set_dst(flowm, D2TK_ID, &pos_nodes[j]); + + D2TK_BASE_FLOWMATRIX_ARC(base, flowm, nin, nout, &pos_nodes[i], + &pos_nodes[j], &pos_arcs[i][j], arc, &state) + { + const d2tk_rect_t *bnd = d2tk_flowmatrix_arc_get_rect(arc); + const unsigned k = d2tk_flowmatrix_arc_get_index(arc); + const unsigned x = d2tk_flowmatrix_arc_get_index_x(arc); + const unsigned y = d2tk_flowmatrix_arc_get_index_y(arc); + + assert(pos_nodes[i].x == 0); + assert(pos_nodes[i].y == 0); + assert(pos_nodes[j].x == 0); + assert(pos_nodes[j].y == 0); + assert(pos_arcs[i][j].x == 0); + assert(pos_arcs[i][j].y == 0); + assert(bnd); //FIXME check x,y,w,h + (void)k; //FIXME + (void)x; //FIXME + (void)y; //FIXME + } + + assert(state == D2TK_STATE_NONE); + } + } + + // draw nodes + for(int i = 0; i < N; i++) + { + d2tk_state_t state = D2TK_STATE_NONE; + + D2TK_BASE_FLOWMATRIX_NODE(base, flowm, &pos_nodes[i], node, &state) + { + const d2tk_rect_t *bnd = d2tk_flowmatrix_node_get_rect(node); + + assert(pos_nodes[i].x == 150 + 150*i); + assert(pos_nodes[i].y == 25 + 25*i); + assert(bnd); //FIXME check x,y,w,h + } + + assert(state == D2TK_STATE_NONE); + } } d2tk_base_free(base); @@ -102,6 +1764,46 @@ int main(int argc __attribute__((unused)), char **argv __attribute__((unused))) { _test_hot(); + _test_mouse_fwd_focus(); + _test_mouse_bwd_focus(); + _test_key_fwd_focus(); + _test_key_bwd_focus(); + _test_get_set(); + _test_table(); + _test_frame(); + _test_layout_relative_x(); + _test_layout_relative_y(); + _test_layout_absolute_x(); + _test_layout_absolute_y(); + _test_clip(); + _test_state(); + _test_hit(); + _test_default_style(); + _test_scrollbar_x(); + _test_scrollbar_y(); + _test_pane_x(); + _test_pane_y(); + _test_cursor(); + _test_button_label_image(); + _test_button_label(); + _test_button_image(); + _test_button(); + _test_toggle_label(); + _test_toggle(); + _test_meter(); + _test_combo(); + _test_combo_scroll_up(); + _test_combo_scroll_down(); + _test_text_field(); + _test_label(); + _test_dial_bool(); + _test_dial_int32(); + _test_dial_int64(); + _test_dial_float(); + _test_dial_double(); + _test_prop_int32(); + _test_prop_float(); + _test_flowmatrix(); return EXIT_SUCCESS; } |