more wip on api rewrites

This commit is contained in:
Andrea Blankenstijn 2022-01-25 17:13:03 +01:00
parent a36fe9cae5
commit 860b656bf7
23 changed files with 177 additions and 159 deletions

View file

@ -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);
},

View file

@ -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}));
}

View file

@ -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(

View file

@ -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

View file

@ -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,
});

View file

@ -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();
}

View file

@ -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.

View file

@ -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;
};
}

View file

@ -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;
};
}

View file

@ -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;

View file

@ -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};
};
}

View file

@ -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;

View file

@ -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.

View file

@ -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;

View file

@ -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;
};

View file

@ -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));

View file

@ -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};

View file

@ -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); });
}

View file

@ -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) {

View file

@ -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));

View file

@ -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)

View file

@ -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;

View file

@ -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();