Redesign ColorPicker widget with the new slider capabilities in mind.

This commit is contained in:
2025-06-24 01:57:53 -05:00
parent 9d901c6300
commit 96239db592
2 changed files with 160 additions and 130 deletions

View File

@@ -8,153 +8,52 @@
#include "../Style/TextStyler.hpp"
#include <JUI/Widgets/Slider.hpp>
namespace JUI {
#include "Window.hpp"
std::string rgb2hex(int r, int g, int b, bool with_head)
{
std::stringstream ss;
if (with_head)
ss << "#";
ss << std::hex << (r << 16 | g << 8 | b );
return ss.str();
}
/// TODO: Move to a utility library or something...
/// Converts a set of R,G,B values to it's hexadecimal string representation.
std::string rgb2hex(int r, int g, int b, bool with_head);
namespace JUI {
/// A JUI Widget that displays a HSV color input dialog.
class ColorPicker : public Rect, public TextStyler {
public:
void Font(const JGL::Font &value) override {
TextStyler::Font(value);
hue_label->Font(value);
sat_label->Font(value);
bri_label->Font(value);
hex_label->Font(value);
}
/// Sets the font of the text elements contained in this widget.
void Font(const JGL::Font &value) override;
/// Sets the point size of the text elements contained in this widget.
void TextSize(int size) override;
/// Sets the point size of the text elements contained in this widget.
void TextColor(const Color4 &color) override;
void TextSize(int size) override {
TextStyler::TextSize(size);
hue_label->TextSize(size);
sat_label->TextSize(size);
bri_label->TextSize(size);
hex_label->TextSize(size);
}
void TextColor(const Color4 &color) override {
TextStyler::TextColor(color);
hue_label->TextColor(color);
sat_label->TextColor(color);
bri_label->TextColor(color);
hex_label->TextColor(color);
}
Event<Color4> OnColorValueChanged;
void SetColorValue(const Color4& color);
Color4 GetColorValue() const;
float hue = 0;
float sat = 1.f;
float bri = 1.f; // AKA val
ColorPicker() : Rect() {
Name("ColorPicker");
ColorPicker();
Size({100_percent, 100_percent});
auto* row_layout = new JUI::VerticalListLayout(this);
row_layout->Padding(5_px);
explicit ColorPicker(Widget* parent);
hue_slider = new JUI::Slider(row_layout);
hue_slider->Size({100_percent, 28_px});
hue_slider->Minimum(0.f); hue_slider->Maximum(360);
hue_slider->Interval(1e-3f);
hue_slider->ValueChanged += [this] (float val) mutable {
//val = val*360;
hue_label->Content(std::format("Hue: {}", Math::FloorInt(val)));
hue = val;
hue_slider->ScrubberColor(Color4::FromHSV(hue, 1.f, 1.f));
OnColorValueChanged.Invoke(Color4::FromHSV(hue, sat, bri));
Color4 computed = Color4::FromHSV(hue, sat, bri);
hex_label->TextColor(computed);
hex_label->Content(std::format("{}", rgb2hex(computed.r, computed.g, computed.b, true)));
};
hue_label = new JUI::Text(hue_slider);
hue_label->AlignCenterHorizontally();
hue_label->AlignTop();
hue_label->TextColor(Colors::Black);
hue_label->Content("Hue: 0");
sat_slider = new JUI::Slider(row_layout);
sat_slider->Size({100_percent, 28_px});
sat_slider->Minimum(0); sat_slider->Maximum(1);
sat_slider->Interval(1e-3f);
sat_slider->ValueChanged += [this] (float val) mutable {
sat_label->Content(std::format("Saturation: {}%", Math::Floor(val*100.f)));
sat = val;
OnColorValueChanged.Invoke(Color4::FromHSV(hue, sat, bri));
Color4 computed = Color4::FromHSV(hue, sat, bri);
hex_label->TextColor(computed);
hex_label->Content(std::format("{}", rgb2hex(computed.r, computed.g, computed.b, true)));
};
sat_label = new JUI::Text(sat_slider);
sat_label->AlignCenterHorizontally();
sat_label->AlignTop();
sat_label->TextColor(Colors::Black);
sat_label->Content("Saturation: 100%");
bri_slider = new JUI::Slider(row_layout);
bri_slider->Size({100_percent, 28_px});
bri_slider->Minimum(0); bri_slider->Maximum(1);
bri_slider->Interval(1e-3f);
bri_slider->ValueChanged += [this] (float val) mutable {
bri_label->Content(std::format("Brightness: {}%", Math::Floor(val*100.f)));
bri = val;
OnColorValueChanged.Invoke(Color4::FromHSV(hue, sat, bri));
Color4 computed = Color4::FromHSV(hue, sat, bri);
hex_label->TextColor(computed);
hex_label->Content(std::format("{}", rgb2hex(computed.r, computed.g, computed.b, true)));
};
bri_label = new JUI::Text(bri_slider);
bri_label->AlignCenterHorizontally();
bri_label->AlignTop();
bri_label->TextColor(Colors::Black);
bri_label->Content("Brightness: 100%");
//auto* hue_box = new JUI::Rect();
hex_label = new JUI::TextRect(row_layout);
hex_label->AlignCenterHorizontally();
hex_label->Size({100_percent, 28_px});
hex_label->Content("#FFZZGG");
}
explicit ColorPicker(Widget* parent) : ColorPicker() {
Parent(parent);
}
public: /// Subcomponents.
/*JUI::Text* HueLabel() { return hue_label; }
JUI::Text* SatLabel() { return sat_label; }
JUI::Text* BriLabel() { return bri_label; }
JUI::Slider* HueSlider() { return hue_slider; }
JUI::Slider* SatSlider() { return sat_slider; }
JUI::Slider* BriSlider() { return bri_slider; }
JUI::TextRect* HexLabel() { return hex_label; }*/
protected:
/// Calculates the colors of the label, and the inverse color for the text.
void RecomputeVisuals();
/// Applies this widget's specific styling to it's slider sub-components.
void StyleSlider(Slider* slider);
JUI::Slider* hue_slider = nullptr;
JUI::Slider* sat_slider = nullptr;
JUI::Slider* bri_slider = nullptr;

View File

@@ -1,3 +1,134 @@
//
// Created by dawsh on 5/1/25.
//
#include <JUI/Widgets/ColorPicker.hpp>
std::string rgb2hex(int r, int g, int b, bool with_head) {
std::stringstream ss;
if (with_head)
ss << "#";
ss << std::hex << (r << 16 | g << 8 | b );
return ss.str();
}
void JUI::ColorPicker::Font(const JGL::Font &value) {
TextStyler::Font(value);
hue_label->Font(value);
sat_label->Font(value);
bri_label->Font(value);
hex_label->Font(value);
}
void JUI::ColorPicker::TextSize(int size) {
TextStyler::TextSize(size);
hue_label->TextSize(size);
sat_label->TextSize(size);
bri_label->TextSize(size);
hex_label->TextSize(size);
}
void JUI::ColorPicker::TextColor(const Color4 &color) {
TextStyler::TextColor(color);
hue_label->TextColor(color);
sat_label->TextColor(color);
bri_label->TextColor(color);
hex_label->TextColor(color);
}
void JUI::ColorPicker::StyleSlider(Slider *slider) {
slider->ScrubberSize({16_px, 16_px});
slider->CornerRounding(8);
slider->BGColor(Colors::DarkGray);
slider->ScrubberRounding(8);
slider->Size({100_percent-10_px, 16_px});
}
JUI::ColorPicker::ColorPicker(): Rect() {
Name("ColorPicker");
Size({100_percent, 100_percent});
//auto* row_layout = new JUI::VerticalListLayout(this);
hue_slider = new JUI::Slider(this);
StyleSlider(hue_slider);
hue_slider->Position({50_percent, 4_px});
hue_slider->AnchorPoint({0.5f, 0.f});
hue_slider->Minimum(0.f);
hue_slider->Maximum(360);
hue_slider->Interval(1.f / 360.f);
hue_slider->ValueChanged += [this] (float val) mutable {
hue_label->Content(std::format("Hue: {}", Math::FloorInt(val)));
hue = val;
hue_slider->ScrubberColor(Color4::FromHSV(hue, 1.f, 1.f));
OnColorValueChanged.Invoke(Color4::FromHSV(hue, sat, bri));
RecomputeVisuals();
};
hue_label = new JUI::Text(hue_slider);
hue_label->AlignCenterHorizontally();
hue_label->AlignTop();
hue_label->TextColor(Colors::White);
hue_label->Content("Hue: 0");
sat_slider = new JUI::Slider(this);
StyleSlider(sat_slider);
sat_slider->Position({50_percent, 24_px});
sat_slider->AnchorPoint({0.5f, 0.f});
sat_slider->Minimum(0);
sat_slider->Maximum(1);
sat_slider->Interval(1e-3f);
sat_slider->ValueChanged += [this] (float val) mutable {
sat_label->Content(std::format("Saturation: {}%", Math::Floor(val*100.f)));
sat = val;
OnColorValueChanged.Invoke(Color4::FromHSV(hue, sat, bri));
RecomputeVisuals();
};
sat_label = new JUI::Text(sat_slider);
sat_label->AlignCenterHorizontally();
sat_label->AlignTop();
sat_label->TextColor(Colors::White);
sat_label->Content("Saturation: 100%");
bri_slider = new JUI::Slider(this);
StyleSlider(bri_slider);
bri_slider->Position({50_percent, 44_px});
bri_slider->AnchorPoint({0.5f, 0.f});
bri_slider->Minimum(0);
bri_slider->Maximum(1);
bri_slider->Interval(1e-3f);
bri_slider->ValueChanged += [this] (float val) mutable {
bri_label->Content(std::format("Brightness: {}%", Math::Floor(val*100.f)));
bri = val;
OnColorValueChanged.Invoke(Color4::FromHSV(hue, sat, bri));
RecomputeVisuals();
};
bri_label = new JUI::Text(bri_slider);
bri_label->AlignCenterHorizontally();
bri_label->AlignTop();
bri_label->TextColor(Colors::White);
bri_label->Content("Brightness: 100%");
//auto* hue_box = new JUI::Rect();
hex_label = new JUI::TextRect(this);
hex_label->AlignCenterHorizontally();
hex_label->Size({100_percent, 24_px});
hex_label->Position({0_px, 100_percent});
hex_label->Content("#FFZZGG");
}
JUI::ColorPicker::ColorPicker(Widget *parent): ColorPicker() {
Parent(parent);
}
void JUI::ColorPicker::RecomputeVisuals() {
Color4 computed = Color4::FromHSV(hue, sat, bri);
Color4 inverse = Color4(255 - computed.r, 255 - computed.g, 255 - computed.b);
hex_label->TextColor(inverse);
hex_label->BGColor(computed);
hex_label->Content(std::format("{}", rgb2hex(computed.r, computed.g, computed.b, true)));
}