diff --git a/include/ekg/core/pools.hpp b/include/ekg/core/pools.hpp index 19c73f62..10792bd9 100644 --- a/include/ekg/core/pools.hpp +++ b/include/ekg/core/pools.hpp @@ -38,32 +38,30 @@ #include "ekg/ui/frame/frame.hpp" #include "ekg/ui/frame/widget.hpp" +#include "ekg/ui/label/label.hpp" +#include "ekg/ui/label/widget.hpp" + namespace ekg::core { void registry(ekg::property_t &property); } -#define ekg_abstract_todo(ekg_abstract_todo_at_type, ekg_abstract_todo_at, ekg_abstract_todo_todo) \ - switch (ekg_abstract_todo_at_type) { \ - case ekg::type::button: { \ - ekg::button_t &descriptor { \ - ekg::query(ekg_abstract_todo_at) \ - }; \ - if (descriptor == ekg::button_t::not_found) { \ - break; \ - } \ - ekg_abstract_todo_todo \ - break; \ - } \ - case ekg::type::frame: { \ - ekg::frame_t &descriptor { \ - ekg::query(ekg_abstract_todo_at) \ +#define ekg_core_declare_widget_case_todo(descriptor_t, widget_descriptor_at, ekg_core_widget_todo) \ + case descriptor_t::type: { \ + descriptor_t &descriptor { \ + ekg::query(widget_descriptor_at) \ }; \ - if (descriptor == ekg::frame_t::not_found) { \ + if (descriptor == descriptor_t::not_found) { \ break; \ } \ - ekg_abstract_todo_todo \ + ekg_core_widget_todo \ break; \ - } \ + } + +#define ekg_core_abstract_todo(widget_descriptor_type, widget_descriptor_at, ekg_core_widget_todo) \ + switch (widget_descriptor_type) { \ + ekg_core_declare_widget_case_todo(ekg::frame_t, widget_descriptor_at, ekg_core_widget_todo); \ + ekg_core_declare_widget_case_todo(ekg::button_t, widget_descriptor_at, ekg_core_widget_todo); \ + ekg_core_declare_widget_case_todo(ekg::label_t, widget_descriptor_at, ekg_core_widget_todo); \ } #define ekg_registry_widget(widget_descriptor_t, register_widget_pool, register_property_pool, is_container, register_settings) \ @@ -122,6 +120,9 @@ namespace ekg { ekg::pool frame_property {}; ekg::pool frame {}; + + ekg::pool label_property {}; + ekg::pool label {}; } pools; template @@ -151,6 +152,10 @@ namespace ekg { return ekg::io::any_static_cast( &ekg::pools.frame_property.query(at) ); + case ekg::type::label: + return ekg::io::any_static_cast( + &ekg::pools.label_property.query(at) + ); } case ekg::type::button: return ekg::io::any_static_cast( @@ -160,6 +165,10 @@ namespace ekg { return ekg::io::any_static_cast( &ekg::pools.frame.query(at) ); + case ekg::type::label: + return ekg::io::any_static_cast( + &ekg::pools.label.query(at) + ); } return t::not_found; @@ -170,6 +179,47 @@ namespace ekg { t descriptor ) { switch (t::type) { + case ekg::type::frame: { + ekg_registry_widget( + ekg::frame_t, + ekg::pools.frame, + ekg::pools.frame_property, + true, + { + property.widget.is_childnizate = true; + property.widget.is_children_docknizable = true; + widget.color_scheme = global_theme.frame_color_scheme; + } + ); + } + + case ekg::type::button: { + ekg_registry_widget( + ekg::button_t, + ekg::pools.button, + ekg::pools.button_property, + false, + { + property.widget.is_childnizate = false; + property.widget.is_children_docknizable = false; + widget.color_scheme = global_theme.button_color_scheme; + } + ); + } + + case ekg::type::label: { + ekg_registry_widget( + ekg::label_t, + ekg::pools.label, + ekg::pools.label_property, + true, + { + property.widget.is_childnizate = false; + property.widget.is_children_docknizable = false; + widget.color_scheme = global_theme.label_color_scheme; + } + ); + } case ekg::type::stack: { ekg::stack_t &stack { ekg::pools.stack.push_back( @@ -195,32 +245,7 @@ namespace ekg { ekg::io::any_static_cast(&descriptor) ) ); - case ekg::type::button: { - ekg_registry_widget( - ekg::button_t, - ekg::pools.button, - ekg::pools.button_property, - false, - { - property.widget.is_childnizate = false; - property.widget.is_children_docknizable = false; - widget.color_scheme = global_theme.button_color_scheme; - } - ); } - case ekg::type::frame: { - ekg_registry_widget( - ekg::frame_t, - ekg::pools.frame, - ekg::pools.frame_property, - true, - { - property.widget.is_childnizate = true; - property.widget.is_children_docknizable = true; - widget.color_scheme = global_theme.frame_color_scheme; - } - ); - }} return t::not_found; } diff --git a/include/ekg/handler/theme.hpp b/include/ekg/handler/theme.hpp index 10fa4b72..01ee08e6 100644 --- a/include/ekg/handler/theme.hpp +++ b/include/ekg/handler/theme.hpp @@ -26,6 +26,7 @@ #include "ekg/ui/button/button.hpp" #include "ekg/ui/frame/frame.hpp" +#include "ekg/ui/label/label.hpp" namespace ekg { struct theme_t { @@ -38,6 +39,7 @@ namespace ekg { ekg::pixel_t layout_margin_thickness {2}; ekg::button_color_scheme_t button_color_scheme {}; ekg::frame_color_scheme_t frame_color_scheme {}; + ekg::label_color_scheme_t label_color_scheme {}; }; ekg::theme_t &theme(std::string_view tag = ""); diff --git a/include/ekg/io/descriptor.hpp b/include/ekg/io/descriptor.hpp index 1a25841e..66c05841 100644 --- a/include/ekg/io/descriptor.hpp +++ b/include/ekg/io/descriptor.hpp @@ -35,7 +35,8 @@ namespace ekg { stack = 4, button = 5, scrollbar = 6, - frame = 7 + frame = 7, + label = 8 }; } diff --git a/include/ekg/io/event.hpp b/include/ekg/io/event.hpp index c2ff5b44..7d84f477 100644 --- a/include/ekg/io/event.hpp +++ b/include/ekg/io/event.hpp @@ -35,7 +35,6 @@ namespace ekg { no_auto_set_viewport_when_resize = 2 << 1 }; - constexpr size_t enum_layer_size {8}; enum class layer { bg, outline, @@ -46,14 +45,15 @@ namespace ekg { text_fg, text_outline }; + constexpr size_t enum_layer_size {static_cast(ekg::layer::text_outline)+1}; - constexpr size_t enum_action_size {8}; enum class action { hover, active, press, release }; + constexpr size_t enum_action_size {static_cast(ekg::action::release)+1}; template struct at_array_t { diff --git a/include/ekg/ui/button/button.hpp b/include/ekg/ui/button/button.hpp index 4e546d61..bfed6f55 100644 --- a/include/ekg/ui/button/button.hpp +++ b/include/ekg/ui/button/button.hpp @@ -63,8 +63,8 @@ namespace ekg { ekg::flags_t box {ekg::dock::none}; ekg::flags_t dock {ekg::dock::left}; ekg::button_t::check_t::widget_t widget {}; - ekg::at_array_t layers {}; - ekg::at_array_t actions {}; + ekg::at_array_t layers {}; + ekg::at_array_t actions {}; }; static ekg::button_t not_found; @@ -75,8 +75,8 @@ namespace ekg { std::string tag {}; ekg::flags_t dock {ekg::dock::left | ekg::dock::fill}; ekg::rect_t rect {}; - ekg::at_array_t layers {}; - ekg::at_array_t actions {}; + ekg::at_array_t layers {}; + ekg::at_array_t actions {}; std::vector checks {}; ekg::button_color_scheme_t color_scheme {}; public: diff --git a/include/ekg/ui/label/label.hpp b/include/ekg/ui/label/label.hpp new file mode 100644 index 00000000..de04e55e --- /dev/null +++ b/include/ekg/ui/label/label.hpp @@ -0,0 +1,67 @@ +/** + * MIT License + * + * Copyright (c) 2022-2025 Rina Wilk / vokegpu@gmail.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef EKG_UI_LABEL_HPP +#define EKG_UI_LABEL_HPP + +#include "ekg/io/descriptor.hpp" +#include "ekg/math/geometry.hpp" +#include "ekg/io/event.hpp" +#include "ekg/io/font.hpp" + +namespace ekg { + struct label_color_scheme_t { + public: + ekg::rgba_t background {}; + ekg::rgba_t outline {}; + ekg::rgba_t text_foreground {}; + }; + + struct label_t { + public: + struct widget_t { + public: + ekg::rect_t rect_text {}; + }; + public: + static constexpr ekg::type type {ekg::type::label}; + static ekg::label_t not_found; + public: + ekg::at_t property_at {}; + public: + std::string tag {}; + ekg::rect_t rect {}; + ekg::value text {}; + ekg::flags_t dock {}; + ekg::flags_t dock_text {}; + ekg::font font_size {ekg::font::medium}; + ekg::at_array_t actions {}; + ekg::at_array_t layers {}; + ekg::label_t::widget_t widget {}; + ekg::label_color_scheme_t color_scheme {}; + public: + ekg_descriptor(ekg::label_t); + }; +} + +#endif diff --git a/include/ekg/ui/label/widget.hpp b/include/ekg/ui/label/widget.hpp new file mode 100644 index 00000000..13e1c119 --- /dev/null +++ b/include/ekg/ui/label/widget.hpp @@ -0,0 +1,62 @@ +/** + * MIT License + * + * Copyright (c) 2022-2025 Rina Wilk / vokegpu@gmail.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef EKG_UI_LABEL_WIDGET_HPP +#define EKG_UI_LABEL_WIDGET_HPP + +#include "ekg/ui/property.hpp" +#include "ekg/ui/label/label.hpp" + +namespace ekg::ui { + void reload( + ekg::property_t &property, + ekg::label_t &label + ); + + void event( + ekg::property_t &property, + ekg::label_t &label, + const ekg::io::stage &stage + ); + + void high_frequency( + ekg::property_t &property, + ekg::label_t &label + ); + + void pass( + ekg::property_t &property, + ekg::label_t &label + ); + + void buffering( + ekg::property_t &property, + ekg::label_t &label + ); + + void unmap( + ekg::label_t &label + ); +} + +#endif diff --git a/src/core/runtime.cpp b/src/core/runtime.cpp index 57e5da3d..eb9451c2 100644 --- a/src/core/runtime.cpp +++ b/src/core/runtime.cpp @@ -125,7 +125,7 @@ void ekg::core::reload(ekg::info_t &info) { continue; } - ekg_abstract_todo( + ekg_core_abstract_todo( property.descriptor_at.flags, property.descriptor_at, ekg::ui::reload(property, descriptor); @@ -233,7 +233,7 @@ void ekg::core::poll_event() { (abs_widget.widget.is_absolute || is_on_scrolling_timeout) ) { - ekg_abstract_todo( + ekg_core_abstract_todo( abs_widget.descriptor_at.flags, abs_widget.descriptor_at, @@ -273,7 +273,7 @@ void ekg::core::poll_event() { continue; } - ekg_abstract_todo( + ekg_core_abstract_todo( property.descriptor_at.flags, property.descriptor_at, @@ -326,7 +326,7 @@ void ekg::core::poll_event() { }; if (focused_property != ekg::property_t::not_found) { - ekg_abstract_todo( + ekg_core_abstract_todo( focused_at.flags, focused_at, diff --git a/src/ekg.cpp b/src/ekg.cpp index 7a2e2c54..391575e0 100644 --- a/src/ekg.cpp +++ b/src/ekg.cpp @@ -103,7 +103,7 @@ void ekg::update() { ekg::query(ekg::p_core->high_frequency.at(it)) }; - ekg_abstract_todo( + ekg_core_abstract_todo( property.descriptor_at.flags, property.descriptor_at, ekg::ui::high_frequency(property, descriptor); @@ -147,7 +147,7 @@ void ekg::render() { continue; } - ekg_abstract_todo( + ekg_core_abstract_todo( property.descriptor_at.flags, property.descriptor_at, diff --git a/src/handler/theme/handler.cpp b/src/handler/theme/handler.cpp index 037a3c1d..35ab0a68 100644 --- a/src/handler/theme/handler.cpp +++ b/src/handler/theme/handler.cpp @@ -55,6 +55,10 @@ void ekg::handler::theme::init() { light_pinky_theme.button_color_scheme.box_highlight = {245, 169, 184, 50}; light_pinky_theme.button_color_scheme.box_background = {202, 207, 222, 100}; + light_pinky_theme.label_color_scheme.background = {204, 204, 204, 0}; + light_pinky_theme.label_color_scheme.outline = {202, 207, 222, 0}; + light_pinky_theme.label_color_scheme.text_foreground = {141, 141, 141, 255}; + this->registry(light_pinky_theme.tag) = light_pinky_theme; this->set_current_theme(light_pinky_theme.tag); } diff --git a/src/io/memory.cpp b/src/io/memory.cpp index edfcf153..442852d7 100644 --- a/src/io/memory.cpp +++ b/src/io/memory.cpp @@ -66,7 +66,7 @@ void ekg::unmap(void *pv_address) { ekg::mapped_address_sign_info_t &info {ekg::sign.list.at(it)}; if (info.pv_address == pv_address) { for (ekg::at_t &at : info.ats) { - ekg_abstract_todo( + ekg_core_abstract_todo( at.flags, at, ekg::ui::unmap(descriptor); diff --git a/src/layout/docknize.cpp b/src/layout/docknize.cpp index a63d9fec..4fa58dd3 100644 --- a/src/layout/docknize.cpp +++ b/src/layout/docknize.cpp @@ -275,7 +275,7 @@ void ekg::layout::docknize_widget( } if (parent_property.widget.should_refresh_size) { - ekg_abstract_todo( + ekg_core_abstract_todo( parent_property.descriptor_at.flags, parent_property.descriptor_at, ekg::ui::reload(parent_property, descriptor); @@ -384,7 +384,7 @@ void ekg::layout::docknize_widget( property.widget.should_refresh_size = true; } - ekg_abstract_todo( + ekg_core_abstract_todo( property.descriptor_at.flags, property.descriptor_at, ekg::ui::reload(property, descriptor); @@ -553,7 +553,7 @@ void ekg::layout::docknize_widget( } max_previous_height = rect.h > max_previous_height ? rect.h : max_previous_height; - ekg_abstract_todo( + ekg_core_abstract_todo( property.descriptor_at.flags, property.descriptor_at, @@ -604,7 +604,7 @@ float ekg::layout::get_widget_height_by_children( continue; } - ekg_abstract_todo( + ekg_core_abstract_todo( property.descriptor_at.flags, property.descriptor_at, flags = descriptor.dock; diff --git a/src/layout/extentnize.cpp b/src/layout/extentnize.cpp index 8b44a2ab..bd435090 100644 --- a/src/layout/extentnize.cpp +++ b/src/layout/extentnize.cpp @@ -184,7 +184,7 @@ void ekg::layout::extentnize_widget( is_scrollbar = property.descriptor_at.flags == ekg::type::scrollbar; is_last_index = it == latest_index; - ekg_abstract_todo( + ekg_core_abstract_todo( property.descriptor_at.flags, property.descriptor_at, dock = descriptor.dock; diff --git a/src/ui/button/widget.cpp b/src/ui/button/widget.cpp index dbe984ba..415fd922 100644 --- a/src/ui/button/widget.cpp +++ b/src/ui/button/widget.cpp @@ -35,18 +35,6 @@ void ekg::ui::reload( ekg::property_t &property, ekg::button_t &button ) { - ekg_assert_low_level( - property == ekg::property_t::not_found, - ekg::log() << "warn: invalid property on reload", - return - ); - - ekg_assert_low_level( - button == ekg::button_t::not_found, - ekg::log() << "warn: invalid button on reload", - return - ); - ekg::ui::get_abs_rect( property, button.rect @@ -134,6 +122,7 @@ void ekg::ui::reload( if (property.widget.should_refresh_size) { button.rect.w = ekg::max(ekg::dpi.min_sizes, mask.get_rect().w); + property.widget.should_buffering = true; property.widget.should_refresh_size = false; } } @@ -307,7 +296,10 @@ void ekg::ui::pass( ekg::property_t &property, ekg::button_t &button ) { - ekg_draw_allocator_bind_local(&property.widget.geometry_buffer, &property.widget.gpu_data_buffer); + ekg_draw_allocator_bind_local( + &property.widget.geometry_buffer, + &property.widget.gpu_data_buffer + ); if (property.widget.should_buffering) { return; diff --git a/src/ui/label/label.cpp b/src/ui/label/label.cpp new file mode 100644 index 00000000..4a0937c8 --- /dev/null +++ b/src/ui/label/label.cpp @@ -0,0 +1,28 @@ +/** + * MIT License + * + * Copyright (c) 2022-2025 Rina Wilk / vokegpu@gmail.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "ekg/ui/label/label.hpp" + +ekg::label_t ekg::label_t::not_found { + .at = ekg::at_t::not_found +}; diff --git a/src/ui/label/widget.cpp b/src/ui/label/widget.cpp new file mode 100644 index 00000000..d7791ce8 --- /dev/null +++ b/src/ui/label/widget.cpp @@ -0,0 +1,177 @@ +/** + * MIT License + * + * Copyright (c) 2022-2025 Rina Wilk / vokegpu@gmail.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include "ekg/ui/label/widget.hpp" +#include "ekg/math/geometry.hpp" +#include "ekg/draw/shape/shape.hpp" +#include "ekg/draw/typography/font.hpp" +#include "ekg/layout/docknize.hpp" +#include "ekg/ui/abstract.hpp" +#include "ekg/core/pools.hpp" +#include "ekg/core/runtime.hpp" +#include "ekg/draw/allocator.hpp" + +void ekg::ui::reload( + ekg::property_t &property, + ekg::label_t &label +) { + ekg::ui::get_abs_rect( + property, + label.rect + ); + + ekg::axis pick_axis { + ekg::axis::horizontal + }; + + ekg::draw::font &draw_font { + ekg::draw::get_font_renderer(label.font_size) + }; + + label.widget.rect_text.w = draw_font.get_text_width(label.text.get()); + label.widget.rect_text.h = draw_font.get_text_height(); + + ekg::aligned_t aligned_dimension {}; + ekg::align_rect_dimension( + pick_axis, + label.widget.rect_text, + ekg::dpi.min_sizes, + aligned_dimension + ); + + label.rect.scaled_height = ekg::max(1, label.rect.scaled_height); + label.rect.h = aligned_dimension.h * label.rect.scaled_height; + + ekg::layout::mask mask {}; + mask.preset( + { + aligned_dimension.offset, + aligned_dimension.offset, + label.rect.h + }, + pick_axis, + label.rect.w + ); + + mask.insert( + { + .p_rect = &label.widget.rect_text, + .dock = label.dock_text + } + ); + + mask.docknize(); + + if (property.widget.should_refresh_size) { + label.rect.w = ekg::max(ekg::dpi.min_sizes, mask.get_rect().w); + property.widget.should_refresh_size = false; + } +} + +void ekg::ui::event( + ekg::property_t &property, + ekg::label_t &label, + const ekg::io::stage &stage +) { + switch (stage) { + case ekg::io::stage::pre: + ekg::ui::pre_event(property, label.rect, false); + break; + case ekg::io::stage::post: + ekg::ui::post_event(property); + break; + default: + break; + } +} + +void ekg::ui::high_frequency( + ekg::property_t &property, + ekg::label_t &label +) { + +} + +void ekg::ui::pass( + ekg::property_t &property, + ekg::label_t &label +) { + ekg_draw_allocator_bind_local( + &property.widget.geometry_buffer, + &property.widget.gpu_data_buffer + ); + + if (property.widget.should_buffering) { + return; + } + + if (label.text.was_changed()) { + property.widget.should_buffering = true; + return; + } + + ekg_draw_allocator_pass(); +} + +void ekg::ui::buffering( + ekg::property_t &property, + ekg::label_t &label +) { + ekg::rect_t &rect_abs {ekg::ui::get_abs_rect(property, label.rect)}; + + ekg_draw_allocator_assert_scissor( + property.widget.rect_scissor, + rect_abs, + ekg::query(property.parent_at).widget.rect, + true + ); + + ekg::draw::rect( + rect_abs, + label.color_scheme.background, + ekg::draw::mode::fill, + label.layers[ekg::layer::bg] + ); + + ekg::draw::get_font_renderer(label.font_size) + .blit( + label.text.get(), + rect_abs.x + label.widget.rect_text.x, rect_abs.y + label.widget.rect_text.y, + label.color_scheme.text_foreground + ); + + ekg::draw::rect( + rect_abs, + label.color_scheme.outline, + ekg::draw::mode::outline, + label.layers[ekg::layer::outline] + ); + + ekg_draw_allocator_pass(); +} + +void ekg::ui::unmap( + ekg::label_t &label +) { + label.text.ownership(nullptr); +}