From 16f59eee5d0d1f62804fa9f9a6472c0e283910a1 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Wed, 25 Jan 2023 20:31:07 +0300 Subject: [PATCH] Removed colors palette class for userpic emoji builder. --- .../info_userpic_color_circle_button.cpp | 42 ++++++ .../info_userpic_color_circle_button.h | 32 +++++ .../info_userpic_colors_palette_chooser.cpp | 135 ------------------ .../info_userpic_colors_palette_chooser.h | 36 ----- .../info_userpic_emoji_builder_widget.cpp | 87 ++++++++--- Telegram/cmake/td_ui.cmake | 4 +- 6 files changed, 145 insertions(+), 191 deletions(-) create mode 100644 Telegram/SourceFiles/info/userpic/info_userpic_color_circle_button.cpp create mode 100644 Telegram/SourceFiles/info/userpic/info_userpic_color_circle_button.h delete mode 100644 Telegram/SourceFiles/info/userpic/info_userpic_colors_palette_chooser.cpp delete mode 100644 Telegram/SourceFiles/info/userpic/info_userpic_colors_palette_chooser.h diff --git a/Telegram/SourceFiles/info/userpic/info_userpic_color_circle_button.cpp b/Telegram/SourceFiles/info/userpic/info_userpic_color_circle_button.cpp new file mode 100644 index 000000000..97ce58af6 --- /dev/null +++ b/Telegram/SourceFiles/info/userpic/info_userpic_color_circle_button.cpp @@ -0,0 +1,42 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "info/userpic/info_userpic_color_circle_button.h" + +#include "settings/settings_chat.h" // Settings::PaintRoundColorButton. +#include "ui/painter.h" + +namespace UserpicBuilder { + +void CircleButton::setIndex(int index) { + _index = index; +} + +int CircleButton::index() const { + return _index; +} + +void CircleButton::setBrush(QBrush brush) { + _brush = brush; + update(); +} + +void CircleButton::setSelectedProgress(float64 progress) { + if (_selectedProgress != progress) { + _selectedProgress = progress; + update(); + } +} + +void CircleButton::paintEvent(QPaintEvent *event) { + auto p = QPainter(this); + auto hq = PainterHighQualityEnabler(p); + const auto h = height(); + Settings::PaintRoundColorButton(p, h, _brush, _selectedProgress); +} + +} // namespace UserpicBuilder diff --git a/Telegram/SourceFiles/info/userpic/info_userpic_color_circle_button.h b/Telegram/SourceFiles/info/userpic/info_userpic_color_circle_button.h new file mode 100644 index 000000000..2106a9ef4 --- /dev/null +++ b/Telegram/SourceFiles/info/userpic/info_userpic_color_circle_button.h @@ -0,0 +1,32 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +#include "ui/abstract_button.h" + +namespace UserpicBuilder { + +class CircleButton final : public Ui::AbstractButton { +public: + using Ui::AbstractButton::AbstractButton; + + void setIndex(int index); + [[nodiscard]] int index() const; + void setBrush(QBrush brush); + void setSelectedProgress(float64 progress); + +private: + void paintEvent(QPaintEvent *event) override; + + int _index = 0; + float64 _selectedProgress = 0.; + QBrush _brush; + +}; + +} // namespace UserpicBuilder diff --git a/Telegram/SourceFiles/info/userpic/info_userpic_colors_palette_chooser.cpp b/Telegram/SourceFiles/info/userpic/info_userpic_colors_palette_chooser.cpp deleted file mode 100644 index 1259588da..000000000 --- a/Telegram/SourceFiles/info/userpic/info_userpic_colors_palette_chooser.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#include "info/userpic/info_userpic_colors_palette_chooser.h" - -#include "settings/settings_chat.h" // Settings::PaintRoundColorButton. -#include "ui/abstract_button.h" -#include "ui/empty_userpic.h" -#include "ui/painter.h" -#include "styles/style_info_userpic_builder.h" - -namespace UserpicBuilder { -namespace { - -constexpr auto kColorsCount = 7; - -[[nodiscard]] QLinearGradient VerticalGradient( - float64 size, - const QColor &c1, - const QColor &c2) { - auto gradient = QLinearGradient(0, 0, size / 2., size); - gradient.setStops({ { 0., c1 }, { 1., c2 } }); - return gradient; -} - -[[nodiscard]] QLinearGradient GradientByIndex(int index, float64 size) { - const auto colors = Ui::EmptyUserpic::UserpicColor( - Ui::EmptyUserpic::ColorIndex(index)); - return VerticalGradient(size, colors.color1->c, colors.color2->c); -} - -} // namespace - -class ColorsPalette::CircleButton final : public Ui::AbstractButton { -public: - using Ui::AbstractButton::AbstractButton; - - void setIndex(int index); - [[nodiscard]] int index() const; - void setBrush(QBrush brush); - void setSelectedProgress(float64 progress); - -private: - void paintEvent(QPaintEvent *event) override; - - int _index = 0; - float64 _selectedProgress = 0.; - QBrush _brush; - -}; - -void ColorsPalette::CircleButton::setIndex(int index) { - _index = index; -} - -int ColorsPalette::CircleButton::index() const { - return _index; -} - -void ColorsPalette::CircleButton::setBrush(QBrush brush) { - _brush = brush; - update(); -} - -void ColorsPalette::CircleButton::setSelectedProgress(float64 progress) { - if (_selectedProgress != progress) { - _selectedProgress = progress; - update(); - } -} - -void ColorsPalette::CircleButton::paintEvent(QPaintEvent *event) { - auto p = QPainter(this); - auto hq = PainterHighQualityEnabler(p); - const auto h = height(); - Settings::PaintRoundColorButton(p, h, _brush, _selectedProgress); -} - -ColorsPalette::ColorsPalette(not_null parent, int index) -: Ui::RpWidget(parent) -, _currentIndex(index % kColorsCount) { - rebuildButtons(); -} - -rpl::producer ColorsPalette::stopsValue() { - return _currentIndex.value() | rpl::map([=](int index) { - return GradientByIndex(index, resizeGetHeight(0)).stops(); - }); -} - -void ColorsPalette::rebuildButtons() { - const auto size = resizeGetHeight(0); - for (auto i = 0; i < kColorsCount; i++) { - _buttons.emplace_back(base::make_unique_q(this)); - _buttons.back()->resize(size, size); - _buttons.back()->setIndex(i); - _buttons.back()->setBrush(GradientByIndex(i, size)); - _buttons.back()->setClickedCallback([=] { - const auto was = _currentIndex.current(); - const auto now = i; - if (was == now) { - return; - } - _animation.stop(); - _animation.start([=](float64 progress) { - _buttons[was]->setSelectedProgress(1. - progress); - _buttons[now]->setSelectedProgress(progress); - }, 0., 1., st::slideDuration); - _currentIndex = now; - }); - } - _buttons[_currentIndex.current()]->setSelectedProgress(1.); - -} - -void ColorsPalette::resizeEvent(QResizeEvent *event) { - const auto fullWidth = event->size().width(); - const auto buttonWidth = _buttons.front()->width(); - const auto buttonsCount = _buttons.size(); - const auto buttonsWidth = buttonWidth * buttonsCount; - const auto step = (fullWidth - buttonsWidth) / (buttonsCount - 1); - for (auto i = 0; i < buttonsCount; i++) { - _buttons[i]->moveToLeft(i * (buttonWidth + step), 0); - } -} - -int ColorsPalette::resizeGetHeight(int newWidth) { - return st::userpicBuilderEmojiAccentColorSize; -} - -} // namespace UserpicBuilder diff --git a/Telegram/SourceFiles/info/userpic/info_userpic_colors_palette_chooser.h b/Telegram/SourceFiles/info/userpic/info_userpic_colors_palette_chooser.h deleted file mode 100644 index 7d6c58941..000000000 --- a/Telegram/SourceFiles/info/userpic/info_userpic_colors_palette_chooser.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "ui/rp_widget.h" - -#include "ui/effects/animations.h" - -namespace UserpicBuilder { - -class ColorsPalette final : public Ui::RpWidget { -public: - ColorsPalette(not_null parent, int index = 0); - - [[nodiscard]] rpl::producer stopsValue(); - -protected: - void resizeEvent(QResizeEvent *event) override; - int resizeGetHeight(int newWidth) final override; - -private: - class CircleButton; - void rebuildButtons(); - - std::vector> _buttons; - Ui::Animations::Simple _animation; - rpl::variable _currentIndex = 0; - -}; - -} // namespace UserpicBuilder diff --git a/Telegram/SourceFiles/info/userpic/info_userpic_emoji_builder_widget.cpp b/Telegram/SourceFiles/info/userpic/info_userpic_emoji_builder_widget.cpp index 8d8e3f25a..4095aae25 100644 --- a/Telegram/SourceFiles/info/userpic/info_userpic_emoji_builder_widget.cpp +++ b/Telegram/SourceFiles/info/userpic/info_userpic_emoji_builder_widget.cpp @@ -16,7 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/stickers/data_custom_emoji.h" #include "editor/photo_editor_layer_widget.h" // Editor::kProfilePhotoSize. #include "info/userpic/info_userpic_bubble_wrap.h" -#include "info/userpic/info_userpic_colors_palette_chooser.h" +#include "info/userpic/info_userpic_color_circle_button.h" #include "info/userpic/info_userpic_emoji_builder_common.h" #include "info/userpic/info_userpic_emoji_builder_preview.h" #include "lang/lang_keys.h" @@ -41,6 +41,31 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace UserpicBuilder { namespace { +void AlignChildren(not_null widget, int fullWidth) { + const auto children = widget->children(); + const auto widgets = ranges::views::all( + children + ) | ranges::views::filter([](not_null object) { + return object->isWidgetType(); + }) | ranges::views::transform([](not_null object) { + return static_cast(object.get()); + }) | ranges::to_vector; + + const auto widgetWidth = widgets.front()->width(); + const auto widgetsCount = widgets.size(); + const auto widgetsWidth = widgetWidth * widgetsCount; + const auto step = (fullWidth - widgetsWidth) / (widgetsCount - 1); + for (auto i = 0; i < widgetsCount; i++) { + widgets[i]->move(i * (widgetWidth + step), widgets[i]->y()); + } +} + +[[nodiscard]] std::vector ColorsByIndex(int index) { + const auto c = Ui::EmptyUserpic::UserpicColor( + Ui::EmptyUserpic::ColorIndex(index)); + return { c.color1->c, c.color2->c }; +} + class EmojiSelector final : public Ui::RpWidget { public: EmojiSelector( @@ -245,6 +270,13 @@ not_null CreateUserpicBuilder( BothWayCommunication communication) { const auto container = Ui::CreateChild(parent.get()); + struct State { + std::vector> circleButtons; + Ui::Animations::Simple chosenColorAnimation; + int colorIndex = -1; + }; + const auto state = container->lifetime().make_state(); + const auto preview = container->add( object_ptr>( container, @@ -272,22 +304,43 @@ not_null CreateUserpicBuilder( st::userpicBuilderEmojiBubblePaletteSize, [=] { return controller->chatStyle(); }); - const auto palette = Ui::CreateChild( - paletteBg.get(), - data.builderColorIndex); - palette->stopsValue( - ) | rpl::start_with_next([=](QGradientStops stops) { - const auto colors = ranges::views::all( - stops - ) | ranges::views::transform([](const QGradientStop &stop) { - return stop.second; - }) | ranges::to_vector; - preview->setGradientColors(colors); - }, preview->lifetime()); + const auto palette = Ui::CreateChild(paletteBg.get()); + { + constexpr auto kColorsCount = int(7); + const auto size = st::userpicBuilderEmojiAccentColorSize; + for (auto i = 0; i < kColorsCount; i++) { + const auto colors = ColorsByIndex(i); + const auto button = Ui::CreateChild(palette); + state->circleButtons.push_back(button); + button->resize(size, size); + button->setBrush(GenerateGradient(Size(size), colors)); + button->setClickedCallback([=] { + const auto was = state->colorIndex; + const auto now = i; + if (was == now) { + return; + } + state->chosenColorAnimation.stop(); + state->chosenColorAnimation.start([=](float64 progress) { + if (was >= 0) { + state->circleButtons[was]->setSelectedProgress( + 1. - progress); + } + state->circleButtons[now]->setSelectedProgress(progress); + }, 0., 1., st::slideDuration); + state->colorIndex = now; + + preview->setGradientColors(colors); + }); + } + const auto current = data.builderColorIndex % kColorsCount; + state->circleButtons[current]->setSelectedProgress(1.); + state->circleButtons[current]->clicked({}, Qt::LeftButton); + } paletteBg->innerRectValue( ) | rpl::start_with_next([=](const QRect &r) { - palette->setGeometry(r - - st::userpicBuilderEmojiBubblePalettePadding); + palette->setGeometry(r - st::userpicBuilderEmojiBubblePalettePadding); + AlignChildren(palette, palette->width()); }, palette->lifetime()); container->add( @@ -342,9 +395,7 @@ not_null CreateEmojiUserpic( std::move( colorIndex ) | rpl::start_with_next([=](int index) { - const auto c = Ui::EmptyUserpic::UserpicColor( - Ui::EmptyUserpic::ColorIndex(index)); - widget->setGradientColors({ c.color1->c, c.color2->c }); + widget->setGradientColors(ColorsByIndex(index)); }, widget->lifetime()); return widget; } diff --git a/Telegram/cmake/td_ui.cmake b/Telegram/cmake/td_ui.cmake index 80a716fe7..f4627965e 100644 --- a/Telegram/cmake/td_ui.cmake +++ b/Telegram/cmake/td_ui.cmake @@ -97,8 +97,8 @@ PRIVATE info/profile/info_profile_icon.h info/userpic/info_userpic_bubble_wrap.cpp info/userpic/info_userpic_bubble_wrap.h - info/userpic/info_userpic_colors_palette_chooser.cpp - info/userpic/info_userpic_colors_palette_chooser.h + info/userpic/info_userpic_color_circle_button.cpp + info/userpic/info_userpic_color_circle_button.h info/userpic/info_userpic_emoji_builder_layer.cpp info/userpic/info_userpic_emoji_builder_layer.h