mirror of https://github.com/procxx/kepka.git
Allow choosing accent colors from palette.
This commit is contained in:
parent
c2117e7722
commit
a465117689
|
@ -208,3 +208,7 @@ settingsForwardPrivacyPadding: 8px;
|
||||||
settingsForwardPrivacyArrowSkip: 32px;
|
settingsForwardPrivacyArrowSkip: 32px;
|
||||||
settingsForwardPrivacyArrowSize: 6px;
|
settingsForwardPrivacyArrowSize: 6px;
|
||||||
settingsForwardPrivacyTooltipPadding: margins(8px, 6px, 8px, 6px);
|
settingsForwardPrivacyTooltipPadding: margins(8px, 6px, 8px, 6px);
|
||||||
|
|
||||||
|
settingsAccentColorSize: 48px;
|
||||||
|
settingsAccentColorSkip: 3px;
|
||||||
|
settingsAccentColorLine: 2px;
|
||||||
|
|
|
@ -45,6 +45,193 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "styles/style_boxes.h"
|
#include "styles/style_boxes.h"
|
||||||
|
|
||||||
namespace Settings {
|
namespace Settings {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
const auto kSchemesList = Window::Theme::EmbeddedThemes();
|
||||||
|
constexpr auto kColorsPerRow = 5;
|
||||||
|
|
||||||
|
class ColorsPalette final {
|
||||||
|
public:
|
||||||
|
using Type = Window::Theme::EmbeddedType;
|
||||||
|
using Scheme = Window::Theme::EmbeddedScheme;
|
||||||
|
|
||||||
|
explicit ColorsPalette(not_null<Ui::VerticalLayout*> container);
|
||||||
|
|
||||||
|
void show(Type type);
|
||||||
|
|
||||||
|
rpl::producer<QColor> selected() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateInnerGeometry();
|
||||||
|
|
||||||
|
not_null<Ui::SlideWrap<>*> _outer;
|
||||||
|
std::vector<std::vector<std::unique_ptr<Ui::RpWidget>>> _buttons;
|
||||||
|
|
||||||
|
rpl::event_stream<QColor> _selected;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
not_null<Ui::AbstractButton*> CreateColorButton(
|
||||||
|
not_null<Ui::RpWidget*> parent,
|
||||||
|
const QColor &color,
|
||||||
|
bool selected) {
|
||||||
|
const auto result = Ui::CreateChild<Ui::AbstractButton>(parent.get());
|
||||||
|
result->show();
|
||||||
|
result->resize(st::settingsAccentColorSize, st::settingsAccentColorSize);
|
||||||
|
result->paintRequest(
|
||||||
|
) | rpl::start_with_next([=](QRect clip) {
|
||||||
|
Painter p(result);
|
||||||
|
PainterHighQualityEnabler hq(p);
|
||||||
|
|
||||||
|
const auto rect = result->rect();
|
||||||
|
p.setBrush(color);
|
||||||
|
p.setPen(Qt::NoPen);
|
||||||
|
p.drawEllipse(result->rect());
|
||||||
|
if (selected) {
|
||||||
|
const auto skip = st::settingsAccentColorSkip;
|
||||||
|
auto pen = st::boxBg->p;
|
||||||
|
pen.setWidth(st::settingsAccentColorLine);
|
||||||
|
p.setBrush(Qt::NoBrush);
|
||||||
|
p.setPen(pen);
|
||||||
|
p.drawEllipse(rect.marginsRemoved({ skip, skip, skip, skip }));
|
||||||
|
}
|
||||||
|
}, result->lifetime());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
not_null<Ui::AbstractButton*> CreateCustomButton(
|
||||||
|
not_null<Ui::RpWidget*> parent,
|
||||||
|
std::vector<QColor> colors) {
|
||||||
|
const auto shared = std::make_shared<std::vector<QColor>>(
|
||||||
|
std::move(colors));
|
||||||
|
const auto result = Ui::CreateChild<Ui::AbstractButton>(parent.get());
|
||||||
|
result->show();
|
||||||
|
const auto size = st::settingsAccentColorSize;
|
||||||
|
result->resize(size, size);
|
||||||
|
result->paintRequest(
|
||||||
|
) | rpl::start_with_next([=](QRect clip) {
|
||||||
|
Painter p(result);
|
||||||
|
PainterHighQualityEnabler hq(p);
|
||||||
|
|
||||||
|
p.setPen(Qt::NoPen);
|
||||||
|
|
||||||
|
const auto smallSize = size / 8.;
|
||||||
|
const auto &list = *shared;
|
||||||
|
const auto drawAround = [&](QPointF center, int index) {
|
||||||
|
const auto where = QPointF{
|
||||||
|
size * (1. + center.x()) / 2,
|
||||||
|
size * (1. + center.y()) / 2
|
||||||
|
};
|
||||||
|
p.setBrush(list[index]);
|
||||||
|
p.drawEllipse(
|
||||||
|
where.x() - smallSize,
|
||||||
|
where.y() - smallSize,
|
||||||
|
2 * smallSize,
|
||||||
|
2 * smallSize);
|
||||||
|
};
|
||||||
|
drawAround(QPointF(), 0);
|
||||||
|
for (auto i = 0; i != 6; ++i) {
|
||||||
|
const auto angle = i * M_PI / 3.;
|
||||||
|
const auto point = QPointF{ cos(angle), sin(angle) };
|
||||||
|
const auto adjusted = point * (1. - (2 * smallSize / size));
|
||||||
|
drawAround(adjusted, i + 1);
|
||||||
|
}
|
||||||
|
}, result->lifetime());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorsPalette::ColorsPalette(not_null<Ui::VerticalLayout*> container)
|
||||||
|
: _outer(container->add(
|
||||||
|
object_ptr<Ui::SlideWrap<>>(
|
||||||
|
container,
|
||||||
|
object_ptr<Ui::RpWidget>(container)))) {
|
||||||
|
_outer->hide(anim::type::instant);
|
||||||
|
|
||||||
|
const auto inner = _outer->entity();
|
||||||
|
inner->widthValue(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
updateInnerGeometry();
|
||||||
|
}, inner->lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ColorsPalette::show(Type type) {
|
||||||
|
const auto scheme = ranges::find(kSchemesList, type, &Scheme::type);
|
||||||
|
if (scheme == end(kSchemesList)) {
|
||||||
|
_outer->hide(anim::type::instant);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto list = Window::Theme::DefaultAccentColors(type);
|
||||||
|
if (list.empty()) {
|
||||||
|
_outer->hide(anim::type::instant);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
list.insert(list.begin(), scheme->accentColor);
|
||||||
|
const auto color = Core::App().settings().themesAccentColors().get(type);
|
||||||
|
const auto current = color.value_or(scheme->accentColor);
|
||||||
|
const auto i = ranges::find(list, current);
|
||||||
|
if (i == end(list)) {
|
||||||
|
list.back() = current;
|
||||||
|
}
|
||||||
|
_outer->show(anim::type::instant);
|
||||||
|
_buttons.clear();
|
||||||
|
const auto pushButton = [&](not_null<Ui::RpWidget*> button) {
|
||||||
|
if (_buttons.empty() || _buttons.back().size() == kColorsPerRow) {
|
||||||
|
_buttons.emplace_back();
|
||||||
|
}
|
||||||
|
_buttons.back().emplace_back(button.get());
|
||||||
|
};
|
||||||
|
const auto inner = _outer->entity();
|
||||||
|
const auto size = st::settingsAccentColorSize;
|
||||||
|
for (const auto &color : list) {
|
||||||
|
const auto selected = color == current;
|
||||||
|
const auto button = CreateColorButton(inner, color, selected);
|
||||||
|
button->clicks(
|
||||||
|
) | rpl::map([=] {
|
||||||
|
return color;
|
||||||
|
}) | rpl::start_with_next([=](QColor color) {
|
||||||
|
_selected.fire_copy(color);
|
||||||
|
}, button->lifetime());
|
||||||
|
pushButton(button);
|
||||||
|
}
|
||||||
|
const auto custom = CreateCustomButton(inner, std::move(list));
|
||||||
|
custom->clicks(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
const auto box = Ui::show(Box<EditColorBox>(
|
||||||
|
"Choose accent color",
|
||||||
|
current));
|
||||||
|
box->setSaveCallback(crl::guard(custom, [=](QColor result) {
|
||||||
|
_selected.fire_copy(result);
|
||||||
|
}));
|
||||||
|
}, custom->lifetime());
|
||||||
|
pushButton(custom);
|
||||||
|
inner->resize(_outer->width(), inner->height());
|
||||||
|
updateInnerGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
|
rpl::producer<QColor> ColorsPalette::selected() const {
|
||||||
|
return _selected.events();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ColorsPalette::updateInnerGeometry() {
|
||||||
|
const auto inner = _outer->entity();
|
||||||
|
const auto size = st::settingsAccentColorSize;
|
||||||
|
const auto padding = st::settingsButton.padding;
|
||||||
|
const auto width = inner->width() - padding.left() - padding.right();
|
||||||
|
const auto skip = (width - size * kColorsPerRow)
|
||||||
|
/ float64(kColorsPerRow - 1);
|
||||||
|
auto y = st::settingsSectionSkip * 2;
|
||||||
|
for (const auto &row : _buttons) {
|
||||||
|
auto x = float64(padding.left());
|
||||||
|
for (const auto &button : row) {
|
||||||
|
button->moveToLeft(int(std::round(x)), y);
|
||||||
|
x += size + skip;
|
||||||
|
}
|
||||||
|
y += size + int(std::round(skip));
|
||||||
|
}
|
||||||
|
inner->resize(inner->width(), y - int(std::round(skip)));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
class BackgroundRow : public Ui::RpWidget {
|
class BackgroundRow : public Ui::RpWidget {
|
||||||
public:
|
public:
|
||||||
|
@ -770,15 +957,19 @@ void SetupChatBackground(
|
||||||
void SetupDefaultThemes(not_null<Ui::VerticalLayout*> container) {
|
void SetupDefaultThemes(not_null<Ui::VerticalLayout*> container) {
|
||||||
using Type = DefaultTheme::Type;
|
using Type = DefaultTheme::Type;
|
||||||
using Scheme = DefaultTheme::Scheme;
|
using Scheme = DefaultTheme::Scheme;
|
||||||
|
|
||||||
const auto block = container->add(object_ptr<Ui::FixedHeightWidget>(
|
const auto block = container->add(object_ptr<Ui::FixedHeightWidget>(
|
||||||
container));
|
container));
|
||||||
static const auto SchemesList = Window::Theme::EmbeddedThemes();
|
const auto palette = Ui::CreateChild<ColorsPalette>(
|
||||||
|
container.get(),
|
||||||
|
container.get());
|
||||||
|
|
||||||
const auto chosen = [] {
|
const auto chosen = [] {
|
||||||
if (Window::Theme::IsNonDefaultBackground()) {
|
if (Window::Theme::IsNonDefaultBackground()) {
|
||||||
return Type(-1);
|
return Type(-1);
|
||||||
}
|
}
|
||||||
const auto path = Window::Theme::Background()->themeAbsolutePath();
|
const auto path = Window::Theme::Background()->themeAbsolutePath();
|
||||||
for (const auto &scheme : SchemesList) {
|
for (const auto &scheme : kSchemesList) {
|
||||||
if (path == scheme.path) {
|
if (path == scheme.path) {
|
||||||
return scheme.type;
|
return scheme.type;
|
||||||
}
|
}
|
||||||
|
@ -807,9 +998,12 @@ void SetupDefaultThemes(not_null<Ui::VerticalLayout*> container) {
|
||||||
const auto applyWithColor = [=](
|
const auto applyWithColor = [=](
|
||||||
const Scheme &scheme,
|
const Scheme &scheme,
|
||||||
const QColor &color) {
|
const QColor &color) {
|
||||||
const auto colorizer = Window::Theme::ColorizerFrom(
|
auto &colors = Core::App().settings().themesAccentColors();
|
||||||
scheme,
|
if (colors.get(scheme.type) != color) {
|
||||||
color);
|
colors.set(scheme.type, color);
|
||||||
|
Local::writeSettings();
|
||||||
|
}
|
||||||
|
const auto colorizer = Window::Theme::ColorizerFrom(scheme, color);
|
||||||
apply(scheme, &colorizer);
|
apply(scheme, &colorizer);
|
||||||
};
|
};
|
||||||
const auto applyWithColorize = [=](const Scheme &scheme) {
|
const auto applyWithColorize = [=](const Scheme &scheme) {
|
||||||
|
@ -819,10 +1013,6 @@ void SetupDefaultThemes(not_null<Ui::VerticalLayout*> container) {
|
||||||
"Choose accent color",
|
"Choose accent color",
|
||||||
color.value_or(scheme.accentColor)));
|
color.value_or(scheme.accentColor)));
|
||||||
box->setSaveCallback([=](QColor result) {
|
box->setSaveCallback([=](QColor result) {
|
||||||
Core::App().settings().themesAccentColors().set(
|
|
||||||
scheme.type,
|
|
||||||
result);
|
|
||||||
Core::App().saveSettingsDelayed();
|
|
||||||
applyWithColor(scheme, result);
|
applyWithColor(scheme, result);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -843,7 +1033,7 @@ void SetupDefaultThemes(not_null<Ui::VerticalLayout*> container) {
|
||||||
|
|
||||||
auto checks = base::flat_map<Type,not_null<DefaultTheme*>>();
|
auto checks = base::flat_map<Type,not_null<DefaultTheme*>>();
|
||||||
auto buttons = ranges::view::all(
|
auto buttons = ranges::view::all(
|
||||||
SchemesList
|
kSchemesList
|
||||||
) | ranges::view::transform([&](const Scheme &scheme) {
|
) | ranges::view::transform([&](const Scheme &scheme) {
|
||||||
auto check = std::make_unique<DefaultTheme>(scheme, false);
|
auto check = std::make_unique<DefaultTheme>(scheme, false);
|
||||||
const auto weak = check.get();
|
const auto weak = check.get();
|
||||||
|
@ -863,10 +1053,17 @@ void SetupDefaultThemes(not_null<Ui::VerticalLayout*> container) {
|
||||||
}) | ranges::to_vector;
|
}) | ranges::to_vector;
|
||||||
|
|
||||||
const auto refreshColorizer = [=](Type type) {
|
const auto refreshColorizer = [=](Type type) {
|
||||||
|
if (type == chosen()) {
|
||||||
|
palette->show(type);
|
||||||
|
}
|
||||||
|
|
||||||
const auto &colors = Core::App().settings().themesAccentColors();
|
const auto &colors = Core::App().settings().themesAccentColors();
|
||||||
const auto i = checks.find(type);
|
const auto i = checks.find(type);
|
||||||
const auto scheme = ranges::find(SchemesList, type, &Scheme::type);
|
const auto scheme = ranges::find(kSchemesList, type, &Scheme::type);
|
||||||
if (i != end(checks) && scheme != end(SchemesList)) {
|
if (scheme == end(kSchemesList)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (i != end(checks)) {
|
||||||
if (const auto color = colors.get(type)) {
|
if (const auto color = colors.get(type)) {
|
||||||
const auto colorizer = Window::Theme::ColorizerFrom(
|
const auto colorizer = Window::Theme::ColorizerFrom(
|
||||||
*scheme,
|
*scheme,
|
||||||
|
@ -878,7 +1075,7 @@ void SetupDefaultThemes(not_null<Ui::VerticalLayout*> container) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto &scheme : SchemesList) {
|
for (const auto &scheme : kSchemesList) {
|
||||||
refreshColorizer(scheme.type);
|
refreshColorizer(scheme.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -938,11 +1135,15 @@ void SetupDefaultThemes(not_null<Ui::VerticalLayout*> container) {
|
||||||
}
|
}
|
||||||
}, block->lifetime());
|
}, block->lifetime());
|
||||||
|
|
||||||
const auto colors = container->add(
|
palette->selected(
|
||||||
object_ptr<Ui::SlideWrap<>>(
|
) | rpl::start_with_next([=](QColor color) {
|
||||||
container,
|
const auto type = chosen();
|
||||||
object_ptr<Ui::FixedHeightWidget>(
|
const auto scheme = ranges::find(kSchemesList, type, &Scheme::type);
|
||||||
container)));
|
if (scheme == end(kSchemesList)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
applyWithColor(*scheme, color);
|
||||||
|
}, container->lifetime());
|
||||||
|
|
||||||
AddSkip(container);
|
AddSkip(container);
|
||||||
}
|
}
|
||||||
|
|
|
@ -231,10 +231,10 @@ std::vector<EmbeddedScheme> EmbeddedThemes() {
|
||||||
EmbeddedScheme{
|
EmbeddedScheme{
|
||||||
EmbeddedType::NightGreen,
|
EmbeddedType::NightGreen,
|
||||||
Color("485761"),
|
Color("485761"),
|
||||||
Color("75bfab"),
|
Color("75bfb5"),
|
||||||
Color("6b808d"),
|
Color("6b808d"),
|
||||||
Color("6b808d"),
|
Color("6b808d"),
|
||||||
Color("75bfab"),
|
Color("75bfb5"),
|
||||||
tr::lng_settings_theme_matrix,
|
tr::lng_settings_theme_matrix,
|
||||||
":/gui/night-green.tdesktop-theme",
|
":/gui/night-green.tdesktop-theme",
|
||||||
Color("3fc1b0")
|
Color("3fc1b0")
|
||||||
|
@ -242,7 +242,7 @@ std::vector<EmbeddedScheme> EmbeddedThemes() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<QColor> AccentColors(EmbeddedType type) {
|
std::vector<QColor> DefaultAccentColors(EmbeddedType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case EmbeddedType::DayBlue:
|
case EmbeddedType::DayBlue:
|
||||||
return {
|
return {
|
||||||
|
@ -252,9 +252,9 @@ std::vector<QColor> AccentColors(EmbeddedType type) {
|
||||||
Color("da73a2"),
|
Color("da73a2"),
|
||||||
Color("e28830"),
|
Color("e28830"),
|
||||||
Color("9073e7"),
|
Color("9073e7"),
|
||||||
Color("9073e7"),
|
Color("c14126"),
|
||||||
|
Color("71829c"),
|
||||||
Color("e3b63e"),
|
Color("e3b63e"),
|
||||||
Color("71829c")
|
|
||||||
};
|
};
|
||||||
case EmbeddedType::Default:
|
case EmbeddedType::Default:
|
||||||
return {};
|
return {};
|
||||||
|
@ -266,9 +266,9 @@ std::vector<QColor> AccentColors(EmbeddedType type) {
|
||||||
Color("da73a2"),
|
Color("da73a2"),
|
||||||
Color("e28830"),
|
Color("e28830"),
|
||||||
Color("9073e7"),
|
Color("9073e7"),
|
||||||
Color("9073e7"),
|
Color("c14126"),
|
||||||
|
Color("71829c"),
|
||||||
Color("e3b63e"),
|
Color("e3b63e"),
|
||||||
Color("71829c")
|
|
||||||
};
|
};
|
||||||
case EmbeddedType::NightGreen:
|
case EmbeddedType::NightGreen:
|
||||||
return {
|
return {
|
||||||
|
@ -278,9 +278,9 @@ std::vector<QColor> AccentColors(EmbeddedType type) {
|
||||||
Color("da73a2"),
|
Color("da73a2"),
|
||||||
Color("e28830"),
|
Color("e28830"),
|
||||||
Color("9073e7"),
|
Color("9073e7"),
|
||||||
Color("9073e7"),
|
Color("c14126"),
|
||||||
|
Color("71829c"),
|
||||||
Color("e3b63e"),
|
Color("e3b63e"),
|
||||||
Color("71829c")
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Unexpected("Type in Window::Theme::AccentColors.");
|
Unexpected("Type in Window::Theme::AccentColors.");
|
||||||
|
|
Loading…
Reference in New Issue