Add default toggle button implementation

This commit is contained in:
Nikita Lisitsa 2023-01-04 21:14:14 +03:00
parent 42e1136123
commit cdbe162521
2 changed files with 138 additions and 0 deletions

View file

@ -21,6 +21,7 @@ namespace psemek::ui
std::shared_ptr<frame> make_frame() override;
std::shared_ptr<window> make_window(std::string caption) override;
std::shared_ptr<checkbox> make_checkbox(bool value) override;
std::shared_ptr<checkbox> make_toggle_button() override;
std::shared_ptr<slider> make_slider() override;
std::shared_ptr<spinbox> make_spinbox() override;
std::shared_ptr<button> make_arrow_button(int direction) override;

View file

@ -577,6 +577,138 @@ namespace psemek::ui
}
};
struct toggle_button_impl
: checkbox
{
struct shape const & shape() const override
{
return shape_;
}
void reshape(geom::box<float, 2> const & bbox) override
{
shape_.box = bbox;
auto st = merged_own_style();
geom::vector offset{0.f, 0.f};
if (state() == state_t::mousedown || value())
offset = geom::cast<float>(*st->action_offset);
auto c = child_.get();
if (c) c->reshape(geom::shrink(bbox, geom::vector<float, 2>{*st->border_width + (*st->inner_margin)[0], *st->border_width + (*st->inner_margin)[1]}) + offset);
}
void on_state_changed(state_t old) override
{
checkbox::on_state_changed(old);
gfx::color_rgba color{0, 0, 0, 0};
switch (state()) {
case state_t::mouseover:
color = {255, 255, 255, 63};
break;
case state_t::mousedown:
color = {0, 0, 0, 63};
break;
default:
break;
}
if (value())
color = {0, 0, 0, 63};
if (icon())
icon()->set_color(color);
}
void draw(painter & p) const override
{
auto st = merged_own_style();
if (!st) return;
if (st->shadow_offset != geom::vector{0, 0})
p.draw_rect(shape_.box + geom::cast<float>(*st->shadow_offset), *st->shadow_color);
auto offset = geom::vector{0.f, 0.f};
if (state() == state_t::mousedown || value())
offset = geom::cast<float>(*st->action_offset);
if (st->border_width > 0)
p.draw_rect(shape_.box + offset, *st->border_color);
gfx::color_rgba color = *st->fg_color;
if (state() == state_t::mouseover)
color = *st->highlight_color;
else if (state() == state_t::mousedown || value())
color = *st->action_color;
p.draw_rect(geom::shrink(shape_.box, 1.f * (*st->border_width)) + offset, color);
}
geom::box<float, 2> size_constraints() const override
{
auto sc = element::size_constraints();
if (child_)
{
auto csc = child_->size_constraints();
sc[0].min = csc[0].min;
sc[1].min = csc[1].min;
}
if (auto st = merged_own_style())
{
sc[0] += 2.f * (*st->border_width);
sc[1] += 2.f * (*st->border_width);
sc += 2.f * geom::cast<float>(*st->inner_margin);
}
return sc;
}
geom::interval<float> width_constraints(float height) const override
{
auto wc = element::width_constraints(height);
auto st = merged_own_style();
float extra = 2.f * (*st->border_width) + 2.f * geom::cast<float>(*st->inner_margin)[0];
if (child_)
{
auto cwc = child_->width_constraints(height - extra);
wc.min = cwc.min;
}
wc += extra;
return wc;
}
geom::interval<float> height_constraints(float width) const override
{
auto hc = element::height_constraints(width);
auto st = merged_own_style();
float extra = 2.f * (*st->border_width) + 2.f * geom::cast<float>(*st->inner_margin)[1];
if (child_)
{
auto chc = child_->height_constraints(width - extra);
hc.min = chc.min;
}
hc += extra;
return hc;
}
private:
box_shape shape_;
};
struct slider_impl
: slider
{
@ -934,6 +1066,11 @@ namespace psemek::ui
return c;
}
std::shared_ptr<checkbox> default_element_factory::make_toggle_button()
{
return std::make_shared<toggle_button_impl>();
}
std::shared_ptr<slider> default_element_factory::make_slider()
{
return std::make_shared<slider_impl>();