more wip on api and also on a scrollable thing widget

This commit is contained in:
Andrea Blankenstijn 2022-01-26 18:38:47 +01:00
parent 860b656bf7
commit af7b9803d2
22 changed files with 306 additions and 82 deletions

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"),
18); // NOLINT(readability-magic-numbers)
14); // NOLINT(readability-magic-numbers)
auto win = std::unique_ptr<SDL_Window, bwidgets::Deleter>(
bwidgets::ptr_or_throw<bwidgets::SDLError>(SDL_CreateWindow(

View file

@ -0,0 +1,11 @@
#include <basic_widgets/w/widget_factory.hpp>
#include "run.hpp"
auto main() -> int
{
run_example<bwidgets::ScrollableArea>(
[]() { return bwidgets::create_scrollable_area(); },
[](auto w, auto f, auto x, auto y) { w->font(f); });
return 0;
}

View file

@ -1,20 +1,11 @@
#include <iostream>
#include <basic_widgets/w/widget_factory.hpp>
#include "run.hpp"
auto main() -> int
{
run_example<bwidgets::ScrollBar>(
[]() { return bwidgets::create_scrollbar(); },
[](auto w, auto f, auto x, auto y) {
w->font(f);
w->orientation(bwidgets::ScrollBar::Orientation::HORIZONTAL);
w->on_scroll([x, y](const int value) {
std::cout << "scrollbar(" << x << ',' << y << "): " << value << '%'
<< std::endl;
});
});
run_example<bwidgets::ScrollableArea>(
[]() { return bwidgets::create_scrollable_area(); },
[](auto w, auto f, auto x, auto y) {});
return 0;
}

View file

@ -19,7 +19,6 @@ namespace bwidgets
public:
using WidgetImpl::WidgetImpl;
// TODO: remove widget
void handle_event(const SDL_Event&) override;
protected:

View file

@ -17,6 +17,7 @@ namespace bwidgets
[[nodiscard]] virtual auto color_input_bg_active() const -> const Color& = 0;
[[nodiscard]] virtual auto color_input_fg() const -> const Color& = 0;
[[nodiscard]] virtual auto color_widget_bg() const -> const Color& = 0;
[[nodiscard]] virtual auto color_widget_bg_dark() const -> const Color& = 0;
[[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

View file

@ -29,7 +29,7 @@ namespace bwidgets
virtual void _handle_renderer_change(const std::shared_ptr<Renderer>&) {}
// Called on rendering.
virtual void _handle_rendering() = 0;
virtual void _handle_theme_change(const std::shared_ptr<Theme>&) {} // = 0;
virtual void _handle_theme_change(const std::shared_ptr<Theme>&) {}
private:
Widget* _parent;

View file

@ -16,6 +16,7 @@ namespace bwidgets
[[nodiscard]] auto color_input_bg_active() const -> const Color& override;
[[nodiscard]] auto color_input_fg() const -> const Color& override;
[[nodiscard]] auto color_widget_bg() const -> const Color& override;
[[nodiscard]] auto color_widget_bg_dark() const -> const Color& override;
[[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;
@ -29,6 +30,7 @@ namespace bwidgets
static const Color _color_input_bg_active;
static const Color _color_input_fg;
static const Color _color_widget_bg;
static const Color _color_widget_bg_dark;
static const Color _color_widget_bg_hl;
static const Color _color_widget_border;
static const Color _color_widget_border_pushed;

View file

@ -46,8 +46,8 @@ namespace bwidgets
// Called on font changes.
virtual void _handle_font_change(const std::shared_ptr<Font>&) = 0;
// Called on font color changes.
virtual void _handle_font_color_change(Color, Color) = 0;
// Called on font color changes. TODO: remove that, use theme
virtual void _handle_font_color_change(Color, Color) {}
};
}

View file

@ -29,8 +29,10 @@ namespace bwidgets
// Set mouse motion handler.
virtual void
mouse_motion_handler(std::function<void(const SDL_MouseMotionEvent&)>) = 0;
virtual void
mouse_wheel_handler(std::function<void(const SDL_MouseWheelEvent&)>) = 0;
// Get current push state (mouse button down)
[[nodiscard]] virtual bool pushed() const = 0;
[[nodiscard]] virtual bool pushed() const = 0;
};
}

View file

@ -14,9 +14,10 @@ namespace bwidgets
bool _hovered {false};
bool _pushed {false};
std::function<void(const SDL_MouseButtonEvent&)> _click_handler {[](auto) {}};
std::function<void(bool)> _hover_handler {[](auto) {}};
std::function<void(const SDL_MouseMotionEvent&)> _motion_handler {[](auto) {}};
std::function<void(const SDL_MouseButtonEvent&)> _click_handler {nullptr};
std::function<void(bool)> _hover_handler {nullptr};
std::function<void(const SDL_MouseMotionEvent&)> _motion_handler {nullptr};
std::function<void(const SDL_MouseWheelEvent&)> _wheel_handler {nullptr};
public:
void click_handler(decltype(_click_handler) handler) override
@ -28,7 +29,10 @@ namespace bwidgets
void enable_mouse_handler(const SDL_Rect&, const SDL_Rect&) override;
[[nodiscard]] bool hovered() const override { return _hovered; }
[[nodiscard]] bool hovered() const override
{
return _hovered;
}
void hover_handler(decltype(_hover_handler) handler) override
{
@ -40,7 +44,12 @@ namespace bwidgets
_motion_handler = std::move(handler);
}
[[nodiscard]] bool pushed() const override { return _pushed; }
void mouse_wheel_handler(decltype(_wheel_handler)) override;
[[nodiscard]] bool pushed() const override
{
return _pushed;
}
protected:
using MouseHandler::MouseHandler;

View file

@ -0,0 +1,20 @@
#ifndef BWIDGETS_SCROLLABLE_AREA_HPP
#define BWIDGETS_SCROLLABLE_AREA_HPP
#include <basic_widgets/w/base/widget.hpp>
#include <basic_widgets/w/feat/font_handler.hpp>
#include "basic_widgets/core/texture.hpp"
namespace bwidgets
{
class ScrollableArea : public virtual Widget,
public virtual FontHandler
{
public:
virtual auto texture() -> const std::shared_ptr<Texture>& = 0;
virtual void texture(std::shared_ptr<Texture>) = 0;
};
}
#endif

View file

@ -0,0 +1,38 @@
#ifndef BWIDGETS_SCROLLABLE_AREA_IMPL_HPP
#define BWIDGETS_SCROLLABLE_AREA_IMPL_HPP
#include <basic_widgets/w/base/widget_impl.hpp>
#include <basic_widgets/w/feat/font_handler_impl.hpp>
#include <basic_widgets/w/scrollable_area.hpp>
#include <basic_widgets/w/scrollbar.hpp>
namespace bwidgets
{
class ScrollableAreaImpl : public virtual ScrollableArea,
public virtual WidgetImpl,
public virtual FontHandlerImpl
{
public:
ScrollableAreaImpl(Widget* parent = nullptr);
void handle_event(const SDL_Event&) override;
auto size() const noexcept -> Size override;
auto texture() -> const std::shared_ptr<Texture>& override;
void texture(std::shared_ptr<Texture>) override;
protected:
void _handle_font_change(const std::shared_ptr<Font>&) override;
void _handle_geometry_change(const SDL_Rect&) override;
void _handle_renderer_change(const std::shared_ptr<Renderer>&) override;
void _handle_rendering() override;
void _handle_theme_change(const std::shared_ptr<Theme>&) override;
private:
std::unique_ptr<ScrollBar> _scrollbar_h;
std::unique_ptr<ScrollBar> _scrollbar_v;
std::shared_ptr<Texture> _texture;
SDL_Rect _texture_area;
};
}
#endif

View file

@ -20,8 +20,6 @@ namespace bwidgets
VERTICAL
};
using Widget::Widget;
virtual void on_scroll(std::function<void(int)>) = 0;
[[nodiscard]] virtual auto orientation() const -> Orientation = 0;
virtual void orientation(Orientation) = 0;

View file

@ -44,6 +44,7 @@ namespace bwidgets
void _handle_geometry_change(const SDL_Rect&) override;
void _handle_renderer_change(const std::shared_ptr<Renderer>&) override;
void _handle_rendering() override;
void _handle_theme_change(const std::shared_ptr<Theme>&) override;
};
}

View file

@ -5,6 +5,7 @@
#include <basic_widgets/w/button.hpp>
#include <basic_widgets/w/caption.hpp>
#include <basic_widgets/w/numeric_input.hpp>
#include <basic_widgets/w/scrollable_area.hpp>
#include <basic_widgets/w/scrollbar.hpp>
namespace bwidgets
@ -14,6 +15,7 @@ namespace bwidgets
auto create_horizontal_layout(Widget* p = nullptr) -> std::unique_ptr<AlignedLayout>;
auto create_input_float(Widget* p = nullptr) -> std::unique_ptr<NumericInput<float>>;
auto create_input_int(Widget* p = nullptr) -> std::unique_ptr<NumericInput<int>>;
auto create_scrollable_area(Widget* p = nullptr) -> std::unique_ptr<ScrollableArea>;
auto create_scrollbar(Widget* p = nullptr) -> std::unique_ptr<ScrollBar>;
auto create_vertical_layout(Widget* p = nullptr) -> std::unique_ptr<AlignedLayout>;
}

View file

@ -36,6 +36,7 @@ libbasic_widgets = static_library('basic_widgets',
'src/w/feat/event_handler_impl.cpp',
'src/w/feat/keyboard_handler_impl.cpp',
'src/w/feat/mouse_handler_impl.cpp',
'src/w/scrollable_area_impl.cpp',
'src/w/scrollbar_impl.cpp',
'src/w/widget_factory.cpp',
dependencies : [sdl, fontconfig],
@ -75,6 +76,13 @@ executable('input_demo',
link_with : libbasic_widgets,
install : false)
executable('scrollable_area_demo',
'examples/scrollable_area_example.cpp',
dependencies : [sdl],
include_directories : pub_api,
link_with : libbasic_widgets,
install : false)
executable('scrollbar_demo',
'examples/scrollbar_example.cpp',
dependencies : [sdl],

View file

@ -82,6 +82,7 @@ void CaptionImpl::_handle_renderer_change(const std::shared_ptr<Renderer>&)
void CaptionImpl::_handle_rendering()
{
if (!_text_texture) _handle_texture_update();
// TODO: what if texture can't be loaded?
// fill caption viewport with background color when using
// shaded text rendering mode.

View file

@ -11,6 +11,7 @@ const Color DefaultTheme::_color_input_bg = {180, 180, 180, SDL_ALPHA_OPA
const Color DefaultTheme::_color_input_bg_active = _color_font_bg;
const Color DefaultTheme::_color_input_fg = _color_font_fg;
const Color DefaultTheme::_color_widget_bg = {160, 160, 160, SDL_ALPHA_OPAQUE};
const Color DefaultTheme::_color_widget_bg_dark = {100, 100, 100, SDL_ALPHA_OPAQUE};
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};
@ -42,6 +43,11 @@ auto DefaultTheme::color_input_fg() const -> const Color&
return _color_input_fg;
}
auto DefaultTheme::color_widget_bg_dark() const -> const Color&
{
return _color_widget_bg_dark;
}
auto DefaultTheme::color_widget_bg() const -> const Color&
{
return _color_widget_bg;

View file

@ -33,16 +33,31 @@ void MouseHandlerImpl::enable_mouse_handler(const SDL_Rect& rel_area,
// has been pushed and released over the widget.
if (mouse_in_rect({ev.button.x, ev.button.y})) {
focus(true);
_click_handler(ev.button);
if (_click_handler) _click_handler(ev.button);
}
}
}});
_add_event_handler({SDL_MOUSEMOTION, [this, mouse_in_rect](const SDL_Event& ev) {
if (!mouse_in_rect({ev.motion.x, ev.motion.y})) {
if (_hovered) _hover_handler(_hovered = false);
if (_hovered) {
_hovered = false;
if (_hover_handler) _hover_handler(_hovered);
}
return;
}
if (!_hovered) _hover_handler(_hovered = true);
_motion_handler(ev.motion);
if (!_hovered) {
_hovered = true;
if (_hover_handler) _hover_handler(_hovered);
}
if (_motion_handler) _motion_handler(ev.motion);
}});
_add_event_handler({SDL_MOUSEWHEEL, [this](const SDL_Event& ev) {
if (hovered() && _wheel_handler) _wheel_handler(ev.wheel);
}});
}
void MouseHandlerImpl::mouse_wheel_handler(
std::function<void(const SDL_MouseWheelEvent&)> handler)
{
_wheel_handler = std::move(handler);
}

View file

@ -0,0 +1,79 @@
#include <utility>
#include <basic_widgets/core/draw.hpp>
#include <basic_widgets/w/scrollable_area_impl.hpp>
#include <basic_widgets/w/widget_factory.hpp>
using namespace bwidgets;
using namespace std;
ScrollableAreaImpl::ScrollableAreaImpl(Widget* p)
: WidgetImpl {p},
_scrollbar_h {create_scrollbar(this)},
_scrollbar_v {create_scrollbar(this)},
_texture {nullptr},
_texture_area {}
{
_scrollbar_h->orientation(ScrollBar::Orientation::HORIZONTAL);
_scrollbar_v->orientation(ScrollBar::Orientation::VERTICAL);
}
void ScrollableAreaImpl::handle_event(const SDL_Event& ev)
{
WidgetImpl::handle_event(ev);
_scrollbar_h->handle_event(ev);
_scrollbar_v->handle_event(ev);
}
auto ScrollableAreaImpl::size() const noexcept -> Size
{
return {100, 100};
}
auto ScrollableAreaImpl::texture() -> const shared_ptr<Texture>&
{
return _texture;
}
void ScrollableAreaImpl::texture(shared_ptr<Texture> t)
{
_texture = move(t);
}
void ScrollableAreaImpl::_handle_font_change(const shared_ptr<Font>& f)
{
_scrollbar_h->font(f);
_scrollbar_v->font(f);
}
void ScrollableAreaImpl::_handle_geometry_change(const SDL_Rect& vp)
{
const auto reserved_h = _scrollbar_h->size().w;
const auto reserved_w = _scrollbar_v->size().w;
_texture_area = {0, 0, vp.w - reserved_w, vp.h - reserved_h};
_scrollbar_h->viewport({vp.x, vp.y + _texture_area.h, vp.w, reserved_h});
_scrollbar_v->viewport(
{vp.x + _texture_area.w, vp.y, reserved_w, vp.h - reserved_h});
}
void ScrollableAreaImpl::_handle_renderer_change(const shared_ptr<Renderer>& r)
{
_scrollbar_h->renderer(r);
_scrollbar_v->renderer(r);
}
void ScrollableAreaImpl::_handle_rendering()
{
fill_rect_gradient(*renderer(), _texture_area, theme()->color_widget_border(),
theme()->color_widget_bg(), theme()->size_widget_border());
_scrollbar_h->render();
_scrollbar_v->render();
}
void ScrollableAreaImpl::_handle_theme_change(const shared_ptr<Theme>& t)
{
_scrollbar_h->theme(t);
_scrollbar_v->theme(t);
}

View file

@ -12,6 +12,20 @@
using namespace bwidgets;
using namespace std;
auto common_size(const Widget* w1, const Widget* w2) -> Size
{
const auto size1 = w1->size();
const auto size2 = w2->size();
return {size1.w > size2.w ? size1.w : size2.w,
size1.h > size2.h ? size1.h : size2.h};
}
auto square_size(Size s) -> int
{
return s.w > s.h ? s.w : s.h;
}
ScrollBarImpl::ScrollBarImpl(Widget* parent)
: WidgetImpl {parent},
_button_minus {create_button(this)},
@ -38,10 +52,20 @@ ScrollBarImpl::ScrollBarImpl(Widget* parent)
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, _bar_area.h) * 100 / _bar_area.h);
value(clamp(p.y, 0, _bar_area.h) * 100 / _bar_area.h);
}
else {
value(std::clamp(p.x, 0, _bar_area.w) * 100 / _bar_area.w);
value(clamp(p.x, 0, _bar_area.w) * 100 / _bar_area.w);
}
});
mouse_wheel_handler([this](SDL_MouseWheelEvent ev) {
if (orientation() == ScrollBar::Orientation::VERTICAL) {
if (ev.y < 0) value(value() + 5);
else if (ev.y > 0) value(value() - 5);
}
else {
if (ev.x > 0) value(value() + 5);
else if (ev.x < 0) value(value() - 5);
}
});
enable_mouse_handler(_bar_area, viewport());
@ -66,9 +90,9 @@ void ScrollBarImpl::handle_event(const SDL_Event& ev)
_button_plus->handle_event(ev);
}
void ScrollBarImpl::on_scroll(std::function<void(int)> cb)
void ScrollBarImpl::on_scroll(function<void(int)> cb)
{
_on_scroll = std::move(cb);
_on_scroll = move(cb);
}
auto ScrollBarImpl::orientation() const -> Orientation
@ -93,23 +117,23 @@ void ScrollBarImpl::orientation(const Orientation o)
auto ScrollBarImpl::size() const noexcept -> Size
{
const auto minus_size = _button_minus->size();
const auto plus_size = _button_plus->size();
const auto button_size =
square_size(common_size(_button_minus.get(), _button_plus.get()));
if (_orientation == Orientation::VERTICAL) {
const auto width = [this, minus_size, plus_size]() {
const auto width = [this, button_size]() {
const auto button_max_width =
minus_size.w > plus_size.w ? minus_size.w : plus_size.w;
button_size > button_size ? button_size : button_size;
return button_max_width > _cursor_size.w ? button_max_width : _cursor_size.w;
}();
return {width, minus_size.h + plus_size.h + 3 * _cursor_size.h};
return {width, button_size + button_size + 3 * _cursor_size.h};
}
const auto height = [this, minus_size, plus_size]() {
const auto height = [this, button_size]() {
const auto button_max_height =
minus_size.h > plus_size.h ? minus_size.h : plus_size.h;
button_size > button_size ? button_size : button_size;
return button_max_height > _cursor_size.w ? button_max_height : _cursor_size.w;
}();
return {height, minus_size.w + plus_size.w + 3 * _cursor_size.h};
return {height, button_size + button_size + 3 * _cursor_size.h};
}
auto ScrollBarImpl::value() const -> int
@ -119,14 +143,14 @@ auto ScrollBarImpl::value() const -> int
void ScrollBarImpl::value(const int v)
{
const auto new_value = std::clamp(v, 0, 100);
const auto new_value = clamp(v, 0, 100);
if (new_value != _value) {
_value = new_value;
_on_scroll(new_value);
if (_on_scroll) _on_scroll(new_value);
}
}
void ScrollBarImpl::_handle_font_change(const std::shared_ptr<Font>& f)
void ScrollBarImpl::_handle_font_change(const shared_ptr<Font>& f)
{
_button_minus->font(f);
_button_plus->font(f);
@ -140,23 +164,24 @@ void ScrollBarImpl::_handle_font_color_change(const Color fg, Color)
void ScrollBarImpl::_handle_geometry_change(const SDL_Rect& vp)
{
const auto minus_size = _button_minus->size();
const auto plus_size = _button_plus->size();
const auto button_size =
square_size(common_size(_button_minus.get(), _button_plus.get()));
if (_orientation == Orientation::VERTICAL) {
_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));
_bar_area = {0, button_size, vp.w, vp.h - 2 * button_size};
_button_minus->viewport(rect_offset({0, 0, vp.w, button_size}, vp));
_button_plus->viewport(
rect_offset({0, _bar_area.y + _bar_area.h, vp.w, plus_size.h}, vp));
rect_offset({0, _bar_area.y + _bar_area.h, vp.w, button_size}, vp));
}
else {
_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));
_bar_area = {button_size, 0, vp.w - 2 * button_size, vp.h};
_button_minus->viewport(rect_offset({0, 0, button_size, vp.h}, vp));
_button_plus->viewport(
rect_offset({_bar_area.x + _bar_area.w, 0, plus_size.w, vp.h}, vp));
rect_offset({_bar_area.x + _bar_area.w, 0, button_size, vp.h}, vp));
}
}
void ScrollBarImpl::_handle_renderer_change(const std::shared_ptr<Renderer>& r)
void ScrollBarImpl::_handle_renderer_change(const shared_ptr<Renderer>& r)
{
_button_minus->renderer(r);
_button_plus->renderer(r);
@ -164,9 +189,8 @@ 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(), _bar_area, theme()->color_widget_bg(),
theme()->color_widget_border());
fill_rect_gradient(*renderer(), _bar_area, theme()->color_widget_border(),
theme()->color_widget_bg_dark());
auto c = hovered() ? theme()->color_widget_bg_hl() : theme()->color_widget_bg();
fill_rect_gradient(*renderer(), cursor_area(), theme()->color_widget_border(), c);
@ -174,3 +198,9 @@ void ScrollBarImpl::_handle_rendering()
_button_minus->render();
_button_plus->render();
}
void ScrollBarImpl::_handle_theme_change(const shared_ptr<Theme>& t)
{
_button_minus->theme(t);
_button_plus->theme(t);
}

View file

@ -2,40 +2,51 @@
#include <basic_widgets/w/button_impl.hpp>
#include <basic_widgets/w/caption_impl.hpp>
#include <basic_widgets/w/numeric_input_impl.hpp>
#include <basic_widgets/w/scrollable_area_impl.hpp>
#include <basic_widgets/w/scrollbar_impl.hpp>
#include <basic_widgets/w/widget_factory.hpp>
auto bwidgets::create_horizontal_layout(Widget* parent) -> std::unique_ptr<AlignedLayout>
{
return std::make_unique<AlignedLayoutImpl<LayoutAlignment::HORIZONTAL>>(parent);
}
using namespace std;
auto bwidgets::create_vertical_layout(Widget* parent) -> std::unique_ptr<AlignedLayout>
namespace bwidgets
{
return std::make_unique<AlignedLayoutImpl<LayoutAlignment::VERTICAL>>(parent);
}
auto create_horizontal_layout(Widget* parent) -> unique_ptr<AlignedLayout>
{
return make_unique<AlignedLayoutImpl<LayoutAlignment::HORIZONTAL>>(parent);
}
auto bwidgets::create_button(Widget* parent) -> std::unique_ptr<Button>
{
return std::make_unique<ButtonImpl>(parent);
}
auto create_vertical_layout(Widget* parent) -> unique_ptr<AlignedLayout>
{
return make_unique<AlignedLayoutImpl<LayoutAlignment::VERTICAL>>(parent);
}
auto bwidgets::create_caption(Widget* parent) -> std::unique_ptr<Caption>
{
return std::make_unique<CaptionImpl>(parent);
}
auto create_button(Widget* parent) -> unique_ptr<Button>
{
return make_unique<ButtonImpl>(parent);
}
auto bwidgets::create_input_float(Widget* parent) -> std::unique_ptr<NumericInput<float>>
{
return std::make_unique<NumericInputImpl<float>>(parent);
}
auto create_caption(Widget* parent) -> unique_ptr<Caption>
{
return make_unique<CaptionImpl>(parent);
}
auto bwidgets::create_scrollbar(Widget* parent) -> std::unique_ptr<ScrollBar>
{
return std::make_unique<ScrollBarImpl>(parent);
}
auto create_input_float(Widget* parent) -> unique_ptr<NumericInput<float>>
{
return make_unique<NumericInputImpl<float>>(parent);
}
auto bwidgets::create_input_int(Widget* parent) -> std::unique_ptr<NumericInput<int>>
{
return std::make_unique<NumericInputImpl<int>>(parent);
auto create_scrollable_area(Widget* parent) -> unique_ptr<ScrollableArea>
{
return make_unique<ScrollableAreaImpl>(parent);
}
auto create_scrollbar(Widget* parent) -> unique_ptr<ScrollBar>
{
return make_unique<ScrollBarImpl>(parent);
}
auto create_input_int(Widget* parent) -> unique_ptr<NumericInput<int>>
{
return make_unique<NumericInputImpl<int>>(parent);
}
}