Add ui::color_picker composite element
This commit is contained in:
parent
5af0c66599
commit
8e0c27c8c0
2 changed files with 209 additions and 0 deletions
28
libs/ui/include/psemek/ui/color_picker.hpp
Normal file
28
libs/ui/include/psemek/ui/color_picker.hpp
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
#include <psemek/ui/element.hpp>
|
||||
#include <psemek/ui/single_container.hpp>
|
||||
#include <psemek/ui/element_factory.hpp>
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace psemek::ui
|
||||
{
|
||||
|
||||
struct color_picker
|
||||
: single_container
|
||||
{
|
||||
virtual gfx::color_rgba color() const = 0;
|
||||
virtual void set_color(gfx::color_rgba value, bool notify = true) = 0;
|
||||
|
||||
using on_value_changed_callback = std::function<void(gfx::color_rgba)>;
|
||||
|
||||
virtual void on_value_changed(on_value_changed_callback callback) { on_value_changed_callback_ = callback; }
|
||||
|
||||
protected:
|
||||
on_value_changed_callback on_value_changed_callback_;
|
||||
};
|
||||
|
||||
std::shared_ptr<color_picker> make_color_picker(element_factory & factory);
|
||||
|
||||
}
|
||||
181
libs/ui/source/color_picker.cpp
Normal file
181
libs/ui/source/color_picker.cpp
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
#include <psemek/ui/color_picker.hpp>
|
||||
#include <psemek/ui/frame.hpp>
|
||||
#include <psemek/ui/color_view.hpp>
|
||||
#include <psemek/ui/grid_layout.hpp>
|
||||
#include <psemek/ui/slider.hpp>
|
||||
#include <psemek/ui/label.hpp>
|
||||
#include <psemek/ui/screen.hpp>
|
||||
#include <psemek/util/to_string.hpp>
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace psemek::ui
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct color_picker_impl
|
||||
: color_picker
|
||||
{
|
||||
color_picker_impl(element_factory & factory)
|
||||
{
|
||||
auto frame = std::make_shared<ui::frame>();
|
||||
frame->set_min_size(geom::vector{250.f, 0.f});
|
||||
|
||||
auto main_layout = factory.make_grid_layout();
|
||||
main_layout->set_size(1, 2);
|
||||
main_layout->set_column_weight(0, 0.f);
|
||||
main_layout->set_outer_margin(false);
|
||||
main_layout->set_width_first(false);
|
||||
|
||||
color_view_ = std::make_shared<ui::color_view>();
|
||||
color_view_->set_square(true);
|
||||
|
||||
auto sliders_layout = factory.make_grid_layout();
|
||||
sliders_layout->set_size(3, 2);
|
||||
sliders_layout->set_column_weight(0, 0.f);
|
||||
sliders_layout->set_outer_margin(false);
|
||||
|
||||
hidden_label_ = factory.make_label("000");
|
||||
hidden_label_->set_hidden(true);
|
||||
|
||||
auto hidden_screen = factory.make_screen();
|
||||
hidden_screen->add_child(hidden_label_, screen::x_policy::fill, screen::y_policy::fill);
|
||||
|
||||
red_label_ = factory.make_label("");
|
||||
red_label_->set_halign(label::halignment::right);
|
||||
red_label_->set_valign(label::valignment::center);
|
||||
|
||||
green_label_ = factory.make_label("");
|
||||
green_label_->set_halign(label::halignment::right);
|
||||
green_label_->set_valign(label::valignment::center);
|
||||
|
||||
blue_label_ = factory.make_label("");
|
||||
blue_label_->set_halign(label::halignment::right);
|
||||
blue_label_->set_valign(label::valignment::center);
|
||||
|
||||
auto slider_callback = [this](int){
|
||||
set_color(color(), true);
|
||||
};
|
||||
|
||||
red_slider_ = factory.make_slider();
|
||||
red_slider_->set_value_range({0, 255}, false);
|
||||
red_slider_->on_value_changed(slider_callback, false);
|
||||
|
||||
green_slider_ = factory.make_slider();
|
||||
green_slider_->set_value_range({0, 255}, false);
|
||||
green_slider_->on_value_changed(slider_callback, false);
|
||||
|
||||
blue_slider_ = factory.make_slider();
|
||||
blue_slider_->set_value_range({0, 255}, false);
|
||||
blue_slider_->on_value_changed(slider_callback, false);
|
||||
|
||||
hidden_screen->add_child(red_label_, screen::x_policy::fill, screen::y_policy::fill);
|
||||
|
||||
sliders_layout->set(0, 0, hidden_screen);
|
||||
sliders_layout->set(1, 0, green_label_);
|
||||
sliders_layout->set(2, 0, blue_label_);
|
||||
sliders_layout->set(0, 1, red_slider_);
|
||||
sliders_layout->set(1, 1, green_slider_);
|
||||
sliders_layout->set(2, 1, blue_slider_);
|
||||
|
||||
main_layout->set(0, 0, color_view_);
|
||||
main_layout->set(0, 1, sliders_layout);
|
||||
|
||||
frame->set_child(main_layout);
|
||||
|
||||
set_child(frame);
|
||||
}
|
||||
|
||||
struct shape const & shape() const override
|
||||
{
|
||||
return child_->shape();
|
||||
}
|
||||
|
||||
void reshape(geom::box<float, 2> const & box) override
|
||||
{
|
||||
child_->reshape(box);
|
||||
}
|
||||
|
||||
void draw(painter &) const override
|
||||
{}
|
||||
|
||||
geom::box<float, 2> size_constraints() const override
|
||||
{
|
||||
return child_->size_constraints();
|
||||
}
|
||||
|
||||
geom::interval<float> width_constraints(float height) const override
|
||||
{
|
||||
return child_->width_constraints(height);
|
||||
}
|
||||
|
||||
geom::interval<float> height_constraints(float width) const override
|
||||
{
|
||||
return child_->height_constraints(width);
|
||||
}
|
||||
|
||||
gfx::color_rgba color() const override
|
||||
{
|
||||
return {
|
||||
red_slider_->value(),
|
||||
green_slider_->value(),
|
||||
blue_slider_->value(),
|
||||
255
|
||||
};
|
||||
}
|
||||
|
||||
void set_color(gfx::color_rgba value, bool notify) override
|
||||
{
|
||||
color_view_->set_color(value);
|
||||
|
||||
red_label_ ->set_tagged_text(util::to_string("[color:f00]", static_cast<int>(value[0]), "[/color]"));
|
||||
green_label_->set_tagged_text(util::to_string("[color:0f0]", static_cast<int>(value[1]), "[/color]"));
|
||||
blue_label_ ->set_tagged_text(util::to_string("[color:00f]", static_cast<int>(value[2]), "[/color]"));
|
||||
|
||||
red_slider_->set_value(value[0], false);
|
||||
green_slider_->set_value(value[1], false);
|
||||
blue_slider_->set_value(value[2], false);
|
||||
|
||||
if (notify && on_value_changed_callback_)
|
||||
post([cb = on_value_changed_callback_, value]{ cb(value); });
|
||||
}
|
||||
|
||||
void style_updated() const override
|
||||
{
|
||||
color_picker::style_updated();
|
||||
|
||||
auto st = merged_own_style();
|
||||
if (!st->font) return;
|
||||
|
||||
auto glyphs = st->font->shape("0123456789", {});
|
||||
|
||||
float max_width = 0.f;
|
||||
char max_width_char = '0';
|
||||
for (auto const & g : glyphs)
|
||||
if (geom::make_max(max_width, g.position[0].length()))
|
||||
max_width_char = g.character;
|
||||
|
||||
hidden_label_->set_text(std::string(3, max_width_char));
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<color_view> color_view_;
|
||||
std::shared_ptr<label> hidden_label_;
|
||||
std::shared_ptr<label> red_label_;
|
||||
std::shared_ptr<label> green_label_;
|
||||
std::shared_ptr<label> blue_label_;
|
||||
std::shared_ptr<slider> red_slider_;
|
||||
std::shared_ptr<slider> green_slider_;
|
||||
std::shared_ptr<slider> blue_slider_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
std::shared_ptr<color_picker> make_color_picker(element_factory & factory)
|
||||
{
|
||||
return std::make_shared<color_picker_impl>(factory);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue