some comment edits, readme draft
This commit is contained in:
parent
d8f56e0e5f
commit
a54dc9c2b2
123
README.md
123
README.md
|
@ -1,4 +1,125 @@
|
||||||
# sdl2_basic_widgets
|
# sdl2_basic_widgets
|
||||||
|
|
||||||
A (very) basic widget library for SDL applications.
|
A (very) basic and incomplete widget library for SDL applications.
|
||||||
|
|
||||||
|
## Build
|
||||||
|
The build dependencies are SDL2, SDL_ttf and fontconfig dev libs
|
||||||
|
and headers. Meson is used as build system, so you'll need it too.
|
||||||
|
|
||||||
|
As the code use some C++20 features, you'll need a recent compiler
|
||||||
|
which support that version of the standard.
|
||||||
|
|
||||||
|
Then, inside the project root directory, run the following commands:
|
||||||
|
|
||||||
|
```ShellSession
|
||||||
|
$ meson build
|
||||||
|
$ meson compile -C build -j0
|
||||||
|
```
|
||||||
|
|
||||||
|
After that you'll have in the build directory the static library and the
|
||||||
|
example programs.
|
||||||
|
|
||||||
|
## API overview
|
||||||
|
|
||||||
|
The library API is divided in two main parts:
|
||||||
|
- the core, which provides some basic wrapping of
|
||||||
|
SDL, SDL_ttf and fontconfig functionalities.
|
||||||
|
- the widget API built on top of the core.
|
||||||
|
|
||||||
|
### Core
|
||||||
|
|
||||||
|
The main classes of the core are:
|
||||||
|
|
||||||
|
- [Font](inc/basic_widgets/core/font.hpp):
|
||||||
|
wraps TTF_Font object with the most common operations
|
||||||
|
of SDL_ttf. Also provide a helper function to
|
||||||
|
search system fonts by using fontconfig.
|
||||||
|
- [Renderer](inc/basic_widgets/core/renderer.hpp):
|
||||||
|
wraps SDL_Renderer object with common operation from
|
||||||
|
the SDL 2D accelerated rendering API.
|
||||||
|
- [Texture](inc/basic_widgets/core/texture.hpp):
|
||||||
|
wraps SDL_Texture object with common operations
|
||||||
|
to manipulate it.
|
||||||
|
|
||||||
|
Apart from the SDL API wrappers, some generic utility functions and
|
||||||
|
data types are defined:
|
||||||
|
|
||||||
|
- [Color](inc/basic_widgets/core/type/color.hpp):
|
||||||
|
wraps SDL_Color object and adds convenience operators
|
||||||
|
overloads to operate on all color channels and/or
|
||||||
|
alpha channel.
|
||||||
|
- [draw.hpp](inc/basic_widgets/core/draw.hpp):
|
||||||
|
2D drawing utilities. Currently, provides a couple of basic utility
|
||||||
|
functions for software rendered textures: circle rendering
|
||||||
|
and an antialising algorithm.
|
||||||
|
- [math.hpp](inc/basic_widgets/core/math.hpp): mostly provides
|
||||||
|
frequently used formulas to work with rectangles and points
|
||||||
|
on a 2D coordinate system.
|
||||||
|
- [concepts.hpp](inc/basic_widgets/core/type/concepts.hpp):
|
||||||
|
a few concept definitions for used for generic programming.
|
||||||
|
- [Size](inc/basic_widgets/core/type/size.hpp): representation
|
||||||
|
of a 2D size. There are also a few operator overloads to
|
||||||
|
operate on Size objects.
|
||||||
|
|
||||||
|
## Widgets
|
||||||
|
|
||||||
|
Widgets are classes that implements the common widget interface and
|
||||||
|
optionally one or more "handler" interfaces. Handlers are interfaces
|
||||||
|
for event or external resources handling.
|
||||||
|
|
||||||
|
These interfaces are:
|
||||||
|
|
||||||
|
- [Widget](inc/basic_widgets/w/base/widget.hpp): the common base
|
||||||
|
interface of every widget.
|
||||||
|
- [EventHandler](inc/basic_widgets/w/feat/event_handler.hpp): base
|
||||||
|
interface for event handlers.
|
||||||
|
- [FocusHandler](inc/basic_widgets/w/feat/focus_handler.hpp): base
|
||||||
|
interface for handler having a focus notion.
|
||||||
|
- [KeyboardHandler](inc/basic_widgets/w/feat/keyboard_handler.hpp):
|
||||||
|
interface for key and text input events handling.
|
||||||
|
- [MouseHandler](inc/basic_widgets/w/feat/mouse_handler.hpp):
|
||||||
|
interface for mouse events handling. Handle click and focus state
|
||||||
|
changes and also introduce a notion of "pushed" state.
|
||||||
|
- [FontHandler](inc/basic_widgets/w/feat/font_handler.hpp): interface
|
||||||
|
for widgets using a font. Declares methods to set the widget font and
|
||||||
|
set background and text color used for text rendering.
|
||||||
|
- [TextureHandler](inc/basic_widgets/w/feat/texture_handler.hpp): it exists
|
||||||
|
but I'm thinking now that it shouldn't.
|
||||||
|
|
||||||
|
Based on these interfaces, there's implementation for a few basic widgets.
|
||||||
|
Currently, the following ones are defined:
|
||||||
|
|
||||||
|
- [Button](inc/basic_widgets/w/button.hpp): a push button.
|
||||||
|
- [Caption](inc/basic_widgets/w/caption.hpp): a caption
|
||||||
|
that displays a rendered string. No multiline support.
|
||||||
|
- [Input<T>](inc/basic_widgets/w/base/input.hpp): base
|
||||||
|
class for widgets using an input field.
|
||||||
|
- [NumericInput<Numeric>](inc/basic_widgets/w/numeric_input.hpp) an
|
||||||
|
input widget for numeric values with two buttons to increase/decrease
|
||||||
|
the hold value.
|
||||||
|
|
||||||
|
There are also "containers" widgets which are widget that hold a collection of
|
||||||
|
widgets and manage their geometry:
|
||||||
|
|
||||||
|
- [Layout](inc/basic_widgets/w/base/layout.hpp): abstract class for container widgets.
|
||||||
|
- [AlignedLayout](inc/basic_widgets/w/aligned_layout.hpp): layout that is done by distributing
|
||||||
|
widgets on a horizontal or vertical row.
|
||||||
|
|
||||||
|
To create widget objects, the corresponding function from [widget_factory.hpp](inc/basic_widgets/w/widget_factory.hpp)
|
||||||
|
should be used. It's done this way for interface-implementation sake.
|
||||||
|
|
||||||
|
## Source code organization overview
|
||||||
|
|
||||||
|
The header and source directory hierarchies is organized in the following way:
|
||||||
|
|
||||||
|
- core: C→C++ wrappers and commonly used generic functions.
|
||||||
|
- core/type: basic data types and concepts.
|
||||||
|
- w: the widget library
|
||||||
|
- w/base: the abstract widget classes.
|
||||||
|
- w/feat: handlers (optional widget features)
|
||||||
|
|
||||||
|
Widget code intent to separate public API from implementation details. For that
|
||||||
|
a Widget has two classes, a pure virtual one (Widget) which is the public API and another
|
||||||
|
class (WidgetImpl) that implements the interface of the first one. Unless an access
|
||||||
|
to implementation details is required, the interface (pure virtual) type should
|
||||||
|
be used.
|
||||||
|
|
|
@ -13,12 +13,12 @@ namespace bwidgets
|
||||||
class Renderer;
|
class Renderer;
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
// Add transparency to color c relative to the distance d from
|
// Add transparency to color base_color relative to the distance d from
|
||||||
// a limit to produce an AntiAliasing effect.
|
// a limit to produce an AntiAliasing effect.
|
||||||
// d >= 0 → full transparency;
|
// d >= 0 → full transparency;
|
||||||
// −(aa_pixels) <= d < 0 → smoothsteped transparency gradient;
|
// −(aa_pixels) <= d < 0 → smoothsteped transparency gradient;
|
||||||
// d < −(aa_pixels) → fully opaque.
|
// d < −(aa_pixels) → fully opaque.
|
||||||
[[nodiscard]] auto aa(Color c, int aa_pixels, float d) noexcept -> Color;
|
[[nodiscard]] auto aa(Color base_color, int aa_pixels, float d) noexcept -> Color;
|
||||||
// Render a filled circle texture of color c and diameter resolution with
|
// Render a filled circle texture of color c and diameter resolution with
|
||||||
// aa_pixels used for antialiasing.
|
// aa_pixels used for antialiasing.
|
||||||
[[nodiscard]] auto filled_circle(Color c, int resolution, const Renderer&,
|
[[nodiscard]] auto filled_circle(Color c, int resolution, const Renderer&,
|
||||||
|
|
|
@ -55,6 +55,7 @@ namespace bwidgets
|
||||||
const std::string style_name;
|
const std::string style_name;
|
||||||
|
|
||||||
explicit Font(TTF_Font*);
|
explicit Font(TTF_Font*);
|
||||||
|
// Load font at given path and with given size.
|
||||||
Font(std::string_view, int);
|
Font(std::string_view, int);
|
||||||
Font(const Font&) = delete;
|
Font(const Font&) = delete;
|
||||||
Font(Font&&) = delete;
|
Font(Font&&) = delete;
|
||||||
|
|
|
@ -16,6 +16,7 @@ namespace bwidgets
|
||||||
public:
|
public:
|
||||||
using LayoutImpl::LayoutImpl;
|
using LayoutImpl::LayoutImpl;
|
||||||
|
|
||||||
|
// Return smallest usable size.
|
||||||
[[nodiscard]] auto size() const noexcept -> Size override
|
[[nodiscard]] auto size() const noexcept -> Size override
|
||||||
{
|
{
|
||||||
Size min_size {0, 0};
|
Size min_size {0, 0};
|
||||||
|
@ -31,6 +32,7 @@ namespace bwidgets
|
||||||
min_size.h + 2 * margins.h};
|
min_size.h + 2 * margins.h};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Vertical
|
||||||
for (const auto& w : _widgets) {
|
for (const auto& w : _widgets) {
|
||||||
if (w->size().w > min_size.w) min_size.w = w->size().w;
|
if (w->size().w > min_size.w) min_size.w = w->size().w;
|
||||||
|
|
||||||
|
@ -55,7 +57,7 @@ namespace bwidgets
|
||||||
w->size().h});
|
w->size().h});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else { // Vertical
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
for (std::vector<Widget*>::size_type i = 0; i < _widgets.size(); i++) {
|
for (std::vector<Widget*>::size_type i = 0; i < _widgets.size(); i++) {
|
||||||
const auto& w {_widgets[i]};
|
const auto& w {_widgets[i]};
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace bwidgets
|
||||||
Color color_bg_focused = default_color_bg_focused;
|
Color color_bg_focused = default_color_bg_focused;
|
||||||
int float_precision = default_float_precision;
|
int float_precision = default_float_precision;
|
||||||
int input_min_width = default_min_width;
|
int input_min_width = default_min_width;
|
||||||
char input_width_unit = 'W';
|
char input_width_unit = 'W'; // char used as unit for text length computation.
|
||||||
T value {};
|
T value {};
|
||||||
|
|
||||||
// Get the current displayed string.
|
// Get the current displayed string.
|
||||||
|
@ -40,8 +40,8 @@ namespace bwidgets
|
||||||
// Set displayed string
|
// Set displayed string
|
||||||
virtual void input_text(std::string) = 0;
|
virtual void input_text(std::string) = 0;
|
||||||
virtual void input_text_color(Color) = 0;
|
virtual void input_text_color(Color) = 0;
|
||||||
// Check if a character is allowed to be inputed. String is used because we could
|
// Check if a character is allowed to be inputted. String are used because we
|
||||||
// have multibytes characters to represent using 8bits chars.
|
// could have multibytes characters to represent using 8bits chars.
|
||||||
[[nodiscard]] virtual auto is_valid_input(std::string_view) const noexcept
|
[[nodiscard]] virtual auto is_valid_input(std::string_view) const noexcept
|
||||||
-> bool = 0;
|
-> bool = 0;
|
||||||
|
|
||||||
|
|
|
@ -120,6 +120,8 @@ namespace bwidgets
|
||||||
InputImpl(Widget* parent = nullptr)
|
InputImpl(Widget* parent = nullptr)
|
||||||
: WidgetImpl {parent}, _input_caption {create_caption(this)}
|
: WidgetImpl {parent}, _input_caption {create_caption(this)}
|
||||||
{
|
{
|
||||||
|
// Start text input on focus. Stop it on focus loss and save the inputted
|
||||||
|
// value.
|
||||||
focus_handler([this](const bool focus) {
|
focus_handler([this](const bool focus) {
|
||||||
if (focus) {
|
if (focus) {
|
||||||
_input_caption->font_color_bg(InputImpl::color_bg_focused);
|
_input_caption->font_color_bg(InputImpl::color_bg_focused);
|
||||||
|
@ -137,6 +139,7 @@ namespace bwidgets
|
||||||
key_handler([this](const SDL_KeyboardEvent& key) {
|
key_handler([this](const SDL_KeyboardEvent& key) {
|
||||||
if (key.type == SDL_KEYDOWN) {
|
if (key.type == SDL_KEYDOWN) {
|
||||||
switch (key.keysym.sym) {
|
switch (key.keysym.sym) {
|
||||||
|
// Discard inputted value on escape key.
|
||||||
case SDLK_ESCAPE: {
|
case SDLK_ESCAPE: {
|
||||||
focus(false);
|
focus(false);
|
||||||
input_text(value_to_string(InputImpl::value));
|
input_text(value_to_string(InputImpl::value));
|
||||||
|
@ -149,6 +152,7 @@ namespace bwidgets
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// Save inputted value and unfocus the widget on enter key.
|
||||||
case SDLK_RETURN:
|
case SDLK_RETURN:
|
||||||
case SDLK_RETURN2: // what is return2 btw?
|
case SDLK_RETURN2: // what is return2 btw?
|
||||||
case SDLK_KP_ENTER:
|
case SDLK_KP_ENTER:
|
||||||
|
@ -158,6 +162,9 @@ namespace bwidgets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// Just keep the string representation of input in the input field caption
|
||||||
|
// text but don't save the parsed value until some other event
|
||||||
|
// (Esc/Enter/focus loss)
|
||||||
text_input_handler([this](const SDL_TextInputEvent& input) {
|
text_input_handler([this](const SDL_TextInputEvent& input) {
|
||||||
if (is_valid_input(input.text)) {
|
if (is_valid_input(input.text)) {
|
||||||
input_text(std::string(input_text()) + input.text);
|
input_text(std::string(input_text()) + input.text);
|
||||||
|
@ -165,6 +172,7 @@ namespace bwidgets
|
||||||
});
|
});
|
||||||
enable_keyboard_handler();
|
enable_keyboard_handler();
|
||||||
|
|
||||||
|
// Highlight input field on mouse hover.
|
||||||
hover_handler([this](const bool _hover) {
|
hover_handler([this](const bool _hover) {
|
||||||
if (_hover) _input_caption->font_color_bg(InputImpl::color_bg_focused);
|
if (_hover) _input_caption->font_color_bg(InputImpl::color_bg_focused);
|
||||||
else _input_caption->font_color_bg(InputImpl::color_bg_default);
|
else _input_caption->font_color_bg(InputImpl::color_bg_default);
|
||||||
|
|
|
@ -17,6 +17,7 @@ namespace bwidgets
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Parent widget for bidirectional message passing between widgets.
|
// Parent widget for bidirectional message passing between widgets.
|
||||||
|
// Currently not used by this lib.
|
||||||
Widget* parent;
|
Widget* parent;
|
||||||
|
|
||||||
explicit Widget(Widget* p = nullptr) noexcept : parent {p} {}
|
explicit Widget(Widget* p = nullptr) noexcept : parent {p} {}
|
||||||
|
@ -27,7 +28,7 @@ namespace bwidgets
|
||||||
virtual void renderer(std::shared_ptr<Renderer>) = 0;
|
virtual void renderer(std::shared_ptr<Renderer>) = 0;
|
||||||
// Get prefered or minimal widget size.
|
// Get prefered or minimal widget size.
|
||||||
[[nodiscard]] virtual auto size() const noexcept -> Size = 0;
|
[[nodiscard]] virtual auto size() const noexcept -> Size = 0;
|
||||||
// Set the viewport delimiting the widget rendering area and origin
|
// Set the viewport delimiting the widget rendering area and the origin
|
||||||
// for relative coordinates.
|
// for relative coordinates.
|
||||||
virtual void viewport(const SDL_Rect&) = 0;
|
virtual void viewport(const SDL_Rect&) = 0;
|
||||||
// Get current viewport.
|
// Get current viewport.
|
||||||
|
|
|
@ -17,6 +17,7 @@ namespace bwidgets
|
||||||
public:
|
public:
|
||||||
ButtonImpl(Widget* parent = nullptr) noexcept;
|
ButtonImpl(Widget* parent = nullptr) noexcept;
|
||||||
|
|
||||||
|
// Smallest valid button size.
|
||||||
[[nodiscard]] auto size() const noexcept -> Size override;
|
[[nodiscard]] auto size() const noexcept -> Size override;
|
||||||
[[nodiscard]] auto text() const noexcept -> std::string_view override;
|
[[nodiscard]] auto text() const noexcept -> std::string_view override;
|
||||||
void text(std::string) override;
|
void text(std::string) override;
|
||||||
|
|
|
@ -24,13 +24,13 @@ namespace bwidgets
|
||||||
inline static const Color default_color_fg = {0, 0, 0, SDL_ALPHA_OPAQUE};
|
inline static const Color default_color_fg = {0, 0, 0, SDL_ALPHA_OPAQUE};
|
||||||
inline static const Size default_margins = {3, 3};
|
inline static const Size default_margins = {3, 3};
|
||||||
|
|
||||||
// How text is horizontally aligned on the rendering viewport.
|
// Text horizontal alignment on the caption viewport.
|
||||||
Alignment alignment {Alignment::LEFT};
|
Alignment alignment {Alignment::LEFT};
|
||||||
Size margins {default_margins};
|
Size margins {default_margins};
|
||||||
|
|
||||||
using Widget::Widget;
|
using Widget::Widget;
|
||||||
|
|
||||||
// Set used font rendering mode.
|
// Set caption text rendering mode.
|
||||||
virtual void render_mode(Font::RenderMode) = 0;
|
virtual void render_mode(Font::RenderMode) = 0;
|
||||||
// Get caption text.
|
// Get caption text.
|
||||||
[[nodiscard]] virtual auto text() const noexcept -> std::string_view = 0;
|
[[nodiscard]] virtual auto text() const noexcept -> std::string_view = 0;
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace bwidgets
|
||||||
|
|
||||||
virtual ~EventHandler() = default;
|
virtual ~EventHandler() = default;
|
||||||
|
|
||||||
// Pass an event to be handled.
|
// Pass the event to be handled.
|
||||||
virtual void handle_event(const SDL_Event&) = 0;
|
virtual void handle_event(const SDL_Event&) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,10 +20,10 @@ namespace bwidgets
|
||||||
|
|
||||||
// Set the used font.
|
// Set the used font.
|
||||||
virtual void font(std::shared_ptr<Font> f) = 0;
|
virtual void font(std::shared_ptr<Font> f) = 0;
|
||||||
// Set font background color for shaded font rendering
|
// Set background color used for shaded text rendering
|
||||||
// mode
|
// mode.
|
||||||
virtual void font_color_bg(Color c) = 0;
|
virtual void font_color_bg(Color c) = 0;
|
||||||
// Set font foreground (text) color.
|
// Set foreground (glyphs) color.
|
||||||
virtual void font_color_fg(Color c) = 0;
|
virtual void font_color_fg(Color c) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -23,7 +23,8 @@ namespace bwidgets
|
||||||
Self::input_min_width = 10; // NOLINT(readability-magic-numbers)
|
Self::input_min_width = 10; // NOLINT(readability-magic-numbers)
|
||||||
Self::input_width_unit = '0';
|
Self::input_width_unit = '0';
|
||||||
|
|
||||||
// +/- buttons click handler. op is the function to apply on current value.
|
// +/- buttons click handler. op is the operation (+/-) to apply on current
|
||||||
|
// value.
|
||||||
const auto button_action = [this](const std::function<T(T, T)> op) {
|
const auto button_action = [this](const std::function<T(T, T)> op) {
|
||||||
const T new_value = [this, &op]() {
|
const T new_value = [this, &op]() {
|
||||||
auto _new_value = op(this->value, NumericInput<T>::button_step);
|
auto _new_value = op(this->value, NumericInput<T>::button_step);
|
||||||
|
@ -79,7 +80,7 @@ namespace bwidgets
|
||||||
if (input[0] == '.'
|
if (input[0] == '.'
|
||||||
&& Self::input_text().find('.') == std::string::npos)
|
&& Self::input_text().find('.') == std::string::npos)
|
||||||
return true;
|
return true;
|
||||||
// Allow "-" at input string start for signed types.
|
// Allow "-" as first input char for signed types.
|
||||||
if constexpr (std::is_signed_v<T>) {
|
if constexpr (std::is_signed_v<T>) {
|
||||||
std::string_view displayed_value = Self::input_text();
|
std::string_view displayed_value = Self::input_text();
|
||||||
if (input[0] == '-' && displayed_value.empty()) return true;
|
if (input[0] == '-' && displayed_value.empty()) return true;
|
||||||
|
|
|
@ -9,7 +9,7 @@ project('sdl2_basic_widgets', 'cpp',
|
||||||
],
|
],
|
||||||
license: 'EUPL-1.2')
|
license: 'EUPL-1.2')
|
||||||
|
|
||||||
add_project_arguments('-pedantic', language: 'cpp')
|
add_project_arguments('-Wconversion', '-pedantic', language: 'cpp')
|
||||||
|
|
||||||
if (get_option('buildtype').startswith('debug'))
|
if (get_option('buildtype').startswith('debug'))
|
||||||
add_project_arguments('-DBWIDGETS_DEBUG', language: 'cpp')
|
add_project_arguments('-DBWIDGETS_DEBUG', language: 'cpp')
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace bwidgets
|
||||||
{
|
{
|
||||||
Color c = [aa_pixels, base_color, d]() -> Color {
|
Color c = [aa_pixels, base_color, d]() -> Color {
|
||||||
const auto [r, g, b, a] = base_color();
|
const auto [r, g, b, a] = base_color();
|
||||||
|
// AA disabled, returns fully opaque or fully transparent colors
|
||||||
if (aa_pixels == 0) {
|
if (aa_pixels == 0) {
|
||||||
if (d > 0) return {r, g, b, 0};
|
if (d > 0) return {r, g, b, 0};
|
||||||
return {r, g, b, a};
|
return {r, g, b, a};
|
||||||
|
|
|
@ -75,6 +75,7 @@ void ButtonImpl::_handle_rendering()
|
||||||
border_size.w > border_size.h ? border_size.w : border_size.h;
|
border_size.w > border_size.h ? border_size.w : border_size.h;
|
||||||
const auto& max_xy = border_size.w > border_size.h ? x : y;
|
const auto& max_xy = border_size.w > border_size.h ? x : y;
|
||||||
|
|
||||||
|
// Render button borders.
|
||||||
while (x < border_size.w || y < border_size.h) {
|
while (x < border_size.w || y < border_size.h) {
|
||||||
_renderer->draw_color(border_gradient(biggest_dimension, max_xy, divider))
|
_renderer->draw_color(border_gradient(biggest_dimension, max_xy, divider))
|
||||||
->draw_rect(rect_margin(_widget_area, {x, y}));
|
->draw_rect(rect_margin(_widget_area, {x, y}));
|
||||||
|
@ -89,6 +90,7 @@ void ButtonImpl::_handle_rendering()
|
||||||
|
|
||||||
void ButtonImpl::_on_push(const bool state)
|
void ButtonImpl::_on_push(const bool state)
|
||||||
{
|
{
|
||||||
|
// Move slightly the caption position to give a push effect.
|
||||||
const auto offset = [state, this]() -> SDL_Point {
|
const auto offset = [state, this]() -> SDL_Point {
|
||||||
if (state) {
|
if (state) {
|
||||||
return {_viewport.x + 1, _viewport.y + 1};
|
return {_viewport.x + 1, _viewport.y + 1};
|
||||||
|
|
|
@ -77,6 +77,8 @@ void CaptionImpl::_handle_rendering()
|
||||||
{
|
{
|
||||||
if (!_text_texture) _handle_texture_update();
|
if (!_text_texture) _handle_texture_update();
|
||||||
|
|
||||||
|
// fill caption viewport with background color when using
|
||||||
|
// shaded text rendering mode.
|
||||||
if (_render_mode == Font::RenderMode::SHADED) {
|
if (_render_mode == Font::RenderMode::SHADED) {
|
||||||
_renderer->draw_color(_font_color_bg)
|
_renderer->draw_color(_font_color_bg)
|
||||||
->fill_rect({0, 0, _viewport.w, _viewport.h});
|
->fill_rect({0, 0, _viewport.w, _viewport.h});
|
||||||
|
|
|
@ -29,6 +29,8 @@ void MouseHandlerImpl::enable_mouse_handler(const SDL_Rect& rel_area,
|
||||||
_add_event_handler({SDL_MOUSEBUTTONUP, [this, mouse_in_rect](const SDL_Event& ev) {
|
_add_event_handler({SDL_MOUSEBUTTONUP, [this, mouse_in_rect](const SDL_Event& ev) {
|
||||||
if (_pushed) {
|
if (_pushed) {
|
||||||
_on_push(_pushed = false);
|
_on_push(_pushed = false);
|
||||||
|
// Only execute handler and give focus if mouse button
|
||||||
|
// has been pushed and released over the widget.
|
||||||
if (mouse_in_rect({ev.button.x, ev.button.y})) {
|
if (mouse_in_rect({ev.button.x, ev.button.y})) {
|
||||||
focus(true);
|
focus(true);
|
||||||
_click_handler(ev.button);
|
_click_handler(ev.button);
|
||||||
|
|
Loading…
Reference in a new issue