diff --git a/inc/basic_widgets/core/draw.hpp b/inc/basic_widgets/core/draw.hpp index 4439207..0ac9c02 100644 --- a/inc/basic_widgets/core/draw.hpp +++ b/inc/basic_widgets/core/draw.hpp @@ -13,9 +13,18 @@ namespace bwidgets class Renderer; class Texture; - [[nodiscard]] auto aa(Color, int, float) noexcept -> Color; - [[nodiscard]] auto filled_circle(Color, int resolution, const Renderer&, + // Add transparency to color c relative to the distance d from + // a limit to produce an AntiAliasing effect. + // d >= 0 → full transparency; + // −(aa_pixels) <= d < 0 → smoothsteped transparency gradient; + // d < −(aa_pixels) → fully opaque. + [[nodiscard]] auto aa(Color c, int aa_pixels, float d) noexcept -> Color; + // Render a filled circle texture of color c and diameter resolution with + // aa_pixels used for antialiasing. + [[nodiscard]] auto filled_circle(Color c, int resolution, const Renderer&, int aa_pixels = 3) -> std::shared_ptr; + // Set the color of every pixels of a Texture using the passed function to compute + // pixel color. void set_pixels_color(Texture*, const std::function&); diff --git a/inc/basic_widgets/core/error_helper.hpp b/inc/basic_widgets/core/error_helper.hpp index 02d4648..737a5c3 100644 --- a/inc/basic_widgets/core/error_helper.hpp +++ b/inc/basic_widgets/core/error_helper.hpp @@ -11,6 +11,7 @@ extern "C" { namespace bwidgets { + // Throw a E exception with message w if ptr is null. Otherwise return ptr. template inline auto ptr_or_throw(T* const ptr, const std::string_view w = "unknown") -> T* { @@ -23,11 +24,15 @@ namespace bwidgets return ptr; } + // Check a return code with the success function passed. If success return false + // throw an E Exception with message w. template inline auto success_or_throw( const T code, const std::string_view w = "unknown", const std::function& success = [](T code) { return code == 0; }) -> T { + // If exception type is SDLError and no value or unknown was passed for w, get + // the last error message using SDL facilities. if constexpr (std::is_same_v) { const std::string what {w == "unknown" ? SDL_GetError() : w}; if (code < 0) throw E(what); diff --git a/inc/basic_widgets/core/font.hpp b/inc/basic_widgets/core/font.hpp index ea62927..506fb26 100644 --- a/inc/basic_widgets/core/font.hpp +++ b/inc/basic_widgets/core/font.hpp @@ -11,6 +11,7 @@ namespace bwidgets { + // Wrap TTF_Font from SDL_ttf and provide a font finding function. class Font final : OpaqueStruct::Wrapper { public: @@ -71,6 +72,7 @@ namespace bwidgets auto style(uint8_t) noexcept -> Font*; [[nodiscard]] auto text_size(std::string_view) const noexcept -> Size; + // Get file path of the font best matching a give fontconfig pattern. [[nodiscard]] static auto find(std::string_view) -> std::string; }; } diff --git a/inc/basic_widgets/core/math.hpp b/inc/basic_widgets/core/math.hpp index 1deabe1..076894d 100644 --- a/inc/basic_widgets/core/math.hpp +++ b/inc/basic_widgets/core/math.hpp @@ -11,11 +11,16 @@ namespace bwidgets { + // Get the start coordinate offset required to center a ligne with a length used_len on another + // line with a length available_len. [[nodiscard]] inline auto center_line(const int available_len, const int used_len) noexcept -> int { return (available_len - used_len) / 2; } + // Get the squared distance of two points on a 2D plan. This avoid computing square root + // when for instance we need to compare two lenght but knowing the actual lenght is not + // needed. [[nodiscard]] inline auto distance_sqrd(const SDL_Point a, const SDL_Point b) noexcept -> float { @@ -23,11 +28,13 @@ namespace bwidgets + float(a.y - b.y) * float(a.y - b.y); } + // Get distance of two points on a 2D plan. [[nodiscard]] inline auto distance(const SDL_Point a, const SDL_Point b) noexcept -> float { return std::sqrt(distance_sqrd(a, b)); } + // Like std::lerp but for use with Color object. lerp function is applied only to enabled channels. template [[nodiscard]] inline auto lerp(const Color a, const Color b, const F x, const bool op_alpha=false, const bool op_color=true) noexcept -> Color { @@ -39,12 +46,14 @@ namespace bwidgets }}; } + // Reverse lerp. template [[nodiscard]] inline auto linear(const N x, const N a, const N b) noexcept -> float { return (float)(x - a) / (float)(b - a); } + // Check if a rectangle is completly inside of another rectangle. [[nodiscard]] inline auto rect_in_rect(const SDL_Rect& outer, const SDL_Rect& inner) noexcept -> bool { @@ -55,24 +64,28 @@ namespace bwidgets && (SDL_PointInRect(&bottom_right, &outer) == SDL_TRUE); } + // Get the rectangle inside r leaving margins of given size between inner and outer rectangle. [[nodiscard]] inline auto rect_margin(const SDL_Rect& r, const Size margin) noexcept -> SDL_Rect { return {r.x + margin.w, r.y + margin.h, r.w - 2 * margin.w, r.h - 2 * margin.h}; } + // Get the rectangle obtained from adding offset to its origin coordinate. [[nodiscard]] inline auto rect_offset(const SDL_Rect& r, const SDL_Point offset) noexcept -> SDL_Rect { return {r.x + offset.x, r.y + offset.y, r.w, r.h}; } + // Commodity function to use another rectangle as a size for the offset to be added to r. [[nodiscard]] inline auto rect_offset(const SDL_Rect& r, const SDL_Rect& offset) noexcept -> SDL_Rect { return rect_offset(r, SDL_Point {offset.x, offset.y}); } + // Standard smoothstep algorithm. template [[nodiscard]] inline auto smoothstep(const N x, const N a, const N b) noexcept -> float { diff --git a/inc/basic_widgets/core/renderer.hpp b/inc/basic_widgets/core/renderer.hpp index 83581c3..d04cb48 100644 --- a/inc/basic_widgets/core/renderer.hpp +++ b/inc/basic_widgets/core/renderer.hpp @@ -14,6 +14,7 @@ namespace bwidgets { class Texture; + // Wrap some of SDL's 2D accelerated rendering API. class Renderer final : OpaqueStruct::Wrapper { friend Texture; diff --git a/inc/basic_widgets/core/texture.hpp b/inc/basic_widgets/core/texture.hpp index b2fb445..443f331 100644 --- a/inc/basic_widgets/core/texture.hpp +++ b/inc/basic_widgets/core/texture.hpp @@ -12,6 +12,7 @@ namespace bwidgets { class Renderer; + // Wrap most of the texture functions of SDL 2D rendering API. class Texture final : OpaqueStruct::Wrapper { friend Renderer; diff --git a/inc/basic_widgets/core/type/color.hpp b/inc/basic_widgets/core/type/color.hpp index 34d4f1c..04e63b7 100644 --- a/inc/basic_widgets/core/type/color.hpp +++ b/inc/basic_widgets/core/type/color.hpp @@ -10,6 +10,7 @@ namespace bwidgets { + // Wrap SDL_Color to provide operator overloads. class Color final { public: @@ -29,16 +30,21 @@ namespace bwidgets Color(Color&&) noexcept = default; ~Color() = default; - [[nodiscard]] auto alpha() const noexcept -> Color + // Enable/disable operations on alpha channel. Disabled by default on + // construction. + [[nodiscard]] auto alpha(const bool state = true) const noexcept -> Color { - return {sdl_type, _operate_on_colors, true}; + return {sdl_type, _operate_on_colors, state}; } - [[nodiscard]] auto colors() const noexcept -> Color + // Enable/disable operations on color channels.Enabled by default on + // construction. + [[nodiscard]] auto colors(const bool state = true) const noexcept -> Color { - return {sdl_type, true, _operate_on_alpha}; + return {sdl_type, state, _operate_on_alpha}; } + // Get reference to the wrapped SDL native object. [[nodiscard]] auto& operator()() noexcept { return sdl_type; @@ -49,24 +55,28 @@ namespace bwidgets return sdl_type; } + // Add operand to enabled channels. template [[nodiscard]] auto operator+(const N operand) const noexcept { return _operate(operand, [](N a, N b) { return a + b; }); } + // Substract operand from enabled channels. template [[nodiscard]] auto operator-(const N operand) const noexcept { return _operate(operand, [](N a, N b) { return a - b; }); } + // Multiply enabled channel values by opererand. template [[nodiscard]] auto operator*(const N operand) const noexcept { return _operate(operand, [](N a, N b) { return a * b; }); } + // Divide enabled channel values by operand. template [[nodiscard]] auto operator/(const N operand) const { @@ -84,6 +94,8 @@ namespace bwidgets return *this; } + // Compare for equality of the enabled channel values between two Color + // instances. [[nodiscard]] auto operator==(const Color other) const noexcept { return (_operate_on_colors && sdl_type.r == other().r @@ -91,6 +103,8 @@ namespace bwidgets || (_operate_on_alpha && sdl_type.a == other().a); } + // Compare for inequality of the enabled channel values between two Color + // instances. [[nodiscard]] auto operator!=(const Color other) const noexcept { return (sdl_type.r != other().r || sdl_type.g != other().g diff --git a/inc/basic_widgets/core/type/concepts.hpp b/inc/basic_widgets/core/type/concepts.hpp index e55db20..2e961bc 100644 --- a/inc/basic_widgets/core/type/concepts.hpp +++ b/inc/basic_widgets/core/type/concepts.hpp @@ -6,18 +6,22 @@ namespace bwidgets { + // T can be converted to string with to_string. template concept CanToString = requires(T value) { std::to_string(value); }; + // T is a floating point type. template concept FloatingPoint = std::is_floating_point_v; + // T can be any numeric type. template concept Numeric = std::is_arithmetic_v; + // T can be converted to string by using ostream. template concept Printable = requires(T value) { diff --git a/inc/basic_widgets/core/type/exception.hpp b/inc/basic_widgets/core/type/exception.hpp index e1720d2..c8dd5ed 100644 --- a/inc/basic_widgets/core/type/exception.hpp +++ b/inc/basic_widgets/core/type/exception.hpp @@ -7,11 +7,14 @@ namespace bwidgets { - struct BaseException : std::runtime_error + // Base type for custom runtime errors. + class BaseException : std::runtime_error { + protected: using runtime_error::runtime_error; }; + // T derives from BaseException. template concept Exception = std::derived_from; } diff --git a/inc/basic_widgets/core/type/fc_error.hpp b/inc/basic_widgets/core/type/fc_error.hpp index 961d9ae..91b1e17 100644 --- a/inc/basic_widgets/core/type/fc_error.hpp +++ b/inc/basic_widgets/core/type/fc_error.hpp @@ -5,6 +5,7 @@ namespace bwidgets { + // Exception type for fontconfig errors struct FCError final : BaseException { using BaseException::BaseException; diff --git a/inc/basic_widgets/core/type/opaque_struct.hpp b/inc/basic_widgets/core/type/opaque_struct.hpp index d41c986..1b16592 100644 --- a/inc/basic_widgets/core/type/opaque_struct.hpp +++ b/inc/basic_widgets/core/type/opaque_struct.hpp @@ -5,6 +5,7 @@ namespace bwidgets { + // Wrap opaque structures to be able to use a destructor to free them. template class OpaqueStruct { @@ -15,6 +16,8 @@ namespace bwidgets T* const _c_pod; public: + // Construct an instance managing resource pointed by ptr using Deleter d to free + // it on wrapper destruction. OpaqueStruct(T* ptr, Deleter d) : _deleter {std::move(d)}, _c_pod {ptr} {} OpaqueStruct(const OpaqueStruct&) = delete; @@ -25,6 +28,7 @@ namespace bwidgets _deleter(_c_pod); }; + // Get the pointer to the wrapped opaque struct. [[nodiscard]] auto* operator()() const { return _c_pod; @@ -33,9 +37,11 @@ namespace bwidgets auto operator=(const OpaqueStruct&) = delete; auto operator=(OpaqueStruct&&) = delete; + // Base class for defining custom wrappers. class Wrapper { public: + // Forward args to OpaqueStruct ctor. Wrapper(T* ptr, Deleter d) : _data(ptr, std::move(d)) {} protected: diff --git a/inc/basic_widgets/core/type/sdl_error.hpp b/inc/basic_widgets/core/type/sdl_error.hpp index 7d15c6a..9fe0f8b 100644 --- a/inc/basic_widgets/core/type/sdl_error.hpp +++ b/inc/basic_widgets/core/type/sdl_error.hpp @@ -5,6 +5,7 @@ namespace bwidgets { + // Custom exception type for SDL errors. struct SDLError final : BaseException { using BaseException::BaseException; diff --git a/inc/basic_widgets/core/type/size.hpp b/inc/basic_widgets/core/type/size.hpp index d45de8c..4da376f 100644 --- a/inc/basic_widgets/core/type/size.hpp +++ b/inc/basic_widgets/core/type/size.hpp @@ -5,22 +5,26 @@ namespace bwidgets { + // Represent size of a 2D surface. struct Size { int w; int h; }; + // Addition the dimensions of two Size objects. [[nodiscard]] inline auto operator+(const Size a, const Size b) noexcept -> Size { return {a.w + b.w, a.h + b.h}; } + // Substract dimensions of a Size object from another. [[nodiscard]] inline auto operator-(const Size a, const Size b) noexcept -> Size { return {a.w - b.w, a.h - b.h}; } + // Multiply dimensions of a Size instance by a number. template [[nodiscard]] inline auto operator*(const Size a, const N b) noexcept -> Size { diff --git a/inc/basic_widgets/w/aligned_layout.hpp b/inc/basic_widgets/w/aligned_layout.hpp index 66c21bc..5aa3bc3 100644 --- a/inc/basic_widgets/w/aligned_layout.hpp +++ b/inc/basic_widgets/w/aligned_layout.hpp @@ -11,6 +11,7 @@ namespace bwidgets VERTICAL }; + // Align vertically or horizontally widgets. class AlignedLayout : public virtual Layout { public: diff --git a/inc/basic_widgets/w/base/input.hpp b/inc/basic_widgets/w/base/input.hpp index 182f550..50b3d17 100644 --- a/inc/basic_widgets/w/base/input.hpp +++ b/inc/basic_widgets/w/base/input.hpp @@ -35,16 +35,23 @@ namespace bwidgets char input_width_unit = 'W'; T value {}; - virtual void color_fg(Color c) = 0; + // Get the current displayed string. [[nodiscard]] virtual auto input_text() const -> std::string_view = 0; - virtual void input_text(std::string txt) = 0; + // Set displayed string + virtual void input_text(std::string) = 0; + virtual void input_text_color(Color) = 0; + // Check if a character is allowed to be inputed. String is used because we could + // have multibytes characters to represent using 8bits chars. [[nodiscard]] virtual auto is_valid_input(std::string_view) const noexcept - -> bool = 0; - [[nodiscard]] virtual auto process_value(T x) const noexcept -> T = 0; - [[nodiscard]] virtual auto value_from_string(std::string_view s) const noexcept - -> T = 0; - [[nodiscard]] virtual auto value_to_string(T value) const noexcept - -> std::string = 0; + -> bool = 0; + + // Process a value for instance to modify it before saving it. + [[nodiscard]] virtual auto process_value(T) const noexcept -> T = 0; + // Get string representation to be shown of the stored value. + [[nodiscard]] virtual auto value_from_string(std::string_view) const noexcept + -> T = 0; + // Parse a string to get its representation in T type of input value memory. + [[nodiscard]] virtual auto value_to_string(T) const noexcept -> std::string = 0; }; } diff --git a/inc/basic_widgets/w/base/input_impl.hpp b/inc/basic_widgets/w/base/input_impl.hpp index b7d575b..00bc44e 100644 --- a/inc/basic_widgets/w/base/input_impl.hpp +++ b/inc/basic_widgets/w/base/input_impl.hpp @@ -206,7 +206,9 @@ namespace bwidgets { const auto& color_end = focus() ? InputImpl::color_bg_focused : InputImpl::color_bg_default; + const auto color_start = color_end / 2; + // Render input borders. for (int i = InputImpl::border_width - 1; i >= 0; i--) { const auto factor = linear(i, 0, InputImpl::border_width); _renderer->draw_color(lerp(color_start, color_end, factor)) diff --git a/inc/basic_widgets/w/base/layout.hpp b/inc/basic_widgets/w/base/layout.hpp index d64aaae..dc91ac7 100644 --- a/inc/basic_widgets/w/base/layout.hpp +++ b/inc/basic_widgets/w/base/layout.hpp @@ -11,11 +11,13 @@ namespace bwidgets public: static inline const Size default_margins {8, 8}; + // Margins between layout widgets. Size margins = default_margins; using Widget::Widget; - + // Add widget to the layout virtual void add_widget(std::unique_ptr) = 0; + // Apply a function to every layout widget. virtual void for_widgets(const std::function&) = 0; }; } diff --git a/inc/basic_widgets/w/base/layout_impl.hpp b/inc/basic_widgets/w/base/layout_impl.hpp index 13e8b78..e88a020 100644 --- a/inc/basic_widgets/w/base/layout_impl.hpp +++ b/inc/basic_widgets/w/base/layout_impl.hpp @@ -30,6 +30,7 @@ namespace bwidgets void _handle_renderer_change(const std::shared_ptr&) override; void _handle_rendering() override; + // Compute and set widget geometry. virtual void _update_layout(const SDL_Rect&) = 0; }; } diff --git a/inc/basic_widgets/w/base/widget.hpp b/inc/basic_widgets/w/base/widget.hpp index 3f78b63..0747376 100644 --- a/inc/basic_widgets/w/base/widget.hpp +++ b/inc/basic_widgets/w/base/widget.hpp @@ -16,14 +16,21 @@ namespace bwidgets class Widget : public virtual EventHandler { public: + // Parent widget for bidirectional message passing between widgets. Widget* parent; explicit Widget(Widget* p = nullptr) noexcept : parent {p} {} + // Render widget on current renderer target. virtual void render() = 0; + // Set widget renderer. virtual void renderer(std::shared_ptr) = 0; + // Get prefered or minimal widget size. [[nodiscard]] virtual auto size() const noexcept -> Size = 0; + // Set the viewport delimiting the widget rendering area and origin + // for relative coordinates. virtual void viewport(const SDL_Rect&) = 0; + // Get current viewport. [[nodiscard]] virtual auto viewport() const -> const SDL_Rect& = 0; }; } diff --git a/inc/basic_widgets/w/base/widget_impl.hpp b/inc/basic_widgets/w/base/widget_impl.hpp index c707f67..8710bf2 100644 --- a/inc/basic_widgets/w/base/widget_impl.hpp +++ b/inc/basic_widgets/w/base/widget_impl.hpp @@ -18,12 +18,16 @@ namespace bwidgets protected: std::shared_ptr _renderer; SDL_Rect _viewport {0, 0, 0, 0}; + // Area actually used by the widget. SDL_Rect _widget_area {0, 0, 0, 0}; using Widget::Widget; + // Called on viewport change. virtual void _handle_geometry_change(const SDL_Rect&) = 0; + // Called on renderer change. virtual void _handle_renderer_change(const std::shared_ptr&) {} + // Called on rendering. virtual void _handle_rendering() = 0; }; } diff --git a/inc/basic_widgets/w/button.hpp b/inc/basic_widgets/w/button.hpp index a878470..77e616d 100644 --- a/inc/basic_widgets/w/button.hpp +++ b/inc/basic_widgets/w/button.hpp @@ -27,7 +27,9 @@ namespace bwidgets using Widget::Widget; + // Get button text (label). [[nodiscard]] virtual auto text() const noexcept -> std::string_view = 0; + // Set button text virtual void text(std::string) = 0; }; } diff --git a/inc/basic_widgets/w/caption.hpp b/inc/basic_widgets/w/caption.hpp index f0bc21c..95b4679 100644 --- a/inc/basic_widgets/w/caption.hpp +++ b/inc/basic_widgets/w/caption.hpp @@ -24,13 +24,17 @@ namespace bwidgets inline static const Color default_color_fg = {0, 0, 0, SDL_ALPHA_OPAQUE}; inline static const Size default_margins = {3, 3}; + // How text is horizontally aligned on the rendering viewport. Alignment alignment {Alignment::LEFT}; Size margins {default_margins}; using Widget::Widget; + // Set used font rendering mode. virtual void render_mode(Font::RenderMode) = 0; + // Get caption text. [[nodiscard]] virtual auto text() const noexcept -> std::string_view = 0; + // Set caption text. virtual void text(std::string) = 0; }; } diff --git a/inc/basic_widgets/w/feat/event_handler.hpp b/inc/basic_widgets/w/feat/event_handler.hpp index be1add0..ef1d612 100644 --- a/inc/basic_widgets/w/feat/event_handler.hpp +++ b/inc/basic_widgets/w/feat/event_handler.hpp @@ -22,6 +22,7 @@ namespace bwidgets virtual ~EventHandler() = default; + // Pass an event to be handled. virtual void handle_event(const SDL_Event&) = 0; }; } diff --git a/inc/basic_widgets/w/feat/event_handler_impl.hpp b/inc/basic_widgets/w/feat/event_handler_impl.hpp index 2b09478..564d5f0 100644 --- a/inc/basic_widgets/w/feat/event_handler_impl.hpp +++ b/inc/basic_widgets/w/feat/event_handler_impl.hpp @@ -16,7 +16,13 @@ namespace bwidgets void handle_event(const SDL_Event&) override; protected: + // Add an handler for a given event type. There can be only one handler by + // event type. Return true if handler is added successfuly. Return false + // if handler cannot be added because there's already an handler for that + // event type. auto _add_event_handler(handler_t) -> bool; + // Remove the handler of a given event type. Return true with the removed + // handler on success, false otherwise. auto _remove_event_handler(SDL_EventType) -> std::pair; }; } diff --git a/inc/basic_widgets/w/feat/focus_handler.hpp b/inc/basic_widgets/w/feat/focus_handler.hpp index 0e6db8a..9996725 100644 --- a/inc/basic_widgets/w/feat/focus_handler.hpp +++ b/inc/basic_widgets/w/feat/focus_handler.hpp @@ -17,8 +17,11 @@ namespace bwidgets auto operator=(const FocusHandler&) = delete; virtual ~FocusHandler() = default; + // set focus state. virtual void focus(bool focus) = 0; + // get focus state. virtual bool focus() = 0; + // set an handler for focus states changes. virtual void focus_handler(std::function) = 0; }; } diff --git a/inc/basic_widgets/w/feat/font_handler.hpp b/inc/basic_widgets/w/feat/font_handler.hpp index df92301..66bdc95 100644 --- a/inc/basic_widgets/w/feat/font_handler.hpp +++ b/inc/basic_widgets/w/feat/font_handler.hpp @@ -19,8 +19,12 @@ namespace bwidgets auto operator=(FontHandler&&) = delete; virtual ~FontHandler() noexcept = default; + // Set the used font. virtual void font(std::shared_ptr f) = 0; + // Set font background color for shaded font rendering + // mode virtual void font_color_bg(Color c) = 0; + // Set font foreground (text) color. virtual void font_color_fg(Color c) = 0; }; } diff --git a/inc/basic_widgets/w/feat/font_handler_impl.hpp b/inc/basic_widgets/w/feat/font_handler_impl.hpp index e3254f1..aa8e783 100644 --- a/inc/basic_widgets/w/feat/font_handler_impl.hpp +++ b/inc/basic_widgets/w/feat/font_handler_impl.hpp @@ -44,7 +44,9 @@ namespace bwidgets Color _font_color_fg = default_font_color_fg; Font::RenderMode _font_render_mode {Font::RenderMode::SHADED}; + // Called on font changes. virtual void _handle_font_change(const std::shared_ptr&) = 0; + // Called on font color changes. virtual void _handle_font_color_change(Color, Color) = 0; }; } diff --git a/inc/basic_widgets/w/feat/keyboard_handler.hpp b/inc/basic_widgets/w/feat/keyboard_handler.hpp index cfdb6e0..413a363 100644 --- a/inc/basic_widgets/w/feat/keyboard_handler.hpp +++ b/inc/basic_widgets/w/feat/keyboard_handler.hpp @@ -16,9 +16,13 @@ namespace bwidgets using EventHandler::EventHandler; public: + // Disable keyboard event handling. virtual void disable_keyboard_handler() = 0; + // Enable keyboard event handling. virtual void enable_keyboard_handler() = 0; + // Set the handler for key press events. virtual void key_handler(std::function) = 0; + // Set the handler for text input events. virtual void text_input_handler(std::function) = 0; }; diff --git a/inc/basic_widgets/w/feat/mouse_handler.hpp b/inc/basic_widgets/w/feat/mouse_handler.hpp index 3f0ce6a..1328bd4 100644 --- a/inc/basic_widgets/w/feat/mouse_handler.hpp +++ b/inc/basic_widgets/w/feat/mouse_handler.hpp @@ -15,16 +15,21 @@ namespace bwidgets protected: using EventHandler::EventHandler; - virtual void _on_push(bool) = 0; - public: + // Set click handler. virtual void click_handler(std::function) = 0; + // Disable mouse event handling. virtual void disable_mouse_handler() = 0; + // Enable mouse event handling. virtual void enable_mouse_handler(const SDL_Rect&, const SDL_Rect&) = 0; + // Called on hover state changes. virtual void hover_handler(std::function) = 0; + // Get current hover state. [[nodiscard]] virtual bool hovered() const = 0; + // Set mouse motion handler. virtual void mouse_motion_handler(std::function) = 0; + // Get current push state (mouse button down) [[nodiscard]] virtual bool pushed() const = 0; }; } diff --git a/inc/basic_widgets/w/feat/mouse_handler_impl.hpp b/inc/basic_widgets/w/feat/mouse_handler_impl.hpp index 88aca2f..10e7fca 100644 --- a/inc/basic_widgets/w/feat/mouse_handler_impl.hpp +++ b/inc/basic_widgets/w/feat/mouse_handler_impl.hpp @@ -51,6 +51,7 @@ namespace bwidgets protected: using MouseHandler::MouseHandler; + // Called on push state changes. void _on_push(bool) override {} }; } diff --git a/inc/basic_widgets/w/feat/texture_handler.hpp b/inc/basic_widgets/w/feat/texture_handler.hpp index 5e28f06..fb8b385 100644 --- a/inc/basic_widgets/w/feat/texture_handler.hpp +++ b/inc/basic_widgets/w/feat/texture_handler.hpp @@ -11,6 +11,7 @@ namespace bwidgets class TextureHandler { protected: + // (Re)render textures. virtual void _handle_texture_update() = 0; public: diff --git a/inc/basic_widgets/w/numeric_input.hpp b/inc/basic_widgets/w/numeric_input.hpp index 15a9f03..654e1fa 100644 --- a/inc/basic_widgets/w/numeric_input.hpp +++ b/inc/basic_widgets/w/numeric_input.hpp @@ -10,12 +10,15 @@ namespace bwidgets class NumericInput : public virtual Input { public: + // Button increment/decrement step. T button_step = 1; using Input::Input; + // Get allowed value range. [[nodiscard]] virtual auto value_range() const noexcept -> const std::pair& = 0; + // Set allowed value range. virtual void value_range(T min, T max) = 0; }; } diff --git a/inc/basic_widgets/w/numeric_input_impl.hpp b/inc/basic_widgets/w/numeric_input_impl.hpp index 82fb3f6..2b52a72 100644 --- a/inc/basic_widgets/w/numeric_input_impl.hpp +++ b/inc/basic_widgets/w/numeric_input_impl.hpp @@ -23,15 +23,20 @@ namespace bwidgets Self::input_min_width = 10; // NOLINT(readability-magic-numbers) Self::input_width_unit = '0'; + // +/- buttons click handler. op is the function to apply on current value. const auto button_action = [this](const std::function op) { const T new_value = [this, &op]() { auto _new_value = op(this->value, NumericInput::button_step); if (_new_value < this->value) { + // if value - button_step is out of allowed range + // set value to the smallest allowed value. if (std::abs(_value_range.first - this->value) < std::abs(NumericInput::button_step)) return _value_range.first; return _new_value; } + // if value + button_step exceeds maximal allowed value + // set value to max allowed value. if (std::abs(_value_range.second - this->value) < std::abs(NumericInput::button_step)) return _value_range.second; @@ -67,11 +72,14 @@ namespace bwidgets -> bool override { bool valid = [input, this]() { + // Allow 0-9 chars. if (input[0] >= '0' && input[0] <= '9') return true; + // Allow one point for float types. if constexpr (std::is_floating_point_v) if (input[0] == '.' && Self::input_text().find('.') == std::string::npos) return true; + // Allow "-" at input string start for signed types. if constexpr (std::is_signed_v) { std::string_view displayed_value = Self::input_text(); if (input[0] == '-' && displayed_value.empty()) return true; @@ -83,6 +91,8 @@ namespace bwidgets [[nodiscard]] auto process_value(const T x) const noexcept -> T override { + // If value is out of allowed range return either min or max allowed + // value. T value = [x, this]() { if (x < _value_range.first) return _value_range.first; if (x > _value_range.second) return _value_range.second; diff --git a/src/core/draw.cpp b/src/core/draw.cpp index d3a7139..b747e39 100644 --- a/src/core/draw.cpp +++ b/src/core/draw.cpp @@ -63,6 +63,7 @@ namespace bwidgets std::vector pixels; pixels.reserve(attr.h * (std::vector::size_type)pitch); + // TODO parallel algo for (auto y = 0; y < attr.h; y++) { for (auto x = 0; x < attr.w; x++) { pixels.emplace_back(pixel_color({x, y}, *attr.format)); diff --git a/src/w/base/widget_impl.cpp b/src/w/base/widget_impl.cpp index 87e5df7..5b71e42 100644 --- a/src/w/base/widget_impl.cpp +++ b/src/w/base/widget_impl.cpp @@ -7,6 +7,7 @@ void WidgetImpl::render() if (!_renderer) return; #ifdef BWIDGETS_DEBUG + // Render a debug outline of widget viewport. _renderer ->draw_color({ // NOLINTNEXTLINE(readability-magic-numbers)