scrollable (texture) area works
This commit is contained in:
parent
af7b9803d2
commit
3f15d1d857
|
@ -8,7 +8,7 @@ auto main() -> int
|
|||
{
|
||||
run_example<bwidgets::Button>(
|
||||
[]() { return bwidgets::create_button(); },
|
||||
[](auto w, auto f, auto x, auto y) {
|
||||
[](auto w, auto f, auto x, auto y, auto) {
|
||||
w->click_handler([x, y](const SDL_MouseButtonEvent&) {
|
||||
std::cout << "button(" << x << ',' << y << "):click!" << std::endl;
|
||||
});
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
auto main() -> int
|
||||
{
|
||||
run_example<bwidgets::Caption>([]() { return bwidgets::create_caption(); },
|
||||
[](auto w, auto f, auto, auto) {
|
||||
[](auto w, auto f, auto, auto, auto) {
|
||||
w->alignment(
|
||||
bwidgets::Caption::Alignment::CENTER);
|
||||
w->text("¡jello!");
|
||||
|
|
|
@ -5,7 +5,7 @@ auto main() -> int
|
|||
{
|
||||
run_example<Example>(
|
||||
[]() { return std::make_unique<Example>(); },
|
||||
[](auto w, auto, auto x, auto y) {
|
||||
[](auto w, auto, auto x, auto y, auto) {
|
||||
w->cycle_r = (x + 1) * 3000; // NOLINT(readability-magic-numbers)
|
||||
w->cycle_b = (y + 1) * 3000; // NOLINT(readability-magic-numbers)
|
||||
w->cycle_b = (1 + x + y) * (y + 1) * 400; // NOLINT(readability-magic-numbers)
|
||||
|
|
|
@ -6,7 +6,7 @@ auto main() -> int
|
|||
{
|
||||
run_example<bwidgets::NumericInput<float>>(
|
||||
[]() { return bwidgets::create_input_float(); },
|
||||
[](auto w, auto f, auto, auto) {
|
||||
[](auto w, auto f, auto, auto, auto) {
|
||||
w->font(f);
|
||||
w->button_step = 0.5; // NOLINT(readability-magic-numbers)
|
||||
w->value_range(-3.14, 8.5); // NOLINT(readability-magic-numbers)
|
||||
|
|
|
@ -11,10 +11,11 @@ template<typename T>
|
|||
concept WidgetType = std::derived_from<T, bwidgets::Widget>;
|
||||
|
||||
template<WidgetType W>
|
||||
void run_example(
|
||||
std::function<std::unique_ptr<W>()> factory,
|
||||
std::function<void(W*, const std::shared_ptr<bwidgets::Font>, int, int)> setup,
|
||||
int w = 3, int h = 3)
|
||||
void run_example(std::function<std::unique_ptr<W>()> factory,
|
||||
std::function<void(W*, const std::shared_ptr<bwidgets::Font>&, int, int,
|
||||
const std::shared_ptr<bwidgets::Renderer>)>
|
||||
setup,
|
||||
int w = 3, int h = 3)
|
||||
{
|
||||
std::atexit([]() {
|
||||
TTF_Quit();
|
||||
|
@ -43,7 +44,7 @@ void run_example(
|
|||
auto col = bwidgets::create_vertical_layout();
|
||||
for (auto y = 0; y < h; y++) {
|
||||
auto widget = factory();
|
||||
setup(widget.get(), font, x, y);
|
||||
setup(widget.get(), font, x, y, renderer);
|
||||
col->add_widget(std::move(widget));
|
||||
}
|
||||
layout->add_widget(std::move(col));
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include <basic_widgets/core/draw.hpp>
|
||||
#include <basic_widgets/w/widget_factory.hpp>
|
||||
|
||||
#include "run.hpp"
|
||||
|
@ -6,6 +7,9 @@ auto main() -> int
|
|||
{
|
||||
run_example<bwidgets::ScrollableArea>(
|
||||
[]() { return bwidgets::create_scrollable_area(); },
|
||||
[](auto w, auto f, auto x, auto y) { w->font(f); });
|
||||
[](auto w, auto f, auto x, auto y, auto r) {
|
||||
w->font(f);
|
||||
w->texture(bwidgets::filled_circle({255, 0, 0, 255}, 300, *r));
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,19 @@
|
|||
#include <iostream>
|
||||
|
||||
#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) {});
|
||||
run_example<bwidgets::ScrollBar>([]() { return bwidgets::create_scrollbar(); },
|
||||
[](auto w, auto f, auto x, auto y, auto) {
|
||||
w->font(f);
|
||||
w->on_scroll([x, y](const float v) {
|
||||
std::cout << "Scroll(" << x << "," << y
|
||||
<< "): " << v * 100 << "%"
|
||||
<< std::endl;
|
||||
});
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -20,11 +20,13 @@ namespace bwidgets
|
|||
VERTICAL
|
||||
};
|
||||
|
||||
virtual void on_scroll(std::function<void(int)>) = 0;
|
||||
[[nodiscard]] virtual auto orientation() const -> Orientation = 0;
|
||||
virtual void orientation(Orientation) = 0;
|
||||
[[nodiscard]] virtual auto value() const -> int = 0;
|
||||
virtual void value(int) = 0;
|
||||
virtual void on_scroll(std::function<void(float)>) = 0;
|
||||
[[nodiscard]] virtual auto orientation() const -> Orientation = 0;
|
||||
virtual void orientation(Orientation) = 0;
|
||||
[[nodiscard]] virtual auto step() const -> float = 0;
|
||||
virtual void step(float) = 0;
|
||||
[[nodiscard]] virtual auto value() const -> float = 0;
|
||||
virtual void value(float) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -22,22 +22,25 @@ namespace bwidgets
|
|||
|
||||
auto cursor_area() const -> SDL_Rect;
|
||||
void handle_event(const SDL_Event&) override;
|
||||
void on_scroll(std::function<void(int)>) override;
|
||||
void on_scroll(std::function<void(float)>) override;
|
||||
[[nodiscard]] auto orientation() const -> Orientation override;
|
||||
void orientation(Orientation) override;
|
||||
[[nodiscard]] auto size() const noexcept -> Size override;
|
||||
[[nodiscard]] auto value() const -> int override;
|
||||
void value(int) override;
|
||||
[[nodiscard]] auto step() const -> float override;
|
||||
void step(float) override;
|
||||
[[nodiscard]] auto value() const -> float override;
|
||||
void value(float) override;
|
||||
|
||||
protected:
|
||||
SDL_Rect _bar_area;
|
||||
std::unique_ptr<Button> _button_minus;
|
||||
std::unique_ptr<Button> _button_plus;
|
||||
const Size _cursor_size {16, 16};
|
||||
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};
|
||||
std::function<void(float)> _on_scroll;
|
||||
Orientation _orientation;
|
||||
float _step;
|
||||
float _value {0};
|
||||
|
||||
void _handle_font_change(const std::shared_ptr<Font>&) override;
|
||||
void _handle_font_color_change(Color, Color) override;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <utility>
|
||||
|
||||
#include <basic_widgets/core/draw.hpp>
|
||||
#include <basic_widgets/core/math.hpp>
|
||||
#include <basic_widgets/w/scrollable_area_impl.hpp>
|
||||
#include <basic_widgets/w/widget_factory.hpp>
|
||||
|
||||
|
@ -68,6 +69,30 @@ void ScrollableAreaImpl::_handle_rendering()
|
|||
{
|
||||
fill_rect_gradient(*renderer(), _texture_area, theme()->color_widget_border(),
|
||||
theme()->color_widget_bg(), theme()->size_widget_border());
|
||||
|
||||
const auto texture_attr = _texture->attributes();
|
||||
const auto copy_dst = [this, &texture_attr]() {
|
||||
auto dst = rect_margin(
|
||||
_texture_area, {theme()->size_widget_border(), theme()->size_widget_border()});
|
||||
if (dst.w > texture_attr.w) {
|
||||
dst.x += center_line(dst.w, texture_attr.w);
|
||||
dst.w = texture_attr.w;
|
||||
}
|
||||
if (dst.h > texture_attr.h) {
|
||||
dst.y += center_line(dst.h, texture_attr.h);
|
||||
dst.h = texture_attr.h;
|
||||
}
|
||||
return dst;
|
||||
}();
|
||||
renderer()->copy(
|
||||
*_texture,
|
||||
{static_cast<int>(_scrollbar_h->value()
|
||||
* std::clamp(texture_attr.w - copy_dst.w, 0, texture_attr.w)),
|
||||
static_cast<int>(_scrollbar_v->value()
|
||||
* std::clamp(texture_attr.h - copy_dst.h, 0, texture_attr.h)),
|
||||
copy_dst.w, copy_dst.h},
|
||||
copy_dst);
|
||||
|
||||
_scrollbar_h->render();
|
||||
_scrollbar_v->render();
|
||||
}
|
||||
|
|
|
@ -30,21 +30,22 @@ ScrollBarImpl::ScrollBarImpl(Widget* parent)
|
|||
: WidgetImpl {parent},
|
||||
_button_minus {create_button(this)},
|
||||
_button_plus {create_button(this)},
|
||||
_orientation {Orientation::VERTICAL}
|
||||
_orientation {Orientation::VERTICAL},
|
||||
_step {.05F}
|
||||
{
|
||||
_button_minus->text("▲");
|
||||
_button_plus->text("▼");
|
||||
|
||||
_button_minus->click_handler([this](auto) { value(value() - 5); });
|
||||
_button_plus->click_handler([this](auto) { value(value() + 5); });
|
||||
_button_minus->click_handler([this](auto) { value(value() - _step); });
|
||||
_button_plus->click_handler([this](auto) { value(value() + _step); });
|
||||
click_handler([this](const SDL_MouseButtonEvent ev) {
|
||||
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 / _bar_area.h);
|
||||
value(p.y / static_cast<float>(_bar_area.h));
|
||||
}
|
||||
else {
|
||||
value(p.x * 100 / _bar_area.w);
|
||||
value(p.x / static_cast<float>(_bar_area.w));
|
||||
}
|
||||
});
|
||||
mouse_motion_handler([this](SDL_MouseMotionEvent ev) {
|
||||
|
@ -52,20 +53,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(clamp(p.y, 0, _bar_area.h) * 100 / _bar_area.h);
|
||||
value(clamp(p.y, 0, _bar_area.h) / static_cast<float>(_bar_area.h));
|
||||
}
|
||||
else {
|
||||
value(clamp(p.x, 0, _bar_area.w) * 100 / _bar_area.w);
|
||||
value(clamp(p.x, 0, _bar_area.w) / static_cast<float>(_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);
|
||||
if (ev.y < 0) value(value() + _step);
|
||||
else if (ev.y > 0) value(value() - _step);
|
||||
}
|
||||
else {
|
||||
if (ev.x > 0) value(value() + 5);
|
||||
else if (ev.x < 0) value(value() - 5);
|
||||
if (ev.x > 0) value(value() + _step);
|
||||
else if (ev.x < 0) value(value() - _step);
|
||||
}
|
||||
});
|
||||
enable_mouse_handler(_bar_area, viewport());
|
||||
|
@ -74,11 +75,11 @@ ScrollBarImpl::ScrollBarImpl(Widget* parent)
|
|||
auto ScrollBarImpl::cursor_area() const -> SDL_Rect
|
||||
{
|
||||
if (_orientation == Orientation::VERTICAL) {
|
||||
const auto offset = value() * _bar_area.h / 100;
|
||||
const auto offset = static_cast<int>(value() * _bar_area.h);
|
||||
return {_bar_area.x, _bar_area.y + offset - _cursor_size.h / 2, _bar_area.w,
|
||||
_cursor_size.h};
|
||||
}
|
||||
const auto offset = value() * _bar_area.w / 100;
|
||||
const auto offset = static_cast<int>(value() * _bar_area.w);
|
||||
return {_bar_area.x + offset - _cursor_size.h / 2, _bar_area.y, _cursor_size.h,
|
||||
_bar_area.h};
|
||||
}
|
||||
|
@ -90,7 +91,7 @@ void ScrollBarImpl::handle_event(const SDL_Event& ev)
|
|||
_button_plus->handle_event(ev);
|
||||
}
|
||||
|
||||
void ScrollBarImpl::on_scroll(function<void(int)> cb)
|
||||
void ScrollBarImpl::on_scroll(function<void(float)> cb)
|
||||
{
|
||||
_on_scroll = move(cb);
|
||||
}
|
||||
|
@ -136,14 +137,24 @@ auto ScrollBarImpl::size() const noexcept -> Size
|
|||
return {height, button_size + button_size + 3 * _cursor_size.h};
|
||||
}
|
||||
|
||||
auto ScrollBarImpl::value() const -> int
|
||||
auto ScrollBarImpl::step() const -> float
|
||||
{
|
||||
return _step;
|
||||
}
|
||||
|
||||
void ScrollBarImpl::step(float s)
|
||||
{
|
||||
_step = s;
|
||||
}
|
||||
|
||||
auto ScrollBarImpl::value() const -> float
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
void ScrollBarImpl::value(const int v)
|
||||
void ScrollBarImpl::value(const float v)
|
||||
{
|
||||
const auto new_value = clamp(v, 0, 100);
|
||||
const auto new_value = clamp(v, 0.F, 1.F);
|
||||
if (new_value != _value) {
|
||||
_value = new_value;
|
||||
if (_on_scroll) _on_scroll(new_value);
|
||||
|
|
Loading…
Reference in a new issue