more wip on api rewrites
This commit is contained in:
parent
a36fe9cae5
commit
860b656bf7
|
@ -6,8 +6,8 @@ auto main() -> int
|
|||
{
|
||||
run_example<bwidgets::Caption>([]() { return bwidgets::create_caption(); },
|
||||
[](auto w, auto f, auto, auto) {
|
||||
w->alignment =
|
||||
bwidgets::Caption::Alignment::CENTER;
|
||||
w->alignment(
|
||||
bwidgets::Caption::Alignment::CENTER);
|
||||
w->text("¡jello!");
|
||||
w->font(f);
|
||||
},
|
||||
|
|
|
@ -14,9 +14,11 @@ using bwidgets::WidgetImpl;
|
|||
|
||||
class Example final : public WidgetImpl
|
||||
{
|
||||
SDL_Rect _widget_area {};
|
||||
|
||||
void _handle_geometry_change(const SDL_Rect& vp) noexcept override
|
||||
{
|
||||
_widget_area = {2, 2, vp.w - 4, vp.h - 4};
|
||||
_widget_area = {0, 0, vp.w, vp.h};
|
||||
}
|
||||
|
||||
void _handle_rendering() override
|
||||
|
@ -32,14 +34,15 @@ class Example final : public WidgetImpl
|
|||
const int border = 10;
|
||||
for (auto i = 0; i < border; i += 3) {
|
||||
uint8_t alpha = 255 * i / border; // NOLINT(readability-magic-numbers)
|
||||
_renderer
|
||||
renderer()
|
||||
->draw_color({
|
||||
{base_color().r, base_color().g, base_color().b, alpha}
|
||||
})
|
||||
->draw_rect(rect_margin(_widget_area, {i, i}));
|
||||
}
|
||||
|
||||
_renderer->draw_color(base_color)
|
||||
renderer()
|
||||
->draw_color(base_color)
|
||||
->draw_rect(nullptr)
|
||||
->fill_rect(rect_margin(_widget_area, {border * 2, border * 2}));
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ void run_example(
|
|||
const bwidgets::Size size_init {854, 480};
|
||||
auto font =
|
||||
std::make_shared<bwidgets::Font>(bwidgets::Font::find("Monospace"),
|
||||
16); // NOLINT(readability-magic-numbers)
|
||||
18); // NOLINT(readability-magic-numbers)
|
||||
|
||||
auto win = std::unique_ptr<SDL_Window, bwidgets::Deleter>(
|
||||
bwidgets::ptr_or_throw<bwidgets::SDLError>(SDL_CreateWindow(
|
||||
|
|
|
@ -5,18 +5,9 @@
|
|||
|
||||
namespace bwidgets
|
||||
{
|
||||
enum struct LayoutAlignment
|
||||
{
|
||||
HORIZONTAL,
|
||||
VERTICAL
|
||||
};
|
||||
|
||||
// Align vertically or horizontally widgets.
|
||||
class AlignedLayout : public virtual Layout
|
||||
{
|
||||
public:
|
||||
using Layout::Layout;
|
||||
};
|
||||
{};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -8,6 +8,12 @@
|
|||
|
||||
namespace bwidgets
|
||||
{
|
||||
enum struct LayoutAlignment
|
||||
{
|
||||
HORIZONTAL,
|
||||
VERTICAL
|
||||
};
|
||||
|
||||
template<LayoutAlignment alignment>
|
||||
class AlignedLayoutImpl final : public virtual AlignedLayout,
|
||||
public virtual LayoutImpl,
|
||||
|
@ -16,6 +22,18 @@ namespace bwidgets
|
|||
public:
|
||||
using LayoutImpl::LayoutImpl;
|
||||
|
||||
void add_widget(std::unique_ptr<Widget> widget_ptr) override
|
||||
{
|
||||
if (renderer()) widget_ptr->renderer(renderer());
|
||||
_widgets.emplace_back(std::move(widget_ptr));
|
||||
_handle_geometry_change(viewport());
|
||||
}
|
||||
|
||||
void for_widgets(const std::function<void(Widget*)>& f)
|
||||
{
|
||||
for (const auto& w : _widgets) f(w.get());
|
||||
}
|
||||
|
||||
// Return smallest usable size.
|
||||
[[nodiscard]] auto size() const noexcept -> Size override
|
||||
{
|
||||
|
@ -28,8 +46,8 @@ namespace bwidgets
|
|||
}
|
||||
|
||||
return {(int)_widgets.size() * min_size.w
|
||||
+ ((int)_widgets.size() + 1) * margins.w,
|
||||
min_size.h + 2 * margins.h};
|
||||
+ ((int)_widgets.size() + 1) * theme()->size_layout_margin().w,
|
||||
min_size.h + 2 * theme()->size_layout_margin().h};
|
||||
}
|
||||
|
||||
// Vertical
|
||||
|
@ -39,22 +57,28 @@ namespace bwidgets
|
|||
min_size.h += w->size().h;
|
||||
}
|
||||
|
||||
return {min_size.w + 2 * margins.w,
|
||||
min_size.h + ((int)_widgets.size() + 1) * margins.h};
|
||||
return {min_size.w + 2 * theme()->size_layout_margin().w,
|
||||
min_size.h
|
||||
+ ((int)_widgets.size() + 1) * theme()->size_layout_margin().h};
|
||||
}
|
||||
|
||||
private:
|
||||
void _update_layout(const SDL_Rect& vp) override
|
||||
std::vector<std::unique_ptr<Widget>> _widgets;
|
||||
|
||||
void _handle_geometry_change(const SDL_Rect& vp) override
|
||||
{
|
||||
if constexpr (alignment == LayoutAlignment::HORIZONTAL) {
|
||||
const int widget_width =
|
||||
(vp.w - ((int)_widgets.size() + 1) * margins.w) / (int)_widgets.size();
|
||||
(vp.w - ((int)_widgets.size() + 1) * theme()->size_layout_margin().w)
|
||||
/ (int)_widgets.size();
|
||||
|
||||
for (std::vector<Widget*>::size_type i = 0; i < _widgets.size(); i++) {
|
||||
const auto& w {_widgets[i]};
|
||||
w->viewport({vp.x + margins.w + (int)i * (widget_width + margins.w),
|
||||
vp.y + center_line(vp.h, w->size().h), widget_width,
|
||||
w->size().h});
|
||||
w->viewport(
|
||||
{vp.x + theme()->size_layout_margin().w
|
||||
+ (int)i * (widget_width + theme()->size_layout_margin().w),
|
||||
vp.y + center_line(vp.h, w->size().h), widget_width,
|
||||
w->size().h});
|
||||
}
|
||||
}
|
||||
else { // Vertical
|
||||
|
@ -63,7 +87,7 @@ namespace bwidgets
|
|||
const auto& w {_widgets[i]};
|
||||
w->viewport({
|
||||
vp.x,
|
||||
vp.y + ((int)i + 1) * margins.h + offset,
|
||||
vp.y + ((int)i + 1) * theme()->size_layout_margin().h + offset,
|
||||
vp.w,
|
||||
w->size().h,
|
||||
});
|
||||
|
|
|
@ -117,6 +117,7 @@ namespace bwidgets
|
|||
|
||||
protected:
|
||||
std::unique_ptr<Caption> _input_caption;
|
||||
SDL_Rect _text_area {};
|
||||
|
||||
InputImpl(Widget* parent = nullptr)
|
||||
: WidgetImpl {parent}, _input_caption {create_caption(this)}
|
||||
|
@ -180,7 +181,7 @@ namespace bwidgets
|
|||
else if (!focus())
|
||||
_input_caption->font_color_bg(theme()->color_input_bg());
|
||||
});
|
||||
enable_mouse_handler(_widget_area, _viewport);
|
||||
enable_mouse_handler(_text_area, viewport());
|
||||
|
||||
_input_caption->font_color_bg(theme()->color_input_bg());
|
||||
}
|
||||
|
@ -188,7 +189,7 @@ namespace bwidgets
|
|||
void _handle_font_change(const std::shared_ptr<Font>& f) override
|
||||
{
|
||||
_input_caption->font(f);
|
||||
_handle_geometry_change(_viewport);
|
||||
_handle_geometry_change(viewport());
|
||||
}
|
||||
|
||||
void _handle_font_color_change(const Color fg, const Color bg) override
|
||||
|
@ -201,11 +202,11 @@ namespace bwidgets
|
|||
{
|
||||
const auto input_h =
|
||||
_input_caption->size().h + 2 * theme()->size_widget_border();
|
||||
_widget_area = {0, center_line(vp.h, input_h), vp.w, input_h};
|
||||
_text_area = {0, center_line(vp.h, input_h), vp.w, input_h};
|
||||
|
||||
_input_caption->viewport(
|
||||
rect_offset({rect_margin(_widget_area, {theme()->size_widget_border(),
|
||||
theme()->size_widget_border()})},
|
||||
rect_offset({rect_margin(_text_area, {theme()->size_widget_border(),
|
||||
theme()->size_widget_border()})},
|
||||
vp));
|
||||
}
|
||||
|
||||
|
@ -219,7 +220,7 @@ namespace bwidgets
|
|||
const auto& color_end =
|
||||
focus() ? theme()->color_input_bg_active() : theme()->color_input_bg();
|
||||
|
||||
fill_rect_gradient(*_renderer, _widget_area, theme()->color_widget_border(),
|
||||
fill_rect_gradient(*renderer(), _text_area, theme()->color_widget_border(),
|
||||
color_end, theme()->size_widget_border());
|
||||
_input_caption->render();
|
||||
}
|
||||
|
|
|
@ -12,11 +12,6 @@ namespace bwidgets
|
|||
using Widget::Widget;
|
||||
|
||||
public:
|
||||
static inline const Size default_margins {8, 8};
|
||||
|
||||
// Margins between layout widgets.
|
||||
Size margins = default_margins;
|
||||
|
||||
// Add widget to the layout
|
||||
virtual void add_widget(std::unique_ptr<Widget>) = 0;
|
||||
// Apply a function to every layout widget.
|
||||
|
|
|
@ -19,19 +19,15 @@ namespace bwidgets
|
|||
public:
|
||||
using WidgetImpl::WidgetImpl;
|
||||
|
||||
void add_widget(std::unique_ptr<Widget>) override;
|
||||
void for_widgets(const std::function<void(Widget*)>&) override;
|
||||
// TODO: remove widget
|
||||
void handle_event(const SDL_Event&) override;
|
||||
|
||||
protected:
|
||||
std::vector<std::unique_ptr<Widget>> _widgets;
|
||||
|
||||
void _handle_geometry_change(const SDL_Rect&) override;
|
||||
void _handle_renderer_change(const std::shared_ptr<Renderer>&) override;
|
||||
void _handle_rendering() override;
|
||||
|
||||
// Compute and set widget geometry.
|
||||
virtual void _update_layout(const SDL_Rect&) = 0;
|
||||
void _handle_theme_change(const std::shared_ptr<Theme>&) override;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -20,8 +20,9 @@ namespace bwidgets
|
|||
[[nodiscard]] virtual auto color_widget_bg_hl() const -> const Color& = 0;
|
||||
[[nodiscard]] virtual auto color_widget_border() const -> const Color& = 0;
|
||||
[[nodiscard]] virtual auto color_widget_border_pushed() const
|
||||
-> const Color& = 0;
|
||||
[[nodiscard]] virtual auto size_widget_border() const -> int = 0;
|
||||
-> const Color& = 0;
|
||||
[[nodiscard]] virtual auto size_layout_margin() const -> const Size& = 0;
|
||||
[[nodiscard]] virtual auto size_widget_border() const -> int = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -17,17 +17,15 @@ namespace bwidgets
|
|||
class Widget : public virtual EventHandler
|
||||
{
|
||||
public:
|
||||
// Parent widget for bidirectional message passing between widgets.
|
||||
// Currently not used by this lib.
|
||||
Widget* parent;
|
||||
|
||||
explicit Widget(Widget* p = nullptr) : parent {p} {}
|
||||
|
||||
explicit Widget(Widget* p = nullptr) {};
|
||||
[[nodiscard]] virtual auto parent() -> Widget* = 0;
|
||||
virtual void parent(Widget*) = 0;
|
||||
// Render widget on current renderer target.
|
||||
virtual void render() = 0;
|
||||
[[nodiscard]] virtual auto renderer() -> const std::shared_ptr<Renderer>& = 0;
|
||||
// Set widget renderer.
|
||||
virtual void renderer(std::shared_ptr<Renderer>) = 0;
|
||||
// Get prefered or minimal widget size.
|
||||
// Get prefered or minimal widget size. TODO: change that.
|
||||
[[nodiscard]] virtual auto size() const noexcept -> Size = 0;
|
||||
[[nodiscard]] virtual auto theme() const -> const std::shared_ptr<Theme>& = 0;
|
||||
virtual void theme(std::shared_ptr<Theme>) = 0;
|
||||
|
|
|
@ -12,7 +12,10 @@ namespace bwidgets
|
|||
public:
|
||||
WidgetImpl(Widget* p = nullptr);
|
||||
|
||||
[[nodiscard]] auto parent() -> Widget* override;
|
||||
void parent(Widget*) override;
|
||||
void render() override;
|
||||
[[nodiscard]] auto renderer() -> const std::shared_ptr<Renderer>& override;
|
||||
void renderer(std::shared_ptr<Renderer>) override;
|
||||
[[nodiscard]] auto theme() const -> const std::shared_ptr<Theme>& override;
|
||||
void theme(std::shared_ptr<Theme>) override;
|
||||
|
@ -20,11 +23,6 @@ namespace bwidgets
|
|||
[[nodiscard]] auto viewport() const -> const SDL_Rect& override;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<Renderer> _renderer;
|
||||
SDL_Rect _viewport {0, 0, 0, 0};
|
||||
// Area actually used by the widget.
|
||||
SDL_Rect _widget_area {0, 0, 0, 0};
|
||||
|
||||
// Called on viewport change.
|
||||
virtual void _handle_geometry_change(const SDL_Rect&) = 0;
|
||||
// Called on renderer change.
|
||||
|
@ -34,7 +32,10 @@ namespace bwidgets
|
|||
virtual void _handle_theme_change(const std::shared_ptr<Theme>&) {} // = 0;
|
||||
|
||||
private:
|
||||
std::shared_ptr<Theme> _theme;
|
||||
Widget* _parent;
|
||||
std::shared_ptr<Renderer> _renderer;
|
||||
std::shared_ptr<Theme> _theme;
|
||||
SDL_Rect _viewport {0, 0, 0, 0};
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -25,9 +25,7 @@ namespace bwidgets
|
|||
protected:
|
||||
std::unique_ptr<Caption> _caption;
|
||||
SDL_Rect _caption_area {};
|
||||
Color _color_bg;
|
||||
Color _color_bg_hl;
|
||||
Color _color_border;
|
||||
SDL_Rect _mouse_area;
|
||||
|
||||
void _handle_font_change(const std::shared_ptr<Font>&) override;
|
||||
void _handle_font_color_change(Color, Color) override;
|
||||
|
|
|
@ -20,14 +20,10 @@ namespace bwidgets
|
|||
LEFT,
|
||||
RIGHT
|
||||
};
|
||||
inline static const Size default_margins = {3, 3};
|
||||
|
||||
// Text horizontal alignment on the caption viewport.
|
||||
Alignment alignment {Alignment::LEFT};
|
||||
Size margins {default_margins};
|
||||
|
||||
using Widget::Widget;
|
||||
|
||||
[[nodiscard]] virtual auto alignment() const -> Alignment = 0;
|
||||
virtual void alignment(Alignment) = 0;
|
||||
// Set caption text rendering mode.
|
||||
virtual void render_mode(Font::RenderMode) = 0;
|
||||
// Get caption text.
|
||||
|
|
|
@ -14,14 +14,18 @@ namespace bwidgets
|
|||
public:
|
||||
CaptionImpl(Widget* p = nullptr) noexcept;
|
||||
|
||||
[[nodiscard]] auto alignment() const -> Alignment override;
|
||||
void alignment(Alignment) override;
|
||||
void render_mode(Font::RenderMode) override;
|
||||
[[nodiscard]] auto size() const noexcept -> Size override;
|
||||
[[nodiscard]] auto text() const noexcept -> std::string_view override;
|
||||
void text(std::string) override;
|
||||
|
||||
protected:
|
||||
Alignment _alignment;
|
||||
Font::RenderMode _render_mode {Font::RenderMode::SHADED};
|
||||
std::string _text;
|
||||
SDL_Rect _text_area;
|
||||
std::shared_ptr<Texture> _text_texture {nullptr};
|
||||
|
||||
void _handle_font_change(const std::shared_ptr<Font>&) override;
|
||||
|
|
|
@ -19,6 +19,7 @@ namespace bwidgets
|
|||
[[nodiscard]] auto color_widget_bg_hl() const -> const Color& override;
|
||||
[[nodiscard]] auto color_widget_border() const -> const Color& override;
|
||||
[[nodiscard]] auto color_widget_border_pushed() const -> const Color& override;
|
||||
[[nodiscard]] auto size_layout_margin() const -> const Size& override;
|
||||
[[nodiscard]] auto size_widget_border() const -> int override;
|
||||
|
||||
private:
|
||||
|
@ -31,6 +32,7 @@ namespace bwidgets
|
|||
static const Color _color_widget_bg_hl;
|
||||
static const Color _color_widget_border;
|
||||
static const Color _color_widget_border_pushed;
|
||||
static const Size _size_layout_margin;
|
||||
static const int _size_widget_border;
|
||||
};
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace bwidgets
|
|||
_increment_button(create_button(this)),
|
||||
_decrement_button(create_button(this))
|
||||
{
|
||||
Self::_input_caption->alignment = Caption::Alignment::RIGHT;
|
||||
Self::_input_caption->alignment(Caption::Alignment::RIGHT);
|
||||
|
||||
Self::input_min_width = 10; // NOLINT(readability-magic-numbers)
|
||||
Self::input_width_unit = '0';
|
||||
|
@ -160,19 +160,19 @@ namespace bwidgets
|
|||
const int spacing = center_line(button_area_width, widest_button);
|
||||
const int field_width = vp.w - 2 * button_area_width;
|
||||
|
||||
Self::_widget_area.x = Self::_widget_area.x + button_area_width;
|
||||
Self::_widget_area.w = field_width;
|
||||
Self::_text_area.x = Self::_text_area.x + button_area_width;
|
||||
Self::_text_area.w = field_width;
|
||||
|
||||
Self::_input_caption->viewport(rect_offset(
|
||||
rect_margin(Self::_widget_area, {Self::theme()->size_widget_border(),
|
||||
Self::theme()->size_widget_border()}),
|
||||
rect_margin(Self::_text_area, {Self::theme()->size_widget_border(),
|
||||
Self::theme()->size_widget_border()}),
|
||||
vp));
|
||||
_decrement_button_area = {spacing, Self::_widget_area.y,
|
||||
_decrement_button_area = {spacing, Self::_text_area.y,
|
||||
_decrement_button->size().w,
|
||||
_decrement_button->size().h};
|
||||
|
||||
_increment_button_area = {vp.w - spacing - _increment_button->size().w,
|
||||
Self::_widget_area.y, _increment_button->size().w,
|
||||
Self::_text_area.y, _increment_button->size().w,
|
||||
_increment_button->size().h};
|
||||
|
||||
_increment_button->viewport(rect_offset(_increment_button_area, vp));
|
||||
|
|
|
@ -30,9 +30,11 @@ namespace bwidgets
|
|||
void value(int) override;
|
||||
|
||||
protected:
|
||||
SDL_Rect _bar_area;
|
||||
std::unique_ptr<Button> _button_minus;
|
||||
std::unique_ptr<Button> _button_plus;
|
||||
const Size _cursor_size {16, 16};
|
||||
// TODO: cursor_area
|
||||
std::function<void(int)> _on_scroll;
|
||||
Orientation _orientation;
|
||||
int _value {0};
|
||||
|
|
|
@ -2,35 +2,23 @@
|
|||
|
||||
using namespace bwidgets;
|
||||
|
||||
void LayoutImpl::add_widget(std::unique_ptr<Widget> widget_ptr)
|
||||
{
|
||||
if (_renderer) widget_ptr->renderer(_renderer);
|
||||
_widgets.emplace_back(std::move(widget_ptr));
|
||||
_update_layout(_viewport);
|
||||
}
|
||||
|
||||
void LayoutImpl::for_widgets(const std::function<void(Widget*)>& f)
|
||||
{
|
||||
for (const auto& w : _widgets) f(w.get());
|
||||
}
|
||||
|
||||
void LayoutImpl::handle_event(const SDL_Event& ev)
|
||||
{
|
||||
EventHandlerImpl::handle_event(ev);
|
||||
for (const auto& w : _widgets) w->handle_event(ev);
|
||||
}
|
||||
|
||||
void LayoutImpl::_handle_geometry_change(const SDL_Rect& vp)
|
||||
{
|
||||
_update_layout(vp);
|
||||
for_widgets([ev](Widget* w) { w->handle_event(ev); });
|
||||
}
|
||||
|
||||
void LayoutImpl::_handle_renderer_change(const std::shared_ptr<Renderer>& r)
|
||||
{
|
||||
for (const auto& w : _widgets) w->renderer(r);
|
||||
for_widgets([r](Widget* w) { w->renderer(r); });
|
||||
}
|
||||
|
||||
void LayoutImpl::_handle_rendering()
|
||||
{
|
||||
for (const auto& w : _widgets) w->render();
|
||||
for_widgets([](Widget* w) { w->render(); });
|
||||
}
|
||||
|
||||
void LayoutImpl::_handle_theme_change(const std::shared_ptr<Theme>& t)
|
||||
{
|
||||
for_widgets([&t](Widget* w) { w->theme(t); });
|
||||
}
|
||||
|
|
|
@ -3,26 +3,31 @@
|
|||
|
||||
using namespace bwidgets;
|
||||
|
||||
WidgetImpl::WidgetImpl(Widget* p) : Widget {p}, _theme {DefaultThemeInstance::get()} {}
|
||||
WidgetImpl::WidgetImpl(Widget* p) : _parent {p}, _theme {DefaultThemeInstance::get()} {}
|
||||
|
||||
auto WidgetImpl::parent() -> Widget*
|
||||
{
|
||||
return _parent;
|
||||
}
|
||||
|
||||
void WidgetImpl::parent(Widget* p)
|
||||
{
|
||||
_parent = p;
|
||||
}
|
||||
|
||||
void WidgetImpl::render()
|
||||
{
|
||||
if (!_renderer) return;
|
||||
|
||||
#ifdef BWIDGETS_DEBUG
|
||||
// Render a debug outline of widget viewport.
|
||||
_renderer
|
||||
->draw_color({
|
||||
// NOLINTNEXTLINE(readability-magic-numbers)
|
||||
{0, 255, 0, SDL_ALPHA_OPAQUE}
|
||||
})
|
||||
->draw_rect(nullptr);
|
||||
#endif
|
||||
|
||||
_renderer->viewport(&_viewport);
|
||||
_handle_rendering();
|
||||
}
|
||||
|
||||
auto WidgetImpl::renderer() -> const std::shared_ptr<Renderer>&
|
||||
{
|
||||
return _renderer;
|
||||
}
|
||||
|
||||
void WidgetImpl::renderer(std::shared_ptr<Renderer> r)
|
||||
{
|
||||
if (r != _renderer) {
|
||||
|
|
|
@ -10,14 +10,10 @@ using namespace bwidgets;
|
|||
ButtonImpl::ButtonImpl(Widget* parent) noexcept
|
||||
: WidgetImpl {parent}, _caption {create_caption(this)}
|
||||
{
|
||||
enable_mouse_handler(_widget_area, _viewport);
|
||||
enable_mouse_handler(_mouse_area, viewport());
|
||||
|
||||
_caption->alignment = Caption::Alignment::CENTER;
|
||||
_caption->alignment(Caption::Alignment::CENTER);
|
||||
_caption->render_mode(Font::RenderMode::BLENDED);
|
||||
|
||||
_color_bg = theme()->color_widget_bg();
|
||||
_color_bg_hl = theme()->color_widget_bg_hl();
|
||||
_color_border = theme()->color_widget_border();
|
||||
}
|
||||
|
||||
auto ButtonImpl::size() const noexcept -> Size
|
||||
|
@ -33,13 +29,13 @@ auto ButtonImpl::text() const noexcept -> std::string_view
|
|||
void ButtonImpl::text(std::string txt)
|
||||
{
|
||||
_caption->text(std::move(txt));
|
||||
_handle_geometry_change(_viewport);
|
||||
_handle_geometry_change(viewport());
|
||||
}
|
||||
|
||||
void ButtonImpl::_handle_font_change(const std::shared_ptr<Font>& f)
|
||||
{
|
||||
_caption->font(f);
|
||||
_handle_geometry_change(_viewport);
|
||||
_handle_geometry_change(viewport());
|
||||
}
|
||||
|
||||
void ButtonImpl::_handle_font_color_change(const Color fg, Color)
|
||||
|
@ -49,7 +45,7 @@ void ButtonImpl::_handle_font_color_change(const Color fg, Color)
|
|||
|
||||
void ButtonImpl::_handle_geometry_change(const SDL_Rect& vp)
|
||||
{
|
||||
_widget_area = {0, 0, vp.w, vp.h};
|
||||
_mouse_area = {0, 0, vp.w, vp.h};
|
||||
|
||||
const auto txt_size = _caption->size();
|
||||
_caption_area = {center_line(vp.w, txt_size.w), center_line(vp.h, txt_size.h),
|
||||
|
@ -65,14 +61,15 @@ void ButtonImpl::_handle_renderer_change(const std::shared_ptr<Renderer>& r)
|
|||
|
||||
void ButtonImpl::_handle_rendering()
|
||||
{
|
||||
const Color& c = hovered() ? _color_bg_hl : _color_bg;
|
||||
const Color& c =
|
||||
hovered() ? theme()->color_widget_bg_hl() : theme()->color_widget_bg();
|
||||
|
||||
if (pushed())
|
||||
fill_rect_gradient(*_renderer, _widget_area,
|
||||
fill_rect_gradient(*renderer(), _mouse_area,
|
||||
theme()->color_widget_border_pushed(), c,
|
||||
theme()->size_widget_border());
|
||||
else
|
||||
fill_rect_gradient(*_renderer, _widget_area, theme()->color_widget_border(), c,
|
||||
fill_rect_gradient(*renderer(), _mouse_area, theme()->color_widget_border(), c,
|
||||
theme()->size_widget_border());
|
||||
|
||||
_caption->font_color_bg(c);
|
||||
|
@ -84,9 +81,9 @@ void ButtonImpl::_on_push(const bool state)
|
|||
// Move slightly the caption position to give a push effect.
|
||||
const auto offset = [state, this]() -> SDL_Point {
|
||||
if (state) {
|
||||
return {_viewport.x + 1, _viewport.y + 1};
|
||||
return {viewport().x + 1, viewport().y + 1};
|
||||
}
|
||||
return {_viewport.x, _viewport.y};
|
||||
return {viewport().x, viewport().y};
|
||||
}();
|
||||
|
||||
_caption->viewport(rect_offset(_caption_area, offset));
|
||||
|
|
|
@ -11,6 +11,16 @@ CaptionImpl::CaptionImpl(Widget* parent) noexcept : WidgetImpl {parent}
|
|||
_font_color_fg = theme()->color_font_fg();
|
||||
}
|
||||
|
||||
auto CaptionImpl::alignment() const -> Alignment
|
||||
{
|
||||
return _alignment;
|
||||
}
|
||||
|
||||
void CaptionImpl::alignment(Alignment a)
|
||||
{
|
||||
_alignment = a;
|
||||
}
|
||||
|
||||
void CaptionImpl::render_mode(const Font::RenderMode m)
|
||||
{
|
||||
if (m != _render_mode) {
|
||||
|
@ -23,8 +33,7 @@ auto CaptionImpl::size() const noexcept -> Size
|
|||
{
|
||||
if (!_font) return {0, 0};
|
||||
|
||||
const auto [w, h] = _font->text_size(_text);
|
||||
return {w + 2 * margins.w, h + 2 * margins.h};
|
||||
return _font->text_size(_text);
|
||||
}
|
||||
|
||||
auto CaptionImpl::text() const noexcept -> std::string_view
|
||||
|
@ -56,11 +65,11 @@ void CaptionImpl::_handle_font_color_change(const Color fg, const Color bg)
|
|||
|
||||
void CaptionImpl::_handle_geometry_change(const SDL_Rect& vp)
|
||||
{
|
||||
if (vp.w != _viewport.w) {
|
||||
_widget_area = rect_margin({0, 0, vp.w, vp.h}, margins);
|
||||
if (vp.w != viewport().w) {
|
||||
_text_area = {0, 0, vp.w, vp.h};
|
||||
}
|
||||
else if (vp.h != _viewport.h) {
|
||||
_widget_area = rect_margin({0, 0, vp.w, vp.h}, margins);
|
||||
else if (vp.h != viewport().h) {
|
||||
_text_area = {0, 0, vp.w, vp.h};
|
||||
_text_texture.reset();
|
||||
}
|
||||
}
|
||||
|
@ -77,30 +86,31 @@ void CaptionImpl::_handle_rendering()
|
|||
// fill caption viewport with background color when using
|
||||
// shaded text rendering mode.
|
||||
if (_render_mode == Font::RenderMode::SHADED) {
|
||||
_renderer->draw_color(_font_color_bg)
|
||||
->fill_rect({0, 0, _viewport.w, _viewport.h});
|
||||
renderer()
|
||||
->draw_color(_font_color_bg)
|
||||
->fill_rect({0, 0, viewport().w, viewport().h});
|
||||
}
|
||||
|
||||
const Size size_dst {
|
||||
(int)((float)_text_texture->attributes().w / (float)_text_texture->attributes().h
|
||||
* (float)_widget_area.h),
|
||||
_widget_area.h};
|
||||
* (float)_text_area.h),
|
||||
_text_area.h};
|
||||
|
||||
const auto texture_dst = [size_dst, this]() -> SDL_Rect {
|
||||
switch (alignment) {
|
||||
switch (alignment()) {
|
||||
case Alignment::CENTER:
|
||||
return {center_line(_widget_area.w, size_dst.w) + _widget_area.x,
|
||||
margins.h, size_dst.w, size_dst.h};
|
||||
return {center_line(_text_area.w, size_dst.w) + _text_area.x,
|
||||
_text_area.y, size_dst.w, size_dst.h};
|
||||
case Alignment::LEFT:
|
||||
return {margins.w, margins.h, size_dst.w, size_dst.h};
|
||||
return {_text_area.x, _text_area.y, size_dst.w, size_dst.h};
|
||||
case Alignment::RIGHT:
|
||||
return {_widget_area.w - size_dst.w - margins.w + _widget_area.x,
|
||||
margins.h, size_dst.w, size_dst.h};
|
||||
return {_text_area.w - size_dst.w + _text_area.x, _text_area.y,
|
||||
size_dst.w, size_dst.h};
|
||||
default:
|
||||
throw std::logic_error("missing switch case.");
|
||||
}
|
||||
}();
|
||||
_renderer->copy(*_text_texture, nullptr, texture_dst);
|
||||
renderer()->copy(*_text_texture, nullptr, texture_dst);
|
||||
}
|
||||
|
||||
void CaptionImpl::_handle_texture_update()
|
||||
|
@ -117,7 +127,7 @@ void CaptionImpl::_handle_texture_update()
|
|||
return _font->render(_render_mode, _text, _font_color_fg);
|
||||
}
|
||||
}();
|
||||
_text_texture = std::make_shared<Texture>(*_renderer, s.get());
|
||||
_text_texture = std::make_shared<Texture>(*renderer(), s.get());
|
||||
}
|
||||
|
||||
void CaptionImpl::_handle_theme_change(const std::shared_ptr<Theme>& t)
|
||||
|
|
|
@ -14,6 +14,7 @@ const Color DefaultTheme::_color_widget_bg = {160, 160, 160, SDL_ALPHA_OPA
|
|||
const Color DefaultTheme::_color_widget_bg_hl = {180, 180, 180, SDL_ALPHA_OPAQUE};
|
||||
const Color DefaultTheme::_color_widget_border = {130, 130, 130, SDL_ALPHA_OPAQUE};
|
||||
const Color DefaultTheme::_color_widget_border_pushed = {90, 90, 90, SDL_ALPHA_OPAQUE};
|
||||
const Size DefaultTheme::_size_layout_margin = {4, 4};
|
||||
const int DefaultTheme::_size_widget_border = 4;
|
||||
|
||||
auto DefaultTheme::color_font_bg() const -> const Color&
|
||||
|
@ -61,6 +62,11 @@ auto DefaultTheme::color_widget_border_pushed() const -> const Color&
|
|||
return _color_widget_border_pushed;
|
||||
}
|
||||
|
||||
auto DefaultTheme::size_layout_margin() const -> const Size&
|
||||
{
|
||||
return _size_layout_margin;
|
||||
}
|
||||
|
||||
auto DefaultTheme::size_widget_border() const -> int
|
||||
{
|
||||
return _size_widget_border;
|
||||
|
|
|
@ -24,39 +24,39 @@ ScrollBarImpl::ScrollBarImpl(Widget* parent)
|
|||
_button_minus->click_handler([this](auto) { value(value() - 5); });
|
||||
_button_plus->click_handler([this](auto) { value(value() + 5); });
|
||||
click_handler([this](const SDL_MouseButtonEvent ev) {
|
||||
SDL_Point p {ev.x - _viewport.x - _widget_area.x,
|
||||
ev.y - _viewport.y - _widget_area.y};
|
||||
SDL_Point p {ev.x - viewport().x - _bar_area.x,
|
||||
ev.y - viewport().y - _bar_area.y};
|
||||
if (_orientation == Orientation::VERTICAL) {
|
||||
value(p.y * 100 / _widget_area.h);
|
||||
value(p.y * 100 / _bar_area.h);
|
||||
}
|
||||
else {
|
||||
value(p.x * 100 / _widget_area.w);
|
||||
value(p.x * 100 / _bar_area.w);
|
||||
}
|
||||
});
|
||||
mouse_motion_handler([this](SDL_MouseMotionEvent ev) {
|
||||
if (!pushed()) return;
|
||||
SDL_Point p = {ev.x - _viewport.x - _widget_area.x,
|
||||
ev.y - _viewport.y - _widget_area.y};
|
||||
SDL_Point p = {ev.x - viewport().x - _bar_area.x,
|
||||
ev.y - viewport().y - _bar_area.y};
|
||||
if (_orientation == Orientation::VERTICAL) {
|
||||
value(std::clamp(p.y, 0, _widget_area.h) * 100 / _widget_area.h);
|
||||
value(std::clamp(p.y, 0, _bar_area.h) * 100 / _bar_area.h);
|
||||
}
|
||||
else {
|
||||
value(std::clamp(p.x, 0, _widget_area.w) * 100 / _widget_area.w);
|
||||
value(std::clamp(p.x, 0, _bar_area.w) * 100 / _bar_area.w);
|
||||
}
|
||||
});
|
||||
enable_mouse_handler(_widget_area, _viewport);
|
||||
enable_mouse_handler(_bar_area, viewport());
|
||||
}
|
||||
|
||||
auto ScrollBarImpl::cursor_area() const -> SDL_Rect
|
||||
{
|
||||
if (_orientation == Orientation::VERTICAL) {
|
||||
const auto offset = value() * _widget_area.h / 100;
|
||||
return {_widget_area.x, _widget_area.y + offset - _cursor_size.h / 2,
|
||||
_widget_area.w, _cursor_size.h};
|
||||
const auto offset = value() * _bar_area.h / 100;
|
||||
return {_bar_area.x, _bar_area.y + offset - _cursor_size.h / 2, _bar_area.w,
|
||||
_cursor_size.h};
|
||||
}
|
||||
const auto offset = value() * _widget_area.w / 100;
|
||||
return {_widget_area.x + offset - _cursor_size.h / 2, _widget_area.y, _cursor_size.h,
|
||||
_widget_area.h};
|
||||
const auto offset = value() * _bar_area.w / 100;
|
||||
return {_bar_area.x + offset - _cursor_size.h / 2, _bar_area.y, _cursor_size.h,
|
||||
_bar_area.h};
|
||||
}
|
||||
|
||||
void ScrollBarImpl::handle_event(const SDL_Event& ev)
|
||||
|
@ -143,16 +143,16 @@ void ScrollBarImpl::_handle_geometry_change(const SDL_Rect& vp)
|
|||
const auto minus_size = _button_minus->size();
|
||||
const auto plus_size = _button_plus->size();
|
||||
if (_orientation == Orientation::VERTICAL) {
|
||||
_widget_area = {0, minus_size.h, vp.w, vp.h - minus_size.h - plus_size.h};
|
||||
_bar_area = {0, minus_size.h, vp.w, vp.h - minus_size.h - plus_size.h};
|
||||
_button_minus->viewport(rect_offset({0, 0, vp.w, minus_size.h}, vp));
|
||||
_button_plus->viewport(
|
||||
rect_offset({0, _widget_area.y + _widget_area.h, vp.w, plus_size.h}, vp));
|
||||
rect_offset({0, _bar_area.y + _bar_area.h, vp.w, plus_size.h}, vp));
|
||||
}
|
||||
else {
|
||||
_widget_area = {minus_size.w, 0, vp.w - minus_size.w - plus_size.w, vp.h};
|
||||
_bar_area = {minus_size.w, 0, vp.w - minus_size.w - plus_size.w, vp.h};
|
||||
_button_minus->viewport(rect_offset({0, 0, minus_size.w, vp.h}, vp));
|
||||
_button_plus->viewport(
|
||||
rect_offset({_widget_area.x + _widget_area.w, 0, plus_size.w, vp.h}, vp));
|
||||
rect_offset({_bar_area.x + _bar_area.w, 0, plus_size.w, vp.h}, vp));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,12 +164,12 @@ void ScrollBarImpl::_handle_renderer_change(const std::shared_ptr<Renderer>& r)
|
|||
|
||||
void ScrollBarImpl::_handle_rendering()
|
||||
{
|
||||
_renderer->draw_color(theme()->color_widget_border());
|
||||
fill_rect_gradient(*_renderer, _widget_area, theme()->color_widget_bg(),
|
||||
renderer()->draw_color(theme()->color_widget_border());
|
||||
fill_rect_gradient(*renderer(), _bar_area, theme()->color_widget_bg(),
|
||||
theme()->color_widget_border());
|
||||
|
||||
auto c = hovered() ? theme()->color_widget_bg_hl() : theme()->color_widget_bg();
|
||||
fill_rect_gradient(*_renderer, cursor_area(), theme()->color_widget_border(), c);
|
||||
fill_rect_gradient(*renderer(), cursor_area(), theme()->color_widget_border(), c);
|
||||
|
||||
_button_minus->render();
|
||||
_button_plus->render();
|
||||
|
|
Loading…
Reference in a new issue