button.ui.tests.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include <planet/debug/ui.hpp>
#include <planet/ostream.hpp>
#include <planet/widget/button.hpp>

#include <felspar/test.hpp>


namespace {


    constexpr planet::ui::reflowable::constrained_type screen{
            {40, 0, 40}, {30, 0, 30}};

Lay a button out over a known rectangle and register it for input

16
17
18
19
20
21
22
23
24
    template<typename Button>
    void place(planet::ui::baseplate &bp, Button &btn) {
        btn.add_to(bp);
        btn.reflow({.screen = screen}, screen);
        btn.move_to(
                {.screen = screen},
                {{15, 20}, planet::affine::extents2d{4, 3}});
        btn.draw();
    }

A press of the left button over the rectangle place gives a button

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
    void
            press(planet::ui::baseplate &bp,
                  planet::events::modifiers const modifiers = {}) {
        bp.events.mouse.push(
                {.button = planet::events::button::left,
                 .action = planet::events::action::down,
                 .location = {18, 21},
                 .modifiers = modifiers});
        bp.events.mouse.push(
                {.button = planet::events::button::left,
                 .action = planet::events::action::up,
                 .location = {18, 21},
                 .clicks = 1,
                 .modifiers = modifiers});
    }


    auto const suite = felspar::testsuite("button.ui");


    auto const callback = suite.test("callback", [](auto check, auto &log) {

A callback taking nothing is told only that the button was pressed

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
        planet::ui::baseplate bp;
        std::size_t presses{};
        auto btn = planet::widget::button{
                "clicked", planet::debug::fixed_element{log, {4, 3}},
                [&presses]() { ++presses; }};
        place(bp, btn);

        press(bp);
        check(presses) == 1u;
        press(bp, {.shift = true});
        check(presses) == 2u;
    });


    auto const future = suite.test("future", [](auto check, auto &log) {

A press of a button delivering into a future carries no value, so the future is a future<void> and the first press is the whole of what it delivers: the value is set and the behaviour ends, leaving later presses with nothing to do.

70
71
72
73
74
75
76
77
78
        planet::ui::baseplate bp;
        felspar::coro::future<void> pressed;
        auto btn = planet::widget::button{
                "clicked", planet::debug::fixed_element{log, {4, 3}}, pressed};
        place(bp, btn);
        check(pressed.has_value()) == false;

        press(bp);
        check(pressed.has_value()) == true;

A second press sets nothing, which a set future would throw over

80
81
82
83
84
85
        press(bp);
        check(pressed.has_value()) == true;
    });


    auto const clicks = suite.test("click-callback", [](auto check, auto &log) {

A callback taking a click is handed the whole event, so the modifiers held at the time are there to be read and a shift-click can be told from the plain kind.

 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
        planet::ui::baseplate bp;
        std::vector<planet::events::click> presses;
        auto btn = planet::widget::button{
                "clicked", planet::debug::fixed_element{log, {4, 3}},
                [&presses](planet::events::click const c) {
                    presses.push_back(c);
                }};
        place(bp, btn);

        press(bp);
        check(presses.size()) == 1u;
        check(presses.back().modifiers == planet::events::modifiers{}) == true;
        check(presses.back().count) == 1u;
        check(presses.back().location) == planet::affine::point2d{18, 21};

        press(bp, {.shift = true});
        check(presses.size()) == 2u;
        check(presses.back().modifiers
              == planet::events::modifiers{.shift = true})
                == true;
    });


}