From 31bb8a3ac5569cad6a9ab8d2ea7295b026ea0fa2 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sat, 25 Oct 2025 15:26:11 +0300 Subject: [PATCH] Extracted ColorSelector class to td_ui. --- .../boxes/peers/edit_peer_color_box.cpp | 108 +----------------- Telegram/SourceFiles/ui/peer/color_sample.cpp | 88 ++++++++++++++ Telegram/SourceFiles/ui/peer/color_sample.h | 24 +++- 3 files changed, 113 insertions(+), 107 deletions(-) diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp index a3860a1646..756cfbf1cb 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp @@ -570,111 +570,7 @@ void Apply( } } -class ColorSelector final : public Ui::RpWidget { -public: - ColorSelector( - not_null box, - std::shared_ptr style, - rpl::producer> indices, - rpl::producer index, - Fn callback); -private: - void fillFrom(std::vector indices); - - int resizeGetHeight(int newWidth) override; - - const std::shared_ptr _style; - std::vector> _samples; - const Fn _callback; - rpl::variable _index; - -}; - -ColorSelector::ColorSelector( - not_null box, - std::shared_ptr style, - rpl::producer> indices, - rpl::producer index, - Fn callback) -: RpWidget(box) -, _style(style) -, _callback(std::move(callback)) -, _index(std::move(index)) { - std::move( - indices - ) | rpl::start_with_next([=](std::vector indices) { - fillFrom(std::move(indices)); - }, lifetime()); -} - -void ColorSelector::fillFrom(std::vector indices) { - auto samples = std::vector>(); - const auto initial = _index.current(); - const auto add = [&](uint8 index) { - auto i = ranges::find(_samples, index, &Ui::ColorSample::index); - if (i != end(_samples)) { - samples.push_back(std::move(*i)); - _samples.erase(i); - } else { - samples.push_back(std::make_unique( - this, - _style, - index, - index == initial)); - samples.back()->show(); - samples.back()->setClickedCallback([=] { - _callback(index); - }); - } - }; - for (const auto index : indices) { - add(index); - } - if (initial != kUnsetColorIndex && !ranges::contains(indices, initial)) { - add(initial); - } - _samples = std::move(samples); - if (width() > 0) { - resizeToWidth(width()); - } - - _index.value( - ) | rpl::combine_previous( - ) | rpl::start_with_next([=](uint8 was, uint8 now) { - const auto i = ranges::find(_samples, was, &Ui::ColorSample::index); - if (i != end(_samples)) { - i->get()->setSelected(false); - } - const auto j = ranges::find(_samples, now, &Ui::ColorSample::index); - if (j != end(_samples)) { - j->get()->setSelected(true); - } - }, lifetime()); -} - -int ColorSelector::resizeGetHeight(int newWidth) { - if (newWidth <= 0) { - return 0; - } - const auto count = int(_samples.size()); - const auto columns = Ui::kSimpleColorIndexCount; - const auto skip = st::settingsColorRadioSkip; - const auto size = (newWidth - skip * (columns - 1)) / float64(columns); - const auto isize = int(base::SafeRound(size)); - auto top = 0; - auto left = 0.; - for (auto i = 0; i != count; ++i) { - _samples[i]->resize(isize, isize); - _samples[i]->move(int(base::SafeRound(left)), top); - left += size + skip; - if (!((i + 1) % columns)) { - top += isize + skip; - left = 0.; - } - } - return (top - skip) + ((count % columns) ? (isize + skip) : 0); -} [[nodiscard]] auto ButtonStyleWithAddedPadding( not_null parent, @@ -1458,8 +1354,8 @@ void EditPeerColorSection( const auto margin = st::settingsColorRadioMargin; const auto skip = st::settingsColorRadioSkip; container->add( - object_ptr( - box, + object_ptr( + container, style, std::move(indices), state->index.value(), diff --git a/Telegram/SourceFiles/ui/peer/color_sample.cpp b/Telegram/SourceFiles/ui/peer/color_sample.cpp index cb55282bf1..173945a55f 100644 --- a/Telegram/SourceFiles/ui/peer/color_sample.cpp +++ b/Telegram/SourceFiles/ui/peer/color_sample.cpp @@ -7,16 +7,19 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "ui/peer/color_sample.h" +#include "base/algorithm.h" #include "ui/chat/chat_style.h" #include "ui/color_contrast.h" #include "ui/painter.h" #include "ui/text/text_utilities.h" +#include "ui/widgets/buttons.h" #include "styles/style_settings.h" namespace Ui { namespace { constexpr auto kSelectAnimationDuration = crl::time(150); +constexpr auto kUnsetColorIndex = uint8(0xFF); } // namespace @@ -217,4 +220,89 @@ uint8 ColorSample::index() const { return _index; } +ColorSelector::ColorSelector( + not_null parent, + std::shared_ptr style, + rpl::producer> indices, + rpl::producer index, + Fn callback) +: RpWidget(parent) +, _style(style) +, _callback(std::move(callback)) +, _index(std::move(index)) { + std::move( + indices + ) | rpl::start_with_next([=](std::vector indices) { + fillFrom(std::move(indices)); + }, lifetime()); +} + +void ColorSelector::fillFrom(std::vector indices) { + auto samples = std::vector>(); + const auto initial = _index.current(); + const auto add = [&](uint8 index) { + auto i = ranges::find(_samples, index, &ColorSample::index); + if (i != end(_samples)) { + samples.push_back(std::move(*i)); + _samples.erase(i); + } else { + samples.push_back(std::make_unique( + this, + _style, + index, + index == initial)); + samples.back()->show(); + samples.back()->setClickedCallback([=] { + _callback(index); + }); + } + }; + for (const auto index : indices) { + add(index); + } + if (initial != 0xFF && !ranges::contains(indices, initial)) { + add(initial); + } + _samples = std::move(samples); + if (width() > 0) { + resizeToWidth(width()); + } + + _index.value( + ) | rpl::combine_previous( + ) | rpl::start_with_next([=](uint8 was, uint8 now) { + const auto i = ranges::find(_samples, was, &ColorSample::index); + if (i != end(_samples)) { + i->get()->setSelected(false); + } + const auto j = ranges::find(_samples, now, &ColorSample::index); + if (j != end(_samples)) { + j->get()->setSelected(true); + } + }, lifetime()); +} + +int ColorSelector::resizeGetHeight(int newWidth) { + if (newWidth <= 0) { + return 0; + } + const auto count = int(_samples.size()); + const auto columns = 8; // kSimpleColorIndexCount + const auto skip = st::settingsColorRadioSkip; + const auto size = (newWidth - skip * (columns - 1)) / float64(columns); + const auto isize = int(base::SafeRound(size)); + auto top = 0; + auto left = 0.; + for (auto i = 0; i != count; ++i) { + _samples[i]->resize(isize, isize); + _samples[i]->move(int(base::SafeRound(left)), top); + left += size + skip; + if (!((i + 1) % columns)) { + top += isize + skip; + left = 0.; + } + } + return (top - skip) + ((count % columns) ? (isize + skip) : 0); +} + } // namespace Ui \ No newline at end of file diff --git a/Telegram/SourceFiles/ui/peer/color_sample.h b/Telegram/SourceFiles/ui/peer/color_sample.h index d2ce8dec71..a774c4610d 100644 --- a/Telegram/SourceFiles/ui/peer/color_sample.h +++ b/Telegram/SourceFiles/ui/peer/color_sample.h @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/buttons.h" #include "ui/text/text.h" #include "ui/effects/animations.h" +#include "ui/rp_widget.h" #include "data/data_peer_colors.h" namespace Ui { @@ -58,4 +59,25 @@ private: }; -} // namespace Ui \ No newline at end of file +class ColorSelector final : public RpWidget { +public: + ColorSelector( + not_null parent, + std::shared_ptr style, + rpl::producer> indices, + rpl::producer index, + Fn callback); + +private: + void fillFrom(std::vector indices); + + int resizeGetHeight(int newWidth) override; + + const std::shared_ptr _style; + std::vector> _samples; + const Fn _callback; + rpl::variable _index; + +}; + +} // namespace Ui