33#include " color_picker.hpp"
44#include " graphics/point.hpp"
55#include " graphics/rect.hpp"
6+ #include " helper/color.hpp"
67#include " helper/graphic_utils.hpp"
8+ #include " helper/utils.hpp"
79#include " manager/resource_manager.hpp"
810#include " ui/components/textinput.hpp"
911#include " ui/layout.hpp"
@@ -35,9 +37,8 @@ detail::ColorSlider::ColorSlider(
3537 const auto h = bar_rect ().height ();
3638
3739 for (u32 x = 0 ; x < w; x++) {
38- const Color color{
39- HSVColor{(static_cast <double >(x) / static_cast <double >(w)) * 360.0 , 1.0 , 1.0 }
40- };
40+ const Color color =
41+ HSVColor ((static_cast <double >(x) / static_cast <double >(w)) * 360.0 , 1.0 , 1.0 ).to_rgb_color ();
4142
4243 service_provider->renderer ().draw_line (
4344 shapes::UPoint{ x, 0 }, shapes::UPoint{ x, static_cast <u32 >(h - 1 ) }, color
@@ -122,17 +123,19 @@ void detail::ColorCanvas::render(const ServiceProvider& service_provider) const
122123void detail::ColorCanvas::draw_pseudo_circle (const ServiceProvider& service_provider) const {
123124 const auto & renderer = service_provider.renderer ();
124125
125- u32 diameter = 2 ;
126+ u32 diameter = 5 ;
126127
127128 // width == height here, since we assured that in the construction of the layout fro this component, so instead of taking the min of width and height i just use width, this fact is only used here, since it's not that bad, if it changes sometime in teh future
128- if (const double one_percent = static_cast <double >(layout ().get_rect ().width ()) * 0.01 ; one_percent >= 2.0 ) {
129- diameter = static_cast <u32 >(one_percent);
129+ if (const double percentage_diameter = static_cast <double >(layout ().get_rect ().width ()) * 0.03 ;
130+ percentage_diameter >= static_cast <double >(diameter)) {
131+ diameter = static_cast <u32 >(percentage_diameter);
130132 }
131133
132134 const auto [width, height] = layout ().get_rect ().to_dimension_point ().cast <double >();
133135
134- const auto center = shapes::AbstractPoint<double >(m_current_color.s * width, m_current_color.v * height).cast <u32 >()
135- + layout ().get_rect ().top_left ;
136+ const auto center =
137+ shapes::AbstractPoint<double >(m_current_color.s * width, (1.0 - m_current_color.v ) * height).cast <u32 >()
138+ + layout ().get_rect ().top_left ;
136139
137140 const auto circle_color = m_is_dragging ? " #C7C7C7" _c : " #FFFFFF" _c;
138141
@@ -158,11 +161,12 @@ detail::ColorCanvas::handle_event(const SDL_Event& event, const Window* window)
158161 };
159162 }
160163 } else if (utils::event_is_click_event (event, utils::CrossPlatformClickEvent::ButtonUp)) {
161-
162- m_is_dragging = false ;
163- SDL_CaptureMouse (SDL_FALSE);
164- handled = true ;
165-
164+ // only handle this, if already dragging, otherwise it's a button down from previously or some other widget
165+ if (m_is_dragging) {
166+ m_is_dragging = false ;
167+ SDL_CaptureMouse (SDL_FALSE);
168+ handled = true ;
169+ }
166170 } else if (utils::event_is_click_event (event, utils::CrossPlatformClickEvent::Motion)) {
167171
168172 if (m_is_dragging) {
@@ -174,8 +178,9 @@ detail::ColorCanvas::handle_event(const SDL_Event& event, const Window* window)
174178
175179 if (handled) {
176180
177- const auto & [x, y] = utils::get_raw_coordinates (window, event) ;
181+ const auto previous_color = m_current_color ;
178182
183+ const auto & [x, y] = utils::get_raw_coordinates (window, event);
179184
180185 if (x <= static_cast <i32 >(fill_rect.top_left .x )) {
181186 m_current_color.s = 0.0 ;
@@ -188,15 +193,20 @@ detail::ColorCanvas::handle_event(const SDL_Event& event, const Window* window)
188193 }
189194
190195 if (y <= static_cast <i32 >(fill_rect.top_left .y )) {
191- m_current_color.v = 0.0 ;
192- } else if (y >= static_cast <i32 >(fill_rect.bottom_right .y )) {
193196 m_current_color.v = 1.0 ;
197+ } else if (y >= static_cast <i32 >(fill_rect.bottom_right .y )) {
198+ m_current_color.v = 0.0 ;
194199 } else {
195200 const double percentage =
196- static_cast <double >(y - fill_rect.top_left .y ) / static_cast <double >(fill_rect.height ());
201+ 1.0 - static_cast <double >(y - fill_rect.top_left .y ) / static_cast <double >(fill_rect.height ());
197202 m_current_color.v = percentage;
198203 }
199204
205+ // if we hover at e.g. the edges, and don't change anything, we don't need to call the callback
206+ if (previous_color.s == m_current_color.s && previous_color.v == m_current_color.v ) {
207+ return handled;
208+ }
209+
200210 const shapes::AbstractPoint<double > point = { m_current_color.s , m_current_color.v };
201211 m_callback (point);
202212
@@ -209,8 +219,25 @@ detail::ColorCanvas::handle_event(const SDL_Event& event, const Window* window)
209219 return false ;
210220}
211221
212- void detail::ColorCanvas::on_change (const Color& color) {
213- m_current_color = color.to_hsv_color ();
222+ void detail::ColorCanvas::on_change (ColorChangeOrigin origin, const HSVColor& color) {
223+ switch (origin) {
224+ case detail::ColorChangeOrigin::TextInput: {
225+ m_current_color = color;
226+ break ;
227+ }
228+ case detail::ColorChangeOrigin::Canvas: {
229+ // nothing to do, shouldn't be reached
230+ utils::unreachable ();
231+ break ;
232+ }
233+ case detail::ColorChangeOrigin::Slider: {
234+ // only need to change the h value
235+ m_current_color.h = color.h ;
236+ break ;
237+ }
238+ default :
239+ utils::unreachable ();
240+ }
214241
215242 redraw_texture ();
216243}
@@ -230,14 +257,11 @@ void detail::ColorCanvas::redraw_texture() {
230257
231258 const auto hue = m_current_color.h ;
232259
260+ // TODO: try to speed this up, since it is a performance bottle neck, if hovering like a madman (xD) over the color slider
233261 for (u32 y = 0 ; y < h; y++) {
262+ const auto v = 1.0 - (static_cast <double >(y) / static_cast <double >(h));
234263 for (u32 x = 0 ; x < w; x++) {
235- const Color color{
236- HSVColor{
237- hue, static_cast <double >(x) / static_cast <double >(w),
238- 1.0 - (static_cast <double >(y) / static_cast <double >(h)),
239- }
240- };
264+ const Color color = HSVColor (hue, static_cast <double >(x) / static_cast <double >(w), v).to_rgb_color ();
241265
242266 m_service_provider->renderer ().draw_pixel (shapes::UPoint{ x, y }, color);
243267 }
@@ -276,7 +300,7 @@ ui::ColorPicker::ColorPicker(
276300 hsv_color.s = value.x ;
277301 hsv_color.v = value.y ;
278302 this ->m_color = Color{ hsv_color };
279- this ->after_color_change (ColorChangeType::SV );
303+ this ->after_color_change (detail::ColorChangeOrigin::Canvas, hsv_color );
280304 },
281305 ui::Layout{ main_rect }, false
282306 );
@@ -313,11 +337,21 @@ ui::ColorPicker::ColorPicker(
313337 m_color_slider = std::make_unique<detail::ColorSlider>(
314338 service_provider, std::pair<double , double >{ 0.0 , 360.0 },
315339 [this ]() -> double { return this ->m_color .to_hsv_color ().h ; },
316- [this ](const double & value) {
340+ [this ](double value) {
317341 auto hsv_color = m_color.to_hsv_color ();
318342 hsv_color.h = value;
343+
344+ const auto previous_color = this ->m_color ;
345+
319346 this ->m_color = Color{ hsv_color };
320- this ->after_color_change (ColorChangeType::Hue);
347+
348+ // if we hover at e.g. the edges, and don't change anything, we don't need to call after_color_change
349+ // this also helps, since the slider reports change on click and on release, even if teh position doesn't change there
350+ if (previous_color == this ->m_color ) {
351+ return ;
352+ }
353+
354+ this ->after_color_change (detail::ColorChangeOrigin::Slider, hsv_color);
321355 },
322356 5.0 , ui::Layout{ color_bar_rect }, false
323357 );
@@ -334,7 +368,6 @@ ui::ColorPicker::ColorPicker(
334368
335369 const auto rgb_image_path = utils::get_assets_folder () / " icons" / " rgb_color_selector.png" ;
336370
337-
338371 m_rgb_button = std::make_unique<ui::ImageButton>(
339372 service_provider, rgb_image_path, true , focus_id_unused,
340373 [this ](const ImageButton&) -> bool {
@@ -369,7 +402,9 @@ ui::ColorPicker::ColorPicker(
369402 ui::Alignment{ ui::AlignmentHorizontal::Middle, ui::AlignmentVertical::Center }, textinput_layout, false
370403 );
371404
372- after_color_change (ui::ColorChangeType::Both);
405+ // using SLider, that behaviour simulates the one, that I want, since the ColorSlider already gets the change by the getter,
406+ // but the textinput and the canvas need to be set manually by this call
407+ after_color_change (detail::ColorChangeOrigin::Slider, m_color.to_hsv_color ());
373408}
374409
375410ui::ColorPicker::ColorPicker (
@@ -423,21 +458,32 @@ ui::ColorPicker::handle_event(const SDL_Event& event, const Window* window) {
423458 return m_color_canvas->handle_event (event, window);
424459}
425460
426- void ui::ColorPicker::after_color_change (ColorChangeType type ) {
427- if (type != ColorChangeType::Hue ) {
428- m_color_slider-> on_change ();
429- }
461+ void ui::ColorPicker::after_color_change (detail::ColorChangeOrigin origin, const HSVColor& color ) {
462+ switch (origin ) {
463+ case detail::ColorChangeOrigin::TextInput: {
464+ m_color_slider-> on_change ();
430465
431- if (type != ColorChangeType::SV) {
432- m_color_canvas->on_change (m_color);
466+ m_color_canvas->on_change (origin, color);
467+ break ;
468+ }
469+ case detail::ColorChangeOrigin::Canvas: {
470+ // TODO: change the text in the textinput!
471+ break ;
472+ }
473+ case detail::ColorChangeOrigin::Slider: {
474+ m_color_canvas->on_change (origin, color);
475+
476+ // TODO: change the text in the textinput!
477+ break ;
478+ }
479+ default :
480+ utils::unreachable ();
433481 }
434482
435483 m_callback (m_color);
436-
437- // TODO: change the text in the textinput!
438484}
439485
440486void ui::ColorPicker::after_color_mode_change () {
441487 // TODO
442- // TODO: handle textinput chnages and events and also change it's vaöue every time the color is change
488+ // TODO: handle textinput chnages and events and also change it's value every time the color is changed
443489}
0 commit comments