Show chosen element in custom theme selector.

This commit is contained in:
John Preston 2021-09-28 16:23:55 +04:00
parent 1204e282d3
commit a8efd0ef3d
3 changed files with 95 additions and 38 deletions

View file

@ -1450,7 +1450,10 @@ void HistoryWidget::toggleChooseChatTheme(not_null<PeerData*> peer) {
return; return;
} else if (_chooseTheme) { } else if (_chooseTheme) {
if (isChoosingTheme()) { if (isChoosingTheme()) {
_chooseTheme = nullptr; const auto was = base::take(_chooseTheme);
if (Ui::InFocusChain(this)) {
setInnerFocus();
}
update(); update();
} }
return; return;
@ -1614,7 +1617,9 @@ void HistoryWidget::setInnerFocus() {
if (_scroll->isHidden()) { if (_scroll->isHidden()) {
setFocus(); setFocus();
} else if (_list) { } else if (_list) {
if (_nonEmptySelection if (_chooseTheme && _chooseTheme->shouldBeShown()) {
_chooseTheme->setFocus();
} else if (_nonEmptySelection
|| (_list && _list->wasSelectedText()) || (_list && _list->wasSelectedText())
|| isRecording() || isRecording()
|| isBotStart() || isBotStart()
@ -2404,8 +2409,9 @@ void HistoryWidget::updateControlsVisibility() {
toggleOne(_unblock); toggleOne(_unblock);
}; };
if (isChoosingTheme()) { if (isChoosingTheme()) {
toggle(nullptr);
_chooseTheme->show(); _chooseTheme->show();
setInnerFocus();
toggle(nullptr);
} else if (isReportMessages()) { } else if (isReportMessages()) {
toggle(_reportMessages); toggle(_reportMessages);
} else if (isBlocked()) { } else if (isBlocked()) {

View file

@ -137,6 +137,7 @@ struct ChooseThemeController::Entry {
QImage preview; QImage preview;
EmojiPtr emoji = nullptr; EmojiPtr emoji = nullptr;
QRect geometry; QRect geometry;
bool chosen = false;
}; };
ChooseThemeController::ChooseThemeController( ChooseThemeController::ChooseThemeController(
@ -179,7 +180,7 @@ void ChooseThemeController::init(rpl::producer<QSize> outer) {
_wrap.get(), _wrap.get(),
tr::lng_chat_theme_title(), tr::lng_chat_theme_title(),
st::boxTitle), st::boxTitle),
style::margins{ skip * 2, skip, skip * 2, skip }); style::margins{ skip * 2, skip, skip * 2, 0 });
_wrap->paintRequest( _wrap->paintRequest(
) | rpl::start_with_next([=](QRect clip) { ) | rpl::start_with_next([=](QRect clip) {
QPainter(_wrap.get()).fillRect(clip, st::windowBg); QPainter(_wrap.get()).fillRect(clip, st::windowBg);
@ -220,7 +221,7 @@ void ChooseThemeController::initButtons() {
const auto skip = st::normalFont->spacew * 2; const auto skip = st::normalFont->spacew * 2;
controls->resize( controls->resize(
skip + cancel->width() + skip + apply->width() + skip, skip + cancel->width() + skip + apply->width() + skip,
skip + apply->height() + skip); apply->height() + skip);
rpl::combine( rpl::combine(
controls->widthValue(), controls->widthValue(),
cancel->widthValue(), cancel->widthValue(),
@ -231,23 +232,10 @@ void ChooseThemeController::initButtons() {
int applyWidth) { int applyWidth) {
const auto inner = skip + cancelWidth + skip + applyWidth + skip; const auto inner = skip + cancelWidth + skip + applyWidth + skip;
const auto left = (outer - inner) / 2; const auto left = (outer - inner) / 2;
cancel->moveToLeft(left, skip); cancel->moveToLeft(left, 0);
apply->moveToRight(left, skip); apply->moveToRight(left, 0);
}, controls->lifetime()); }, controls->lifetime());
const auto findChosen = [=]() -> const Entry* {
if (_chosen.isEmpty()) {
return nullptr;
}
for (const auto &entry : _entries) {
if (!entry.id && _chosen == kDisableElement.utf16()) {
return &entry;
} else if (_chosen == entry.emoji->text()) {
return &entry;
}
}
return nullptr;
};
const auto changed = [=] { const auto changed = [=] {
if (_chosen.isEmpty()) { if (_chosen.isEmpty()) {
return false; return false;
@ -263,14 +251,7 @@ void ChooseThemeController::initButtons() {
} }
return false; return false;
}; };
cancel->setClickedCallback([=] { cancel->setClickedCallback([=] { close(); });
if (const auto chosen = findChosen()) {
if (Ui::Emoji::Find(_peer->themeEmoji()) != chosen->emoji) {
clearCurrentBackgroundState();
}
}
_controller->toggleChooseChatTheme(_peer);
});
apply->setClickedCallback([=] { apply->setClickedCallback([=] {
if (const auto chosen = findChosen()) { if (const auto chosen = findChosen()) {
if (Ui::Emoji::Find(_peer->themeEmoji()) != chosen->emoji) { if (Ui::Emoji::Find(_peer->themeEmoji()) != chosen->emoji) {
@ -308,12 +289,24 @@ void ChooseThemeController::paintEntry(QPainter &p, const Entry &entry) {
+ (geometry.width() - (size / factor)) / 2), + (geometry.width() - (size / factor)) / 2),
(geometry.y() + geometry.height() - (size / factor) - skip)); (geometry.y() + geometry.height() - (size / factor) - skip));
if (entry.chosen) {
auto hq = PainterHighQualityEnabler(p);
auto pen = st::activeLineFg->p;
const auto width = st::defaultFlatInput.borderWidth;
pen.setWidth(width);
p.setPen(pen);
const auto add = st::lineWidth + width;
p.drawRoundedRect(
entry.geometry.marginsAdded({ add, add, add, add }),
st::roundRadiusLarge + add,
st::roundRadiusLarge + add);
}
} }
void ChooseThemeController::initList() { void ChooseThemeController::initList() {
_content->resize( _content->resize(
_content->width(), _content->width(),
st::settingsThemePreviewSize.height()); 4 * st::normalFont->spacew + st::settingsThemePreviewSize.height());
_inner->setMouseTracking(true); _inner->setMouseTracking(true);
_inner->paintRequest( _inner->paintRequest(
@ -326,8 +319,8 @@ void ChooseThemeController::initList() {
paintEntry(p, entry); paintEntry(p, entry);
} }
}, lifetime()); }, lifetime());
const auto byPoint = [=](QPoint position) -> const Entry* { const auto byPoint = [=](QPoint position) -> Entry* {
for (const auto &entry : _entries) { for (auto &entry : _entries) {
if (entry.geometry.contains(position)) { if (entry.geometry.contains(position)) {
return &entry; return &entry;
} }
@ -360,24 +353,67 @@ void ChooseThemeController::initList() {
const auto chosen = chosenText(entry); const auto chosen = chosenText(entry);
if (entry && chosen == _pressed && chosen != _chosen) { if (entry && chosen == _pressed && chosen != _chosen) {
clearCurrentBackgroundState(); clearCurrentBackgroundState();
if (const auto was = findChosen()) {
was->chosen = false;
}
_chosen = chosen; _chosen = chosen;
entry->chosen = true;
if (entry->theme || !entry->id) { if (entry->theme || !entry->id) {
_controller->overridePeerTheme(_peer, entry->theme); _controller->overridePeerTheme(_peer, entry->theme);
} }
_inner->update();
} }
_pressed = QString(); _pressed = QString();
} }
}, lifetime()); }, lifetime());
_content->events(
) | rpl::start_with_next([=](not_null<QEvent*> event) {
const auto type = event->type();
if (type == QEvent::KeyPress) {
const auto key = static_cast<QKeyEvent*>(event.get());
if (key->key() == Qt::Key_Escape) {
close();
}
}
}, lifetime());
}
void ChooseThemeController::close() {
if (const auto chosen = findChosen()) {
if (Ui::Emoji::Find(_peer->themeEmoji()) != chosen->emoji) {
clearCurrentBackgroundState();
}
}
_controller->toggleChooseChatTheme(_peer);
} }
void ChooseThemeController::clearCurrentBackgroundState() { void ChooseThemeController::clearCurrentBackgroundState() {
for (const auto &entry : _entries) { if (const auto entry = findChosen()) {
if (entry.theme && entry.emoji && entry.emoji->text() == _chosen) { if (entry->theme) {
entry.theme->clearBackgroundState(); entry->theme->clearBackgroundState();
} }
} }
} }
auto ChooseThemeController::findChosen() -> Entry* {
if (_chosen.isEmpty()) {
return nullptr;
}
for (auto &entry : _entries) {
if (!entry.id && _chosen == kDisableElement.utf16()) {
return &entry;
} else if (_chosen == entry.emoji->text()) {
return &entry;
}
}
return nullptr;
}
auto ChooseThemeController::findChosen() const -> const Entry* {
return const_cast<ChooseThemeController*>(this)->findChosen();
}
void ChooseThemeController::fill( void ChooseThemeController::fill(
const std::vector<Data::ChatTheme> &themes) { const std::vector<Data::ChatTheme> &themes) {
if (themes.empty()) { if (themes.empty()) {
@ -387,11 +423,16 @@ void ChooseThemeController::fill(
const auto single = st::settingsThemePreviewSize; const auto single = st::settingsThemePreviewSize;
const auto skip = st::normalFont->spacew * 2; const auto skip = st::normalFont->spacew * 2;
const auto full = single.width() * count + skip * (count + 1); const auto full = single.width() * count + skip * (count + 1);
_inner->resize(full, single.height()); _inner->resize(full, skip + single.height() + skip);
const auto initial = Ui::Emoji::Find(_peer->themeEmoji());
_dark.value( _dark.value(
) | rpl::start_with_next([=](bool dark) { ) | rpl::start_with_next([=](bool dark) {
clearCurrentBackgroundState(); clearCurrentBackgroundState();
if (_chosen.isEmpty() && initial) {
_chosen = initial->text();
}
_cachingLifetime.destroy(); _cachingLifetime.destroy();
const auto old = base::take(_entries); const auto old = base::take(_entries);
@ -399,7 +440,8 @@ void ChooseThemeController::fill(
_entries.push_back({ _entries.push_back({
.preview = GenerateEmptyPreview(), .preview = GenerateEmptyPreview(),
.emoji = Ui::Emoji::Find(QString::fromUtf8("\xe2\x9d\x8c")), .emoji = Ui::Emoji::Find(QString::fromUtf8("\xe2\x9d\x8c")),
.geometry = QRect(QPoint(x, 0), single), .geometry = QRect(QPoint(x, skip), single),
.chosen = (_chosen == kDisableElement.utf16()),
}); });
Assert(_entries.front().emoji != nullptr); Assert(_entries.front().emoji != nullptr);
style::PaletteChanged( style::PaletteChanged(
@ -418,7 +460,8 @@ void ChooseThemeController::fill(
_entries.push_back({ _entries.push_back({
.id = id, .id = id,
.emoji = emoji, .emoji = emoji,
.geometry = QRect(QPoint(x, 0), single), .geometry = QRect(QPoint(x, skip), single),
.chosen = (_chosen == emoji->text()),
}); });
_controller->cachedChatThemeValue( _controller->cachedChatThemeValue(
used used
@ -465,7 +508,6 @@ void ChooseThemeController::fill(
_inner->update(); _inner->update();
}, _cachingLifetime); }, _cachingLifetime);
}, _cachingLifetime); }, _cachingLifetime);
_entries.back().preview;
x += single.width() + skip; x += single.width() + skip;
} }
}, lifetime()); }, lifetime());
@ -497,6 +539,10 @@ void ChooseThemeController::raise() {
_topShadow->raise(); _topShadow->raise();
} }
void ChooseThemeController::setFocus() {
_content->setFocus();
}
rpl::lifetime &ChooseThemeController::lifetime() { rpl::lifetime &ChooseThemeController::lifetime() {
return _wrap->lifetime(); return _wrap->lifetime();
} }

View file

@ -38,6 +38,7 @@ public:
void hide(); void hide();
void show(); void show();
void raise(); void raise();
void setFocus();
[[nodiscard]] rpl::lifetime &lifetime(); [[nodiscard]] rpl::lifetime &lifetime();
@ -48,10 +49,14 @@ private:
void initButtons(); void initButtons();
void initList(); void initList();
void fill(const std::vector<Data::ChatTheme> &themes); void fill(const std::vector<Data::ChatTheme> &themes);
void close();
void clearCurrentBackgroundState(); void clearCurrentBackgroundState();
void paintEntry(QPainter &p, const Entry &entry); void paintEntry(QPainter &p, const Entry &entry);
[[nodiscard]] Entry *findChosen();
[[nodiscard]] const Entry *findChosen() const;
const not_null<Window::SessionController*> _controller; const not_null<Window::SessionController*> _controller;
const not_null<PeerData*> _peer; const not_null<PeerData*> _peer;
const std::unique_ptr<VerticalLayout> _wrap; const std::unique_ptr<VerticalLayout> _wrap;