Public Access
The Launcher shows the Apps as a 4 x 3 grid of 32 x 32 icons, the selected one's name under it (issue #9). The icons are the website's own, doubled, and two drawn the same way for SSH and the Shell; they are PNGs in assets/icons, turned into arrays by scripts/make_icons.py, which CI checks. The selected tile is the website's: dark blue on cyan, with notched corners. - GridModel (lib/ui, host-tested) holds the selection and the scrolling. - App::badge(): a dot on the tile for unread IRC messages, a Track recording, a Capture running, an SSH session open. - Settings > Launcher: Grid or List. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0162FokPdvY2KsS4NBfwyWPk
98 lines
2.5 KiB
C++
98 lines
2.5 KiB
C++
#include <unity.h>
|
|
|
|
#include "grid_model.h"
|
|
|
|
using namespace roro;
|
|
|
|
void setUp() {}
|
|
void tearDown() {}
|
|
|
|
void test_empty_grid_has_no_selection() {
|
|
GridModel g(4, 3);
|
|
TEST_ASSERT_EQUAL(-1, g.selected());
|
|
g.right();
|
|
g.down();
|
|
TEST_ASSERT_EQUAL(-1, g.selected());
|
|
TEST_ASSERT_EQUAL(0, g.rows());
|
|
}
|
|
|
|
void test_left_and_right_go_through_every_item() {
|
|
GridModel g(4, 3);
|
|
g.setCount(11);
|
|
TEST_ASSERT_EQUAL(0, g.selected());
|
|
g.right();
|
|
TEST_ASSERT_EQUAL(1, g.selected());
|
|
g.select(3);
|
|
g.right(); // onto the next row
|
|
TEST_ASSERT_EQUAL(4, g.selected());
|
|
g.left();
|
|
TEST_ASSERT_EQUAL(3, g.selected());
|
|
g.select(10);
|
|
g.right(); // around
|
|
TEST_ASSERT_EQUAL(0, g.selected());
|
|
g.left();
|
|
TEST_ASSERT_EQUAL(10, g.selected());
|
|
}
|
|
|
|
void test_up_and_down_stay_in_the_column() {
|
|
GridModel g(4, 3);
|
|
g.setCount(11); // rows of 4, 4 and 3
|
|
g.select(1);
|
|
g.down();
|
|
TEST_ASSERT_EQUAL(5, g.selected());
|
|
g.down();
|
|
TEST_ASSERT_EQUAL(9, g.selected());
|
|
g.down(); // around
|
|
TEST_ASSERT_EQUAL(1, g.selected());
|
|
g.up();
|
|
TEST_ASSERT_EQUAL(9, g.selected());
|
|
}
|
|
|
|
void test_a_short_last_row_gives_its_last_item() {
|
|
GridModel g(4, 3);
|
|
g.setCount(11);
|
|
g.select(7); // the fourth column, which the last row doesn't have
|
|
g.down();
|
|
TEST_ASSERT_EQUAL(10, g.selected());
|
|
g.select(3);
|
|
g.up();
|
|
TEST_ASSERT_EQUAL(10, g.selected());
|
|
}
|
|
|
|
void test_rows_scroll_to_keep_the_selection_in_view() {
|
|
GridModel g(4, 3);
|
|
g.setCount(18); // 5 rows
|
|
TEST_ASSERT_EQUAL(5, g.rows());
|
|
TEST_ASSERT_EQUAL(0, g.firstVisibleRow());
|
|
g.select(12); // the fourth row
|
|
TEST_ASSERT_EQUAL(1, g.firstVisibleRow());
|
|
g.select(17);
|
|
TEST_ASSERT_EQUAL(2, g.firstVisibleRow());
|
|
g.select(5);
|
|
TEST_ASSERT_EQUAL(1, g.firstVisibleRow());
|
|
g.select(0);
|
|
TEST_ASSERT_EQUAL(0, g.firstVisibleRow());
|
|
}
|
|
|
|
void test_a_smaller_count_keeps_the_selection_inside() {
|
|
GridModel g(4, 3);
|
|
g.setCount(18);
|
|
g.select(17);
|
|
g.setCount(6);
|
|
TEST_ASSERT_EQUAL(5, g.selected());
|
|
TEST_ASSERT_EQUAL(0, g.firstVisibleRow());
|
|
g.setCount(0);
|
|
TEST_ASSERT_EQUAL(-1, g.selected());
|
|
}
|
|
|
|
int main() {
|
|
UNITY_BEGIN();
|
|
RUN_TEST(test_empty_grid_has_no_selection);
|
|
RUN_TEST(test_left_and_right_go_through_every_item);
|
|
RUN_TEST(test_up_and_down_stay_in_the_column);
|
|
RUN_TEST(test_a_short_last_row_gives_its_last_item);
|
|
RUN_TEST(test_rows_scroll_to_keep_the_selection_in_view);
|
|
RUN_TEST(test_a_smaller_count_keeps_the_selection_inside);
|
|
return UNITY_END();
|
|
}
|