Top left holds hide, library, undo, redo and settings; top right holds presets, brush options, color and layers, split around a center gap that follows the camera cutout. The bottom bar keeps brush, eraser and picker and groups paint, selection and transform tools into popups. The left bar shows vertical size and opacity sliders with glyphs for brush and eraser, or the actions of the active tool, and dragging a slider previews the real brush cursor at the canvas center. The previous tablet rail stays as the classic layout. Long press shows tooltips, the library gets a clear scratch action with batched deletion and cached previews, brush presets show stroke samples, and settings titles use the regular font size.
246 lines
7.2 KiB
C++
246 lines
7.2 KiB
C++
#include "BoxLayout.hpp"
|
|
#include "Probes.hpp"
|
|
#include "SettingsView.hpp"
|
|
#include "Ui.hpp"
|
|
#include "UiDriver.hpp"
|
|
|
|
#include "UnitTest++/UnitTest++.h"
|
|
|
|
using namespace tp;
|
|
using namespace tp::ui;
|
|
using namespace tp::ui::testing;
|
|
|
|
namespace {
|
|
struct SettingsScene {
|
|
Widget root;
|
|
Menu main;
|
|
Menu display;
|
|
Menu advanced;
|
|
SettingsView settings;
|
|
int saved = 0;
|
|
bool dark = false;
|
|
int menuClosed = 0;
|
|
|
|
SettingsScene() {
|
|
root.emplaceLayout<ColumnLayout>();
|
|
advanced.addItem("Reset", {});
|
|
display.addToggle("Dark mode", [this]() { return dark; }, [this]() { dark = !dark; });
|
|
display.addSubmenu("Advanced", advanced);
|
|
main.addItem("Save", [this]() { saved++; }, "Ctrl+S");
|
|
main.addSeparator();
|
|
main.addSubmenu("Display", display);
|
|
main.setOnItemActivated([this]() { menuClosed++; });
|
|
settings.setRoot("Settings", main);
|
|
}
|
|
};
|
|
}
|
|
|
|
SUITE(SettingsViewNavigation) {
|
|
TEST(OpensFullscreenWithTheRootPage) {
|
|
SettingsScene scene;
|
|
UiDriver driver(scene.root, { 900, 600 });
|
|
|
|
scene.settings.open(driver.ui());
|
|
driver.settle();
|
|
|
|
CHECK(scene.settings.isOpen());
|
|
CHECK_CLOSE(900.0f, scene.settings.windowRect().size.x, 0.5f);
|
|
CHECK_CLOSE(600.0f, scene.settings.windowRect().size.y, 0.5f);
|
|
CHECK_EQUAL("Settings", scene.settings.currentPage().title());
|
|
CHECK_EQUAL(2u, scene.settings.currentPage().rows().size());
|
|
}
|
|
|
|
TEST(TitleSitsOnTheRightOppositeTheBackButton) {
|
|
SettingsScene scene;
|
|
UiDriver driver(scene.root, { 900, 600 });
|
|
scene.settings.open(driver.ui());
|
|
driver.settle();
|
|
|
|
SettingsPage& page = scene.settings.currentPage();
|
|
CHECK(page.titleLabel().alignment() == TextAlign::End);
|
|
CHECK(page.titleLabel().windowRect().center().x > page.backButton().windowRect().center().x);
|
|
}
|
|
|
|
TEST(TitleAndCloseUseTheRegularFontSize) {
|
|
SettingsScene scene;
|
|
UiDriver driver(scene.root, { 900, 600 });
|
|
Theme large = Theme::standard();
|
|
large.metrics.fontSize = 21;
|
|
driver.ui().setTheme(large);
|
|
scene.settings.open(driver.ui());
|
|
driver.settle();
|
|
|
|
SettingsPage& page = scene.settings.currentPage();
|
|
CHECK_CLOSE(21.0f, page.titleLabel().effectiveFontSize(), 0.01f);
|
|
CHECK(page.titleLabel().windowRect().size.y <= page.backButton().windowRect().size.y + 0.5f);
|
|
}
|
|
|
|
TEST(SubmenusOpenAsPagesAndBackReturns) {
|
|
SettingsScene scene;
|
|
UiDriver driver(scene.root, { 900, 600 });
|
|
scene.settings.open(driver.ui());
|
|
|
|
driver.click(*scene.settings.currentPage().row("Display"));
|
|
CHECK_EQUAL(2u, scene.settings.depth());
|
|
CHECK_EQUAL("Display", scene.settings.currentPage().title());
|
|
driver.click(*scene.settings.currentPage().row("Advanced"));
|
|
CHECK_EQUAL(3u, scene.settings.depth());
|
|
|
|
driver.click(scene.settings.currentPage().backButton());
|
|
CHECK_EQUAL("Display", scene.settings.currentPage().title());
|
|
driver.key(InputID::ESCAPE);
|
|
CHECK_EQUAL("Settings", scene.settings.currentPage().title());
|
|
CHECK(scene.settings.isOpen());
|
|
|
|
driver.click(scene.settings.currentPage().backButton());
|
|
CHECK(!scene.settings.isOpen());
|
|
}
|
|
|
|
TEST(BackToJumpsSeveralPagesAtOnce) {
|
|
SettingsScene scene;
|
|
UiDriver driver(scene.root, { 900, 600 });
|
|
scene.settings.open(driver.ui());
|
|
driver.click(*scene.settings.currentPage().row("Display"));
|
|
driver.click(*scene.settings.currentPage().row("Advanced"));
|
|
REQUIRE CHECK_EQUAL(3u, scene.settings.depth());
|
|
|
|
scene.settings.backTo(1);
|
|
|
|
CHECK_EQUAL(1u, scene.settings.depth());
|
|
CHECK_EQUAL("Settings", scene.settings.currentPage().title());
|
|
CHECK(scene.settings.isOpen());
|
|
}
|
|
|
|
TEST(ActionsRunAndCloseTheView) {
|
|
SettingsScene scene;
|
|
UiDriver driver(scene.root, { 900, 600 });
|
|
scene.settings.open(driver.ui());
|
|
|
|
driver.click(*scene.settings.currentPage().row("Save"));
|
|
|
|
CHECK_EQUAL(1, scene.saved);
|
|
CHECK_EQUAL(1, scene.menuClosed);
|
|
CHECK(!scene.settings.isOpen());
|
|
}
|
|
|
|
TEST(TogglesFlipAndStayOnThePage) {
|
|
SettingsScene scene;
|
|
UiDriver driver(scene.root, { 900, 600 });
|
|
scene.settings.open(driver.ui());
|
|
driver.click(*scene.settings.currentPage().row("Display"));
|
|
|
|
driver.click(*scene.settings.currentPage().row("Dark mode"));
|
|
|
|
CHECK(scene.dark);
|
|
CHECK(scene.settings.isOpen());
|
|
CHECK_EQUAL("Display", scene.settings.currentPage().title());
|
|
}
|
|
|
|
TEST(SeparatorsSplitRowsIntoSections) {
|
|
SettingsScene scene;
|
|
|
|
const std::vector<const MenuItem*> order = scene.main.itemsWithSeparators();
|
|
|
|
REQUIRE CHECK_EQUAL(3u, order.size());
|
|
CHECK(order[0] != nullptr);
|
|
CHECK(order[1] == nullptr);
|
|
CHECK(order[2] != nullptr);
|
|
}
|
|
|
|
TEST(DisabledEntriesCannotBeActivated) {
|
|
SettingsScene scene;
|
|
bool enabled = false;
|
|
int ran = 0;
|
|
scene.main.add([&]() {
|
|
MenuEntry entry = MenuEntry::item("Locked", [&ran]() { ran++; });
|
|
entry.isEnabled = [&enabled]() { return enabled; };
|
|
return entry;
|
|
}());
|
|
UiDriver driver(scene.root, { 900, 600 });
|
|
scene.settings.open(driver.ui());
|
|
|
|
driver.click(*scene.settings.currentPage().row("Locked"));
|
|
|
|
CHECK_EQUAL(0, ran);
|
|
CHECK(scene.settings.isOpen());
|
|
}
|
|
|
|
TEST(CustomContentPagesHaveABackButton) {
|
|
SettingsScene scene;
|
|
Box content;
|
|
content.setPreferred({ 200, 100 });
|
|
UiDriver driver(scene.root, { 900, 600 });
|
|
scene.settings.open(driver.ui());
|
|
|
|
scene.settings.openContent("Custom", content);
|
|
driver.settle();
|
|
CHECK_EQUAL("Custom", scene.settings.currentPage().title());
|
|
CHECK(content.ui() != nullptr);
|
|
|
|
driver.click(scene.settings.currentPage().backButton());
|
|
CHECK_EQUAL("Settings", scene.settings.currentPage().title());
|
|
CHECK(content.ui() == nullptr);
|
|
}
|
|
|
|
TEST(AnEntryCanOpenItsOwnContentPage) {
|
|
SettingsScene scene;
|
|
Box content;
|
|
content.setPreferred({ 200, 100 });
|
|
scene.settings.setOnContentRequested([&](const MenuEntry& entry) {
|
|
if (entry.text != "Save") return false;
|
|
scene.settings.openContent("Save options", content);
|
|
return true;
|
|
});
|
|
UiDriver driver(scene.root, { 900, 600 });
|
|
scene.settings.open(driver.ui());
|
|
|
|
driver.click(*scene.settings.currentPage().row("Save"));
|
|
|
|
CHECK_EQUAL(0, scene.saved);
|
|
CHECK(scene.settings.isOpen());
|
|
CHECK_EQUAL("Save options", scene.settings.currentPage().title());
|
|
}
|
|
|
|
TEST(OpeningSlidesUpFromTheBottom) {
|
|
SettingsScene scene;
|
|
UiDriver driver(scene.root, { 900, 600 });
|
|
driver.setAutoSettle(false);
|
|
|
|
scene.settings.open(driver.ui());
|
|
driver.layout();
|
|
driver.advance(16);
|
|
|
|
CHECK(scene.settings.windowRect().pos.y > 100);
|
|
driver.settle();
|
|
CHECK_CLOSE(0.0f, scene.settings.windowRect().pos.y, 0.5f);
|
|
}
|
|
|
|
TEST(PagesSlideInFromTheSide) {
|
|
SettingsScene scene;
|
|
UiDriver driver(scene.root, { 900, 600 });
|
|
scene.settings.open(driver.ui());
|
|
driver.settle();
|
|
driver.setAutoSettle(false);
|
|
|
|
scene.settings.openMenu("Display", scene.display);
|
|
driver.layout();
|
|
driver.advance(16);
|
|
|
|
const RectF settled = scene.settings.windowRect();
|
|
CHECK(scene.settings.currentPage().windowRect().pos.x > settled.pos.x + 100);
|
|
driver.settle();
|
|
CHECK_CLOSE(settled.pos.x + 16.0f, scene.settings.currentPage().windowRect().pos.x, 0.5f);
|
|
}
|
|
|
|
TEST(LongPagesScroll) {
|
|
SettingsScene scene;
|
|
for (int index = 0; index < 40; index++)
|
|
scene.main.addItem("Item " + std::to_string(index), {});
|
|
UiDriver driver(scene.root, { 900, 400 });
|
|
scene.settings.open(driver.ui());
|
|
driver.settle();
|
|
|
|
const RectF view = scene.settings.windowRect();
|
|
CHECK(scene.settings.currentPage().row("Item 39")->windowRect().pos.y > view.pos.y + view.size.y);
|
|
}
|
|
}
|