Default ui element factory supports arrow buttons

This commit is contained in:
Nikita Lisitsa 2021-03-05 23:13:57 +03:00
parent fec050307d
commit 3faccd1256
2 changed files with 94 additions and 1 deletions

View file

@ -18,6 +18,13 @@ namespace psemek::ui
std::shared_ptr<window> make_window(std::string caption) override;
std::shared_ptr<slider> make_slider() override;
// directions:
// 0 - up
// 1 - down
// 2 - left
// 3 - right
std::shared_ptr<button> make_arrow_button(int direction);
private:
psemek_declare_pimpl
};

View file

@ -5,7 +5,6 @@
#include <psemek/ui/resources/cross_red_16x16_png.hpp>
namespace psemek::ui
{
@ -395,6 +394,88 @@ namespace psemek::ui
}
};
struct arrow_button_impl
: button
{
arrow_button_impl(int direction)
: direction_{direction}
{}
geom::box<float, 2> size_constraints() const override
{
auto b = button::size_constraints();
auto st = merged_style();
b[0].min = *st->ref_height / 2.f;
b[1].min = *st->ref_height / 2.f;
return b;
}
struct shape const & shape() const override
{
return shape_;
}
void reshape(geom::box<float, 2> const & box) override
{
shape_.box = box;
switch (direction_)
{
case 0:
triangle_[0] = box.corner(0.f, 1.f);
triangle_[1] = box.corner(1.f, 1.f);
triangle_[2] = box.corner(0.5f, 0.f);
break;
case 1:
triangle_[0] = box.corner(0.f, 0.f);
triangle_[1] = box.corner(1.f, 0.f);
triangle_[2] = box.corner(0.5f, 1.f);
break;
case 2:
triangle_[0] = box.corner(1.f, 0.f);
triangle_[1] = box.corner(1.f, 1.f);
triangle_[2] = box.corner(0.f, 0.5f);
break;
case 3:
triangle_[0] = box.corner(0.f, 0.f);
triangle_[1] = box.corner(0.f, 1.f);
triangle_[2] = box.corner(1.f, 0.5f);
break;
default:
throw std::runtime_error("Unknown arrow button direction");
}
if (geom::volume(triangle_[0], triangle_[1], triangle_[2]) < 0.f)
std::swap(triangle_[1], triangle_[2]);
}
void draw(painter &p) const override
{
auto st = merged_style();
if (*st->shadow_offset != geom::vector{0, 0})
p.draw_triangle(triangle_ + geom::cast<float>(*st->shadow_offset), *st->shadow_color);
geom::vector off{0.f, 0.f};
if (state() == state_t::mousedown)
off = geom::cast<float>(*st->action_offset);
gfx::color_rgba color = *st->fg_color;
if (state() == state_t::mouseover)
color = *st->highlight_color;
else if (state() == state_t::mousedown)
color = *st->action_color;
p.draw_triangle(triangle_ + off, color);
}
private:
int const direction_;
box_shape shape_;
geom::triangle<geom::point<float, 2>> triangle_;
};
}
struct default_element_factory::impl
@ -440,4 +521,9 @@ namespace psemek::ui
return std::make_shared<slider_impl>();
}
std::shared_ptr<button> default_element_factory::make_arrow_button(int direction)
{
return std::make_shared<arrow_button_impl>(direction);
}
}