Public Access
Add widget kit, input layer with Compose Key, Launcher and demo apps
Steps 5 and 6 of M0. - lib/ui (host-tested): ListModel, LineEditor (UTF-8, byte-limited), wrapText, ToastQueue, DialogModel - lib/input (host-tested): KeyMapper turns keyboard state into logical keys (Fn arrows, ` Back, Fn+` Home) and composes accents with opt - src/ui: off-screen 16-bit frame pushed in one transfer (fixes the flicker), Status Bar, list, text, line editor, dialog, Toast widgets, Notifier (Toast + beep + LED), vendored public-domain Latin-1 fonts - Apps: minimal Launcher, Widget demo, Diagnostics (SD erase now behind a confirmation dialog) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
#include <unity.h>
|
||||
|
||||
#include "list_model.h"
|
||||
|
||||
using namespace roro;
|
||||
|
||||
void setUp() {}
|
||||
void tearDown() {}
|
||||
|
||||
void test_empty_list_has_no_selection() {
|
||||
ListModel l(5);
|
||||
TEST_ASSERT_EQUAL(-1, l.selected());
|
||||
l.down();
|
||||
TEST_ASSERT_EQUAL(-1, l.selected());
|
||||
}
|
||||
|
||||
void test_selection_starts_at_first_item() {
|
||||
ListModel l(5);
|
||||
l.setCount(3);
|
||||
TEST_ASSERT_EQUAL(0, l.selected());
|
||||
}
|
||||
|
||||
void test_down_and_up_move_the_selection() {
|
||||
ListModel l(5);
|
||||
l.setCount(3);
|
||||
l.down();
|
||||
TEST_ASSERT_EQUAL(1, l.selected());
|
||||
l.up();
|
||||
TEST_ASSERT_EQUAL(0, l.selected());
|
||||
}
|
||||
|
||||
void test_selection_wraps_around_at_both_ends() {
|
||||
ListModel l(5);
|
||||
l.setCount(3);
|
||||
l.up();
|
||||
TEST_ASSERT_EQUAL(2, l.selected());
|
||||
l.down();
|
||||
TEST_ASSERT_EQUAL(0, l.selected());
|
||||
}
|
||||
|
||||
void test_scrolls_to_keep_the_selection_visible() {
|
||||
ListModel l(3);
|
||||
l.setCount(10);
|
||||
for (int i = 0; i < 4; i++) l.down(); // selected 4
|
||||
TEST_ASSERT_EQUAL(4, l.selected());
|
||||
TEST_ASSERT_EQUAL(2, l.firstVisible()); // rows 2,3,4
|
||||
for (int i = 0; i < 3; i++) l.up(); // selected 1
|
||||
TEST_ASSERT_EQUAL(1, l.firstVisible());
|
||||
}
|
||||
|
||||
void test_wrapping_to_the_end_scrolls_to_the_last_page() {
|
||||
ListModel l(3);
|
||||
l.setCount(10);
|
||||
l.up();
|
||||
TEST_ASSERT_EQUAL(9, l.selected());
|
||||
TEST_ASSERT_EQUAL(7, l.firstVisible());
|
||||
}
|
||||
|
||||
void test_shrinking_the_list_keeps_selection_in_range() {
|
||||
ListModel l(3);
|
||||
l.setCount(10);
|
||||
l.up(); // 9
|
||||
l.setCount(4);
|
||||
TEST_ASSERT_EQUAL(3, l.selected());
|
||||
TEST_ASSERT_EQUAL(1, l.firstVisible());
|
||||
l.setCount(0);
|
||||
TEST_ASSERT_EQUAL(-1, l.selected());
|
||||
}
|
||||
|
||||
void test_page_moves_by_visible_rows_without_wrapping() {
|
||||
ListModel l(3);
|
||||
l.setCount(10);
|
||||
l.pageDown();
|
||||
TEST_ASSERT_EQUAL(3, l.selected());
|
||||
l.pageDown();
|
||||
l.pageDown();
|
||||
l.pageDown();
|
||||
TEST_ASSERT_EQUAL(9, l.selected());
|
||||
l.pageUp();
|
||||
TEST_ASSERT_EQUAL(6, l.selected());
|
||||
}
|
||||
|
||||
int main() {
|
||||
UNITY_BEGIN();
|
||||
RUN_TEST(test_empty_list_has_no_selection);
|
||||
RUN_TEST(test_selection_starts_at_first_item);
|
||||
RUN_TEST(test_down_and_up_move_the_selection);
|
||||
RUN_TEST(test_selection_wraps_around_at_both_ends);
|
||||
RUN_TEST(test_scrolls_to_keep_the_selection_visible);
|
||||
RUN_TEST(test_wrapping_to_the_end_scrolls_to_the_last_page);
|
||||
RUN_TEST(test_shrinking_the_list_keeps_selection_in_range);
|
||||
RUN_TEST(test_page_moves_by_visible_rows_without_wrapping);
|
||||
return UNITY_END();
|
||||
}
|
||||
Reference in New Issue
Block a user