/* 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 "passport/passport_panel_form.h" #include "passport/passport_panel_controller.h" #include "lang/lang_keys.h" #include "boxes/abstract_box.h" #include "core/click_handler_types.h" #include "ui/widgets/shadow.h" #include "ui/widgets/buttons.h" #include "ui/widgets/scroll_area.h" #include "ui/widgets/labels.h" #include "ui/wrap/vertical_layout.h" #include "ui/wrap/fade_wrap.h" #include "ui/wrap/padding_wrap.h" #include "ui/text_options.h" #include "ui/special_buttons.h" #include "styles/style_passport.h" #include "styles/style_boxes.h" namespace Passport { class PanelForm::Row : public Ui::RippleButton { public: Row( QWidget *parent, const QString &title, const QString &description); void setReady(bool ready); protected: int resizeGetHeight(int newWidth) override; void paintEvent(QPaintEvent *e) override; private: int countAvailableWidth() const; int countAvailableWidth(int newWidth) const; Text _title; Text _description; int _titleHeight = 0; int _descriptionHeight = 0; bool _ready = false; }; PanelForm::Row::Row( QWidget *parent, const QString &title, const QString &description) : RippleButton(parent, st::passportRowRipple) , _title( st::semiboldTextStyle, title, Ui::NameTextOptions(), st::boxWideWidth / 2) , _description( st::defaultTextStyle, description, Ui::NameTextOptions(), st::boxWideWidth / 2) { } void PanelForm::Row::setReady(bool ready) { _ready = ready; resizeToWidth(width()); update(); } int PanelForm::Row::resizeGetHeight(int newWidth) { const auto availableWidth = countAvailableWidth(newWidth); _titleHeight = _title.countHeight(availableWidth); _descriptionHeight = _description.countHeight(availableWidth); const auto result = st::passportRowPadding.top() + _titleHeight + st::passportRowSkip + _descriptionHeight + st::passportRowPadding.bottom(); return result; } int PanelForm::Row::countAvailableWidth(int newWidth) const { return newWidth - st::passportRowPadding.left() - st::passportRowPadding.right() - (_ready ? st::passportRowReadyIcon : st::passportRowEmptyIcon).width(); } int PanelForm::Row::countAvailableWidth() const { return countAvailableWidth(width()); } void PanelForm::Row::paintEvent(QPaintEvent *e) { Painter p(this); const auto ms = getms(); paintRipple(p, 0, 0, ms); const auto left = st::passportRowPadding.left(); const auto availableWidth = countAvailableWidth(); auto top = st::passportRowPadding.top(); p.setPen(st::passportRowTitleFg); _title.drawLeft(p, left, top, availableWidth, width()); top += _titleHeight + st::passportRowSkip; p.setPen(st::passportRowDescriptionFg); _description.drawLeft(p, left, top, availableWidth, width()); top += _descriptionHeight + st::passportRowPadding.bottom(); const auto &icon = _ready ? st::passportRowReadyIcon : st::passportRowEmptyIcon; icon.paint( p, width() - st::passportRowPadding.right() - icon.width(), (height() - icon.height()) / 2, width()); } PanelForm::PanelForm( QWidget *parent, not_null controller) : RpWidget(parent) , _controller(controller) , _scroll(this, st::passportPanelScroll) , _topShadow(this) , _bottomShadow(this) , _submit( this, langFactory(lng_passport_authorize), st::passportPanelAuthorize) { setupControls(); } void PanelForm::setupControls() { const auto inner = setupContent(); using namespace rpl::mappers; _topShadow->toggleOn( _scroll->scrollTopValue() | rpl::map(_1 > 0)); _bottomShadow->toggleOn(rpl::combine( _scroll->scrollTopValue(), _scroll->heightValue(), inner->heightValue(), _1 + _2 < _3)); } not_null PanelForm::setupContent() { const auto bot = _controller->bot(); const auto inner = _scroll->setOwnedWidget( object_ptr(this)); _scroll->widthValue( ) | rpl::start_with_next([=](int width) { inner->resizeToWidth(width); }, inner->lifetime()); const auto userpicWrap = inner->add( object_ptr( inner, st::passportFormUserpic.size.height()), st::passportFormUserpicPadding); _userpic = Ui::AttachParentChild( userpicWrap, object_ptr( userpicWrap, bot, Ui::UserpicButton::Role::Custom, st::passportFormUserpic)); userpicWrap->widthValue( ) | rpl::start_with_next([=](int width) { _userpic->move((width - _userpic->width()) / 2, _userpic->y()); }, _userpic->lifetime()); auto about1 = object_ptr( inner, lng_passport_request1(lt_bot, App::peerName(bot)), Ui::FlatLabel::InitType::Simple, st::passportPasswordLabelBold); _about1 = about1.data(); inner->add( object_ptr(inner, std::move(about1)), st::passportFormAbout1Padding); auto about2 = object_ptr( inner, lang(lng_passport_request2), Ui::FlatLabel::InitType::Simple, st::passportPasswordLabel); _about2 = about2.data(); inner->add( object_ptr(inner, std::move(about2)), st::passportFormAbout2Padding); inner->add(object_ptr( inner, st::passportFormDividerHeight)); inner->add( object_ptr( inner, lang(lng_passport_header), Ui::FlatLabel::InitType::Simple, st::passportFormHeader), st::passportFormHeaderPadding); auto index = 0; _controller->fillRows([&]( QString title, QString description, bool ready) { _rows.push_back(inner->add(object_ptr( this, title, description))); _rows.back()->addClickHandler([=] { _controller->editScope(index); }); _rows.back()->setReady(ready); ++index; }); const auto policyUrl = _controller->privacyPolicyUrl(); const auto policy = inner->add( object_ptr( inner, (policyUrl.isEmpty() ? lng_passport_allow(lt_bot, '@' + bot->username) : lng_passport_accept_allow( lt_policy, textcmdLink( 1, lng_passport_policy(lt_bot, App::peerName(bot))), lt_bot, '@' + bot->username)), Ui::FlatLabel::InitType::Rich, st::passportFormPolicy), st::passportFormPolicyPadding); if (!policyUrl.isEmpty()) { policy->setLink(1, std::make_shared(policyUrl)); } return inner; } void PanelForm::resizeEvent(QResizeEvent *e) { updateControlsGeometry(); } void PanelForm::updateControlsGeometry() { const auto submitTop = height() - _submit->height(); _scroll->setGeometry(0, 0, width(), submitTop); _topShadow->resizeToWidth(width()); _topShadow->moveToLeft(0, 0); _bottomShadow->resizeToWidth(width()); _bottomShadow->moveToLeft(0, submitTop - st::lineWidth); _submit->resizeToWidth(width()); _submit->moveToLeft(0, submitTop); _scroll->updateBars(); } } // namespace Passport