@@ -91,6 +91,10 @@ jobs:
|
||||
restore-keys: conan-${{ runner.os }}-
|
||||
- name: Configure native release
|
||||
run: python3 modulus.py configure --target x86_64_gcc12_release
|
||||
- name: Check code style
|
||||
run: |
|
||||
python3 -m pip install --no-cache-dir -r build/build_tools/docker/format-requirements.txt
|
||||
python3 modulus.py format --check
|
||||
- name: Build native release
|
||||
run: python3 modulus.py build --target x86_64_gcc12_release
|
||||
- name: Test native release
|
||||
|
||||
@@ -6,6 +6,8 @@ Luma uses Modulus for shared build tooling, Boost.JSON, and raylib integration.
|
||||
|
||||
## Build
|
||||
|
||||
Code style is managed by Modulus: run `./modulus.py format` or `./modulus.py format --check`. The generated Neovim integration uses the same pinned container formatter for C++ and Python, including existing format-on-save toggles. Configure first to prepare tooling; customize `tooling.editor.clang_format` and `tooling.format.exclude` in `modulus.json`, not generated editor files. See the shared Modulus README for the compact layout and no-alias policy.
|
||||
|
||||
Configure, build, and test the default target:
|
||||
|
||||
```sh
|
||||
|
||||
@@ -40,15 +40,12 @@ class luma_conan(conan.ConanFile):
|
||||
"tests/*.cpp",
|
||||
"tests/*.hpp",
|
||||
)
|
||||
|
||||
def config_options(self):
|
||||
if self.settings.os == "Windows":
|
||||
del self.options.fPIC
|
||||
|
||||
def configure(self):
|
||||
if self.options.shared:
|
||||
del self.options.fPIC
|
||||
|
||||
def requirements(self):
|
||||
self.requires(
|
||||
"modulus/latest",
|
||||
@@ -58,7 +55,6 @@ class luma_conan(conan.ConanFile):
|
||||
"with_raylib": True,
|
||||
},
|
||||
)
|
||||
|
||||
def generate(self):
|
||||
deps = conan.tools.cmake.CMakeDeps(self)
|
||||
deps.generate()
|
||||
@@ -68,14 +64,12 @@ class luma_conan(conan.ConanFile):
|
||||
toolchain.variables["BUILD_SHARED_LIBS"] = bool(self.options.shared)
|
||||
toolchain.variables["BUILD_TESTING"] = bool(self.options.with_tests)
|
||||
toolchain.generate()
|
||||
|
||||
def build(self):
|
||||
cmake = conan.tools.cmake.CMake(self)
|
||||
cmake.configure()
|
||||
cmake.build()
|
||||
if self.options.with_tests and conan.tools.build.can_run(self):
|
||||
cmake.test(target="check")
|
||||
|
||||
def package_id(self):
|
||||
self.info.options.rm_safe("with_tests")
|
||||
for requirement in (
|
||||
@@ -85,11 +79,9 @@ class luma_conan(conan.ConanFile):
|
||||
):
|
||||
if requirement in self.info.requires.pkg_names:
|
||||
self.info.requires.remove(requirement)
|
||||
|
||||
def package(self):
|
||||
cmake = conan.tools.cmake.CMake(self)
|
||||
cmake.install()
|
||||
|
||||
def package_info(self):
|
||||
self.cpp_info.set_property(
|
||||
"cmake_file_name",
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <modulus.hpp>
|
||||
|
||||
|
||||
namespace luma {
|
||||
|
||||
enum class easing {
|
||||
|
||||
@@ -23,7 +23,9 @@
|
||||
namespace luma {
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct application_core;
|
||||
|
||||
}
|
||||
|
||||
struct frame_stats {
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <luma/render.hpp>
|
||||
|
||||
|
||||
namespace luma {
|
||||
|
||||
class renderer_resources {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <luma/theme.hpp>
|
||||
|
||||
|
||||
namespace luma {
|
||||
|
||||
struct display_config {
|
||||
|
||||
@@ -6,10 +6,13 @@
|
||||
|
||||
#include <luma/geometry.hpp>
|
||||
|
||||
|
||||
namespace luma {
|
||||
|
||||
class draw_context;
|
||||
|
||||
struct theme;
|
||||
|
||||
struct touch_event;
|
||||
|
||||
class control {
|
||||
|
||||
@@ -76,7 +76,6 @@ public:
|
||||
std::weak_ptr<void> lifetime{};
|
||||
std::function<void()> callback{};
|
||||
};
|
||||
|
||||
text_input_state(luma::text_field_options options, std::function<void(std::string)> on_change);
|
||||
auto snapshot() const -> luma::text_field_options;
|
||||
auto text() const -> std::string;
|
||||
@@ -162,7 +161,6 @@ template <typename... CONTROLS>
|
||||
auto luma::children(CONTROLS &&...controls) -> std::expected<std::vector<std::unique_ptr<luma::control>>, modulus::error> {
|
||||
auto result = std::vector<std::unique_ptr<luma::control>>{};
|
||||
result.reserve(sizeof...(controls));
|
||||
|
||||
auto append = [&result](auto &&input) -> std::expected<void, modulus::error> {
|
||||
auto child = luma::detail::normalize_child(std::forward<decltype(input)>(input));
|
||||
if (!child) {
|
||||
@@ -171,13 +169,13 @@ auto luma::children(CONTROLS&&... controls) -> std::expected<std::vector<std::un
|
||||
result.push_back(std::move(*child));
|
||||
return {};
|
||||
};
|
||||
|
||||
auto status = std::expected<void, modulus::error>{};
|
||||
([&] {
|
||||
if (status) {
|
||||
status = append(std::forward<CONTROLS>(controls));
|
||||
}
|
||||
}(), ...);
|
||||
}(),
|
||||
...);
|
||||
if (!status) {
|
||||
return modulus::fail<std::vector<std::unique_ptr<luma::control>>>(status.error());
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <modulus.hpp>
|
||||
|
||||
|
||||
namespace luma::detail {
|
||||
|
||||
constexpr std::int32_t error_invalid_argument{1};
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <modulus.hpp>
|
||||
|
||||
|
||||
namespace luma {
|
||||
|
||||
struct point {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <luma/geometry.hpp>
|
||||
|
||||
|
||||
namespace luma {
|
||||
|
||||
enum class touch_phase {
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <luma/control.hpp>
|
||||
|
||||
|
||||
namespace luma {
|
||||
|
||||
enum class dialog_result {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <luma/geometry.hpp>
|
||||
#include <luma/theme.hpp>
|
||||
|
||||
|
||||
namespace luma {
|
||||
|
||||
struct texture_info {
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <luma/control.hpp>
|
||||
|
||||
|
||||
namespace luma {
|
||||
|
||||
class router {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <modulus.hpp>
|
||||
|
||||
|
||||
namespace luma {
|
||||
|
||||
struct color {
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <luma/control.hpp>
|
||||
#include <luma/geometry.hpp>
|
||||
|
||||
|
||||
namespace luma {
|
||||
|
||||
class window_manager;
|
||||
|
||||
+6
-2
@@ -16,6 +16,7 @@ COMMANDS = (
|
||||
"package",
|
||||
"lsp",
|
||||
"clangd",
|
||||
"format",
|
||||
)
|
||||
COMMON_DIR = pathlib.Path("build") / "build_common"
|
||||
TOOLS_DIR = pathlib.Path("build") / "build_tools"
|
||||
@@ -60,6 +61,9 @@ def runtime_ready(root):
|
||||
and (root / TOOLS_DIR / "clangd.py").is_file()
|
||||
and (root / RUNTIME_DIR / "modulus" / "cli.py").is_file()
|
||||
and (root / RUNTIME_DIR / "modulus" / "export.py").is_file()
|
||||
and (root / TOOLS_DIR / "format.py").is_file()
|
||||
and (root / RUNTIME_DIR / "modulus" / "formatting.py").is_file()
|
||||
and (root / RUNTIME_DIR / "modulus" / "format_layout.py").is_file()
|
||||
)
|
||||
|
||||
def optional_credentials():
|
||||
@@ -340,9 +344,9 @@ def ensure_runtime(root):
|
||||
|
||||
def delegate(command, argv):
|
||||
root = repo_root()
|
||||
if command == "clangd":
|
||||
if command in {"clangd", "format"}:
|
||||
if not runtime_ready(root):
|
||||
print("Modulus clangd tooling is missing; run ./modulus.py configure first", file=sys.stderr)
|
||||
print(f"Modulus {command} tooling is missing; run ./modulus.py configure first", file=sys.stderr)
|
||||
return 1
|
||||
else:
|
||||
ensure_runtime(root)
|
||||
|
||||
+1
-4
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <luma/detail/errors.hpp>
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
auto invalid(std::string message) -> std::expected<void, modulus::error> {
|
||||
@@ -104,12 +105,10 @@ auto luma::animation_graph::tick(std::chrono::steady_clock::duration delta) -> s
|
||||
if (ticking_) {
|
||||
return internal("animation graph is already ticking");
|
||||
}
|
||||
|
||||
auto active = std::move(animations_);
|
||||
animations_.clear();
|
||||
ticking_ = true;
|
||||
clear_requested_ = false;
|
||||
|
||||
auto fail_tick = [this](std::expected<void, modulus::error> status) {
|
||||
ticking_ = false;
|
||||
clear_requested_ = false;
|
||||
@@ -117,7 +116,6 @@ auto luma::animation_graph::tick(std::chrono::steady_clock::duration delta) -> s
|
||||
pending_.clear();
|
||||
return status;
|
||||
};
|
||||
|
||||
for (auto &running : active) {
|
||||
running.elapsed += delta;
|
||||
auto duration = std::chrono::duration_cast<std::chrono::steady_clock::duration>(running.animation.duration);
|
||||
@@ -160,7 +158,6 @@ auto luma::animation_graph::tick(std::chrono::steady_clock::duration delta) -> s
|
||||
}
|
||||
animations_.push_back(std::move(running));
|
||||
}
|
||||
|
||||
ticking_ = false;
|
||||
for (auto &operation : pending_) {
|
||||
if (operation.kind == luma::animation_graph::pending_kind::CLEAR) {
|
||||
|
||||
+24
-28
@@ -38,6 +38,7 @@
|
||||
#include <luma/render.hpp>
|
||||
#include <luma/routing.hpp>
|
||||
|
||||
|
||||
namespace luma::detail {
|
||||
|
||||
struct application_core {
|
||||
@@ -75,7 +76,6 @@ namespace {
|
||||
struct font_key {
|
||||
std::string path{};
|
||||
std::int32_t size{};
|
||||
|
||||
auto operator==(font_key const &other) const -> std::bool_t;
|
||||
};
|
||||
|
||||
@@ -298,11 +298,9 @@ auto dispatch_to_ui(std::shared_ptr<luma::detail::application_core> const& core,
|
||||
if (!core) {
|
||||
return unavailable<VALUE>("application is not initialized");
|
||||
}
|
||||
|
||||
auto task = std::decay_t<TASK>{std::forward<TASK>(input)};
|
||||
auto should_post = false;
|
||||
auto wait_for_startup = false;
|
||||
|
||||
{
|
||||
auto lock = std::unique_lock{core->lifecycle_mutex};
|
||||
if (core->stopping.load(std::memory_order_acquire)) {
|
||||
@@ -317,7 +315,6 @@ auto dispatch_to_ui(std::shared_ptr<luma::detail::application_core> const& core,
|
||||
should_post = running && accepting;
|
||||
wait_for_startup = running && !accepting;
|
||||
}
|
||||
|
||||
if (!should_post || wait_for_startup) {
|
||||
auto immediate_lock = std::scoped_lock{core->immediate_mutex};
|
||||
auto lock = std::unique_lock{core->lifecycle_mutex};
|
||||
@@ -337,7 +334,6 @@ auto dispatch_to_ui(std::shared_ptr<luma::detail::application_core> const& core,
|
||||
}
|
||||
should_post = true;
|
||||
}
|
||||
|
||||
auto future = std::future<std::expected<VALUE, modulus::error>>{};
|
||||
auto promise = std::make_shared<std::promise<std::expected<VALUE, modulus::error>>>();
|
||||
future = promise->get_future();
|
||||
@@ -364,7 +360,6 @@ auto dispatch_to_ui(std::shared_ptr<luma::detail::application_core> const& core,
|
||||
} catch (...) {
|
||||
return internal<VALUE>("failed to queue UI task");
|
||||
}
|
||||
|
||||
return future.get();
|
||||
}
|
||||
|
||||
@@ -543,7 +538,8 @@ auto font_key_hash::operator()(font_key const& key) const noexcept -> std::size_
|
||||
return seed;
|
||||
}
|
||||
|
||||
scope_exit::scope_exit(std::function<void()> action) : action_{std::move(action)} {}
|
||||
scope_exit::scope_exit(std::function<void()> action)
|
||||
: action_{std::move(action)} {}
|
||||
|
||||
scope_exit::~scope_exit() {
|
||||
if (!active_ || !action_) {
|
||||
@@ -576,7 +572,8 @@ auto drawing_scope::end() -> void {
|
||||
}
|
||||
}
|
||||
|
||||
ui_traversal_scope::ui_traversal_scope(luma::detail::application_core& core) : core_{core} {
|
||||
ui_traversal_scope::ui_traversal_scope(luma::detail::application_core &core)
|
||||
: core_{core} {
|
||||
++core_.traversal_depth;
|
||||
}
|
||||
|
||||
@@ -586,7 +583,8 @@ ui_traversal_scope::~ui_traversal_scope() {
|
||||
flush_retired_controls(core_);
|
||||
}
|
||||
|
||||
raylib_texture::raylib_texture(std::shared_ptr<raylib_resource_state::texture_record> record, std::shared_ptr<raylib_resource_state> state) : record_{std::move(record)}, state_{std::move(state)} {
|
||||
raylib_texture::raylib_texture(std::shared_ptr<raylib_resource_state::texture_record> record, std::shared_ptr<raylib_resource_state> state)
|
||||
: record_{std::move(record)}, state_{std::move(state)} {
|
||||
assert(record_ != nullptr);
|
||||
assert(record_->texture.id != 0);
|
||||
assert(record_->texture.width > 0);
|
||||
@@ -623,7 +621,8 @@ auto raylib_texture::native() const -> Texture2D {
|
||||
return record_->texture;
|
||||
}
|
||||
|
||||
raylib_resources::raylib_resources(std::shared_ptr<raylib_resource_state> state) : state_{std::move(state)} {
|
||||
raylib_resources::raylib_resources(std::shared_ptr<raylib_resource_state> state)
|
||||
: state_{std::move(state)} {
|
||||
assert(state_ != nullptr);
|
||||
}
|
||||
|
||||
@@ -652,7 +651,8 @@ auto raylib_resources::state() const -> std::shared_ptr<raylib_resource_state> {
|
||||
return state_;
|
||||
}
|
||||
|
||||
raylib_draw_context::raylib_draw_context(std::shared_ptr<raylib_resource_state> state) : state_{std::move(state)} {
|
||||
raylib_draw_context::raylib_draw_context(std::shared_ptr<raylib_resource_state> state)
|
||||
: state_{std::move(state)} {
|
||||
assert(state_ != nullptr);
|
||||
}
|
||||
|
||||
@@ -663,7 +663,8 @@ auto raylib_draw_context::fill_rect(luma::rect bounds, luma::color color) -> voi
|
||||
.y = bounds.y,
|
||||
.width = bounds.width,
|
||||
.height = bounds.height,
|
||||
}, to_raylib(color));
|
||||
},
|
||||
to_raylib(color));
|
||||
}
|
||||
|
||||
auto raylib_draw_context::stroke_rect(luma::rect bounds, std::float32_t thickness, luma::color color) -> void {
|
||||
@@ -674,7 +675,8 @@ auto raylib_draw_context::stroke_rect(luma::rect bounds, std::float32_t thicknes
|
||||
.y = bounds.y,
|
||||
.width = bounds.width,
|
||||
.height = bounds.height,
|
||||
}, thickness, to_raylib(color));
|
||||
},
|
||||
thickness, to_raylib(color));
|
||||
}
|
||||
|
||||
auto raylib_draw_context::stroke_line(luma::point from, luma::point to, std::float32_t thickness, luma::color color) -> void {
|
||||
@@ -728,7 +730,8 @@ auto raylib_draw_context::draw_text(std::string_view text, luma::point origin, l
|
||||
DrawTextEx(font, owned.c_str(), {
|
||||
.x = origin.x,
|
||||
.y = origin.y,
|
||||
}, style.size, 1.0F, to_raylib(color));
|
||||
},
|
||||
style.size, 1.0F, to_raylib(color));
|
||||
}
|
||||
|
||||
auto raylib_draw_context::draw_texture(luma::texture const &texture, luma::rect source, luma::rect destination, luma::color tint) -> void {
|
||||
@@ -791,9 +794,11 @@ auto raylib_draw_context::measure_text(std::string_view text, luma::text_style c
|
||||
|
||||
}
|
||||
|
||||
luma::detail::application_core::application_core(luma::application_config value) : ui_strand{boost::asio::make_strand(ui_context)}, config{std::move(value)} {}
|
||||
luma::detail::application_core::application_core(luma::application_config value)
|
||||
: ui_strand{boost::asio::make_strand(ui_context)}, config{std::move(value)} {}
|
||||
|
||||
luma::application::application(luma::application_config config) : core_{std::make_shared<luma::detail::application_core>(std::move(config))} {
|
||||
luma::application::application(luma::application_config config)
|
||||
: core_{std::make_shared<luma::detail::application_core>(std::move(config))} {
|
||||
assert(core_ != nullptr);
|
||||
install_retire_handlers(core_);
|
||||
core_->windows.bind_layout_invalidator(make_layout_invalidator(core_));
|
||||
@@ -888,9 +893,7 @@ auto luma::application::pop_route() -> std::expected<void, modulus::error> {
|
||||
|
||||
auto luma::application::current_route() const -> std::expected<std::string, modulus::error> {
|
||||
auto core = core_snapshot();
|
||||
return dispatch_to_ui<std::string>(core, [core] {
|
||||
return modulus::success(std::string{core->router.current_route()});
|
||||
}, false);
|
||||
return dispatch_to_ui<std::string>(core, [core] { return modulus::success(std::string{core->router.current_route()}); }, false);
|
||||
}
|
||||
|
||||
auto luma::application::add_animation(luma::animation animation) -> std::expected<void, modulus::error> {
|
||||
@@ -910,9 +913,7 @@ auto luma::application::clear_animations() -> std::expected<void, modulus::error
|
||||
|
||||
auto luma::application::animations_empty() const -> std::expected<std::bool_t, modulus::error> {
|
||||
auto core = core_snapshot();
|
||||
return dispatch_to_ui<std::bool_t>(core, [core] {
|
||||
return modulus::success(core->animations.empty());
|
||||
}, false);
|
||||
return dispatch_to_ui<std::bool_t>(core, [core] { return modulus::success(core->animations.empty()); }, false);
|
||||
}
|
||||
|
||||
auto luma::application::open_window(luma::window_options options, std::unique_ptr<luma::control> content) -> std::expected<std::uint64_t, modulus::error> {
|
||||
@@ -981,8 +982,7 @@ auto luma::application::load_texture(std::string path) -> std::expected<std::sha
|
||||
if (!core->renderer_active.load(std::memory_order_acquire) || !core->assets) {
|
||||
return unavailable<std::shared_ptr<luma::texture>>("texture loading requires an active renderer");
|
||||
}
|
||||
return core->assets->texture(path);
|
||||
}, false);
|
||||
return core->assets->texture(path); }, false);
|
||||
}
|
||||
|
||||
auto luma::application::request_layout() -> std::expected<void, modulus::error> {
|
||||
@@ -1100,7 +1100,6 @@ auto luma::application::run() -> std::expected<void, modulus::error> {
|
||||
core->running.store(true, std::memory_order_release);
|
||||
core->accepting_tasks.store(false, std::memory_order_release);
|
||||
}
|
||||
|
||||
auto resource_state = std::shared_ptr<raylib_resource_state>{};
|
||||
auto window_ready = false;
|
||||
[[maybe_unused]] auto cleanup = scope_exit{[&core, &resource_state, &window_ready] {
|
||||
@@ -1123,7 +1122,6 @@ auto luma::application::run() -> std::expected<void, modulus::error> {
|
||||
}
|
||||
finish_run(*core);
|
||||
}};
|
||||
|
||||
InitWindow(core->config.display.width, core->config.display.height, core->config.title.c_str());
|
||||
if (!IsWindowReady()) {
|
||||
return unavailable<void>("failed to initialize raylib window");
|
||||
@@ -1135,7 +1133,6 @@ auto luma::application::run() -> std::expected<void, modulus::error> {
|
||||
auto current_target_fps = core->config.display.target_fps;
|
||||
auto const idle_fps = core->config.display.idle_fps;
|
||||
SetTargetFPS(current_target_fps);
|
||||
|
||||
resource_state = std::make_shared<raylib_resource_state>();
|
||||
resource_state->ui_thread = std::this_thread::get_id();
|
||||
resource_state->active.store(true, std::memory_order_release);
|
||||
@@ -1147,7 +1144,6 @@ auto luma::application::run() -> std::expected<void, modulus::error> {
|
||||
core->accepting_tasks.store(true, std::memory_order_release);
|
||||
}
|
||||
startup_lock.unlock();
|
||||
|
||||
auto context = raylib_draw_context{resource_state};
|
||||
auto previous_touches = std::unordered_map<std::int32_t, luma::point>{};
|
||||
auto previous_frame = std::chrono::steady_clock::now();
|
||||
|
||||
+3
-1
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <luma/detail/errors.hpp>
|
||||
|
||||
|
||||
struct luma::asset_cache::in_flight_load {
|
||||
std::condition_variable ready{};
|
||||
std::thread::id owner{};
|
||||
@@ -23,7 +24,8 @@ struct luma::asset_cache::in_flight_load {
|
||||
std::bool_t done{false};
|
||||
};
|
||||
|
||||
luma::asset_cache::asset_cache(luma::renderer_resources& resources) : resources_{&resources} {
|
||||
luma::asset_cache::asset_cache(luma::renderer_resources &resources)
|
||||
: resources_{&resources} {
|
||||
assert(resources_ != nullptr);
|
||||
}
|
||||
|
||||
|
||||
+6
-4
@@ -15,13 +15,13 @@
|
||||
#include <luma/detail/errors.hpp>
|
||||
#include <luma/theme.hpp>
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr auto json_options = modulus::json_config::options{
|
||||
.category = "luma",
|
||||
.invalid_argument_code = luma::detail::error_invalid_argument,
|
||||
.not_found_code = luma::detail::error_not_found
|
||||
};
|
||||
.not_found_code = luma::detail::error_not_found};
|
||||
|
||||
auto invalid_display(std::string message) -> std::expected<luma::display_config, modulus::error> {
|
||||
assert(!message.empty());
|
||||
@@ -93,7 +93,8 @@ auto luma::parse_display_config(boost::json::value const& value) -> std::expecte
|
||||
"target_fps",
|
||||
"idle_fps",
|
||||
"fullscreen",
|
||||
}, "display", json_options);
|
||||
},
|
||||
"display", json_options);
|
||||
if (!unknown) {
|
||||
return invalid_display(std::string{unknown.error().message()});
|
||||
}
|
||||
@@ -160,7 +161,8 @@ auto luma::parse_application_config(boost::json::value const& value) -> std::exp
|
||||
"display",
|
||||
"touch",
|
||||
"theme",
|
||||
}, "application config", json_options);
|
||||
},
|
||||
"application config", json_options);
|
||||
if (!unknown) {
|
||||
return invalid_application(std::string{unknown.error().message()});
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <modulus.hpp>
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
auto valid_rect(luma::rect value) -> std::bool_t {
|
||||
|
||||
+46
-30
@@ -27,14 +27,14 @@
|
||||
#include <luma/render.hpp>
|
||||
#include <luma/theme.hpp>
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr auto panel_padding = luma::edge_insets{
|
||||
.left = 8.0F,
|
||||
.top = 8.0F,
|
||||
.right = 8.0F,
|
||||
.bottom = 8.0F
|
||||
};
|
||||
.bottom = 8.0F};
|
||||
constexpr auto scroll_drag_threshold = std::float32_t{6.0F};
|
||||
|
||||
class label_control final : public luma::control {
|
||||
@@ -359,7 +359,8 @@ auto fit_rect(luma::rect bounds, luma::texture_info info, luma::image_fit fit) -
|
||||
};
|
||||
}
|
||||
|
||||
label_control::label_control(std::string text) : text_{std::move(text)} {
|
||||
label_control::label_control(std::string text)
|
||||
: text_{std::move(text)} {
|
||||
assert(!text_.empty());
|
||||
}
|
||||
|
||||
@@ -375,10 +376,12 @@ auto label_control::draw(luma::draw_context& context, luma::theme const& theme)
|
||||
context.draw_text(text_, {
|
||||
.x = bounds().x,
|
||||
.y = bounds().y,
|
||||
}, theme.body, enabled() ? theme.text : theme.text_muted);
|
||||
},
|
||||
theme.body, enabled() ? theme.text : theme.text_muted);
|
||||
}
|
||||
|
||||
button_control::button_control(std::string text, std::function<void()> on_click) : text_{std::move(text)}, on_click_{std::move(on_click)} {
|
||||
button_control::button_control(std::string text, std::function<void()> on_click)
|
||||
: text_{std::move(text)}, on_click_{std::move(on_click)} {
|
||||
assert(!text_.empty());
|
||||
assert(on_click_);
|
||||
}
|
||||
@@ -390,7 +393,8 @@ auto button_control::measure(luma::draw_context& context, luma::theme const& the
|
||||
return luma::clamp({
|
||||
.width = text_size.width + 32.0F,
|
||||
.height = std::max(std::float32_t{48}, text_size.height + std::float32_t{16}),
|
||||
}, limits);
|
||||
},
|
||||
limits);
|
||||
}
|
||||
|
||||
auto button_control::draw(luma::draw_context &context, luma::theme const &theme) const -> void {
|
||||
@@ -434,7 +438,8 @@ auto button_control::focusable() const -> std::bool_t {
|
||||
return true;
|
||||
}
|
||||
|
||||
text_field_control::text_field_control(std::shared_ptr<luma::text_input_state> input) : input_{std::move(input)} {
|
||||
text_field_control::text_field_control(std::shared_ptr<luma::text_input_state> input)
|
||||
: input_{std::move(input)} {
|
||||
assert(input_ != nullptr);
|
||||
}
|
||||
|
||||
@@ -453,7 +458,8 @@ auto text_field_control::measure(luma::draw_context& context, luma::theme const&
|
||||
cached_size_ = luma::clamp({
|
||||
.width = std::max(std::float32_t{240}, measured.width + std::float32_t{24}),
|
||||
.height = std::max(std::float32_t{48}, measured.height + std::float32_t{16}),
|
||||
}, limits);
|
||||
},
|
||||
limits);
|
||||
return cached_size_;
|
||||
}
|
||||
|
||||
@@ -470,7 +476,8 @@ auto text_field_control::draw(luma::draw_context& context, luma::theme const& th
|
||||
context.draw_text(text, {
|
||||
.x = bounds().x + 12.0F,
|
||||
.y = bounds().y + 8.0F,
|
||||
}, theme.body, options.text.empty() ? theme.text_muted : theme.text);
|
||||
},
|
||||
theme.body, options.text.empty() ? theme.text_muted : theme.text);
|
||||
}
|
||||
|
||||
auto text_field_control::handle_touch(luma::touch_event const &event) -> std::bool_t {
|
||||
@@ -513,12 +520,14 @@ auto text_field_control::focusable() const -> std::bool_t {
|
||||
return true;
|
||||
}
|
||||
|
||||
soft_keyboard_control::soft_keyboard_control(luma::keyboard_layout layout, std::function<void(std::string)> on_text, std::function<void()> on_enter) : layout_{std::move(layout)}, on_text_{std::move(on_text)}, on_enter_{std::move(on_enter)} {
|
||||
soft_keyboard_control::soft_keyboard_control(luma::keyboard_layout layout, std::function<void(std::string)> on_text, std::function<void()> on_enter)
|
||||
: layout_{std::move(layout)}, on_text_{std::move(on_text)}, on_enter_{std::move(on_enter)} {
|
||||
assert(!layout_.rows.empty());
|
||||
assert(on_text_);
|
||||
}
|
||||
|
||||
soft_keyboard_control::soft_keyboard_control(luma::keyboard_layout layout, std::shared_ptr<luma::text_input_state> input, std::function<void()> on_enter) : layout_{std::move(layout)}, on_enter_{std::move(on_enter)}, input_{std::move(input)} {
|
||||
soft_keyboard_control::soft_keyboard_control(luma::keyboard_layout layout, std::shared_ptr<luma::text_input_state> input, std::function<void()> on_enter)
|
||||
: layout_{std::move(layout)}, on_enter_{std::move(on_enter)}, input_{std::move(input)} {
|
||||
assert(!layout_.rows.empty());
|
||||
assert(input_ != nullptr);
|
||||
}
|
||||
@@ -528,7 +537,8 @@ auto soft_keyboard_control::measure(luma::draw_context&, luma::theme const&, lum
|
||||
return luma::clamp({
|
||||
.width = 640.0F,
|
||||
.height = static_cast<std::float32_t>(layout_.rows.size()) * 56.0F,
|
||||
}, limits);
|
||||
},
|
||||
limits);
|
||||
}
|
||||
|
||||
auto soft_keyboard_control::draw(luma::draw_context &context, luma::theme const &theme) const -> void {
|
||||
@@ -551,7 +561,8 @@ auto soft_keyboard_control::draw(luma::draw_context& context, luma::theme const&
|
||||
context.draw_text(row[column_index].label, {
|
||||
.x = rect.x + 12.0F,
|
||||
.y = rect.y + 10.0F,
|
||||
}, theme.body, theme.text);
|
||||
},
|
||||
theme.body, theme.text);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -604,7 +615,8 @@ auto soft_keyboard_control::handle_touch(luma::touch_event const& event) -> std:
|
||||
return true;
|
||||
}
|
||||
|
||||
panel_control::panel_control(std::vector<std::unique_ptr<luma::control>> children) : children_{std::move(children)} {}
|
||||
panel_control::panel_control(std::vector<std::unique_ptr<luma::control>> children)
|
||||
: children_{std::move(children)} {}
|
||||
|
||||
auto panel_control::measure(luma::draw_context &context, luma::theme const &theme, luma::constraints limits) -> luma::size {
|
||||
assert(finite_constraints(limits));
|
||||
@@ -658,7 +670,8 @@ auto panel_control::bind_layout_invalidator(std::function<void()> invalidator) -
|
||||
}
|
||||
}
|
||||
|
||||
spacer_control::spacer_control(luma::size value) : value_{value} {
|
||||
spacer_control::spacer_control(luma::size value)
|
||||
: value_{value} {
|
||||
assert(finite_size(value_));
|
||||
}
|
||||
|
||||
@@ -669,7 +682,8 @@ auto spacer_control::measure(luma::draw_context&, luma::theme const&, luma::cons
|
||||
|
||||
auto spacer_control::draw(luma::draw_context &, luma::theme const &) const -> void {}
|
||||
|
||||
progress_bar_control::progress_bar_control(std::float32_t value) : value_{std::clamp(value, std::float32_t{}, std::float32_t{1})} {
|
||||
progress_bar_control::progress_bar_control(std::float32_t value)
|
||||
: value_{std::clamp(value, std::float32_t{}, std::float32_t{1})} {
|
||||
assert(std::isfinite(value));
|
||||
}
|
||||
|
||||
@@ -678,7 +692,8 @@ auto progress_bar_control::measure(luma::draw_context&, luma::theme const&, luma
|
||||
return luma::clamp({
|
||||
.width = 160.0F,
|
||||
.height = 16.0F,
|
||||
}, limits);
|
||||
},
|
||||
limits);
|
||||
}
|
||||
|
||||
auto progress_bar_control::draw(luma::draw_context &context, luma::theme const &theme) const -> void {
|
||||
@@ -688,10 +703,12 @@ auto progress_bar_control::draw(luma::draw_context& context, luma::theme const&
|
||||
.y = bounds().y,
|
||||
.width = bounds().width * value_,
|
||||
.height = bounds().height,
|
||||
}, theme.accent);
|
||||
},
|
||||
theme.accent);
|
||||
}
|
||||
|
||||
image_control::image_control(std::shared_ptr<luma::texture> texture, luma::image_fit fit) : texture_{std::move(texture)}, fit_{fit} {
|
||||
image_control::image_control(std::shared_ptr<luma::texture> texture, luma::image_fit fit)
|
||||
: texture_{std::move(texture)}, fit_{fit} {
|
||||
assert(texture_ != nullptr);
|
||||
}
|
||||
|
||||
@@ -704,7 +721,8 @@ auto image_control::measure(luma::draw_context&, luma::theme const&, luma::const
|
||||
return luma::clamp({
|
||||
.width = static_cast<std::float32_t>(info.width),
|
||||
.height = static_cast<std::float32_t>(info.height),
|
||||
}, limits);
|
||||
},
|
||||
limits);
|
||||
}
|
||||
|
||||
auto image_control::draw(luma::draw_context &context, luma::theme const &theme) const -> void {
|
||||
@@ -721,7 +739,8 @@ auto image_control::draw(luma::draw_context& context, luma::theme const& theme)
|
||||
context.draw_texture(*texture_, source, fit_rect(bounds(), info, fit_), theme.text);
|
||||
}
|
||||
|
||||
linear_control::linear_control(luma::direction direction, std::vector<std::unique_ptr<luma::control>> children, std::float32_t gap, luma::alignment align) : direction_{direction}, children_{std::move(children)}, gap_{gap}, align_{align} {
|
||||
linear_control::linear_control(luma::direction direction, std::vector<std::unique_ptr<luma::control>> children, std::float32_t gap, luma::alignment align)
|
||||
: direction_{direction}, children_{std::move(children)}, gap_{gap}, align_{align} {
|
||||
assert(std::isfinite(gap_));
|
||||
assert(gap_ >= 0.0F);
|
||||
}
|
||||
@@ -818,8 +837,8 @@ auto linear_control::bind_layout_invalidator(std::function<void()> invalidator)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
stack_control::stack_control(std::vector<std::unique_ptr<luma::control>> children) : children_{std::move(children)} {}
|
||||
stack_control::stack_control(std::vector<std::unique_ptr<luma::control>> children)
|
||||
: children_{std::move(children)} {}
|
||||
|
||||
auto stack_control::measure(luma::draw_context &context, luma::theme const &theme, luma::constraints limits) -> luma::size {
|
||||
assert(finite_constraints(limits));
|
||||
@@ -868,8 +887,8 @@ auto stack_control::bind_layout_invalidator(std::function<void()> invalidator) -
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
scroll_view_control::scroll_view_control(std::unique_ptr<luma::control> child, std::bool_t vertical, std::bool_t horizontal) : child_{std::move(child)}, vertical_{vertical}, horizontal_{horizontal} {
|
||||
scroll_view_control::scroll_view_control(std::unique_ptr<luma::control> child, std::bool_t vertical, std::bool_t horizontal)
|
||||
: child_{std::move(child)}, vertical_{vertical}, horizontal_{horizontal} {
|
||||
assert(child_ != nullptr);
|
||||
assert(vertical_ || horizontal_);
|
||||
}
|
||||
@@ -938,13 +957,11 @@ auto scroll_view_control::handle_point(luma::touch_event const& event, luma::tou
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
auto found = touches_.find(point.id);
|
||||
if (found == touches_.end()) {
|
||||
return false;
|
||||
}
|
||||
auto &state = found->second;
|
||||
|
||||
if (point.phase == luma::touch_phase::MOVE) {
|
||||
auto delta = luma::point{
|
||||
.x = point.position.x - state.last.x,
|
||||
@@ -994,7 +1011,6 @@ auto scroll_view_control::handle_point(luma::touch_event const& event, luma::tou
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (point.phase == luma::touch_phase::UP || point.phase == luma::touch_phase::CANCEL) {
|
||||
auto const scrolling = scroll_id_ == point.id && dragging_;
|
||||
if (state.child_active) {
|
||||
@@ -1015,7 +1031,6 @@ auto scroll_view_control::handle_point(luma::touch_event const& event, luma::tou
|
||||
touches_.erase(found);
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1135,7 +1150,8 @@ auto collect_layout_listeners(std::vector<luma::text_input_state::layout_listene
|
||||
|
||||
}
|
||||
|
||||
luma::text_input_state::text_input_state(luma::text_field_options options, std::function<void(std::string)> on_change) : options_{std::move(options)}, on_change_{std::move(on_change)} {
|
||||
luma::text_input_state::text_input_state(luma::text_field_options options, std::function<void(std::string)> on_change)
|
||||
: options_{std::move(options)}, on_change_{std::move(on_change)} {
|
||||
assert(options_.max_length > 0);
|
||||
assert(on_change_);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <modulus.hpp>
|
||||
|
||||
|
||||
auto luma::detail::make_error(std::int32_t code, std::string message, modulus::source_location location) -> modulus::error {
|
||||
return modulus::make_error("luma", code, std::move(message), location);
|
||||
}
|
||||
|
||||
+11
-5
@@ -17,6 +17,7 @@
|
||||
#include <luma/render.hpp>
|
||||
#include <luma/theme.hpp>
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class scope_exit {
|
||||
@@ -89,7 +90,8 @@ auto draw_button(luma::draw_context& context, luma::theme const& theme, luma::re
|
||||
context.draw_text(text, {
|
||||
.x = bounds.x + (bounds.width - measured.width) * 0.5F,
|
||||
.y = bounds.y + (bounds.height - measured.height) * 0.5F,
|
||||
}, theme.body, theme.text);
|
||||
},
|
||||
theme.body, theme.text);
|
||||
}
|
||||
|
||||
auto first_point_inside(luma::touch_event const &event, luma::rect bounds, luma::touch_phase phase) -> luma::touch_point const * {
|
||||
@@ -116,7 +118,8 @@ auto throw_if_failed(std::expected<void, modulus::error> const& status) -> void
|
||||
}
|
||||
}
|
||||
|
||||
scope_exit::scope_exit(std::function<void()> action) : action_{std::move(action)} {}
|
||||
scope_exit::scope_exit(std::function<void()> action)
|
||||
: action_{std::move(action)} {}
|
||||
|
||||
scope_exit::~scope_exit() {
|
||||
if (action_) {
|
||||
@@ -126,7 +129,8 @@ scope_exit::~scope_exit() {
|
||||
|
||||
}
|
||||
|
||||
luma::overlay_host::overlay_host(std::unique_ptr<luma::control> content) : content_{std::move(content)} {
|
||||
luma::overlay_host::overlay_host(std::unique_ptr<luma::control> content)
|
||||
: content_{std::move(content)} {
|
||||
assert(content_ != nullptr);
|
||||
}
|
||||
|
||||
@@ -278,7 +282,8 @@ auto luma::overlay_host::draw(luma::draw_context& context, luma::theme const& th
|
||||
context.draw_text(title, {
|
||||
.x = dialog.x + 16.0F,
|
||||
.y = dialog.y + 16.0F,
|
||||
}, theme.title, theme.text);
|
||||
},
|
||||
theme.title, theme.text);
|
||||
body->draw(context, theme);
|
||||
auto has_cancel = !cancel_text.empty();
|
||||
if (has_cancel) {
|
||||
@@ -297,7 +302,8 @@ auto luma::overlay_host::draw(luma::draw_context& context, luma::theme const& th
|
||||
context.draw_text(toasts_.front().message, {
|
||||
.x = toast_bounds.x + 16.0F,
|
||||
.y = toast_bounds.y + 10.0F,
|
||||
}, theme.body, theme.text);
|
||||
},
|
||||
theme.body, theme.text);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <luma/detail/errors.hpp>
|
||||
|
||||
|
||||
auto luma::router::register_route(std::string name, std::function<std::expected<std::unique_ptr<luma::control>, modulus::error>()> factory) -> std::expected<void, modulus::error> {
|
||||
if (name.empty()) {
|
||||
return luma::detail::fail<void>(luma::detail::error_invalid_argument, "route name must not be empty");
|
||||
|
||||
+8
-5
@@ -16,13 +16,13 @@
|
||||
|
||||
#include <luma/detail/errors.hpp>
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr auto json_options = modulus::json_config::options{
|
||||
.category = "luma",
|
||||
.invalid_argument_code = luma::detail::error_invalid_argument,
|
||||
.not_found_code = luma::detail::error_not_found
|
||||
};
|
||||
.not_found_code = luma::detail::error_not_found};
|
||||
|
||||
auto invalid_color(std::string message) -> std::expected<luma::color, modulus::error> {
|
||||
assert(!message.empty());
|
||||
@@ -73,7 +73,8 @@ auto apply_text_style(boost::json::object const& object, std::char_t const* name
|
||||
"font",
|
||||
"size",
|
||||
"line_height",
|
||||
}, name, json_options);
|
||||
},
|
||||
name, json_options);
|
||||
if (!unknown) {
|
||||
return modulus::fail<void>(unknown.error());
|
||||
}
|
||||
@@ -157,7 +158,8 @@ auto luma::parse_color(boost::json::value const& value) -> std::expected<luma::c
|
||||
"g",
|
||||
"b",
|
||||
"a",
|
||||
}, "color", json_options);
|
||||
},
|
||||
"color", json_options);
|
||||
if (!unknown) {
|
||||
return invalid_color(std::string{unknown.error().message()});
|
||||
}
|
||||
@@ -212,7 +214,8 @@ auto luma::parse_theme(boost::json::value const& value) -> std::expected<luma::t
|
||||
"title",
|
||||
"radius",
|
||||
"spacing",
|
||||
}, "theme", json_options);
|
||||
},
|
||||
"theme", json_options);
|
||||
if (!unknown) {
|
||||
return invalid_theme(std::string{unknown.error().message()});
|
||||
}
|
||||
|
||||
+7
-4
@@ -19,6 +19,7 @@
|
||||
#include <luma/render.hpp>
|
||||
#include <luma/theme.hpp>
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class scope_exit {
|
||||
@@ -84,7 +85,8 @@ auto make_event(luma::touch_event const& event, luma::touch_point point) -> luma
|
||||
};
|
||||
}
|
||||
|
||||
scope_exit::scope_exit(std::function<void()> action) : action_{std::move(action)} {}
|
||||
scope_exit::scope_exit(std::function<void()> action)
|
||||
: action_{std::move(action)} {}
|
||||
|
||||
scope_exit::~scope_exit() {
|
||||
if (action_) {
|
||||
@@ -94,7 +96,8 @@ scope_exit::~scope_exit() {
|
||||
|
||||
}
|
||||
|
||||
luma::window::window(std::uint64_t id, luma::window_options options, std::unique_ptr<luma::control> content) : id_{id}, options_{std::move(options)}, content_{std::move(content)} {
|
||||
luma::window::window(std::uint64_t id, luma::window_options options, std::unique_ptr<luma::control> content)
|
||||
: id_{id}, options_{std::move(options)}, content_{std::move(content)} {
|
||||
assert(id_ != 0);
|
||||
assert(finite_rect(options_.bounds));
|
||||
assert(content_ != nullptr);
|
||||
@@ -335,7 +338,8 @@ auto luma::window_manager::draw(luma::draw_context& context, luma::theme const&
|
||||
context.draw_text(window->options().title, {
|
||||
.x = title.x + 8.0F,
|
||||
.y = title.y + window_title_vertical_padding,
|
||||
}, theme.body, theme.text);
|
||||
},
|
||||
theme.body, theme.text);
|
||||
}
|
||||
context.stroke_rect(bounds, 1.0F, theme.border);
|
||||
}
|
||||
@@ -368,7 +372,6 @@ auto luma::window_manager::handle_touch(luma::touch_event const& event) -> std::
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto current = windows_.rbegin(); current != windows_.rend(); ++current) {
|
||||
assert(*current != nullptr);
|
||||
if (!(*current)->visible()) {
|
||||
|
||||
+69
-33
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <test.hpp>
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
struct fake_draw_context final : public luma::draw_context {
|
||||
@@ -268,7 +269,8 @@ auto fake_draw_context::measure_text(std::string_view text, luma::text_style con
|
||||
};
|
||||
}
|
||||
|
||||
fixed_control::fixed_control(luma::size value) : value_{value} {}
|
||||
fixed_control::fixed_control(luma::size value)
|
||||
: value_{value} {}
|
||||
|
||||
auto fixed_control::measure(luma::draw_context &, luma::theme const &, luma::constraints) -> luma::size {
|
||||
return value_;
|
||||
@@ -292,7 +294,8 @@ auto fixed_control::handle_touch(luma::touch_event const& event) -> std::bool_t
|
||||
return false;
|
||||
}
|
||||
|
||||
counting_control::counting_control(luma::size value) : value_{value} {}
|
||||
counting_control::counting_control(luma::size value)
|
||||
: value_{value} {}
|
||||
|
||||
auto counting_control::measure(luma::draw_context &, luma::theme const &, luma::constraints) -> luma::size {
|
||||
++measure_count;
|
||||
@@ -325,7 +328,8 @@ auto filling_control::measure(luma::draw_context&, luma::theme const&, luma::con
|
||||
return luma::clamp({
|
||||
.width = 20.0F,
|
||||
.height = 20.0F,
|
||||
}, limits);
|
||||
},
|
||||
limits);
|
||||
}
|
||||
|
||||
auto filling_control::arrange(luma::rect bounds) -> void {
|
||||
@@ -337,7 +341,8 @@ auto filling_control::draw(luma::draw_context& context, luma::theme const&) cons
|
||||
context.fill_rect(bounds(), {});
|
||||
}
|
||||
|
||||
fake_texture::fake_texture(std::int32_t width, std::int32_t height) : info_{.width = width, .height = height} {}
|
||||
fake_texture::fake_texture(std::int32_t width, std::int32_t height)
|
||||
: info_{.width = width, .height = height} {}
|
||||
|
||||
auto fake_texture::info() const -> luma::texture_info {
|
||||
return info_;
|
||||
@@ -414,7 +419,8 @@ auto recording_control::handle_touch(luma::touch_event const& event) -> std::boo
|
||||
return true;
|
||||
}
|
||||
|
||||
destroy_probe_control::destroy_probe_control(std::shared_ptr<lifetime_state> state) : state_{std::move(state)} {}
|
||||
destroy_probe_control::destroy_probe_control(std::shared_ptr<lifetime_state> state)
|
||||
: state_{std::move(state)} {}
|
||||
|
||||
destroy_probe_control::~destroy_probe_control() {
|
||||
state_->destroyed = true;
|
||||
@@ -432,7 +438,8 @@ auto destroy_probe_control::measure(luma::draw_context&, luma::theme const&, lum
|
||||
|
||||
auto destroy_probe_control::draw(luma::draw_context &, luma::theme const &) const -> void {}
|
||||
|
||||
closing_window_control::closing_window_control(luma::window_manager& manager, std::uint64_t& id, std::shared_ptr<lifetime_state> state) : manager_{manager}, id_{id}, state_{std::move(state)} {}
|
||||
closing_window_control::closing_window_control(luma::window_manager &manager, std::uint64_t &id, std::shared_ptr<lifetime_state> state)
|
||||
: manager_{manager}, id_{id}, state_{std::move(state)} {}
|
||||
|
||||
closing_window_control::~closing_window_control() {
|
||||
state_->destroyed = true;
|
||||
@@ -458,7 +465,8 @@ auto closing_window_control::handle_touch(luma::touch_event const&) -> std::bool
|
||||
return true;
|
||||
}
|
||||
|
||||
opening_window_control::opening_window_control(luma::window_manager& manager, std::shared_ptr<lifetime_state> state) : manager_{manager}, state_{std::move(state)} {}
|
||||
opening_window_control::opening_window_control(luma::window_manager &manager, std::shared_ptr<lifetime_state> state)
|
||||
: manager_{manager}, state_{std::move(state)} {}
|
||||
|
||||
auto opening_window_control::measure(luma::draw_context &, luma::theme const &, luma::constraints) -> luma::size {
|
||||
return {
|
||||
@@ -478,7 +486,8 @@ auto opening_window_control::handle_touch(luma::touch_event const&) -> std::bool
|
||||
.width = 50.0F,
|
||||
.height = 50.0F,
|
||||
},
|
||||
}, std::make_unique<recording_control>());
|
||||
},
|
||||
std::make_unique<recording_control>());
|
||||
state_->status_ok = opened.has_value();
|
||||
if (opened) {
|
||||
state_->opened_id = *opened;
|
||||
@@ -487,7 +496,8 @@ auto opening_window_control::handle_touch(luma::touch_event const&) -> std::bool
|
||||
return true;
|
||||
}
|
||||
|
||||
updating_window_control::updating_window_control(luma::window_manager& manager, std::uint64_t& id, std::shared_ptr<lifetime_state> state) : manager_{manager}, id_{id}, state_{std::move(state)} {}
|
||||
updating_window_control::updating_window_control(luma::window_manager &manager, std::uint64_t &id, std::shared_ptr<lifetime_state> state)
|
||||
: manager_{manager}, id_{id}, state_{std::move(state)} {}
|
||||
|
||||
auto updating_window_control::measure(luma::draw_context &, luma::theme const &, luma::constraints) -> luma::size {
|
||||
return {
|
||||
@@ -513,7 +523,8 @@ auto updating_window_control::handle_touch(luma::touch_event const&) -> std::boo
|
||||
return true;
|
||||
}
|
||||
|
||||
closing_dialog_control::closing_dialog_control(luma::overlay_host& host, std::shared_ptr<lifetime_state> state, close_phase phase) : host_{host}, state_{std::move(state)}, phase_{phase} {}
|
||||
closing_dialog_control::closing_dialog_control(luma::overlay_host &host, std::shared_ptr<lifetime_state> state, close_phase phase)
|
||||
: host_{host}, state_{std::move(state)}, phase_{phase} {}
|
||||
|
||||
closing_dialog_control::~closing_dialog_control() {
|
||||
state_->destroyed = true;
|
||||
@@ -558,7 +569,8 @@ auto closing_dialog_control::close_if(close_phase phase) const -> void {
|
||||
state_->in_handle = false;
|
||||
}
|
||||
|
||||
replacing_root_invalidate_control::replacing_root_invalidate_control(luma::application& app, std::shared_ptr<lifetime_state> state) : app_{app}, state_{std::move(state)} {}
|
||||
replacing_root_invalidate_control::replacing_root_invalidate_control(luma::application &app, std::shared_ptr<lifetime_state> state)
|
||||
: app_{app}, state_{std::move(state)} {}
|
||||
|
||||
replacing_root_invalidate_control::~replacing_root_invalidate_control() {
|
||||
state_->destroyed = true;
|
||||
@@ -584,7 +596,8 @@ auto replacing_root_invalidate_control::invalidate_layout() -> void {
|
||||
state_->in_handle = false;
|
||||
}
|
||||
|
||||
closing_window_invalidate_control::closing_window_invalidate_control(luma::window_manager& manager, std::uint64_t& id, std::shared_ptr<lifetime_state> state) : manager_{manager}, id_{id}, state_{std::move(state)} {}
|
||||
closing_window_invalidate_control::closing_window_invalidate_control(luma::window_manager &manager, std::uint64_t &id, std::shared_ptr<lifetime_state> state)
|
||||
: manager_{manager}, id_{id}, state_{std::move(state)} {}
|
||||
|
||||
closing_window_invalidate_control::~closing_window_invalidate_control() {
|
||||
state_->destroyed = true;
|
||||
@@ -599,6 +612,7 @@ auto closing_window_invalidate_control::measure(luma::draw_context&, luma::theme
|
||||
.height = 20.0F,
|
||||
};
|
||||
}
|
||||
|
||||
auto closing_window_invalidate_control::draw(luma::draw_context &, luma::theme const &) const -> void {}
|
||||
|
||||
auto closing_window_invalidate_control::invalidate_layout() -> void {
|
||||
@@ -835,7 +849,8 @@ BOOST_AUTO_TEST_CASE(text_controls_measure_with_supplied_theme) {
|
||||
BOOST_TEST(large_button.height > small_button.height);
|
||||
auto field = luma::text_field({
|
||||
.text = "Scale",
|
||||
}, [](std::string) {});
|
||||
},
|
||||
[](std::string) {});
|
||||
BOOST_REQUIRE(field);
|
||||
auto small_field = (*field)->measure(context, small, {
|
||||
.max = {
|
||||
@@ -882,6 +897,7 @@ BOOST_AUTO_TEST_CASE(application_dispatch_serializes_concurrent_callers) {
|
||||
BOOST_REQUIRE(result);
|
||||
});
|
||||
}
|
||||
|
||||
for (auto &thread : threads) {
|
||||
thread.join();
|
||||
}
|
||||
@@ -959,7 +975,8 @@ BOOST_AUTO_TEST_CASE(custom_control_unique_ptr_overloads_are_unambiguous) {
|
||||
auto children = luma::children(std::make_unique<fixed_control>(luma::size{
|
||||
.width = 10.0F,
|
||||
.height = 10.0F,
|
||||
}), luma::label("Label"));
|
||||
}),
|
||||
luma::label("Label"));
|
||||
BOOST_REQUIRE(children);
|
||||
BOOST_TEST(children->size() == 2U);
|
||||
}
|
||||
@@ -969,7 +986,8 @@ BOOST_AUTO_TEST_CASE(factory_validation_returns_errors) {
|
||||
BOOST_TEST(!luma::button("OK", {}));
|
||||
BOOST_TEST(!luma::text_field({
|
||||
.max_length = 0,
|
||||
}, [](std::string) {}));
|
||||
},
|
||||
[](std::string) {}));
|
||||
BOOST_TEST(!luma::image(nullptr));
|
||||
BOOST_TEST(!luma::image(std::make_shared<fake_texture>(0, 16)));
|
||||
BOOST_TEST(!luma::scroll_view(std::unique_ptr<luma::control>{}));
|
||||
@@ -1066,7 +1084,8 @@ BOOST_AUTO_TEST_CASE(text_input_state_filters_modes_and_keyboard_updates_bound_f
|
||||
auto input = luma::make_text_input({
|
||||
.mode = luma::text_input_mode::INTEGER,
|
||||
.max_length = 3,
|
||||
}, [&](std::string text) {
|
||||
},
|
||||
[&](std::string text) {
|
||||
changes.push_back(std::move(text));
|
||||
});
|
||||
BOOST_REQUIRE(input);
|
||||
@@ -1089,7 +1108,8 @@ BOOST_AUTO_TEST_CASE(text_input_state_filters_modes_and_keyboard_updates_bound_f
|
||||
},
|
||||
},
|
||||
},
|
||||
}, *input);
|
||||
},
|
||||
*input);
|
||||
BOOST_REQUIRE(keyboard);
|
||||
(*keyboard)->arrange({
|
||||
.x = 0.0F,
|
||||
@@ -1129,7 +1149,8 @@ BOOST_AUTO_TEST_CASE(text_input_state_filters_modes_and_keyboard_updates_bound_f
|
||||
BOOST_AUTO_TEST_CASE(decimal_text_input_accepts_one_decimal_point) {
|
||||
auto input = luma::make_text_input({
|
||||
.mode = luma::text_input_mode::DECIMAL,
|
||||
}, [](std::string) {});
|
||||
},
|
||||
[](std::string) {});
|
||||
BOOST_REQUIRE(input);
|
||||
BOOST_REQUIRE((*input)->append("1.5"));
|
||||
BOOST_TEST(!(*input)->append("."));
|
||||
@@ -1150,7 +1171,8 @@ BOOST_AUTO_TEST_CASE(text_input_callback_exceptions_return_errors) {
|
||||
BOOST_AUTO_TEST_CASE(text_input_state_notifies_bound_layout_invalidator) {
|
||||
auto input = luma::make_text_input({
|
||||
.text = "a",
|
||||
}, [](std::string) {});
|
||||
},
|
||||
[](std::string) {});
|
||||
BOOST_REQUIRE(input);
|
||||
auto field = luma::text_field(*input);
|
||||
BOOST_REQUIRE(field);
|
||||
@@ -1172,7 +1194,8 @@ BOOST_AUTO_TEST_CASE(text_input_state_notifies_bound_layout_invalidator) {
|
||||
BOOST_AUTO_TEST_CASE(text_field_layout_invalidator_propagates_through_containers) {
|
||||
auto input = luma::make_text_input({
|
||||
.text = "a",
|
||||
}, [](std::string) {});
|
||||
},
|
||||
[](std::string) {});
|
||||
BOOST_REQUIRE(input);
|
||||
auto field = luma::text_field(*input);
|
||||
BOOST_REQUIRE(field);
|
||||
@@ -1407,7 +1430,8 @@ BOOST_AUTO_TEST_CASE(window_manager_captures_touch_by_id) {
|
||||
.width = 100.0F,
|
||||
.height = 100.0F,
|
||||
},
|
||||
}, std::move(content));
|
||||
},
|
||||
std::move(content));
|
||||
BOOST_REQUIRE(id);
|
||||
BOOST_TEST(*id != 0U);
|
||||
BOOST_TEST(manager.handle_touch({
|
||||
@@ -1459,7 +1483,8 @@ BOOST_AUTO_TEST_CASE(window_set_bounds_validates_release_inputs) {
|
||||
.width = 100.0F,
|
||||
.height = 100.0F,
|
||||
},
|
||||
}, std::make_unique<recording_control>());
|
||||
},
|
||||
std::make_unique<recording_control>());
|
||||
BOOST_REQUIRE(id);
|
||||
auto *window = manager.find(*id);
|
||||
BOOST_REQUIRE(window != nullptr);
|
||||
@@ -1497,7 +1522,8 @@ BOOST_AUTO_TEST_CASE(window_manager_uses_decorated_client_area_for_content) {
|
||||
.width = 100.0F,
|
||||
.height = 80.0F,
|
||||
},
|
||||
}, std::move(content));
|
||||
},
|
||||
std::move(content));
|
||||
BOOST_REQUIRE(id);
|
||||
manager.measure(context, theme, {
|
||||
.max = {
|
||||
@@ -1541,7 +1567,8 @@ BOOST_AUTO_TEST_CASE(window_manager_uses_theme_body_line_height_for_decorated_ch
|
||||
.width = 100.0F,
|
||||
.height = 100.0F,
|
||||
},
|
||||
}, std::move(content));
|
||||
},
|
||||
std::move(content));
|
||||
BOOST_REQUIRE(id);
|
||||
manager.measure(context, theme, {
|
||||
.max = {
|
||||
@@ -1583,7 +1610,8 @@ BOOST_AUTO_TEST_CASE(window_manager_skips_hidden_windows_during_measure) {
|
||||
.height = 80.0F,
|
||||
},
|
||||
.visible = false,
|
||||
}, std::move(content));
|
||||
},
|
||||
std::move(content));
|
||||
BOOST_REQUIRE(id);
|
||||
manager.measure(context, theme, {
|
||||
.max = {
|
||||
@@ -1612,7 +1640,8 @@ BOOST_AUTO_TEST_CASE(window_manager_id_mutators_validate_and_update_windows) {
|
||||
.width = 100.0F,
|
||||
.height = 100.0F,
|
||||
},
|
||||
}, std::make_unique<recording_control>());
|
||||
},
|
||||
std::make_unique<recording_control>());
|
||||
BOOST_REQUIRE(id);
|
||||
BOOST_TEST(!manager.set_bounds(0, {
|
||||
.x = 1.0F,
|
||||
@@ -1650,7 +1679,8 @@ BOOST_AUTO_TEST_CASE(window_manager_find_pointer_is_stable_across_open_and_reord
|
||||
.width = 10.0F,
|
||||
.height = 10.0F,
|
||||
},
|
||||
}, std::make_unique<recording_control>());
|
||||
},
|
||||
std::make_unique<recording_control>());
|
||||
BOOST_REQUIRE(first);
|
||||
auto *first_ptr = manager.find(*first);
|
||||
BOOST_REQUIRE(first_ptr != nullptr);
|
||||
@@ -1663,7 +1693,8 @@ BOOST_AUTO_TEST_CASE(window_manager_find_pointer_is_stable_across_open_and_reord
|
||||
.width = 10.0F,
|
||||
.height = 10.0F,
|
||||
},
|
||||
}, std::make_unique<recording_control>());
|
||||
},
|
||||
std::make_unique<recording_control>());
|
||||
BOOST_REQUIRE(opened);
|
||||
}
|
||||
BOOST_TEST(manager.find(*first) == first_ptr);
|
||||
@@ -1683,7 +1714,8 @@ BOOST_AUTO_TEST_CASE(window_manager_defers_reentrant_close_until_touch_returns)
|
||||
.width = 100.0F,
|
||||
.height = 100.0F,
|
||||
},
|
||||
}, std::make_unique<closing_window_control>(manager, id, state));
|
||||
},
|
||||
std::make_unique<closing_window_control>(manager, id, state));
|
||||
BOOST_REQUIRE(opened);
|
||||
id = *opened;
|
||||
BOOST_TEST(manager.handle_touch({
|
||||
@@ -1716,7 +1748,8 @@ BOOST_AUTO_TEST_CASE(window_manager_defers_reentrant_close_until_invalidation_re
|
||||
.width = 100.0F,
|
||||
.height = 100.0F,
|
||||
},
|
||||
}, std::make_unique<closing_window_invalidate_control>(manager, id, state));
|
||||
},
|
||||
std::make_unique<closing_window_invalidate_control>(manager, id, state));
|
||||
BOOST_REQUIRE(opened);
|
||||
id = *opened;
|
||||
manager.invalidate_layout();
|
||||
@@ -1737,7 +1770,8 @@ BOOST_AUTO_TEST_CASE(window_manager_defers_reentrant_open_and_returns_reserved_i
|
||||
.width = 100.0F,
|
||||
.height = 100.0F,
|
||||
},
|
||||
}, std::make_unique<opening_window_control>(manager, state));
|
||||
},
|
||||
std::make_unique<opening_window_control>(manager, state));
|
||||
BOOST_REQUIRE(opened);
|
||||
BOOST_TEST(manager.handle_touch({
|
||||
.points = {
|
||||
@@ -1769,7 +1803,8 @@ BOOST_AUTO_TEST_CASE(window_manager_defers_reentrant_bounds_and_visibility_updat
|
||||
.width = 100.0F,
|
||||
.height = 100.0F,
|
||||
},
|
||||
}, std::make_unique<updating_window_control>(manager, id, state));
|
||||
},
|
||||
std::make_unique<updating_window_control>(manager, id, state));
|
||||
BOOST_REQUIRE(opened);
|
||||
id = *opened;
|
||||
BOOST_TEST(manager.handle_touch({
|
||||
@@ -1803,7 +1838,8 @@ BOOST_AUTO_TEST_CASE(application_window_facade_validates_pre_run_calls) {
|
||||
.width = 100.0F,
|
||||
.height = 100.0F,
|
||||
},
|
||||
}, std::make_unique<recording_control>());
|
||||
},
|
||||
std::make_unique<recording_control>());
|
||||
BOOST_REQUIRE(opened);
|
||||
BOOST_REQUIRE(app.set_window_bounds(*opened, {
|
||||
.x = 5.0F,
|
||||
|
||||
Reference in New Issue
Block a user