From d2e940f1ff65637e744471766d4324b1f6d82d87 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Tue, 24 Jan 2023 00:34:34 +0300 Subject: [PATCH] Added initial implementation of color chooser for userpic builder. --- .../info/userpic/info_userpic_builder.style | 10 ++ .../info_userpic_colors_palette_chooser.cpp | 133 ++++++++++++++++++ .../info_userpic_colors_palette_chooser.h | 36 +++++ Telegram/cmake/td_ui.cmake | 3 + 4 files changed, 182 insertions(+) create mode 100644 Telegram/SourceFiles/info/userpic/info_userpic_builder.style create mode 100644 Telegram/SourceFiles/info/userpic/info_userpic_colors_palette_chooser.cpp create mode 100644 Telegram/SourceFiles/info/userpic/info_userpic_colors_palette_chooser.h diff --git a/Telegram/SourceFiles/info/userpic/info_userpic_builder.style b/Telegram/SourceFiles/info/userpic/info_userpic_builder.style new file mode 100644 index 000000000..0dddfbf4a --- /dev/null +++ b/Telegram/SourceFiles/info/userpic/info_userpic_builder.style @@ -0,0 +1,10 @@ +/* +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 +*/ +using "ui/basic.style"; + +userpicBuilderEmojiAccentColorSize: 30px; diff --git a/Telegram/SourceFiles/info/userpic/info_userpic_colors_palette_chooser.cpp b/Telegram/SourceFiles/info/userpic/info_userpic_colors_palette_chooser.cpp new file mode 100644 index 000000000..d3cecdb9e --- /dev/null +++ b/Telegram/SourceFiles/info/userpic/info_userpic_colors_palette_chooser.cpp @@ -0,0 +1,133 @@ +/* +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 { + +[[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) +: Ui::RpWidget(parent) { + rebuildButtons(); +} + +rpl::producer ColorsPalette::stopsValue() { + return _currentIndex.value() | rpl::map([=](int index) { + return GradientByIndex(index, resizeGetHeight(0)).stops(); + }); +} + +void ColorsPalette::rebuildButtons() { + constexpr auto kColorsCount = 7; + 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 new file mode 100644 index 000000000..e6ab2ac8f --- /dev/null +++ b/Telegram/SourceFiles/info/userpic/info_userpic_colors_palette_chooser.h @@ -0,0 +1,36 @@ +/* +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); + + [[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/cmake/td_ui.cmake b/Telegram/cmake/td_ui.cmake index 10e98932b..09af2325d 100644 --- a/Telegram/cmake/td_ui.cmake +++ b/Telegram/cmake/td_ui.cmake @@ -23,6 +23,7 @@ set(style_files calls/calls.style export/view/export.style info/info.style + info/userpic/info_userpic_builder.style intro/intro.style media/player/media_player.style passport/passport.style @@ -94,6 +95,8 @@ PRIVATE info/profile/info_profile_icon.cpp info/profile/info_profile_icon.h + info/userpic/info_userpic_colors_palette_chooser.cpp + info/userpic/info_userpic_colors_palette_chooser.h layout/abstract_layout_item.cpp layout/abstract_layout_item.h