mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/telegramdesktop/tdesktop
synced 2026-09-21 00:23:56 +08:00
217 lines
6.6 KiB
C++
217 lines
6.6 KiB
C++
/*
|
|
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 "dialogs/ui/restore_windows_offer.h"
|
|
|
|
#include "dialogs/ui/dialogs_pill.h"
|
|
#include "dialogs/ui/dialogs_top_bar_suggestion_content.h"
|
|
#include "lang/lang_keys.h"
|
|
#include "ui/painter.h"
|
|
#include "ui/ui_utility.h"
|
|
#include "ui/widgets/buttons.h"
|
|
#include "styles/style_dialogs.h"
|
|
#include "styles/style_layers.h"
|
|
#include "styles/style_widgets.h"
|
|
|
|
namespace Dialogs {
|
|
namespace {
|
|
|
|
[[nodiscard]] int ButtonTextMargin() {
|
|
const auto width = st::dialogsUnconfirmedAuthButton.width;
|
|
return (width < 0) ? (-width / 2) : 0;
|
|
}
|
|
|
|
[[nodiscard]] int CloseRippleOverhang() {
|
|
const auto &st = st::restoreWindowsOfferClose;
|
|
return st.width - st.rippleAreaPosition.x() - st.rippleAreaSize;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
RestoreWindowsOffer::RestoreWindowsOffer(not_null<Ui::RpWidget*> parent)
|
|
: Ui::RpWidget(parent)
|
|
, _always(Ui::CreateChild<Ui::RoundButton>(
|
|
this,
|
|
tr::lng_restore_windows_always(),
|
|
st::dialogsUnconfirmedAuthButton))
|
|
, _restore(Ui::CreateChild<Ui::RoundButton>(
|
|
this,
|
|
tr::lng_restore_windows_restore(),
|
|
st::dialogsUnconfirmedAuthButton))
|
|
, _never(Ui::CreateChild<Ui::RoundButton>(
|
|
this,
|
|
tr::lng_restore_windows_never(),
|
|
st::dialogsUnconfirmedAuthButtonNo))
|
|
, _wideAlways(Ui::CreateChild<Ui::RoundButton>(
|
|
this,
|
|
tr::lng_restore_windows_always(),
|
|
st::defaultLightButton))
|
|
, _wideRestore(Ui::CreateChild<Ui::RoundButton>(
|
|
this,
|
|
tr::lng_restore_windows_restore(),
|
|
st::defaultLightButton))
|
|
, _wideNever(Ui::CreateChild<Ui::RoundButton>(
|
|
this,
|
|
tr::lng_restore_windows_never(),
|
|
st::attentionBoxButton))
|
|
, _close(Ui::CreateChild<Ui::IconButton>(
|
|
this,
|
|
st::restoreWindowsOfferClose))
|
|
, _shadow(st::dialogsTopBarSuggestionShadow) {
|
|
_question.setText(
|
|
st::restoreWindowsOfferQuestionStyle,
|
|
tr::lng_restore_windows_question(tr::now));
|
|
const auto choose = [=](RestoreWindowsChoice choice) {
|
|
return [=] { _chosen.fire_copy(choice); };
|
|
};
|
|
_always->setClickedCallback(choose(RestoreWindowsChoice::Always));
|
|
_restore->setClickedCallback(choose(RestoreWindowsChoice::Once));
|
|
_never->setClickedCallback(choose(RestoreWindowsChoice::Never));
|
|
_wideAlways->setClickedCallback(choose(RestoreWindowsChoice::Always));
|
|
_wideRestore->setClickedCallback(choose(RestoreWindowsChoice::Once));
|
|
_wideNever->setClickedCallback(choose(RestoreWindowsChoice::Never));
|
|
_close->setClickedCallback(choose(RestoreWindowsChoice::Dismiss));
|
|
}
|
|
|
|
void RestoreWindowsOffer::setAvailableWidth(int available) {
|
|
if (_maxWidth != available) {
|
|
_maxWidth = available;
|
|
relayout();
|
|
}
|
|
}
|
|
|
|
rpl::producer<RestoreWindowsChoice> RestoreWindowsOffer::chosen() const {
|
|
return _chosen.events();
|
|
}
|
|
|
|
Ui::Text::GeometryDescriptor RestoreWindowsOffer::questionGeometry() const {
|
|
const auto first = _questionFirstLine;
|
|
const auto other = _questionOther;
|
|
return { .layout = [=](int line) {
|
|
return Ui::Text::LineGeometry{ .width = line ? other : first };
|
|
} };
|
|
}
|
|
|
|
void RestoreWindowsOffer::relayout() {
|
|
const auto &margins = st::dialogsTopBarSuggestionMargins;
|
|
const auto &padding = st::restoreWindowsOfferPadding;
|
|
const auto textMargin = ButtonTextMargin();
|
|
const auto buttonSkip = st::restoreWindowsOfferButtonSkip;
|
|
const auto frame = margins.left()
|
|
+ padding.left()
|
|
+ padding.right()
|
|
+ margins.right();
|
|
const auto lineHeight
|
|
= st::restoreWindowsOfferQuestionStyle.font->height;
|
|
const auto closeReserve = _close->width()
|
|
- textMargin
|
|
- CloseRippleOverhang()
|
|
+ buttonSkip;
|
|
const auto buttonsInner = _always->width()
|
|
+ buttonSkip
|
|
+ _restore->width()
|
|
+ buttonSkip
|
|
+ _never->width()
|
|
- 2 * textMargin;
|
|
const auto questionInner = _question.maxWidth() + closeReserve;
|
|
const auto wide = std::max(buttonsInner, questionInner);
|
|
const auto horizontal = (frame + wide <= _maxWidth);
|
|
const auto inner = horizontal
|
|
? wide
|
|
: std::max(_maxWidth - frame, closeReserve + lineHeight);
|
|
_questionFirstLine = inner - closeReserve;
|
|
_questionOther = inner;
|
|
const auto question = std::max(
|
|
_question.countDimensions(questionGeometry()).height,
|
|
lineHeight);
|
|
const auto block = std::max(question, _close->height());
|
|
const auto questionTop = margins.top()
|
|
+ padding.top()
|
|
+ std::max((block - question) / 2, 0);
|
|
const auto buttonsTop = margins.top()
|
|
+ padding.top()
|
|
+ block
|
|
+ st::restoreWindowsOfferSkip;
|
|
const auto buttonHeight = _always->height();
|
|
const auto wideHeight = _wideAlways->height()
|
|
+ buttonSkip
|
|
+ _wideRestore->height()
|
|
+ buttonSkip
|
|
+ _wideNever->height();
|
|
const auto bottom = padding.bottom() + margins.bottom();
|
|
const auto totalWidth = frame + inner;
|
|
for (const auto button : { _always, _restore, _never }) {
|
|
button->setVisible(horizontal);
|
|
}
|
|
for (const auto button : { _wideAlways, _wideRestore, _wideNever }) {
|
|
button->setVisible(!horizontal);
|
|
}
|
|
resize(
|
|
totalWidth,
|
|
horizontal
|
|
? (buttonsTop + buttonHeight + bottom)
|
|
: (buttonsTop + wideHeight + bottom));
|
|
_questionPosition = QPoint(
|
|
margins.left() + padding.left(),
|
|
questionTop);
|
|
_close->moveToRight(
|
|
margins.right()
|
|
+ padding.right()
|
|
- textMargin
|
|
- CloseRippleOverhang(),
|
|
questionTop + (lineHeight - _close->height()) / 2);
|
|
const auto left = margins.left() + padding.left() - textMargin;
|
|
if (horizontal) {
|
|
_always->moveToLeft(left, buttonsTop);
|
|
_never->moveToRight(
|
|
margins.right() + padding.right() - textMargin,
|
|
buttonsTop);
|
|
const auto alwaysEnd = left + _always->width();
|
|
const auto neverStart = totalWidth
|
|
- (margins.right() + padding.right() - textMargin)
|
|
- _never->width();
|
|
_restore->moveToLeft(
|
|
(alwaysEnd + neverStart - _restore->width()) / 2,
|
|
buttonsTop);
|
|
} else {
|
|
const auto wideWidth = inner;
|
|
auto top = buttonsTop;
|
|
for (const auto button : { _wideAlways, _wideRestore, _wideNever }) {
|
|
button->resizeToWidth(wideWidth);
|
|
button->moveToLeft(margins.left() + padding.left(), top);
|
|
top += button->height() + buttonSkip;
|
|
}
|
|
}
|
|
}
|
|
|
|
void RestoreWindowsOffer::paintEvent(QPaintEvent *e) {
|
|
auto p = QPainter(this);
|
|
const auto pill = rect() - st::dialogsTopBarSuggestionMargins;
|
|
const auto radius = std::min({
|
|
PillRadius(),
|
|
pill.width() / 2,
|
|
pill.height() / 2,
|
|
});
|
|
_shadow.paint(p, pill, radius);
|
|
{
|
|
auto hq = PainterHighQualityEnabler(p);
|
|
p.setBrush(st::dialogsBg);
|
|
p.setPen(Qt::NoPen);
|
|
p.drawRoundedRect(pill, radius, radius);
|
|
}
|
|
PaintPillOutline(p, pill, radius);
|
|
p.setPen(st::windowFg);
|
|
_question.draw(p, {
|
|
.position = _questionPosition,
|
|
.outerWidth = width(),
|
|
.availableWidth = _questionOther,
|
|
.geometry = questionGeometry(),
|
|
});
|
|
}
|
|
|
|
} // namespace Dialogs
|