From 2796c535426262cad705c8d5424beefe589bf3b7 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 2 Dec 2016 22:16:35 +0300 Subject: [PATCH] Some more ripple animations. --- .../icons/profile_divider_bottom.png | Bin 0 -> 81 bytes .../icons/profile_divider_bottom@2x.png | Bin 0 -> 85 bytes .../Resources/icons/profile_divider_fill.png | Bin 96 -> 0 bytes .../icons/profile_divider_fill@2x.png | Bin 109 -> 0 bytes .../Resources/icons/profile_divider_left.png | Bin 114 -> 106 bytes .../icons/profile_divider_left@2x.png | Bin 155 -> 130 bytes .../Resources/icons/profile_divider_top.png | Bin 0 -> 88 bytes .../icons/profile_divider_top@2x.png | Bin 0 -> 106 bytes Telegram/Resources/langs/lang.strings | 2 +- Telegram/SourceFiles/boxes/addcontactbox.cpp | 22 +- Telegram/SourceFiles/boxes/addcontactbox.h | 3 +- Telegram/SourceFiles/boxes/autolockbox.cpp | 2 +- Telegram/SourceFiles/boxes/boxes.style | 17 +- Telegram/SourceFiles/boxes/confirmbox.cpp | 10 +- Telegram/SourceFiles/boxes/connectionbox.cpp | 32 +-- Telegram/SourceFiles/boxes/contactsbox.cpp | 48 ++-- .../SourceFiles/boxes/downloadpathbox.cpp | 18 +- Telegram/SourceFiles/boxes/languagebox.cpp | 4 +- Telegram/SourceFiles/boxes/report_box.cpp | 18 +- Telegram/SourceFiles/boxes/send_files_box.cpp | 6 +- Telegram/SourceFiles/boxes/stickers_box.cpp | 1 - Telegram/SourceFiles/facades.cpp | 4 + Telegram/SourceFiles/facades.h | 2 + Telegram/SourceFiles/historywidget.cpp | 6 +- Telegram/SourceFiles/localimageloader.cpp | 2 +- Telegram/SourceFiles/profile/profile.style | 4 +- .../SourceFiles/profile/profile_cover.cpp | 20 +- .../profile/profile_settings_widget.cpp | 2 +- .../settings/settings_block_widget.cpp | 7 +- .../SourceFiles/settings/settings_cover.cpp | 14 +- .../settings/settings_scale_widget.cpp | 5 +- Telegram/SourceFiles/ui/abstract_button.cpp | 15 +- Telegram/SourceFiles/ui/abstract_button.h | 2 +- .../ui/effects/ripple_animation.cpp | 14 +- .../SourceFiles/ui/effects/ripple_animation.h | 2 +- .../SourceFiles/ui/effects/widget_fade_wrap.h | 7 + .../ui/effects/widget_slide_wrap.cpp | 36 ++- .../ui/effects/widget_slide_wrap.h | 1 + Telegram/SourceFiles/ui/twidget.h | 46 +++- Telegram/SourceFiles/ui/widgets/buttons.cpp | 11 +- Telegram/SourceFiles/ui/widgets/buttons.h | 5 +- Telegram/SourceFiles/ui/widgets/checkbox.cpp | 226 ++++++------------ Telegram/SourceFiles/ui/widgets/checkbox.h | 36 +-- .../ui/widgets/discrete_sliders.cpp | 71 +++++- .../SourceFiles/ui/widgets/discrete_sliders.h | 17 +- .../SourceFiles/ui/widgets/input_fields.cpp | 201 ++++------------ .../SourceFiles/ui/widgets/input_fields.h | 44 ++-- .../SourceFiles/ui/widgets/multi_select.cpp | 2 + Telegram/SourceFiles/ui/widgets/scroll_area.h | 4 + Telegram/SourceFiles/ui/widgets/widgets.style | 66 ++--- 50 files changed, 518 insertions(+), 537 deletions(-) create mode 100644 Telegram/Resources/icons/profile_divider_bottom.png create mode 100644 Telegram/Resources/icons/profile_divider_bottom@2x.png delete mode 100644 Telegram/Resources/icons/profile_divider_fill.png delete mode 100644 Telegram/Resources/icons/profile_divider_fill@2x.png create mode 100644 Telegram/Resources/icons/profile_divider_top.png create mode 100644 Telegram/Resources/icons/profile_divider_top@2x.png diff --git a/Telegram/Resources/icons/profile_divider_bottom.png b/Telegram/Resources/icons/profile_divider_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..31fee84f91d4bfe79b4cb01529cee5544c0554a5 GIT binary patch literal 81 zcmeAS@N?(olHy`uVBq!ia0vp^j6lrF!3HE-TH59VDG5&(#}JO0$q5MwKh7UHaNt0L ei-EDRF$05WGo#?P74Zr{H4L7velF{r5}E+O7!*zb literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/profile_divider_bottom@2x.png b/Telegram/Resources/icons/profile_divider_bottom@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..87fb6562126db7292842b7b319e1c7e04a399bde GIT binary patch literal 85 zcmeAS@N?(olHy`uVBq!ia0vp^OhC-V!3HGfJ?-}dQZk+{jv*W~lT#8Bew;r51V+AY# v%kJ;5H#YeD_xJS1&c;SY>w{;`oMB+-oz7+REdAa_pcV#CS3j3^P6gTe~ HDWM4fI)5eg diff --git a/Telegram/Resources/icons/profile_divider_left.png b/Telegram/Resources/icons/profile_divider_left.png index c4d4c3aa116da865dddfc792ee476b5ee83423c1..9bcfd455e14a23b180fe2c8f298cdd8b5bafbdb6 100644 GIT binary patch literal 106 zcmeAS@N?(olHy`uVBq!ia0vp^OhC-V!3HGfJ?-}dQih%`jv*W~dyj48J>bA`z~Ol! z!?*h)oDcOUF&1654PEM0X0Byv{6^2ErJ?=&{3n+0^^H#nsapwe30lak|Lc7Rj9o5Rydh(X-_M^yK!Dn;X&+Hs-MDz*j}cfYWnufLzw+?c`Y ech0vXEz&*`=1NnyI`;q#W$<+Mb6Mw<&;$TbjVT`h literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^Y(Ol+0V3C3^0@(|l001;LnNlIoe;=%K!L}3{^IQ) z{v9{Dd;G)-;qCK9nPx4^-17CFu!3g(GHD` z$d)eu-=}^t>i6kazlC21J+3{(RsGve*W5BPROkUqByXJ2{8@I=K-(BRUHx3vIVCg! E0PjyW5dZ)H diff --git a/Telegram/Resources/icons/profile_divider_top.png b/Telegram/Resources/icons/profile_divider_top.png new file mode 100644 index 0000000000000000000000000000000000000000..6dcdc143c0c16a25c8744dfc0d33722afc934ceb GIT binary patch literal 88 zcmeAS@N?(olHy`uVBq!ia0vp^j6lrF!3HE-TH59VDS1y9#}JO0tOp$h85lU270$74 ms1J!3ev|k7ok!4%1I+Q-Y|4jbJ0AopW$<+Mb6Mw<&;$S>>lTIp literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/profile_divider_top@2x.png b/Telegram/Resources/icons/profile_divider_top@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5bc32a739b61ee044003537da63f62bbacc2358f GIT binary patch literal 106 zcmeAS@N?(olHy`uVBq!ia0vp^OhC-V!3HGfJ?-}dQih%`jv*W~Q%@W6H5l-)9JF+K z|9}70iOzyjN5U@Wtjaq4^zFNM&0DV>Jky|ZQ=n$Oz1)RB9+id<2H%0289ZJ6T-G@y GGywoN=Omo~ literal 0 HcmV?d00001 diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 24f4f753c..6b6185750 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -877,7 +877,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org "lng_really_send_image" = "Do you want to send this image?"; "lng_really_send_file" = "Do you want to send this file?"; "lng_really_share_contact" = "Do you want to share this contact?"; -"lng_send_images_compress" = "Compressed {count:_not_used_|image|images}"; +"lng_send_images_compress" = "Compress {count:_not_used_|image|images}"; "lng_send_image_non_local" = "Could not send a non local file: {name}"; "lng_send_image_empty" = "Could not send an empty file: {name}"; "lng_send_image_too_large" = "Could not send a file, because it is larger than 1500 MB: {name}"; diff --git a/Telegram/SourceFiles/boxes/addcontactbox.cpp b/Telegram/SourceFiles/boxes/addcontactbox.cpp index cb9a570c7..8489cfd1e 100644 --- a/Telegram/SourceFiles/boxes/addcontactbox.cpp +++ b/Telegram/SourceFiles/boxes/addcontactbox.cpp @@ -426,9 +426,9 @@ void GroupInfoBox::onPhotoReady(const QImage &img) { SetupChannelBox::SetupChannelBox(ChannelData *channel, bool existing) : AbstractBox() , _channel(channel) , _existing(existing) -, _public(this, qsl("channel_privacy"), 0, lang(channel->isMegagroup() ? lng_create_public_group_title : lng_create_public_channel_title), true) -, _private(this, qsl("channel_privacy"), 1, lang(channel->isMegagroup() ? lng_create_private_group_title : lng_create_private_channel_title)) -, _aboutPublicWidth(width() - st::boxPadding.left() - st::boxButtonPadding.right() - st::newGroupPadding.left() - st::defaultRadiobutton.textPosition.x()) +, _public(this, qsl("channel_privacy"), 0, lang(channel->isMegagroup() ? lng_create_public_group_title : lng_create_public_channel_title), true, st::defaultBoxCheckbox) +, _private(this, qsl("channel_privacy"), 1, lang(channel->isMegagroup() ? lng_create_private_group_title : lng_create_private_channel_title), false, st::defaultBoxCheckbox) +, _aboutPublicWidth(width() - st::boxPadding.left() - st::boxButtonPadding.right() - st::newGroupPadding.left() - st::defaultBoxCheckbox.textPosition.x()) , _aboutPublic(st::normalFont, lang(channel->isMegagroup() ? lng_create_public_group_about : lng_create_public_channel_about), _defaultOptions, _aboutPublicWidth) , _aboutPrivate(st::normalFont, lang(channel->isMegagroup() ? lng_create_private_group_about : lng_create_private_channel_about), _defaultOptions, _aboutPublicWidth) , _link(this, st::defaultInputField, QString(), channel->username, true) @@ -467,9 +467,9 @@ void SetupChannelBox::doSetInnerFocus() { void SetupChannelBox::updateMaxHeight() { if (!_channel->isMegagroup() || _public->checked()) { - setMaxHeight(st::boxPadding.top() + st::newGroupPadding.top() + _public->height() + _aboutPublicHeight + st::newGroupSkip + _private->height() + _aboutPrivate.countHeight(_aboutPublicWidth) + st::newGroupSkip + st::newGroupPadding.bottom() + st::newGroupLinkPadding.top() + _link->height() + st::newGroupLinkPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom()); + setMaxHeight(st::boxPadding.top() + st::newGroupPadding.top() + _public->heightNoMargins() + _aboutPublicHeight + st::newGroupSkip + _private->heightNoMargins() + _aboutPrivate.countHeight(_aboutPublicWidth) + st::newGroupSkip + st::newGroupPadding.bottom() + st::newGroupLinkPadding.top() + _link->height() + st::newGroupLinkPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom()); } else { - setMaxHeight(st::boxPadding.top() + st::newGroupPadding.top() + _public->height() + _aboutPublicHeight + st::newGroupSkip + _private->height() + _aboutPrivate.countHeight(_aboutPublicWidth) + st::newGroupSkip + st::newGroupPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom()); + setMaxHeight(st::boxPadding.top() + st::newGroupPadding.top() + _public->heightNoMargins() + _aboutPublicHeight + st::newGroupSkip + _private->heightNoMargins() + _aboutPrivate.countHeight(_aboutPublicWidth) + st::newGroupSkip + st::newGroupPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom()); } } @@ -494,10 +494,10 @@ void SetupChannelBox::paintEvent(QPaintEvent *e) { p.fillRect(e->rect(), st::boxBg); p.setPen(st::newGroupAboutFg); - QRect aboutPublic(st::boxPadding.left() + st::newGroupPadding.left() + st::defaultRadiobutton.textPosition.x(), _public->y() + _public->height(), _aboutPublicWidth, _aboutPublicHeight); + QRect aboutPublic(st::boxPadding.left() + st::newGroupPadding.left() + st::defaultBoxCheckbox.textPosition.x(), _public->bottomNoMargins(), _aboutPublicWidth, _aboutPublicHeight); _aboutPublic.drawLeft(p, aboutPublic.x(), aboutPublic.y(), aboutPublic.width(), width()); - QRect aboutPrivate(st::boxPadding.left() + st::newGroupPadding.left() + st::defaultRadiobutton.textPosition.x(), _private->y() + _private->height(), _aboutPublicWidth, _aboutPublicHeight); + QRect aboutPrivate(st::boxPadding.left() + st::newGroupPadding.left() + st::defaultBoxCheckbox.textPosition.x(), _private->bottomNoMargins(), _aboutPublicWidth, _aboutPublicHeight); _aboutPrivate.drawLeft(p, aboutPrivate.x(), aboutPrivate.y(), aboutPrivate.width(), width()); if (!_channel->isMegagroup() || !_link->isHidden()) { @@ -536,10 +536,10 @@ void SetupChannelBox::paintEvent(QPaintEvent *e) { void SetupChannelBox::resizeEvent(QResizeEvent *e) { _public->moveToLeft(st::boxPadding.left() + st::newGroupPadding.left(), st::boxPadding.top() + st::newGroupPadding.top()); - _private->moveToLeft(st::boxPadding.left() + st::newGroupPadding.left(), _public->y() + _public->height() + _aboutPublicHeight + st::newGroupSkip); + _private->moveToLeft(st::boxPadding.left() + st::newGroupPadding.left(), _public->bottomNoMargins() + _aboutPublicHeight + st::newGroupSkip); _link->resize(width() - st::boxPadding.left() - st::newGroupLinkPadding.left() - st::boxPadding.right(), _link->height()); - _link->moveToLeft(st::boxPadding.left() + st::newGroupLinkPadding.left(), _private->y() + _private->height() + _aboutPrivate.countHeight(_aboutPublicWidth) + st::newGroupSkip + st::newGroupPadding.bottom() + st::newGroupLinkPadding.top()); + _link->moveToLeft(st::boxPadding.left() + st::newGroupLinkPadding.left(), _private->bottomNoMargins() + _aboutPrivate.countHeight(_aboutPublicWidth) + st::newGroupSkip + st::newGroupPadding.bottom() + st::newGroupLinkPadding.top()); _invitationLink = QRect(_link->x(), _link->y() + (_link->height() / 2) - st::boxTextFont->height, _link->width(), 2 * st::boxTextFont->height); _save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height()); @@ -1006,7 +1006,7 @@ void EditChannelBox::updateMaxHeight() { int32 h = titleHeight() + st::newGroupInfoPadding.top() + _title->height(); h += st::newGroupDescriptionPadding.top() + _description->height() + st::newGroupDescriptionPadding.bottom(); if (!_channel->isMegagroup()) { - h += st::newGroupPublicLinkPadding.top() + _sign->height() + st::newGroupPublicLinkPadding.bottom(); + h += st::newGroupPublicLinkPadding.top() + _sign->heightNoMargins() + st::newGroupPublicLinkPadding.bottom(); } if (_channel->canEditUsername()) { h += st::newGroupPublicLinkPadding.top() + _publicLink->height() + st::newGroupPublicLinkPadding.bottom(); @@ -1026,7 +1026,7 @@ void EditChannelBox::resizeEvent(QResizeEvent *e) { if (_channel->isMegagroup()) { _publicLink->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _description->y() + _description->height() + st::newGroupDescriptionPadding.bottom() + st::newGroupPublicLinkPadding.top()); } else { - _publicLink->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _sign->y() + _sign->height() + st::newGroupDescriptionPadding.bottom() + st::newGroupPublicLinkPadding.top()); + _publicLink->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _sign->bottomNoMargins() + st::newGroupDescriptionPadding.bottom() + st::newGroupPublicLinkPadding.top()); } _save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height()); diff --git a/Telegram/SourceFiles/boxes/addcontactbox.h b/Telegram/SourceFiles/boxes/addcontactbox.h index 4267d30a4..ad66f4369 100644 --- a/Telegram/SourceFiles/boxes/addcontactbox.h +++ b/Telegram/SourceFiles/boxes/addcontactbox.h @@ -170,7 +170,8 @@ private: ChannelData *_channel; bool _existing; - ChildWidget _public, _private; + ChildWidget _public; + ChildWidget _private; int32 _aboutPublicWidth, _aboutPublicHeight; Text _aboutPublic, _aboutPrivate; diff --git a/Telegram/SourceFiles/boxes/autolockbox.cpp b/Telegram/SourceFiles/boxes/autolockbox.cpp index 1da05fa02..88222a709 100644 --- a/Telegram/SourceFiles/boxes/autolockbox.cpp +++ b/Telegram/SourceFiles/boxes/autolockbox.cpp @@ -45,7 +45,7 @@ AutoLockBox::AutoLockBox() : _close(this, lang(lng_box_ok), st::defaultBoxButton int32 v = opts[i]; _options.push_back(new Ui::Radiobutton(this, qsl("autolock"), v, (v % 3600) ? lng_passcode_autolock_minutes(lt_count, v / 60) : lng_passcode_autolock_hours(lt_count, v / 3600), (Global::AutoLock() == v), st::langsButton)); _options.back()->move(st::boxPadding.left() + st::boxOptionListPadding.left(), y); - y += _options.back()->height() + st::boxOptionListPadding.top(); + y += _options.back()->heightNoMargins() + st::boxOptionListPadding.top(); connect(_options.back(), SIGNAL(changed()), this, SLOT(onChange())); } diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style index f668a8128..6f02e122a 100644 --- a/Telegram/SourceFiles/boxes/boxes.style +++ b/Telegram/SourceFiles/boxes/boxes.style @@ -233,17 +233,12 @@ contactsNameFont: semiboldFont; contactsStatusTop: 23px; contactsStatusFont: font(fsize); contactsCheckPosition: point(8px, 16px); -contactsAllAdminsTop: 18px; -contactsAboutBg: #f7f7f7; +contactsAllAdminsTop: 15px; +contactsAboutBg: windowBgOver; +contactsAboutFg: windowSubTextFgOver; contactsAboutShadow: #0000001F; -contactsAdminCheckbox: Checkbox(defaultBoxCheckbox) { - font: semiboldFont; - textBg: #f7f7f7; - textPosition: point(34px, 1px); -} -contactsAboutSkip: 53px; -contactsAboutHeight: 42px; -contactsAboutTop: 9px; +contactsAboutTop: 60px; +contactsAboutBottom: 19px; contactsScroll: FlatScroll(boxScroll) { deltab: 0px; } @@ -489,7 +484,7 @@ connectionPasswordInputField: InputField(defaultInputField) { connectionIPv6Skip: 11px; langsWidth: 256px; -langsButton: Radiobutton(defaultRadiobutton) { +langsButton: Checkbox(defaultBoxCheckbox) { width: 200px; } diff --git a/Telegram/SourceFiles/boxes/confirmbox.cpp b/Telegram/SourceFiles/boxes/confirmbox.cpp index a8cd84a9a..464b0073a 100644 --- a/Telegram/SourceFiles/boxes/confirmbox.cpp +++ b/Telegram/SourceFiles/boxes/confirmbox.cpp @@ -380,7 +380,7 @@ PinMessageBox::PinMessageBox(ChannelData *channel, MsgId msgId) : AbstractBox(st , _pin(this, lang(lng_pinned_pin), st::defaultBoxButton) , _cancel(this, lang(lng_cancel), st::cancelBoxButton) { _text->resizeToWidth(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()); - setMaxHeight(st::boxPadding.top() + _text->height() + st::boxMediumSkip + _notify->height() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _pin->height() + st::boxButtonPadding.bottom()); + setMaxHeight(st::boxPadding.top() + _text->height() + st::boxMediumSkip + _notify->heightNoMargins() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _pin->height() + st::boxButtonPadding.bottom()); connect(_pin, SIGNAL(clicked()), this, SLOT(onPin())); connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); @@ -430,7 +430,7 @@ RichDeleteMessageBox::RichDeleteMessageBox(ChannelData *channel, UserData *from, t_assert(_channel != nullptr); _text->resizeToWidth(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()); - setMaxHeight(st::boxPadding.top() + _text->height() + st::boxMediumSkip + _banUser->height() + st::boxLittleSkip + _reportSpam->height() + st::boxLittleSkip + _deleteAll->height() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _delete->height() + st::boxButtonPadding.bottom()); + setMaxHeight(st::boxPadding.top() + _text->height() + st::boxMediumSkip + _banUser->heightNoMargins() + st::boxLittleSkip + _reportSpam->heightNoMargins() + st::boxLittleSkip + _deleteAll->heightNoMargins() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _delete->height() + st::boxButtonPadding.bottom()); connect(_delete, SIGNAL(clicked()), this, SLOT(onDelete())); connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); @@ -438,9 +438,9 @@ RichDeleteMessageBox::RichDeleteMessageBox(ChannelData *channel, UserData *from, void RichDeleteMessageBox::resizeEvent(QResizeEvent *e) { _text->moveToLeft(st::boxPadding.left(), st::boxPadding.top()); - _banUser->moveToLeft(st::boxPadding.left(), _text->y() + _text->height() + st::boxMediumSkip); - _reportSpam->moveToLeft(st::boxPadding.left(), _banUser->y() + _banUser->height() + st::boxLittleSkip); - _deleteAll->moveToLeft(st::boxPadding.left(), _reportSpam->y() + _reportSpam->height() + st::boxLittleSkip); + _banUser->moveToLeft(st::boxPadding.left(), _text->bottomNoMargins() + st::boxMediumSkip); + _reportSpam->moveToLeft(st::boxPadding.left(), _banUser->bottomNoMargins() + st::boxLittleSkip); + _deleteAll->moveToLeft(st::boxPadding.left(), _reportSpam->bottomNoMargins() + st::boxLittleSkip); _delete->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _delete->height()); _cancel->moveToRight(st::boxButtonPadding.right() + _delete->width() + st::boxButtonPadding.left(), _delete->y()); AbstractBox::resizeEvent(e); diff --git a/Telegram/SourceFiles/boxes/connectionbox.cpp b/Telegram/SourceFiles/boxes/connectionbox.cpp index ab031abbc..b7cb5447b 100644 --- a/Telegram/SourceFiles/boxes/connectionbox.cpp +++ b/Telegram/SourceFiles/boxes/connectionbox.cpp @@ -36,9 +36,9 @@ ConnectionBox::ConnectionBox() : AbstractBox(st::boxWidth, lang(lng_connection_h , _portInput(this, st::connectionPortInputField, lang(lng_connection_port_ph), QString::number(Global::ConnectionProxy().port)) , _userInput(this, st::connectionUserInputField, lang(lng_connection_user_ph), Global::ConnectionProxy().user) , _passwordInput(this, st::connectionPasswordInputField, lang(lng_connection_password_ph), Global::ConnectionProxy().password) -, _autoRadio(this, qsl("conn_type"), dbictAuto, lang(lng_connection_auto_rb), (Global::ConnectionType() == dbictAuto)) -, _httpProxyRadio(this, qsl("conn_type"), dbictHttpProxy, lang(lng_connection_http_proxy_rb), (Global::ConnectionType() == dbictHttpProxy)) -, _tcpProxyRadio(this, qsl("conn_type"), dbictTcpProxy, lang(lng_connection_tcp_proxy_rb), (Global::ConnectionType() == dbictTcpProxy)) +, _autoRadio(this, qsl("conn_type"), dbictAuto, lang(lng_connection_auto_rb), (Global::ConnectionType() == dbictAuto), st::defaultBoxCheckbox) +, _httpProxyRadio(this, qsl("conn_type"), dbictHttpProxy, lang(lng_connection_http_proxy_rb), (Global::ConnectionType() == dbictHttpProxy), st::defaultBoxCheckbox) +, _tcpProxyRadio(this, qsl("conn_type"), dbictTcpProxy, lang(lng_connection_tcp_proxy_rb), (Global::ConnectionType() == dbictTcpProxy), st::defaultBoxCheckbox) , _tryIPv6(this, lang(lng_connection_try_ipv6), Global::TryIPv6(), st::defaultBoxCheckbox) , _save(this, lang(lng_connection_save), st::defaultBoxButton) , _cancel(this, lang(lng_cancel), st::cancelBoxButton) { @@ -59,7 +59,7 @@ ConnectionBox::ConnectionBox() : AbstractBox(st::boxWidth, lang(lng_connection_h } void ConnectionBox::updateControlsVisibility() { - int32 h = titleHeight() + st::boxOptionListPadding.top() + _autoRadio->height() + st::boxOptionListPadding.top() + _httpProxyRadio->height() + st::boxOptionListPadding.top() + _tcpProxyRadio->height() + st::boxOptionListPadding.top() + st::connectionIPv6Skip + _tryIPv6->height() + st::boxOptionListPadding.bottom() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom(); + int32 h = titleHeight() + st::boxOptionListPadding.top() + _autoRadio->heightNoMargins() + st::boxOptionListPadding.top() + _httpProxyRadio->heightNoMargins() + st::boxOptionListPadding.top() + _tcpProxyRadio->heightNoMargins() + st::boxOptionListPadding.top() + st::connectionIPv6Skip + _tryIPv6->heightNoMargins() + st::boxOptionListPadding.bottom() + st::boxPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom(); if (_httpProxyRadio->checked() || _tcpProxyRadio->checked()) { h += 2 * st::boxOptionListPadding.top() + 2 * _hostInput->height(); _hostInput->show(); @@ -85,27 +85,27 @@ void ConnectionBox::doSetInnerFocus() { void ConnectionBox::resizeEvent(QResizeEvent *e) { _autoRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), titleHeight() + st::boxOptionListPadding.top()); - _httpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _autoRadio->y() + _autoRadio->height() + st::boxOptionListPadding.top()); + _httpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _autoRadio->bottomNoMargins() + st::boxOptionListPadding.top()); int32 inputy = 0; if (_httpProxyRadio->checked()) { - inputy = _httpProxyRadio->y() + _httpProxyRadio->height() + st::boxOptionListPadding.top(); + inputy = _httpProxyRadio->bottomNoMargins() + st::boxOptionListPadding.top(); _tcpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), inputy + st::boxOptionListPadding.top() + 2 * _hostInput->height() + st::boxOptionListPadding.top()); } else { - _tcpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _httpProxyRadio->y() + _httpProxyRadio->height() + st::boxOptionListPadding.top()); + _tcpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _httpProxyRadio->bottomNoMargins() + st::boxOptionListPadding.top()); if (_tcpProxyRadio->checked()) { - inputy = _tcpProxyRadio->y() + _tcpProxyRadio->height() + st::boxOptionListPadding.top(); + inputy = _tcpProxyRadio->bottomNoMargins() + st::boxOptionListPadding.top(); } } if (inputy) { - _hostInput->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultRadiobutton.textPosition.x() - st::defaultInputField.textMargins.left(), inputy); + _hostInput->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultBoxCheckbox.textPosition.x() - st::defaultInputField.textMargins.left(), inputy); _portInput->moveToRight(st::boxPadding.right(), inputy); - _userInput->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultRadiobutton.textPosition.x() - st::defaultInputField.textMargins.left(), _hostInput->y() + _hostInput->height() + st::boxOptionListPadding.top()); + _userInput->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultBoxCheckbox.textPosition.x() - st::defaultInputField.textMargins.left(), _hostInput->y() + _hostInput->height() + st::boxOptionListPadding.top()); _passwordInput->moveToRight(st::boxPadding.right(), _userInput->y()); } - int32 tryipv6y = (_tcpProxyRadio->checked() ? (_userInput->y() + _userInput->height()) : (_tcpProxyRadio->y() + _tcpProxyRadio->height())) + st::boxOptionListPadding.top() + st::connectionIPv6Skip; + int32 tryipv6y = (_tcpProxyRadio->checked() ? _userInput->bottomNoMargins() : _tcpProxyRadio->bottomNoMargins()) + st::boxOptionListPadding.top() + st::connectionIPv6Skip; _tryIPv6->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), tryipv6y); _save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height()); @@ -212,7 +212,7 @@ AutoDownloadBox::AutoDownloadBox() : AbstractBox(st::boxWidth) , _save(this, lang(lng_connection_save), st::defaultBoxButton) , _cancel(this, lang(lng_cancel), st::cancelBoxButton) { - setMaxHeight(3 * _sectionHeight + st::setLittleSkip + _gifPlay->height() + st::setLittleSkip + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom()); + setMaxHeight(3 * _sectionHeight + st::setLittleSkip + _gifPlay->heightNoMargins() + st::setLittleSkip + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom()); connect(_save, SIGNAL(clicked()), this, SLOT(onSave())); connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); @@ -232,14 +232,14 @@ void AutoDownloadBox::paintEvent(QPaintEvent *e) { void AutoDownloadBox::resizeEvent(QResizeEvent *e) { _photoPrivate->moveToLeft(st::boxTitlePosition.x(), titleHeight() + st::setLittleSkip); - _photoGroups->moveToLeft(st::boxTitlePosition.x(), _photoPrivate->y() + _photoPrivate->height() + st::setLittleSkip); + _photoGroups->moveToLeft(st::boxTitlePosition.x(), _photoPrivate->bottomNoMargins() + st::setLittleSkip); _audioPrivate->moveToLeft(st::boxTitlePosition.x(), _sectionHeight + titleHeight() + st::setLittleSkip); - _audioGroups->moveToLeft(st::boxTitlePosition.x(), _audioPrivate->y() + _audioPrivate->height() + st::setLittleSkip); + _audioGroups->moveToLeft(st::boxTitlePosition.x(), _audioPrivate->bottomNoMargins() + st::setLittleSkip); _gifPrivate->moveToLeft(st::boxTitlePosition.x(), 2 * _sectionHeight + titleHeight() + st::setLittleSkip); - _gifGroups->moveToLeft(st::boxTitlePosition.x(), _gifPrivate->y() + _gifPrivate->height() + st::setLittleSkip); - _gifPlay->moveToLeft(st::boxTitlePosition.x(), _gifGroups->y() + _gifGroups->height() + st::setLittleSkip); + _gifGroups->moveToLeft(st::boxTitlePosition.x(), _gifPrivate->bottomNoMargins() + st::setLittleSkip); + _gifPlay->moveToLeft(st::boxTitlePosition.x(), _gifGroups->bottomNoMargins() + st::setLittleSkip); _save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height()); _cancel->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y()); diff --git a/Telegram/SourceFiles/boxes/contactsbox.cpp b/Telegram/SourceFiles/boxes/contactsbox.cpp index dca4f0202..d82c130e8 100644 --- a/Telegram/SourceFiles/boxes/contactsbox.cpp +++ b/Telegram/SourceFiles/boxes/contactsbox.cpp @@ -25,6 +25,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "styles/style_boxes.h" #include "styles/style_dialogs.h" #include "styles/style_history.h" +#include "styles/style_profile.h" #include "lang.h" #include "boxes/addcontactbox.h" #include "mainwidget.h" @@ -552,7 +553,7 @@ ContactsBox::Inner::ContactData::ContactData(PeerData *peer, const base::lambda_ ContactsBox::Inner::Inner(QWidget *parent, CreatingGroupType creating) : TWidget(parent) , _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) , _creating(creating) -, _allAdmins(this, lang(lng_chat_all_members_admins), false, st::contactsAdminCheckbox) +, _allAdmins(this, lang(lng_chat_all_members_admins), false, st::defaultBoxCheckbox) , _contacts(App::main()->contactsList()) , _addContactLnk(this, lang(lng_add_contact_button)) { init(); @@ -564,7 +565,7 @@ ContactsBox::Inner::Inner(QWidget *parent, ChannelData *channel, MembersFilter m , _membersFilter(membersFilter) , _creating(CreatingGroupChannel) , _already(already) -, _allAdmins(this, lang(lng_chat_all_members_admins), false, st::contactsAdminCheckbox) +, _allAdmins(this, lang(lng_chat_all_members_admins), false, st::defaultBoxCheckbox) , _contacts(App::main()->contactsList()) , _addContactLnk(this, lang(lng_add_contact_button)) { init(); @@ -580,16 +581,16 @@ ContactsBox::Inner::Inner(QWidget *parent, ChatData *chat, MembersFilter members , _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) , _chat(chat) , _membersFilter(membersFilter) -, _allAdmins(this, lang(lng_chat_all_members_admins), !_chat->adminsEnabled(), st::contactsAdminCheckbox) +, _allAdmins(this, lang(lng_chat_all_members_admins), !_chat->adminsEnabled(), st::defaultBoxCheckbox) , _aboutWidth(st::boxWideWidth - st::contactsPadding.left() - st::contactsPadding.right()) -, _aboutAllAdmins(st::boxTextFont, lang(lng_chat_about_all_admins), _defaultOptions, _aboutWidth) -, _aboutAdmins(st::boxTextFont, lang(lng_chat_about_admins), _defaultOptions, _aboutWidth) +, _aboutAllAdmins(st::normalFont, lang(lng_chat_about_all_admins), _defaultOptions, _aboutWidth) +, _aboutAdmins(st::normalFont, lang(lng_chat_about_admins), _defaultOptions, _aboutWidth) , _customList((membersFilter == MembersFilter::Recent) ? std_::unique_ptr() : std_::make_unique(Dialogs::SortMode::Add)) , _contacts((membersFilter == MembersFilter::Recent) ? App::main()->contactsList() : _customList.get()) , _addContactLnk(this, lang(lng_add_contact_button)) { initList(); if (membersFilter == MembersFilter::Admins) { - _aboutHeight = st::contactsAboutSkip + qMax(_aboutAllAdmins.countHeight(_aboutWidth), _aboutAdmins.countHeight(_aboutWidth)) + st::contactsAboutHeight; + _aboutHeight = st::contactsAboutTop + qMax(_aboutAllAdmins.countHeight(_aboutWidth), _aboutAdmins.countHeight(_aboutWidth)) + st::contactsAboutBottom; if (_contacts->isEmpty()) { App::api()->requestFullPeer(_chat); } @@ -611,7 +612,7 @@ void ContactsBox::Inner::addDialogsToList(FilterCallback callback) { ContactsBox::Inner::Inner(QWidget *parent, UserData *bot) : TWidget(parent) , _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) , _bot(bot) -, _allAdmins(this, lang(lng_chat_all_members_admins), false, st::contactsAdminCheckbox) +, _allAdmins(this, lang(lng_chat_all_members_admins), false, st::defaultBoxCheckbox) , _customList(std_::make_unique(Dialogs::SortMode::Add)) , _contacts(_customList.get()) , _addContactLnk(this, lang(lng_add_contact_button)) { @@ -667,7 +668,7 @@ void ContactsBox::Inner::initList() { others.reserve(_chat->participants.size()); } - for (ChatData::Participants::const_iterator i = _chat->participants.cbegin(), e = _chat->participants.cend(); i != e; ++i) { + for (auto i = _chat->participants.cbegin(), e = _chat->participants.cend(); i != e; ++i) { if (i.key()->id == peerFromUser(_chat->creator)) continue; if (!_allAdmins->checked() && _chat->admins.contains(i.key())) { admins.push_back(i.key()); @@ -680,16 +681,16 @@ void ContactsBox::Inner::initList() { } std::sort(admins.begin(), admins.end(), _sortByName); std::sort(others.begin(), others.end(), _sortByName); - if (UserData *creator = App::userLoaded(_chat->creator)) { + if (auto creator = App::userLoaded(_chat->creator)) { if (_chat->participants.contains(creator)) { admins.push_front(creator); } } - for (int32 i = 0, l = admins.size(); i < l; ++i) { - _contacts->addToEnd(App::history(admins.at(i)->id)); + for_const (auto user, admins) { + _contacts->addToEnd(App::history(user->id)); } - for (int32 i = 0, l = others.size(); i < l; ++i) { - _contacts->addToEnd(App::history(others.at(i)->id)); + for_const (auto user, others) { + _contacts->addToEnd(App::history(user->id)); } } @@ -1039,12 +1040,18 @@ void ContactsBox::Inner::paintEvent(QPaintEvent *e) { if (_filter.isEmpty()) { if (!_contacts->isEmpty() || !_byUsername.isEmpty()) { if (_aboutHeight) { - p.fillRect(0, 0, width(), _aboutHeight - st::contactsPadding.bottom() - st::lineWidth, st::contactsAboutBg); - p.fillRect(0, _aboutHeight - st::contactsPadding.bottom() - st::lineWidth, width(), st::lineWidth, st::shadowColor); - p.setPen(st::boxTextFg); - p.drawTextLeft(st::contactsPadding.left(), st::contactsAllAdminsTop, width(), lang(lng_chat_all_members_admins)); + auto infoTop = _allAdmins->bottomNoMargins() + st::contactsAllAdminsTop - st::lineWidth; + + auto infoRect = rtlrect(0, infoTop, width(), _aboutHeight - infoTop - st::contactsPadding.bottom(), width()); + p.fillRect(infoRect, st::contactsAboutBg); + auto dividerFillTop = rtlrect(0, infoRect.y(), width(), st::profileDividerTop.height(), width()); + st::profileDividerTop.fill(p, dividerFillTop); + auto dividerFillBottom = rtlrect(0, infoRect.y() + infoRect.height() - st::profileDividerBottom.height(), width(), st::profileDividerBottom.height(), width()); + st::profileDividerBottom.fill(p, dividerFillBottom); + int aboutw = width() - st::contactsPadding.left() - st::contactsPadding.right(); - (_allAdmins->checked() ? _aboutAllAdmins : _aboutAdmins).draw(p, st::contactsPadding.left(), st::contactsAboutSkip + st::contactsAboutTop, aboutw); + p.setPen(st::contactsAboutFg); + (_allAdmins->checked() ? _aboutAllAdmins : _aboutAdmins).draw(p, st::contactsPadding.left(), st::contactsAboutTop, aboutw); yFrom -= _aboutHeight; yTo -= _aboutHeight; @@ -1090,10 +1097,9 @@ void ContactsBox::Inner::paintEvent(QPaintEvent *e) { text = lang(lng_contacts_loading); p.fillRect(0, 0, width(), _aboutHeight - st::contactsPadding.bottom() - st::lineWidth, st::contactsAboutBg); p.fillRect(0, _aboutHeight - st::contactsPadding.bottom() - st::lineWidth, width(), st::lineWidth, st::shadowColor); - p.setPen(st::boxTextFg); - p.drawTextLeft(st::contactsPadding.left(), st::contactsAllAdminsTop, width(), lang(lng_chat_all_members_admins)); + int aboutw = width() - st::contactsPadding.left() - st::contactsPadding.right(); - (_allAdmins->checked() ? _aboutAllAdmins : _aboutAdmins).draw(p, st::contactsPadding.left(), st::contactsAboutSkip + st::contactsAboutTop, aboutw); + (_allAdmins->checked() ? _aboutAllAdmins : _aboutAdmins).draw(p, st::contactsPadding.left(), st::contactsAboutTop, aboutw); p.translate(0, _aboutHeight); } else if (cContactsReceived() && !_searching) { text = lang(lng_no_contacts); diff --git a/Telegram/SourceFiles/boxes/downloadpathbox.cpp b/Telegram/SourceFiles/boxes/downloadpathbox.cpp index 353463073..adc5ff772 100644 --- a/Telegram/SourceFiles/boxes/downloadpathbox.cpp +++ b/Telegram/SourceFiles/boxes/downloadpathbox.cpp @@ -32,9 +32,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org DownloadPathBox::DownloadPathBox() : AbstractBox() , _path(Global::DownloadPath()) , _pathBookmark(Global::DownloadPathBookmark()) -, _default(this, qsl("dir_type"), 0, lang(lng_download_path_default_radio), _path.isEmpty()) -, _temp(this, qsl("dir_type"), 1, lang(lng_download_path_temp_radio), _path == qsl("tmp")) -, _dir(this, qsl("dir_type"), 2, lang(lng_download_path_dir_radio), !_path.isEmpty() && _path != qsl("tmp")) +, _default(this, qsl("dir_type"), 0, lang(lng_download_path_default_radio), _path.isEmpty(), st::defaultBoxCheckbox) +, _temp(this, qsl("dir_type"), 1, lang(lng_download_path_temp_radio), (_path == qsl("tmp")), st::defaultBoxCheckbox) +, _dir(this, qsl("dir_type"), 2, lang(lng_download_path_dir_radio), (!_path.isEmpty() && _path != qsl("tmp")), st::defaultBoxCheckbox) , _pathLink(this, QString(), st::boxLinkButton) , _save(this, lang(lng_connection_save), st::defaultBoxButton) , _cancel(this, lang(lng_cancel), st::cancelBoxButton) { @@ -57,7 +57,7 @@ DownloadPathBox::DownloadPathBox() : AbstractBox() void DownloadPathBox::updateControlsVisibility() { _pathLink->setVisible(_dir->checked()); - int32 h = titleHeight() + st::boxOptionListPadding.top() + _default->height() + st::boxOptionListPadding.top() + _temp->height() + st::boxOptionListPadding.top() + _dir->height(); + int32 h = titleHeight() + st::boxOptionListPadding.top() + _default->heightNoMargins() + st::boxOptionListPadding.top() + _temp->heightNoMargins() + st::boxOptionListPadding.top() + _dir->heightNoMargins(); if (_dir->checked()) h += st::downloadPathSkip + _pathLink->height(); h += st::boxOptionListPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom(); @@ -66,10 +66,10 @@ void DownloadPathBox::updateControlsVisibility() { void DownloadPathBox::resizeEvent(QResizeEvent *e) { _default->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), titleHeight() + st::boxOptionListPadding.top()); - _temp->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _default->y() + _default->height() + st::boxOptionListPadding.top()); - _dir->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _temp->y() + _temp->height() + st::boxOptionListPadding.top()); - int32 inputx = st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultRadiobutton.textPosition.x(); - int32 inputy = _dir->y() + _dir->height() + st::downloadPathSkip; + _temp->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _default->bottomNoMargins() + st::boxOptionListPadding.top()); + _dir->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _temp->bottomNoMargins() + st::boxOptionListPadding.top()); + int32 inputx = st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultBoxCheckbox.textPosition.x(); + int32 inputy = _dir->bottomNoMargins() + st::downloadPathSkip; _pathLink->moveToLeft(inputx, inputy); @@ -123,6 +123,6 @@ void DownloadPathBox::onSave() { } void DownloadPathBox::setPathText(const QString &text) { - int32 availw = st::boxWideWidth - st::boxPadding.left() - st::defaultRadiobutton.textPosition.x() - st::boxPadding.right(); + int32 availw = st::boxWideWidth - st::boxPadding.left() - st::defaultBoxCheckbox.textPosition.x() - st::boxPadding.right(); _pathLink->setText(st::boxTextFont->elided(text, availw)); } diff --git a/Telegram/SourceFiles/boxes/languagebox.cpp b/Telegram/SourceFiles/boxes/languagebox.cpp index 862f7d476..5db3ebc32 100644 --- a/Telegram/SourceFiles/boxes/languagebox.cpp +++ b/Telegram/SourceFiles/boxes/languagebox.cpp @@ -42,7 +42,7 @@ _close(this, lang(lng_box_ok), st::defaultBoxButton) { if (haveTestLang) { _langs.push_back(new Ui::Radiobutton(this, qsl("lang"), languageTest, qsl("Custom Lang"), (cLang() == languageTest), st::langsButton)); _langs.back()->move(st::boxPadding.left() + st::boxOptionListPadding.left(), y); - y += _langs.back()->height() + st::boxOptionListPadding.top(); + y += _langs.back()->heightNoMargins() + st::boxOptionListPadding.top(); connect(_langs.back(), SIGNAL(changed()), this, SLOT(onChange())); } for (int32 i = 0; i < languageCount; ++i) { @@ -55,7 +55,7 @@ _close(this, lang(lng_box_ok), st::defaultBoxButton) { } _langs.push_back(new Ui::Radiobutton(this, qsl("lang"), i, result.value(lng_language_name, LanguageCodes[i].c_str() + qsl(" language")), (cLang() == i), st::langsButton)); _langs.back()->move(st::boxPadding.left() + st::boxOptionListPadding.left(), y); - y += _langs.back()->height() + st::boxOptionListPadding.top(); + y += _langs.back()->heightNoMargins() + st::boxOptionListPadding.top(); connect(_langs.back(), SIGNAL(changed()), this, SLOT(onChange())); } diff --git a/Telegram/SourceFiles/boxes/report_box.cpp b/Telegram/SourceFiles/boxes/report_box.cpp index 07890d083..0b3c58b72 100644 --- a/Telegram/SourceFiles/boxes/report_box.cpp +++ b/Telegram/SourceFiles/boxes/report_box.cpp @@ -32,10 +32,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org ReportBox::ReportBox(ChannelData *channel) : AbstractBox(st::boxWidth) , _channel(channel) -, _reasonSpam(this, qsl("report_reason"), ReasonSpam, lang(lng_report_reason_spam), true) -, _reasonViolence(this, qsl("report_reason"), ReasonViolence, lang(lng_report_reason_violence)) -, _reasonPornography(this, qsl("report_reason"), ReasonPornography, lang(lng_report_reason_pornography)) -, _reasonOther(this, qsl("report_reason"), ReasonOther, lang(lng_report_reason_other)) +, _reasonSpam(this, qsl("report_reason"), ReasonSpam, lang(lng_report_reason_spam), true, st::defaultBoxCheckbox) +, _reasonViolence(this, qsl("report_reason"), ReasonViolence, lang(lng_report_reason_violence), false, st::defaultBoxCheckbox) +, _reasonPornography(this, qsl("report_reason"), ReasonPornography, lang(lng_report_reason_pornography), false, st::defaultBoxCheckbox) +, _reasonOther(this, qsl("report_reason"), ReasonOther, lang(lng_report_reason_other), false, st::defaultBoxCheckbox) , _report(this, lang(lng_report_button), st::defaultBoxButton) , _cancel(this, lang(lng_cancel), st::cancelBoxButton) { setTitleText(lang(_channel->isMegagroup() ? lng_report_group_title : lng_report_title)); @@ -53,12 +53,12 @@ ReportBox::ReportBox(ChannelData *channel) : AbstractBox(st::boxWidth) void ReportBox::resizeEvent(QResizeEvent *e) { _reasonSpam->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), titleHeight() + st::boxOptionListPadding.top()); - _reasonViolence->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonSpam->y() + _reasonSpam->height() + st::boxOptionListPadding.top()); - _reasonPornography->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonViolence->y() + _reasonViolence->height() + st::boxOptionListPadding.top()); - _reasonOther->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonPornography->y() + _reasonPornography->height() + st::boxOptionListPadding.top()); + _reasonViolence->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonSpam->bottomNoMargins() + st::boxOptionListPadding.top()); + _reasonPornography->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonViolence->bottomNoMargins() + st::boxOptionListPadding.top()); + _reasonOther->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonPornography->bottomNoMargins() + st::boxOptionListPadding.top()); if (_reasonOtherText) { - _reasonOtherText->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left() - st::defaultInputField.textMargins.left(), _reasonOther->y() + _reasonOther->height() + st::newGroupDescriptionPadding.top()); + _reasonOtherText->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left() - st::defaultInputField.textMargins.left(), _reasonOther->bottomNoMargins() + st::newGroupDescriptionPadding.top()); } _report->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _report->height()); @@ -138,7 +138,7 @@ bool ReportBox::reportFail(const RPCError &error) { } void ReportBox::updateMaxHeight() { - int32 h = titleHeight() + 4 * (st::boxOptionListPadding.top() + _reasonSpam->height()) + st::boxButtonPadding.top() + _report->height() + st::boxButtonPadding.bottom(); + int32 h = titleHeight() + 4 * (st::boxOptionListPadding.top() + _reasonSpam->heightNoMargins()) + st::boxButtonPadding.top() + _report->height() + st::boxButtonPadding.bottom(); if (_reasonOtherText) { h += st::newGroupDescriptionPadding.top() + _reasonOtherText->height() + st::newGroupDescriptionPadding.bottom(); } diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp index 7abdbb085..5f81de915 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.cpp +++ b/Telegram/SourceFiles/boxes/send_files_box.cpp @@ -204,7 +204,7 @@ void SendFilesBox::updateBoxSize() { newHeight += st::boxPhotoPadding.top() + st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom(); } if (_compressed) { - newHeight += st::boxPhotoCompressedSkip + _compressed->height(); + newHeight += st::boxPhotoCompressedSkip + _compressed->heightNoMargins(); } if (_caption) { newHeight += st::boxPhotoCaptionSkip + _caption->height(); @@ -318,8 +318,8 @@ void SendFilesBox::updateControlsGeometry() { bottom -= st::boxPhotoCaptionSkip + _caption->height(); } if (_compressed) { - _compressed->moveToLeft(st::boxPhotoPadding.left(), bottom - _compressed->height()); - bottom -= st::boxPhotoCompressedSkip + _compressed->height(); + _compressed->moveToLeft(st::boxPhotoPadding.left(), bottom - _compressed->heightNoMargins()); + bottom -= st::boxPhotoCompressedSkip + _compressed->heightNoMargins(); } } diff --git a/Telegram/SourceFiles/boxes/stickers_box.cpp b/Telegram/SourceFiles/boxes/stickers_box.cpp index 4be741d7d..6c3c15335 100644 --- a/Telegram/SourceFiles/boxes/stickers_box.cpp +++ b/Telegram/SourceFiles/boxes/stickers_box.cpp @@ -217,7 +217,6 @@ void StickersBox::setup() { preloadArchivedSets(); } if (_tabs) { - _tabs->setSelectOnPress(false); _tabs->setSectionActivatedCallback([this] { switchTab(); }); diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp index 60e6981ab..919dab857 100644 --- a/Telegram/SourceFiles/facades.cpp +++ b/Telegram/SourceFiles/facades.cpp @@ -38,6 +38,10 @@ Q_DECLARE_METATYPE(Ui::ShowWay); namespace App { +void LambdaDelayed(int duration, base::lambda &&lambda) { + QTimer::singleShot(duration, base::lambda_slot(App::app(), std_::move(lambda)), SLOT(action())); +} + void sendBotCommand(PeerData *peer, UserData *bot, const QString &cmd, MsgId replyTo) { if (auto m = main()) { m->sendBotCommand(peer, bot, cmd, replyTo); diff --git a/Telegram/SourceFiles/facades.h b/Telegram/SourceFiles/facades.h index 6b6e05952..03d22ef03 100644 --- a/Telegram/SourceFiles/facades.h +++ b/Telegram/SourceFiles/facades.h @@ -33,6 +33,8 @@ class ItemBase; namespace App { +void LambdaDelayed(int duration, base::lambda &&lambda); + void sendBotCommand(PeerData *peer, UserData *bot, const QString &cmd, MsgId replyTo = 0); bool insertBotCommand(const QString &cmd, bool specialGif = false); void activateBotCommand(const HistoryItem *msg, int row, int col); diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index d0d0989a0..bc32fcbcb 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -3101,7 +3101,11 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent) connect(audioCapture(), SIGNAL(done(QByteArray,VoiceWaveform,qint32)), this, SLOT(onRecordDone(QByteArray,VoiceWaveform,qint32))); } - _attachToggle->setClickedCallback([this] { chooseAttach(); }); + _attachToggle->setClickedCallback([this] { + App::LambdaDelayed(st::historyAttach.ripple.hideDuration, base::lambda_guarded(this, [this] { + chooseAttach(); + })); + }); subscribe(FileDialog::QueryDone(), [this](const FileDialog::QueryUpdate &update) { notifyFileQueryUpdated(update); }); diff --git a/Telegram/SourceFiles/localimageloader.cpp b/Telegram/SourceFiles/localimageloader.cpp index b76d56887..f3bfe166a 100644 --- a/Telegram/SourceFiles/localimageloader.cpp +++ b/Telegram/SourceFiles/localimageloader.cpp @@ -362,7 +362,7 @@ void FileLoadTask::process() { { QBuffer buffer(&filedata); - full.save(&buffer, "JPG", 77); + full.save(&buffer, "JPG", 87); } MTPDphoto::Flags photoFlags = 0; diff --git a/Telegram/SourceFiles/profile/profile.style b/Telegram/SourceFiles/profile/profile.style index 2ec913357..2498ae721 100644 --- a/Telegram/SourceFiles/profile/profile.style +++ b/Telegram/SourceFiles/profile/profile.style @@ -72,9 +72,11 @@ profileDropAreaBorderFg: profileDropAreaFg; profileDropAreaBorderWidth: 3px; profileDropAreaDuration: 200; +profileDividerBg: windowBgOver; profileDividerFg: windowShadowFg; profileDividerLeft: icon {{ "profile_divider_left", profileDividerFg }}; -profileDividerFill: icon {{ "profile_divider_fill", profileDividerFg }}; +profileDividerTop: icon {{ "profile_divider_top", profileDividerFg }}; +profileDividerBottom: icon {{ "profile_divider_bottom", profileDividerFg }}; profileBlocksTop: 7px; profileBlocksBottom: 20px; diff --git a/Telegram/SourceFiles/profile/profile_cover.cpp b/Telegram/SourceFiles/profile/profile_cover.cpp index be99fdbb2..75e941787 100644 --- a/Telegram/SourceFiles/profile/profile_cover.cpp +++ b/Telegram/SourceFiles/profile/profile_cover.cpp @@ -139,7 +139,7 @@ int CoverWidget::resizeGetHeight(int newWidth) { newHeight += st::profileMarginBottom; _dividerTop = newHeight; - newHeight += st::profileDividerFill.height(); + newHeight += st::profileDividerLeft.height(); newHeight += st::profileBlocksTop; @@ -319,12 +319,18 @@ void CoverWidget::dropEvent(QDropEvent *e) { } void CoverWidget::paintDivider(Painter &p) { - auto dividerLeft = (Adaptive::OneColumn() ? 0 : st::lineWidth); - st::profileDividerLeft.paint(p, QPoint(dividerLeft, _dividerTop), width()); - - int toFillLeft = dividerLeft + st::profileDividerLeft.width(); - QRect toFill = rtlrect(toFillLeft, _dividerTop, width() - toFillLeft, st::profileDividerFill.height(), width()); - st::profileDividerFill.fill(p, toFill); + auto dividerHeight = st::profileDividerLeft.height(); + auto dividerLeft = Adaptive::OneColumn() ? 0 : st::lineWidth; + auto divider = rtlrect(dividerLeft, _dividerTop, width() - dividerLeft, dividerHeight, width()); + p.fillRect(divider, st::profileDividerBg); + if (!Adaptive::OneColumn()) { + st::profileDividerLeft.paint(p, QPoint(dividerLeft, _dividerTop), width()); + } + auto dividerFillLeft = Adaptive::OneColumn() ? 0 : (st::lineWidth + st::profileDividerLeft.width()); + auto dividerFillTop = rtlrect(dividerFillLeft, _dividerTop, width() - dividerFillLeft, st::profileDividerTop.height(), width()); + st::profileDividerTop.fill(p, dividerFillTop); + auto dividerFillBottom = rtlrect(dividerFillLeft, _dividerTop + dividerHeight - st::profileDividerBottom.height(), width() - dividerFillLeft, st::profileDividerBottom.height(), width()); + st::profileDividerBottom.fill(p, dividerFillBottom); } void CoverWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) { diff --git a/Telegram/SourceFiles/profile/profile_settings_widget.cpp b/Telegram/SourceFiles/profile/profile_settings_widget.cpp index b87d48fb4..b02da6f90 100644 --- a/Telegram/SourceFiles/profile/profile_settings_widget.cpp +++ b/Telegram/SourceFiles/profile/profile_settings_widget.cpp @@ -83,7 +83,7 @@ int SettingsWidget::resizeGetHeight(int newWidth) { int newHeight = contentTop() + st::profileEnableNotificationsTop; _enableNotifications->moveToLeft(st::profileBlockTitlePosition.x(), newHeight); - newHeight += _enableNotifications->height() + st::profileSettingsBlockSkip; + newHeight += _enableNotifications->heightNoMargins() + st::profileSettingsBlockSkip; auto moveLink = [&newHeight, newWidth](Ui::LeftOutlineButton *button) { if (!button) return; diff --git a/Telegram/SourceFiles/settings/settings_block_widget.cpp b/Telegram/SourceFiles/settings/settings_block_widget.cpp index ee8fc62d8..4ed134200 100644 --- a/Telegram/SourceFiles/settings/settings_block_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_block_widget.cpp @@ -44,14 +44,15 @@ int BlockWidget::resizeGetHeight(int newWidth) { int x = contentLeft(), result = contentTop(); int availw = newWidth - x; for_const (auto &row, _rows) { + auto childMargins = row.child->getMargins(); row.child->moveToLeft(x + row.margin.left(), result + row.margin.top(), newWidth); auto availRowWidth = availw - row.margin.left() - row.margin.right() - x; auto natural = row.child->naturalWidth(); auto rowWidth = (natural < 0) ? availRowWidth : qMin(natural, availRowWidth); - if (row.child->width() != rowWidth) { + if (row.child->widthNoMargins() != rowWidth) { row.child->resizeToWidth(rowWidth); } - result += row.child->height() + row.margin.top() + row.margin.bottom(); + result += row.margin.top() + row.child->heightNoMargins() + row.margin.bottom(); } result += st::settingsBlockMarginBottom; return result; @@ -91,7 +92,7 @@ void BlockWidget::createChildRow(ChildWidget &child, style::margin } void BlockWidget::createChildRow(ChildWidget &child, style::margins &margin, const QString &group, int value, const QString &text, const char *slot, bool checked) { - child .create(this, group, value, text, checked, st::defaultRadiobutton); + child .create(this, group, value, text, checked, st::defaultBoxCheckbox); connect(child, SIGNAL(changed()), this, slot); } diff --git a/Telegram/SourceFiles/settings/settings_cover.cpp b/Telegram/SourceFiles/settings/settings_cover.cpp index 368fbe453..ab20322e5 100644 --- a/Telegram/SourceFiles/settings/settings_cover.cpp +++ b/Telegram/SourceFiles/settings/settings_cover.cpp @@ -121,7 +121,7 @@ int CoverWidget::resizeGetHeight(int newWidth) { newHeight += st::settingsMarginBottom; _dividerTop = newHeight; - newHeight += st::profileDividerFill.height(); + newHeight += st::profileDividerLeft.height(); newHeight += st::settingsBlocksTop; @@ -247,11 +247,13 @@ void CoverWidget::dropEvent(QDropEvent *e) { } void CoverWidget::paintDivider(Painter &p) { - st::profileDividerLeft.paint(p, QPoint(0, _dividerTop), width()); - - int toFillLeft = st::profileDividerLeft.width(); - QRect toFill = rtlrect(toFillLeft, _dividerTop, width() - toFillLeft, st::profileDividerFill.height(), width()); - st::profileDividerFill.fill(p, toFill); + auto dividerHeight = st::profileDividerLeft.height(); + auto divider = rtlrect(0, _dividerTop, width(), dividerHeight, width()); + p.fillRect(divider, st::profileDividerBg); + auto dividerFillTop = rtlrect(0, _dividerTop, width(), st::profileDividerTop.height(), width()); + st::profileDividerTop.fill(p, dividerFillTop); + auto dividerFillBottom = rtlrect(0, _dividerTop + dividerHeight - st::profileDividerBottom.height(), width(), st::profileDividerBottom.height(), width()); + st::profileDividerBottom.fill(p, dividerFillBottom); } void CoverWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) { diff --git a/Telegram/SourceFiles/settings/settings_scale_widget.cpp b/Telegram/SourceFiles/settings/settings_scale_widget.cpp index 172d05f95..4c8cbf882 100644 --- a/Telegram/SourceFiles/settings/settings_scale_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_scale_widget.cpp @@ -21,6 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "stdafx.h" #include "settings/settings_scale_widget.h" +#include "styles/style_boxes.h" #include "styles/style_settings.h" #include "ui/widgets/checkbox.h" #include "lang.h" @@ -126,7 +127,9 @@ void ScaleWidget::onRestartNow() { } void ScaleWidget::onCancel() { - setScale(cRealScale()); + App::LambdaDelayed(st::boxDuration, base::lambda_guarded(this, [this] { + setScale(cRealScale()); + })); } } // namespace Settings diff --git a/Telegram/SourceFiles/ui/abstract_button.cpp b/Telegram/SourceFiles/ui/abstract_button.cpp index 3bc62ce8a..22313bb27 100644 --- a/Telegram/SourceFiles/ui/abstract_button.cpp +++ b/Telegram/SourceFiles/ui/abstract_button.cpp @@ -27,13 +27,12 @@ void AbstractButton::leaveEvent(QEvent *e) { if (_state & StateDown) return; setOver(false, StateChangeSource::ByHover); - setMouseTracking(false); return TWidget::leaveEvent(e); } void AbstractButton::enterEvent(QEvent *e) { - setOver(true, StateChangeSource::ByHover); - setMouseTracking(true); + auto over = rect().marginsRemoved(getMargins()).contains(mapFromGlobal(QCursor::pos())); + setOver(over, StateChangeSource::ByHover); return TWidget::enterEvent(e); } @@ -42,11 +41,8 @@ void AbstractButton::setAcceptBoth(bool acceptBoth) { } void AbstractButton::mousePressEvent(QMouseEvent *e) { - if (_acceptBoth || e->buttons() & Qt::LeftButton) { - if (!(_state & StateOver)) { - enterEvent(0); - } - if (!(_state & StateDown)) { + if (_acceptBoth || (e->buttons() & Qt::LeftButton)) { + if ((_state & StateOver) && !(_state & StateDown)) { int oldState = _state; _state |= StateDown; onStateChanged(oldState, StateChangeSource::ByPress); @@ -57,7 +53,7 @@ void AbstractButton::mousePressEvent(QMouseEvent *e) { } void AbstractButton::mouseMoveEvent(QMouseEvent *e) { - if (rect().contains(e->pos())) { + if (rect().marginsRemoved(getMargins()).contains(e->pos())) { setOver(true, StateChangeSource::ByHover); } else { setOver(false, StateChangeSource::ByHover); @@ -83,6 +79,7 @@ void AbstractButton::mouseReleaseEvent(QMouseEvent *e) { } void AbstractButton::setOver(bool over, StateChangeSource source) { + setCursor(over ? style::cur_pointer : style::cur_default); if (over && !(_state & StateOver)) { int oldState = _state; _state |= StateOver; diff --git a/Telegram/SourceFiles/ui/abstract_button.h b/Telegram/SourceFiles/ui/abstract_button.h index 59cd53445..961a9c81d 100644 --- a/Telegram/SourceFiles/ui/abstract_button.h +++ b/Telegram/SourceFiles/ui/abstract_button.h @@ -35,7 +35,7 @@ public: }; AbstractButton(QWidget *parent) : TWidget(parent) { - setCursor(style::cur_pointer); + setMouseTracking(true); } enum { diff --git a/Telegram/SourceFiles/ui/effects/ripple_animation.cpp b/Telegram/SourceFiles/ui/effects/ripple_animation.cpp index d03918f59..b7e2c5255 100644 --- a/Telegram/SourceFiles/ui/effects/ripple_animation.cpp +++ b/Telegram/SourceFiles/ui/effects/ripple_animation.cpp @@ -28,7 +28,7 @@ public: Ripple(const style::RippleAnimation &st, QPoint origin, int startRadius, const QPixmap &mask, const UpdateCallback &update); Ripple(const style::RippleAnimation &st, const QPixmap &mask, const UpdateCallback &update); - void paint(QPainter &p, const QPixmap &mask, TimeMs ms); + void paint(QPainter &p, const QPixmap &mask, TimeMs ms, const QColor *colorOverride); void stop(); void unstop(); @@ -86,7 +86,7 @@ RippleAnimation::Ripple::Ripple(const style::RippleAnimation &st, const QPixmap _hide.start(UpdateCallback(_update), 0., 1., _st.hideDuration); } -void RippleAnimation::Ripple::paint(QPainter &p, const QPixmap &mask, TimeMs ms) { +void RippleAnimation::Ripple::paint(QPainter &p, const QPixmap &mask, TimeMs ms, const QColor *colorOverride) { auto opacity = _hide.current(ms, _hiding ? 0. : 1.); if (opacity == 0.) { return; @@ -99,7 +99,11 @@ void RippleAnimation::Ripple::paint(QPainter &p, const QPixmap &mask, TimeMs ms) Painter p(&_frame); p.setRenderHint(QPainter::HighQualityAntialiasing); p.setPen(Qt::NoPen); - p.setBrush(_st.color); + if (colorOverride) { + p.setBrush(*colorOverride); + } else { + p.setBrush(_st.color); + } p.drawEllipse(_origin, radius, radius); p.setCompositionMode(QPainter::CompositionMode_DestinationIn); @@ -176,7 +180,7 @@ void RippleAnimation::lastFinish() { } } -void RippleAnimation::paint(QPainter &p, int x, int y, int outerWidth, TimeMs ms) { +void RippleAnimation::paint(QPainter &p, int x, int y, int outerWidth, TimeMs ms, const QColor *colorOverride) { if (_ripples.isEmpty()) { return; } @@ -184,7 +188,7 @@ void RippleAnimation::paint(QPainter &p, int x, int y, int outerWidth, TimeMs ms if (rtl()) x = outerWidth - x - (_mask.width() / cIntRetinaFactor()); p.translate(x, y); for (auto ripple : _ripples) { - ripple->paint(p, _mask, ms); + ripple->paint(p, _mask, ms, colorOverride); } p.translate(-x, -y); clearFinished(); diff --git a/Telegram/SourceFiles/ui/effects/ripple_animation.h b/Telegram/SourceFiles/ui/effects/ripple_animation.h index 7333b8a28..a9324b907 100644 --- a/Telegram/SourceFiles/ui/effects/ripple_animation.h +++ b/Telegram/SourceFiles/ui/effects/ripple_animation.h @@ -37,7 +37,7 @@ public: void lastUnstop(); void lastFinish(); - void paint(QPainter &p, int x, int y, int outerWidth, TimeMs ms); + void paint(QPainter &p, int x, int y, int outerWidth, TimeMs ms, const QColor *colorOverride = nullptr); bool empty() const { return _ripples.isEmpty(); diff --git a/Telegram/SourceFiles/ui/effects/widget_fade_wrap.h b/Telegram/SourceFiles/ui/effects/widget_fade_wrap.h index 193fe3157..52f2f5b50 100644 --- a/Telegram/SourceFiles/ui/effects/widget_fade_wrap.h +++ b/Telegram/SourceFiles/ui/effects/widget_fade_wrap.h @@ -98,6 +98,13 @@ public: return _entity; } + QMargins getMargins() const override { + return _entity->getMargins(); + } + int naturalWidth() const override { + return _entity->naturalWidth(); + } + protected: bool eventFilter(QObject *object, QEvent *event) override; void paintEvent(QPaintEvent *e) override; diff --git a/Telegram/SourceFiles/ui/effects/widget_slide_wrap.cpp b/Telegram/SourceFiles/ui/effects/widget_slide_wrap.cpp index 5c78836c0..786c71945 100644 --- a/Telegram/SourceFiles/ui/effects/widget_slide_wrap.cpp +++ b/Telegram/SourceFiles/ui/effects/widget_slide_wrap.cpp @@ -34,16 +34,17 @@ WidgetSlideWrap::WidgetSlideWrap(QWidget *parent , _updateCallback(std_::move(updateCallback)) , _a_height(animation(this, &WidgetSlideWrap::step_height)) { _entity->setParent(this); - _entity->moveToLeft(_padding.left(), _padding.top()); - _realSize = _entity->rect().marginsAdded(_padding).size(); + auto margins = getMargins(); + _entity->moveToLeft(margins.left() + _padding.left(), margins.top() + _padding.top()); + _realSize = _entity->rectNoMargins().marginsAdded(_padding).size(); _entity->installEventFilter(this); - resize(_realSize); + resizeToWidth(_realSize.width()); } void WidgetSlideWrap::slideUp() { if (isHidden()) { _forceHeight = 0; - resize(_realSize.width(), _forceHeight); + resizeToWidth(_realSize.width()); if (_updateCallback) _updateCallback(); return; } @@ -77,7 +78,8 @@ void WidgetSlideWrap::slideDown() { void WidgetSlideWrap::showFast() { show(); _a_height.stop(); - resize(_realSize); + _forceHeight = -1; + resizeToWidth(_realSize.width()); if (_updateCallback) { _updateCallback(); } @@ -87,13 +89,21 @@ void WidgetSlideWrap::hideFast() { _a_height.stop(); a_height = anim::ivalue(0); _forceHeight = 0; - resize(_realSize.width(), 0); + resizeToWidth(_realSize.width()); hide(); if (_updateCallback) { _updateCallback(); } } +QMargins WidgetSlideWrap::getMargins() const { + auto entityMargins = _entity->getMargins(); + if (_forceHeight < 0) { + return entityMargins; + } + return QMargins(entityMargins.left(), 0, entityMargins.right(), 0); +} + int WidgetSlideWrap::naturalWidth() const { auto inner = _entity->naturalWidth(); return (inner < 0) ? inner : (_padding.left() + inner + _padding.right()); @@ -101,9 +111,9 @@ int WidgetSlideWrap::naturalWidth() const { bool WidgetSlideWrap::eventFilter(QObject *object, QEvent *event) { if (object == _entity && event->type() == QEvent::Resize) { - _realSize = _entity->rect().marginsAdded(_padding).size(); + _realSize = _entity->rectNoMargins().marginsAdded(_padding).size(); if (!_inResizeToWidth) { - resize(_realSize.width(), (_forceHeight >= 0) ? _forceHeight : _realSize.height()); + resizeToWidth(_realSize.width()); if (_updateCallback) { _updateCallback(); } @@ -114,9 +124,15 @@ bool WidgetSlideWrap::eventFilter(QObject *object, QEvent *event) { int WidgetSlideWrap::resizeGetHeight(int newWidth) { _inResizeToWidth = true; + auto resized = (_forceHeight >= 0); _entity->resizeToWidth(newWidth - _padding.left() - _padding.right()); + auto margins = getMargins(); + _entity->moveToLeft(margins.left() + _padding.left(), margins.top() + _padding.top()); _inResizeToWidth = false; - return (_forceHeight >= 0) ? _forceHeight : _realSize.height(); + if (resized) { + return _forceHeight; + } + return _realSize.height(); } void WidgetSlideWrap::step_height(float64 ms, bool timer) { @@ -130,7 +146,7 @@ void WidgetSlideWrap::step_height(float64 ms, bool timer) { a_height.update(dt, anim::linear); _forceHeight = a_height.current(); } - resize(_realSize.width(), (_forceHeight >= 0) ? _forceHeight : _realSize.height()); + resizeToWidth(_realSize.width()); if (_updateCallback) { _updateCallback(); } diff --git a/Telegram/SourceFiles/ui/effects/widget_slide_wrap.h b/Telegram/SourceFiles/ui/effects/widget_slide_wrap.h index abb463b0c..fb859c12b 100644 --- a/Telegram/SourceFiles/ui/effects/widget_slide_wrap.h +++ b/Telegram/SourceFiles/ui/effects/widget_slide_wrap.h @@ -48,6 +48,7 @@ public: return _entity; } + QMargins getMargins() const override; int naturalWidth() const override; protected: diff --git a/Telegram/SourceFiles/ui/twidget.h b/Telegram/SourceFiles/ui/twidget.h index e59e6b6e9..bd225a019 100644 --- a/Telegram/SourceFiles/ui/twidget.h +++ b/Telegram/SourceFiles/ui/twidget.h @@ -90,15 +90,31 @@ public: \ virtual void enterFromChildEvent(QEvent *e, QWidget *child) { /* e -- from leaveEvent() of child TWidget */ \ } \ void moveToLeft(int x, int y, int outerw = 0) { \ + auto margins = getMargins(); \ + x -= margins.left(); \ + y -= margins.top(); \ move(rtl() ? ((outerw > 0 ? outerw : parentWidget()->width()) - x - width()) : x, y); \ } \ void moveToRight(int x, int y, int outerw = 0) { \ + auto margins = getMargins(); \ + x -= margins.right(); \ + y -= margins.top(); \ move(rtl() ? x : ((outerw > 0 ? outerw : parentWidget()->width()) - x - width()), y); \ } \ void setGeometryToLeft(int x, int y, int w, int h, int outerw = 0) { \ + auto margins = getMargins(); \ + x -= margins.left(); \ + y -= margins.top(); \ + w -= margins.left() - margins.right(); \ + h -= margins.top() - margins.bottom(); \ setGeometry(rtl() ? ((outerw > 0 ? outerw : parentWidget()->width()) - x - w) : x, y, w, h); \ } \ void setGeometryToRight(int x, int y, int w, int h, int outerw = 0) { \ + auto margins = getMargins(); \ + x -= margins.right(); \ + y -= margins.top(); \ + w -= margins.left() - margins.right(); \ + h -= margins.top() - margins.bottom(); \ setGeometry(rtl() ? x : ((outerw > 0 ? outerw : parentWidget()->width()) - x - w), y, w, h); \ } \ QPoint myrtlpoint(int x, int y) const { \ @@ -160,6 +176,10 @@ public: } } + virtual QMargins getMargins() const { + return QMargins(); + } + // Get the size of the widget as it should be. // Negative return value means no default width. virtual int naturalWidth() const { @@ -168,13 +188,37 @@ public: // Count new height for width=newWidth and resize to it. void resizeToWidth(int newWidth) { - auto newSize = QSize(newWidth, resizeGetHeight(newWidth)); + auto margins = getMargins(); + auto fullWidth = margins.left() + newWidth + margins.right(); + auto fullHeight = margins.top() + resizeGetHeight(newWidth) + margins.bottom(); + auto newSize = QSize(fullWidth, fullHeight); if (newSize != size()) { resize(newSize); update(); } } + QRect rectNoMargins() const { + return rect().marginsRemoved(getMargins()); + } + + int widthNoMargins() const { + return rectNoMargins().width(); + } + + int heightNoMargins() const { + return rectNoMargins().height(); + } + + int bottomNoMargins() const { + auto rectWithoutMargins = rectNoMargins(); + return y() + rectWithoutMargins.y() + rectWithoutMargins.height(); + } + + QSize sizeNoMargins() const { + return rectNoMargins().size(); + } + // Updates the area that is visible inside the scroll container. virtual void setVisibleTopBottom(int visibleTop, int visibleBottom) { } diff --git a/Telegram/SourceFiles/ui/widgets/buttons.cpp b/Telegram/SourceFiles/ui/widgets/buttons.cpp index a7145e7f6..b41231948 100644 --- a/Telegram/SourceFiles/ui/widgets/buttons.cpp +++ b/Telegram/SourceFiles/ui/widgets/buttons.cpp @@ -86,9 +86,9 @@ void RippleButton::setForceRippled(bool rippled, SetForceRippledWay way) { update(); } -void RippleButton::paintRipple(QPainter &p, int x, int y, TimeMs ms) { +void RippleButton::paintRipple(QPainter &p, int x, int y, TimeMs ms, const QColor *colorOverride) { if (_ripple) { - _ripple->paint(p, x, y, width(), ms); + _ripple->paint(p, x, y, width(), ms, colorOverride); if (_ripple->empty()) { _ripple.reset(); } @@ -106,8 +106,11 @@ void RippleButton::onStateChanged(int oldState, StateChangeSource source) { if (down && (source == StateChangeSource::ByPress)) { // Start a ripple only from mouse press. - ensureRipple(); - _ripple->add(prepareRippleStartPosition()); + auto position = prepareRippleStartPosition(); + if (position != disabledRippleStartPosition()) { + ensureRipple(); + _ripple->add(position); + } } else if (!down && _ripple) { // Finish ripple anyway. _ripple->lastStop(); diff --git a/Telegram/SourceFiles/ui/widgets/buttons.h b/Telegram/SourceFiles/ui/widgets/buttons.h index 413219c12..7459739d6 100644 --- a/Telegram/SourceFiles/ui/widgets/buttons.h +++ b/Telegram/SourceFiles/ui/widgets/buttons.h @@ -64,12 +64,15 @@ public: ~RippleButton(); protected: - void paintRipple(QPainter &p, int x, int y, TimeMs ms); + void paintRipple(QPainter &p, int x, int y, TimeMs ms, const QColor *colorOverride = nullptr); void onStateChanged(int oldState, StateChangeSource source) override; virtual QImage prepareRippleMask() const; virtual QPoint prepareRippleStartPosition() const; + QPoint disabledRippleStartPosition() const { + return QPoint(-0x3FFFFFFF, -0x3FFFFFFF); + } private: void ensureRipple(); diff --git a/Telegram/SourceFiles/ui/widgets/checkbox.cpp b/Telegram/SourceFiles/ui/widgets/checkbox.cpp index 94af0c601..e54375ee1 100644 --- a/Telegram/SourceFiles/ui/widgets/checkbox.cpp +++ b/Telegram/SourceFiles/ui/widgets/checkbox.cpp @@ -22,6 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "ui/widgets/checkbox.h" #include "lang.h" +#include "ui/effects/ripple_animation.h" namespace Ui { namespace { @@ -87,32 +88,26 @@ void RadiobuttonGroup::remove(Radiobutton * const &radio) { } } -Checkbox::Checkbox(QWidget *parent, const QString &text, bool checked, const style::Checkbox &st) : AbstractButton(parent) +Checkbox::Checkbox(QWidget *parent, const QString &text, bool checked, const style::Checkbox &st) : RippleButton(parent, st.ripple) , _st(st) -, a_over(0) -, a_checked(checked ? 1 : 0) -, _a_over(animation(this, &Checkbox::step_over)) -, _a_checked(animation(this, &Checkbox::step_checked)) , _text(text) , _fullText(text) , _textWidth(st.font->width(text)) , _checked(checked) { if (_st.width <= 0) { - resize(_textWidth - _st.width, _st.height); + resizeToWidth(_textWidth - _st.width); } else { if (_st.width < _st.textPosition.x() + _textWidth + (_st.textPosition.x() - _st.diameter)) { _text = _st.font->elided(_fullText, qMax(_st.width - (_st.textPosition.x() + (_st.textPosition.x() - _st.diameter)), 1)); _textWidth = _st.font->width(_text); } - resize(_st.width, _st.height); + resizeToWidth(_st.width); } - _checkRect = myrtlrect(0, 0, _st.diameter, _st.diameter); + _checkRect = myrtlrect(_st.margin.left(), _st.margin.top(), _st.diameter, _st.diameter); connect(this, SIGNAL(clicked()), this, SLOT(onClicked())); setCursor(style::cur_pointer); - - setAttribute(Qt::WA_OpaquePaintEvent); } bool Checkbox::checked() const { @@ -122,12 +117,7 @@ bool Checkbox::checked() const { void Checkbox::setChecked(bool checked, NotifyAboutChange notify) { if (_checked != checked) { _checked = checked; - if (_checked) { - a_checked.start(1); - } else { - a_checked.start(0); - } - _a_checked.start(); + _a_checked.start([this] { update(_checkRect); }, _checked ? 0. : 1., _checked ? 1. : 0., _st.duration); if (notify == NotifyAboutChange::Notify) { emit changed(); } @@ -135,30 +125,7 @@ void Checkbox::setChecked(bool checked, NotifyAboutChange notify) { } void Checkbox::finishAnimations() { - a_checked.finish(); - _a_checked.stop(); -} - -void Checkbox::step_over(float64 ms, bool timer) { - float64 dt = ms / _st.duration; - if (dt >= 1) { - _a_over.stop(); - a_over.finish(); - } else { - a_over.update(dt, anim::linear); - } - if (timer) update(_checkRect); -} - -void Checkbox::step_checked(float64 ms, bool timer) { - float64 dt = ms / _st.duration; - if (dt >= 1) { - a_checked.finish(); - _a_checked.stop(); - } else { - a_checked.update(dt, anim::linear); - } - if (timer) update(_checkRect); + _a_checked.finish(); } int Checkbox::naturalWidth() const { @@ -168,52 +135,31 @@ int Checkbox::naturalWidth() const { void Checkbox::paintEvent(QPaintEvent *e) { Painter p(this); - float64 over = a_over.current(), checked = a_checked.current(); - bool cnone = (over == 0. && checked == 0.), cover = (over == 1. && checked == 0.), cchecked = (checked == 1.); - bool cbad = !cnone && !cover && !cchecked; - QColor color; - if (cbad) { - float64 onone = (1. - over) * (1. - checked), oover = over * (1. - checked), ochecked = checked; - color.setRedF(_st.checkFg->c.redF() * onone + _st.checkFgOver->c.redF() * oover + _st.checkFgActive->c.redF() * ochecked); - color.setGreenF(_st.checkFg->c.greenF() * onone + _st.checkFgOver->c.greenF() * oover + _st.checkFgActive->c.greenF() * ochecked); - color.setBlueF(_st.checkFg->c.blueF() * onone + _st.checkFgOver->c.blueF() * oover + _st.checkFgActive->c.blueF() * ochecked); - } + auto ms = getms(); + auto active = _a_checked.current(ms, _checked ? 1. : 0.); + auto color = anim::color(_st.rippleBg, _st.rippleBgActive, active); + paintRipple(p, _st.rippleAreaPosition.x(), _st.rippleAreaPosition.y(), ms, &color); - QRect r(e->rect()); - p.setClipRect(r); - p.fillRect(r, _st.textBg); - if (_checkRect.intersects(r)) { + if (_checkRect.intersects(e->rect())) { p.setRenderHint(QPainter::HighQualityAntialiasing); - QPen pen; - if (cbad) { - pen = QPen(color); - } else { - pen = (cnone ? _st.checkFg : (cover ? _st.checkFgOver : _st.checkFgActive))->p; - color = (cnone ? _st.checkFg : (cover ? _st.checkFgOver : _st.checkFgActive))->c; - } + auto pen = anim::pen(_st.checkFg, _st.checkFgActive, active); pen.setWidth(_st.thickness); p.setPen(pen); - if (checked > 0) { - color.setRedF(color.redF() * checked + _st.checkBg->c.redF() * (1. - checked)); - color.setGreenF(color.greenF() * checked + _st.checkBg->c.greenF() * (1. - checked)); - color.setBlueF(color.blueF() * checked + _st.checkBg->c.blueF() * (1. - checked)); - p.setBrush(color); - } else { - p.setBrush(_st.checkBg); - } + p.setBrush(anim::brush(_st.checkBg, anim::color(_st.checkFg, _st.checkFgActive, active), active)); + p.drawRoundedRect(QRectF(_checkRect).marginsRemoved(QMarginsF(_st.thickness / 2., _st.thickness / 2., _st.thickness / 2., _st.thickness / 2.)), st::buttonRadius - (_st.thickness / 2.), st::buttonRadius - (_st.thickness / 2.)); p.setRenderHint(QPainter::HighQualityAntialiasing, false); - if (checked > 0) { - _st.checkIcon.paint(p, QPoint(0, 0), width()); + if (active > 0) { + _st.checkIcon.paint(p, QPoint(_st.margin.left(), _st.margin.top()), width()); } } - if (_checkRect.contains(r)) return; + if (_checkRect.contains(e->rect())) return; p.setPen(_st.textFg); p.setFont(_st.font); - p.drawTextLeft(_st.textPosition.x(), _st.textPosition.y(), width(), _text, _textWidth); + p.drawTextLeft(_st.margin.left() + _st.textPosition.x(), _st.margin.top() + _st.textPosition.y(), width(), _text, _textWidth); } void Checkbox::onClicked() { @@ -222,13 +168,8 @@ void Checkbox::onClicked() { } void Checkbox::onStateChanged(int oldState, StateChangeSource source) { - if ((_state & StateOver) && !(oldState & StateOver)) { - a_over.start(1); - _a_over.start(); - } else if (!(_state & StateOver) && (oldState & StateOver)) { - a_over.start(0); - _a_over.start(); - } + RippleButton::onStateChanged(oldState, source); + if ((_state & StateDisabled) && !(oldState & StateDisabled)) { setCursor(style::cur_default); } else if (!(_state & StateDisabled) && (oldState & StateDisabled)) { @@ -236,12 +177,24 @@ void Checkbox::onStateChanged(int oldState, StateChangeSource source) { } } -Radiobutton::Radiobutton(QWidget *parent, const QString &group, int32 value, const QString &text, bool checked, const style::Radiobutton &st) : AbstractButton(parent) +int Checkbox::resizeGetHeight(int newWidth) { + return _st.height; +} + +QImage Checkbox::prepareRippleMask() const { + return RippleAnimation::ellipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize)); +} + +QPoint Checkbox::prepareRippleStartPosition() const { + auto position = mapFromGlobal(QCursor::pos()) - _st.rippleAreaPosition; + if (QRect(0, 0, _st.rippleAreaSize, _st.rippleAreaSize).contains(position)) { + return position; + } + return disabledRippleStartPosition(); +} + +Radiobutton::Radiobutton(QWidget *parent, const QString &group, int32 value, const QString &text, bool checked, const style::Checkbox &st) : RippleButton(parent, st.ripple) , _st(st) -, a_over(0) -, a_checked(checked ? 1 : 0) -, _a_over(animation(this, &Radiobutton::step_over)) -, _a_checked(animation(this, &Radiobutton::step_checked)) , _text(text) , _fullText(text) , _textWidth(st.font->width(text)) @@ -249,22 +202,20 @@ Radiobutton::Radiobutton(QWidget *parent, const QString &group, int32 value, con , _group(radiobuttons.reg(group)) , _value(value) { if (_st.width <= 0) { - resize(_textWidth - _st.width, _st.height); + resizeToWidth(_textWidth - _st.width); } else { if (_st.width < _st.textPosition.x() + _textWidth + (_st.textPosition.x() - _st.diameter)) { _text = _st.font->elided(_fullText, qMax(_st.width - (_st.textPosition.x() + (_st.textPosition.x() - _st.diameter)), 1)); _textWidth = _st.font->width(_text); } - resize(_st.width, _st.height); + resizeToWidth(_st.width); } - _checkRect = myrtlrect(0, 0, _st.diameter, _st.diameter); + _checkRect = myrtlrect(_st.margin.left(), _st.margin.top(), _st.diameter, _st.diameter); connect(this, SIGNAL(clicked()), this, SLOT(onClicked())); setCursor(style::cur_pointer); - setAttribute(Qt::WA_OpaquePaintEvent); - reinterpret_cast(_group)->insert(this, true); if (_checked) onChanged(); } @@ -276,66 +227,29 @@ bool Radiobutton::checked() const { void Radiobutton::setChecked(bool checked) { if (_checked != checked) { _checked = checked; - if (_checked) { - a_checked.start(1); - } else { - a_checked.start(0); - } - _a_checked.start(); + _a_checked.start([this] { update(_checkRect); }, _checked ? 0. : 1., _checked ? 1. : 0., _st.duration); onChanged(); emit changed(); } } -void Radiobutton::step_over(float64 ms, bool timer) { - float64 dt = ms / _st.duration; - if (dt >= 1) { - _a_over.stop(); - a_over.finish(); - } else { - a_over.update(dt, anim::linear); - } - if (timer) update(_checkRect); -} - -void Radiobutton::step_checked(float64 ms, bool timer) { - float64 dt = ms / _st.duration; - if (dt >= 1) { - a_checked.finish(); - _a_checked.stop(); - } else { - a_checked.update(dt, anim::linear); - } - if (timer) update(_checkRect); +int Radiobutton::naturalWidth() const { + return _st.textPosition.x() + _st.font->width(_fullText); } void Radiobutton::paintEvent(QPaintEvent *e) { Painter p(this); - float64 over = a_over.current(), checked = a_checked.current(); - bool cnone = (over == 0. && checked == 0.), cover = (over == 1. && checked == 0.), cchecked = (checked == 1.); - bool cbad = !cnone && !cover && !cchecked; - QColor color; - if (cbad) { - float64 onone = (1. - over) * (1. - checked), oover = over * (1. - checked), ochecked = checked; - color.setRedF(_st.checkFg->c.redF() * onone + _st.checkFgOver->c.redF() * oover + _st.checkFgActive->c.redF() * ochecked); - color.setGreenF(_st.checkFg->c.greenF() * onone + _st.checkFgOver->c.greenF() * oover + _st.checkFgActive->c.greenF() * ochecked); - color.setBlueF(_st.checkFg->c.blueF() * onone + _st.checkFgOver->c.blueF() * oover + _st.checkFgActive->c.blueF() * ochecked); - } + auto ms = getms(); + auto active = _a_checked.current(ms, _checked ? 1. : 0.); + auto color = anim::color(_st.rippleBg, _st.rippleBgActive, active); + paintRipple(p, _st.rippleAreaPosition.x(), _st.rippleAreaPosition.y(), ms, &color); - QRect r(e->rect()); - p.setClipRect(r); - p.fillRect(r, _st.textBg->b); - if (_checkRect.intersects(r)) { + if (_checkRect.intersects(e->rect())) { p.setRenderHint(QPainter::HighQualityAntialiasing); - QPen pen; - if (cbad) { - pen = QPen(color); - } else { - pen = (cnone ? _st.checkFg : (cover ? _st.checkFgOver : _st.checkFgActive))->p; - } + auto pen = anim::pen(_st.checkFg, _st.checkFgActive, active); pen.setWidth(_st.thickness); p.setPen(pen); p.setBrush(_st.checkBg); @@ -343,14 +257,11 @@ void Radiobutton::paintEvent(QPaintEvent *e) { //p.drawEllipse(_checkRect.marginsRemoved(QMargins(skip, skip, skip, skip))); p.drawEllipse(QRectF(_checkRect).marginsRemoved(QMarginsF(_st.thickness / 2., _st.thickness / 2., _st.thickness / 2., _st.thickness / 2.))); - if (checked > 0) { + if (active > 0) { p.setPen(Qt::NoPen); - if (cbad) { - p.setBrush(color); - } else { - p.setBrush(cnone ? _st.checkFg : (cover ? _st.checkFgOver : _st.checkFgActive)); - } - float64 skip0 = _checkRect.width() / 2., skip1 = _st.checkSkip / 10., checkSkip = skip0 * (1. - checked) + skip1 * checked; + p.setBrush(anim::brush(_st.checkFg, _st.checkFgActive, active)); + + auto skip0 = _checkRect.width() / 2., skip1 = _st.radioSkip / 10., checkSkip = skip0 * (1. - active) + skip1 * active; p.drawEllipse(QRectF(_checkRect).marginsRemoved(QMarginsF(checkSkip, checkSkip, checkSkip, checkSkip))); //int32 fskip = qFloor(checkSkip), cskip = qCeil(checkSkip); //if (2 * fskip < _checkRect.width()) { @@ -367,11 +278,11 @@ void Radiobutton::paintEvent(QPaintEvent *e) { p.setRenderHint(QPainter::HighQualityAntialiasing, false); } - if (_checkRect.contains(r)) return; + if (_checkRect.contains(e->rect())) return; p.setPen(_st.textFg); p.setFont(_st.font); - p.drawTextLeft(_st.textPosition.x(), _st.textPosition.y(), width(), _text, _textWidth); + p.drawTextLeft(_st.margin.left() + _st.textPosition.x(), _st.margin.top() + _st.textPosition.y(), width(), _text, _textWidth); } void Radiobutton::onClicked() { @@ -380,13 +291,8 @@ void Radiobutton::onClicked() { } void Radiobutton::onStateChanged(int oldState, StateChangeSource source) { - if ((_state & StateOver) && !(oldState & StateOver)) { - a_over.start(1); - _a_over.start(); - } else if (!(_state & StateOver) && (oldState & StateOver)) { - a_over.start(0); - _a_over.start(); - } + RippleButton::onStateChanged(oldState, source); + if ((_state & StateDisabled) && !(oldState & StateDisabled)) { setCursor(style::cur_default); } else if (!(_state & StateDisabled) && (oldState & StateDisabled)) { @@ -394,6 +300,22 @@ void Radiobutton::onStateChanged(int oldState, StateChangeSource source) { } } +int Radiobutton::resizeGetHeight(int newWidth) { + return _st.height; +} + +QImage Radiobutton::prepareRippleMask() const { + return RippleAnimation::ellipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize)); +} + +QPoint Radiobutton::prepareRippleStartPosition() const { + auto position = mapFromGlobal(QCursor::pos()) - _st.rippleAreaPosition; + if (QRect(0, 0, _st.rippleAreaSize, _st.rippleAreaSize).contains(position)) { + return position; + } + return disabledRippleStartPosition(); +} + void Radiobutton::onChanged() { RadiobuttonGroup *group = reinterpret_cast(_group); if (checked()) { diff --git a/Telegram/SourceFiles/ui/widgets/checkbox.h b/Telegram/SourceFiles/ui/widgets/checkbox.h index 2b208c192..221ed21dd 100644 --- a/Telegram/SourceFiles/ui/widgets/checkbox.h +++ b/Telegram/SourceFiles/ui/widgets/checkbox.h @@ -20,12 +20,12 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org */ #pragma once -#include "ui/abstract_button.h" +#include "ui/widgets/buttons.h" #include "styles/style_widgets.h" namespace Ui { -class Checkbox : public AbstractButton { +class Checkbox : public RippleButton { Q_OBJECT public: @@ -40,12 +40,19 @@ public: void finishAnimations(); + QMargins getMargins() const override { + return _st.margin; + } int naturalWidth() const override; protected: void paintEvent(QPaintEvent *e) override; void onStateChanged(int oldState, StateChangeSource source) override; + int resizeGetHeight(int newWidth) override; + + QImage prepareRippleMask() const override; + QPoint prepareRippleStartPosition() const override; public slots: void onClicked(); @@ -54,26 +61,22 @@ signals: void changed(); private: - void step_over(float64 ms, bool timer); - void step_checked(float64 ms, bool timer); - const style::Checkbox &_st; - anim::fvalue a_over, a_checked; - Animation _a_over, _a_checked; QString _text, _fullText; int32 _textWidth; QRect _checkRect; bool _checked; + FloatAnimation _a_checked; }; -class Radiobutton : public AbstractButton { +class Radiobutton : public RippleButton { Q_OBJECT public: - Radiobutton(QWidget *parent, const QString &group, int32 value, const QString &text, bool checked = false, const style::Radiobutton &st = st::defaultRadiobutton); + Radiobutton(QWidget *parent, const QString &group, int32 value, const QString &text, bool checked = false, const style::Checkbox &st = st::defaultCheckbox); bool checked() const; void setChecked(bool checked); @@ -82,8 +85,10 @@ public: return _value; } - void step_over(float64 ms, bool timer); - void step_checked(float64 ms, bool timer); + QMargins getMargins() const override { + return _st.margin; + } + int naturalWidth() const override; ~Radiobutton(); @@ -91,6 +96,10 @@ protected: void paintEvent(QPaintEvent *e) override; void onStateChanged(int oldState, StateChangeSource source) override; + int resizeGetHeight(int newWidth) override; + + QImage prepareRippleMask() const override; + QPoint prepareRippleStartPosition() const override; public slots: void onClicked(); @@ -101,15 +110,14 @@ signals: private: void onChanged(); - const style::Radiobutton &_st; - anim::fvalue a_over, a_checked; - Animation _a_over, _a_checked; + const style::Checkbox &_st; QString _text, _fullText; int32 _textWidth; QRect _checkRect; bool _checked; + FloatAnimation _a_checked; void *_group; int32 _value; diff --git a/Telegram/SourceFiles/ui/widgets/discrete_sliders.cpp b/Telegram/SourceFiles/ui/widgets/discrete_sliders.cpp index 99045d5f1..88e7526a0 100644 --- a/Telegram/SourceFiles/ui/widgets/discrete_sliders.cpp +++ b/Telegram/SourceFiles/ui/widgets/discrete_sliders.cpp @@ -21,6 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "stdafx.h" #include "ui/widgets/discrete_sliders.h" +#include "ui/effects/ripple_animation.h" #include "styles/style_widgets.h" namespace Ui { @@ -36,11 +37,27 @@ void DiscreteSlider::setSectionActivatedCallback(SectionActivatedCallback &&call void DiscreteSlider::setActiveSection(int index) { if (_activeIndex != index) { _activeIndex = index; + activateCallback(); + } + setSelectedSection(index); +} + +void DiscreteSlider::activateCallback() { + if (_timerId >= 0) { + killTimer(_timerId); + } + auto ms = getms(); + if (ms >= _callbackAfterMs) { if (_callback) { _callback(); } + } else { + _timerId = startTimer(_callbackAfterMs - ms, Qt::PreciseTimer); } - setSelectedSection(index); +} + +void DiscreteSlider::timerEvent(QTimerEvent *e) { + activateCallback(); } void DiscreteSlider::setActiveSectionFast(int index) { @@ -82,14 +99,18 @@ int DiscreteSlider::getCurrentActiveLeft(TimeMs ms) { template void DiscreteSlider::enumerateSections(Lambda callback) { for (auto §ion : _sections) { - callback(section); + if (!callback(section)) { + return; + } } } void DiscreteSlider::mousePressEvent(QMouseEvent *e) { + auto index = getIndexFromPosition(e->pos()); if (_selectOnPress) { - setSelectedSection(getIndexFromPosition(e->pos())); + setSelectedSection(index); } + startRipple(index); _pressed = true; } @@ -101,9 +122,14 @@ void DiscreteSlider::mouseMoveEvent(QMouseEvent *e) { } void DiscreteSlider::mouseReleaseEvent(QMouseEvent *e) { - if (!_pressed) return; - _pressed = false; - setActiveSection(getIndexFromPosition(e->pos())); + if (!base::take(_pressed)) return; + auto index = getIndexFromPosition(e->pos()); + if (index >= 0 && index < _sections.size()) { + if (_sections[index].ripple) { + _sections[index].ripple->lastStop(); + } + } + setActiveSection(index); } void DiscreteSlider::setSelectedSection(int index) { @@ -113,7 +139,9 @@ void DiscreteSlider::setSelectedSection(int index) { auto from = _sections[_selected].left; _selected = index; auto to = _sections[_selected].left; - _a_left.start([this] { update(); }, from, to, getAnimationDuration()); + auto duration = getAnimationDuration(); + _a_left.start([this] { update(); }, from, to, duration); + _callbackAfterMs = getms() + duration; } } @@ -134,6 +162,7 @@ DiscreteSlider::Section::Section(const QString &label, const style::font &font) SettingsSlider::SettingsSlider(QWidget *parent, const style::SettingsSlider &st) : DiscreteSlider(parent) , _st(st) { + setSelectOnPress(_st.ripple.showDuration == 0); } const style::font &SettingsSlider::getLabelFont() const { @@ -157,6 +186,7 @@ void SettingsSlider::resizeSections(int newWidth) { x += sectionWidth; section.width = qRound(x) - (section.left - skip); skip += _st.barSkip; + return true; }); stopAnimation(); } @@ -166,13 +196,35 @@ int SettingsSlider::resizeGetHeight(int newWidth) { return _st.height; } +void SettingsSlider::startRipple(int index) { + if (!_st.ripple.showDuration) return; + enumerateSections([this, &index](Section §ion) { + if (!index--) { + if (!section.ripple) { + auto mask = RippleAnimation::rectMask(QSize(section.width, height() - _st.rippleBottomSkip)); + section.ripple = MakeShared(_st.ripple, std_::move(mask), [this] { update(); }); + } + section.ripple->add(mapFromGlobal(QCursor::pos()) - QPoint(section.left, 0)); + return false; + } + return true; + }); +} + void SettingsSlider::paintEvent(QPaintEvent *e) { Painter p(this); - auto activeLeft = getCurrentActiveLeft(getms()); + auto ms = getms(); + auto activeLeft = getCurrentActiveLeft(ms); p.setFont(_st.labelFont); - enumerateSections([this, &p, activeLeft](Section §ion) { + enumerateSections([this, &p, activeLeft, ms](Section §ion) { + if (section.ripple) { + section.ripple->paint(p, section.left, 0, width(), ms); + if (section.ripple->empty()) { + section.ripple.reset(); + } + } auto from = section.left, tofill = section.width; if (activeLeft > from) { auto fill = qMin(tofill, activeLeft - from); @@ -193,6 +245,7 @@ void SettingsSlider::paintEvent(QPaintEvent *e) { } p.setPen(anim::pen(_st.labelFg, _st.labelFgActive, active)); p.drawTextLeft(section.left + (section.width - section.labelWidth) / 2, _st.labelTop, width(), section.label, section.labelWidth); + return true; }); } diff --git a/Telegram/SourceFiles/ui/widgets/discrete_sliders.h b/Telegram/SourceFiles/ui/widgets/discrete_sliders.h index d472f0a87..3915a2610 100644 --- a/Telegram/SourceFiles/ui/widgets/discrete_sliders.h +++ b/Telegram/SourceFiles/ui/widgets/discrete_sliders.h @@ -24,6 +24,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org namespace Ui { +class RippleAnimation; + class DiscreteSlider : public TWidget { public: DiscreteSlider(QWidget *parent); @@ -35,12 +37,12 @@ public: } void setActiveSection(int index); void setActiveSectionFast(int index); - void setSelectOnPress(bool selectOnPress); using SectionActivatedCallback = base::lambda; void setSectionActivatedCallback(SectionActivatedCallback &&callback); protected: + void timerEvent(QTimerEvent *e) override; void mousePressEvent(QMouseEvent *e) override; void mouseMoveEvent(QMouseEvent *e) override; void mouseReleaseEvent(QMouseEvent *e) override; @@ -53,6 +55,7 @@ protected: int left, width; QString label; int labelWidth; + QSharedPointer ripple; }; int getCurrentActiveLeft(TimeMs ms); @@ -64,11 +67,17 @@ protected: template void enumerateSections(Lambda callback); + virtual void startRipple(int index) { + } + void stopAnimation() { _a_left.finish(); } + void setSelectOnPress(bool selectOnPress); + private: + void activateCallback(); virtual const style::font &getLabelFont() const = 0; virtual int getAnimationDuration() const = 0; @@ -85,6 +94,9 @@ private: int _selected = 0; FloatAnimation _a_left; + int _timerId = -1; + TimeMs _callbackAfterMs = 0; + }; class SettingsSlider : public DiscreteSlider { @@ -96,6 +108,8 @@ protected: int resizeGetHeight(int newWidth) override; + void startRipple(int index) override; + private: const style::font &getLabelFont() const override; int getAnimationDuration() const override; @@ -104,6 +118,7 @@ private: const style::SettingsSlider &_st; + }; } // namespace Ui diff --git a/Telegram/SourceFiles/ui/widgets/input_fields.cpp b/Telegram/SourceFiles/ui/widgets/input_fields.cpp index 7b63a3bca..cd8fdbddd 100644 --- a/Telegram/SourceFiles/ui/widgets/input_fields.cpp +++ b/Telegram/SourceFiles/ui/widgets/input_fields.cpp @@ -133,11 +133,7 @@ QString FlatTextarea::tagsMimeType() { } FlatTextarea::FlatTextarea(QWidget *parent, const style::FlatTextarea &st, const QString &pholder, const QString &v, const TagList &tags) : QTextEdit(parent) -, _phVisible(!v.length()) -, a_phLeft(_phVisible ? 0 : st.phShift) -, a_phAlpha(_phVisible ? 1 : 0) -, a_phColorFocused(0) -, _a_appearance(animation(this, &FlatTextarea::step_appearance)) +, _placeholderVisible(!v.length()) , _lastTextWithTags { v, tags } , _st(st) { setCursor(style::cur_text); @@ -217,12 +213,9 @@ void FlatTextarea::setTextWithTags(const TextWithTags &textWithTags, UndoHistory } void FlatTextarea::finishPlaceholder() { - if (_a_appearance.animating()) { - a_phLeft.finish(); - a_phAlpha.finish(); - _a_appearance.stop(); - update(); - } + _a_placeholderFocused.finish(); + _a_placeholderVisible.finish(); + update(); } void FlatTextarea::setMaxLength(int32 maxLength) { @@ -323,24 +316,25 @@ int32 FlatTextarea::fakeMargin() const { } void FlatTextarea::paintEvent(QPaintEvent *e) { - QPainter p(viewport()); - QRect r(rect().intersected(e->rect())); - p.fillRect(r, _st.bgColor->b); - bool phDraw = _phVisible; - if (_a_appearance.animating()) { - p.setOpacity(a_phAlpha.current()); - phDraw = true; - } - if (phDraw) { + Painter p(viewport()); + auto ms = getms(); + auto r = rect().intersected(e->rect()); + p.fillRect(r, _st.bgColor); + auto placeholderOpacity = _a_placeholderVisible.current(ms, _placeholderVisible ? 1. : 0.); + if (placeholderOpacity > 0.) { + p.setOpacity(placeholderOpacity); + + auto placeholderLeft = anim::interpolate(_st.phShift, 0, placeholderOpacity); + p.save(); p.setClipRect(r); p.setFont(_st.font); - p.setPen(anim::pen(_st.phColor, _st.phFocusColor, a_phColorFocused.current())); + p.setPen(anim::pen(_st.phColor, _st.phFocusColor, _a_placeholderFocused.current(ms, hasFocus() ? 1. : 0.))); if (_st.phAlign == style::al_topleft && _phAfter > 0) { int skipWidth = placeholderSkipWidth(); - p.drawText(_st.textMrg.left() - _fakeMargin + a_phLeft.current() + skipWidth, _st.textMrg.top() - _fakeMargin - st::lineWidth + _st.font->ascent, _ph); + p.drawText(_st.textMrg.left() - _fakeMargin + placeholderLeft + skipWidth, _st.textMrg.top() - _fakeMargin - st::lineWidth + _st.font->ascent, _ph); } else { - QRect phRect(_st.textMrg.left() - _fakeMargin + _st.phPos.x() + a_phLeft.current(), _st.textMrg.top() - _fakeMargin + _st.phPos.y(), width() - _st.textMrg.left() - _st.textMrg.right(), height() - _st.textMrg.top() - _st.textMrg.bottom()); + QRect phRect(_st.textMrg.left() - _fakeMargin + _st.phPos.x() + placeholderLeft, _st.textMrg.top() - _fakeMargin + _st.phPos.y(), width() - _st.textMrg.left() - _st.textMrg.right(), height() - _st.textMrg.top() - _st.textMrg.bottom()); p.drawText(phRect, _ph, QTextOption(_st.phAlign)); } p.restore(); @@ -362,14 +356,12 @@ int FlatTextarea::placeholderSkipWidth() const { } void FlatTextarea::focusInEvent(QFocusEvent *e) { - a_phColorFocused.start(1.); - _a_appearance.start(); + _a_placeholderFocused.start([this] { update(); }, 0., 1., _st.phDuration); QTextEdit::focusInEvent(e); } void FlatTextarea::focusOutEvent(QFocusEvent *e) { - a_phColorFocused.start(0.); - _a_appearance.start(); + _a_placeholderFocused.start([this] { update(); }, 1., 0., _st.phDuration); QTextEdit::focusOutEvent(e); } @@ -1313,24 +1305,6 @@ void FlatTextarea::onRedoAvailable(bool avail) { if (App::wnd()) App::wnd()->updateGlobalMenu(); } -void FlatTextarea::step_appearance(float64 ms, bool timer) { - float dt = ms / _st.phDuration; - if (dt >= 1) { - _a_appearance.stop(); - a_phLeft.finish(); - a_phAlpha.finish(); - a_phColorFocused.finish(); - a_phLeft = anim::ivalue(a_phLeft.current()); - a_phAlpha = anim::fvalue(a_phAlpha.current()); - a_phColorFocused = anim::fvalue(a_phColorFocused.current()); - } else { - a_phLeft.update(dt, anim::linear); - a_phAlpha.update(dt, anim::linear); - a_phColorFocused.update(dt, anim::linear); - } - if (timer) update(); -} - void FlatTextarea::setPlaceholder(const QString &ph, int32 afterSymbols) { _ph = ph; if (_phAfter != afterSymbols) { @@ -1339,18 +1313,15 @@ void FlatTextarea::setPlaceholder(const QString &ph, int32 afterSymbols) { } int skipWidth = placeholderSkipWidth(); _phelided = _st.font->elided(_ph, width() - _st.textMrg.left() - _st.textMrg.right() - _st.phPos.x() - 1 - skipWidth); - if (_phVisible) update(); + if (_placeholderVisible) update(); } void FlatTextarea::updatePlaceholder() { - bool vis = (getTextWithTags().text.size() <= _phAfter); - if (vis == _phVisible) return; - - a_phLeft.start(vis ? 0 : _st.phShift); - a_phAlpha.start(vis ? 1 : 0); - _a_appearance.start(); - - _phVisible = vis; + auto placeholderVisible = (getTextWithTags().text.size() <= _phAfter); + if (_placeholderVisible != placeholderVisible) { + _placeholderVisible = placeholderVisible; + _a_placeholderVisible.start([this] { update(); }, _placeholderVisible ? 0. : 1., _placeholderVisible ? 1. : 0., _st.phDuration); + } } QMimeData *FlatTextarea::createMimeDataFromSelection() const { @@ -1478,17 +1449,7 @@ void FlatTextarea::contextMenuEvent(QContextMenuEvent *e) { FlatInput::FlatInput(QWidget *parent, const style::FlatInput &st, const QString &pholder, const QString &v) : QLineEdit(v, parent) , _oldtext(v) , _fullph(pholder) -, _fastph(false) -, _customUpDown(false) -, _phVisible(!v.length()) -, a_phLeft(_phVisible ? 0 : st.phShift) -, a_phAlpha(_phVisible ? 1 : 0) -, a_phColorFocus(0) -, a_borderColorActive(0) -, a_borderColorError(0) -, a_bgColorActive(0) -, _a_appearance(animation(this, &FlatInput::step_appearance)) -, _notingBene(0) +, _placeholderVisible(!v.length()) , _st(st) { setCursor(style::cur_text); resize(_st.width, _st.height); @@ -1578,12 +1539,14 @@ QRect FlatInput::getTextRect() const { void FlatInput::paintEvent(QPaintEvent *e) { Painter p(this); + auto ms = getms(); + auto placeholderFocused = _a_placeholderFocused.current(ms, hasFocus() ? 1. : 0.); + p.setRenderHint(QPainter::HighQualityAntialiasing); - auto borderColor = anim::color(_st.borderColor, _st.borderActive, a_borderColorActive.current()); - auto pen = anim::pen(borderColor, _st.borderError, a_borderColorError.current()); + auto pen = anim::pen(_st.borderColor, _st.borderActive, placeholderFocused); pen.setWidth(_st.borderWidth); p.setPen(pen); - p.setBrush(anim::brush(_st.bgColor, _st.bgActive, a_bgColorActive.current())); + p.setBrush(anim::brush(_st.bgColor, _st.bgActive, placeholderFocused)); p.drawRoundedRect(QRectF(0, 0, width(), height()).marginsRemoved(QMarginsF(_st.borderWidth / 2., _st.borderWidth / 2., _st.borderWidth / 2., _st.borderWidth / 2.)), st::buttonRadius - (_st.borderWidth / 2.), st::buttonRadius - (_st.borderWidth / 2.)); p.setRenderHint(QPainter::HighQualityAntialiasing, false); @@ -1591,17 +1554,17 @@ void FlatInput::paintEvent(QPaintEvent *e) { _st.icon.paint(p, 0, 0, width()); } - bool phDraw = _phVisible; - if (_a_appearance.animating()) { - p.setOpacity(a_phAlpha.current()); - phDraw = true; - } - if (phDraw) { + auto placeholderOpacity = _a_placeholderVisible.current(ms, _placeholderVisible ? 1. : 0.); + if (placeholderOpacity > 0.) { + p.setOpacity(placeholderOpacity); + + auto left = anim::interpolate(_st.phShift, 0, placeholderOpacity); + p.save(); p.setClipRect(rect()); QRect phRect(placeholderRect()); - phRect.moveLeft(phRect.left() + a_phLeft.current()); - phPrepare(p); + phRect.moveLeft(phRect.left() + left); + phPrepare(p, placeholderFocused); p.drawText(phRect, _ph, QTextOption(_st.phAlign)); p.restore(); } @@ -1609,21 +1572,13 @@ void FlatInput::paintEvent(QPaintEvent *e) { } void FlatInput::focusInEvent(QFocusEvent *e) { - a_phColorFocus.start(1.); - a_borderColorActive.start(1.); - a_borderColorError.restart(); - a_bgColorActive.start(1); - _a_appearance.start(); + _a_placeholderFocused.start([this] { update(); }, 0., 1., _st.phDuration); QLineEdit::focusInEvent(e); emit focused(); } void FlatInput::focusOutEvent(QFocusEvent *e) { - a_phColorFocus.start(0.); - a_borderColorActive.start(0.); - a_borderColorError.restart(); - a_bgColorActive.start(0); - _a_appearance.start(); + _a_placeholderFocused.start([this] { update(); }, 1., 0., _st.phDuration); QLineEdit::focusOutEvent(e); emit blurred(); } @@ -1645,16 +1600,6 @@ void FlatInput::updatePlaceholderText() { void FlatInput::contextMenuEvent(QContextMenuEvent *e) { if (auto menu = createStandardContextMenu()) { - //menu->addSeparator(); - //auto action = menu->addAction(QString("test")); - //action->setMenu(new QMenu(this)); - //action->menu()->addAction(QString("test123")); - //action->menu()->addAction(QString("test456")); - //action->menu()->addAction(QString("test678")); - //auto second = action->menu()->addAction(QString("test90")); - //second->setMenu(new QMenu(this)); - //second->menu()->addAction(QString("testing111")); - //second->menu()->addAction(QString("testing222")); (new Ui::PopupMenu(menu))->popup(e->globalPos()); } } @@ -1667,35 +1612,6 @@ QSize FlatInput::minimumSizeHint() const { return geometry().size(); } -void FlatInput::step_appearance(float64 ms, bool timer) { - float dt = ms / _st.phDuration; - if (dt >= 1) { - _a_appearance.stop(); - a_phLeft.finish(); - a_phAlpha.finish(); - a_phColorFocus.finish(); - a_bgColorActive.finish(); - if (_notingBene > 0) { - _notingBene = -1; - a_borderColorActive.restart(); - a_borderColorError.start(0); - _a_appearance.start(); - return; - } else if (_notingBene) { - _notingBene = 0; - } - a_borderColorActive.finish(); - } else { - a_phLeft.update(dt, anim::linear); - a_phAlpha.update(dt, anim::linear); - a_phColorFocus.update(dt, anim::linear); - a_bgColorActive.update(dt, anim::linear); - a_borderColorActive.update(dt, anim::linear); - a_borderColorError.update(dt, anim::linear); - } - if (timer) update(); -} - void FlatInput::setPlaceholder(const QString &ph) { _fullph = ph; updatePlaceholderText(); @@ -1704,26 +1620,21 @@ void FlatInput::setPlaceholder(const QString &ph) { void FlatInput::setPlaceholderFast(bool fast) { _fastph = fast; if (_fastph) { - a_phLeft = anim::ivalue(_phVisible ? 0 : _st.phShift, _phVisible ? 0 : _st.phShift); - a_phAlpha = anim::fvalue(_phVisible ? 1 : 0, _phVisible ? 1 : 0); + _a_placeholderVisible.finish(); update(); } } void FlatInput::updatePlaceholder() { - bool vis = !text().length(); - if (vis == _phVisible) return; - - if (_fastph) { - a_phLeft = anim::ivalue(vis ? 0 : _st.phShift, vis ? 0 : _st.phShift); - a_phAlpha = anim::fvalue(vis ? 1 : 0, vis ? 1 : 0); - update(); - } else { - a_phLeft.start(vis ? 0 : _st.phShift); - a_phAlpha.start(vis ? 1 : 0); - _a_appearance.start(); + auto placeholderVisible = text().isEmpty(); + if (_placeholderVisible != placeholderVisible) { + _placeholderVisible = placeholderVisible; + if (_fastph) { + update(); + } else { + _a_placeholderVisible.start([this] { update(); }, _placeholderVisible ? 0. : 1., _placeholderVisible ? 1. : 0., _st.phDuration); + } } - _phVisible = vis; } const QString &FlatInput::placeholder() const { @@ -1737,9 +1648,9 @@ QRect FlatInput::placeholderRect() const { void FlatInput::correctValue(const QString &was, QString &now) { } -void FlatInput::phPrepare(Painter &p) { +void FlatInput::phPrepare(Painter &p, float64 placeholderFocused) { p.setFont(_st.font); - p.setPen(anim::pen(_st.phColor, _st.phFocusColor, a_phColorFocus.current())); + p.setPen(anim::pen(_st.phColor, _st.phFocusColor, placeholderFocused)); } void FlatInput::keyPressEvent(QKeyEvent *e) { @@ -1790,14 +1701,6 @@ void FlatInput::onTextChange(const QString &text) { if (App::wnd()) App::wnd()->updateGlobalMenu(); } -void FlatInput::notaBene() { - _notingBene = 1; - setFocus(); - a_borderColorError.start(1.); - a_borderColorActive.restart(); - _a_appearance.start(); -} - InputArea::InputArea(QWidget *parent, const style::InputArea &st, const QString &ph, const QString &val) : TWidget(parent) , _maxLength(-1) , _inner(this) diff --git a/Telegram/SourceFiles/ui/widgets/input_fields.h b/Telegram/SourceFiles/ui/widgets/input_fields.h index abbc36f89..a823c7c39 100644 --- a/Telegram/SourceFiles/ui/widgets/input_fields.h +++ b/Telegram/SourceFiles/ui/widgets/input_fields.h @@ -52,8 +52,6 @@ public: QRect getTextRect() const; int32 fakeMargin() const; - void step_appearance(float64 ms, bool timer); - QSize sizeHint() const override; QSize minimumSizeHint() const override; @@ -114,6 +112,10 @@ public: }; void setTagMimeProcessor(std_::unique_ptr &&processor); + QMargins getMargins() const { + return QMargins(); + } + public slots: void onTouchTimer(); @@ -187,11 +189,9 @@ private: QString _ph, _phelided; int _phAfter = 0; - bool _phVisible; - anim::ivalue a_phLeft; - anim::fvalue a_phAlpha; - anim::fvalue a_phColorFocused; - Animation _a_appearance; + bool _placeholderVisible = true; + FloatAnimation _a_placeholderFocused; + FloatAnimation _a_placeholderVisible; TextWithTags _lastTextWithTags; @@ -247,8 +247,6 @@ class FlatInput : public QLineEdit { public: FlatInput(QWidget *parent, const style::FlatInput &st, const QString &ph = QString(), const QString &val = QString()); - void notaBene(); - void setPlaceholder(const QString &ph); void setPlaceholderFast(bool fast); void updatePlaceholder(); @@ -257,8 +255,6 @@ public: QRect getTextRect() const; - void step_appearance(float64 ms, bool timer); - QSize sizeHint() const override; QSize minimumSizeHint() const override; @@ -267,6 +263,10 @@ public: return _oldtext; } + QMargins getMargins() const { + return QMargins(); + } + public slots: void onTextChange(const QString &text); void onTextEdited(); @@ -303,26 +303,20 @@ protected: return _st.font; } - void phPrepare(Painter &p); + void phPrepare(Painter &p, float64 placeholderFocused); private: void updatePlaceholderText(); QString _oldtext, _ph, _fullph; - bool _fastph; + bool _fastph = false; - bool _customUpDown; + bool _customUpDown = false; - bool _phVisible; - anim::ivalue a_phLeft; - anim::fvalue a_phAlpha; - anim::fvalue a_phColorFocus; - anim::fvalue a_borderColorActive; - anim::fvalue a_borderColorError; - anim::fvalue a_bgColorActive; - Animation _a_appearance; + bool _placeholderVisible = true; + FloatAnimation _a_placeholderFocused; + FloatAnimation _a_placeholderVisible; - int _notingBene; const style::FlatInput &_st; QTimer _touchTimer; @@ -702,6 +696,10 @@ public: updatePlaceholder(); } + QMargins getMargins() const { + return QMargins(); + } + public slots: void onTextChange(const QString &text); void onCursorPositionChanged(int oldPosition, int position); diff --git a/Telegram/SourceFiles/ui/widgets/multi_select.cpp b/Telegram/SourceFiles/ui/widgets/multi_select.cpp index 74127f8f5..f2fa728ba 100644 --- a/Telegram/SourceFiles/ui/widgets/multi_select.cpp +++ b/Telegram/SourceFiles/ui/widgets/multi_select.cpp @@ -350,6 +350,8 @@ MultiSelect::MultiSelect(QWidget *parent, const style::MultiSelect &st, const QS }); setAttribute(Qt::WA_OpaquePaintEvent); + auto defaultWidth = _st.item.maxWidth + _st.fieldMinWidth + _st.fieldCancelSkip; + resizeToWidth(_st.padding.left() + defaultWidth + _st.padding.right()); } bool MultiSelect::eventFilter(QObject *o, QEvent *e) { diff --git a/Telegram/SourceFiles/ui/widgets/scroll_area.h b/Telegram/SourceFiles/ui/widgets/scroll_area.h index 16b4cb745..2934b0344 100644 --- a/Telegram/SourceFiles/ui/widgets/scroll_area.h +++ b/Telegram/SourceFiles/ui/widgets/scroll_area.h @@ -186,6 +186,10 @@ public: bool viewportEvent(QEvent *e) override; void keyPressEvent(QKeyEvent *e) override; + QMargins getMargins() const { + return QMargins(); + } + ~ScrollArea(); protected: diff --git a/Telegram/SourceFiles/ui/widgets/widgets.style b/Telegram/SourceFiles/ui/widgets/widgets.style index 2699ba148..ee2d1fbe9 100644 --- a/Telegram/SourceFiles/ui/widgets/widgets.style +++ b/Telegram/SourceFiles/ui/widgets/widgets.style @@ -94,44 +94,29 @@ RoundButton { Checkbox { textFg: color; - textBg: color; checkBg: color; checkFg: color; - checkFgOver: color; checkFgActive: color; width: pixels; height: pixels; + margin: margins; textPosition: point; diameter: pixels; thickness: pixels; + radioSkip: pixels; checkIcon: icon; font: font; duration: int; -} -Radiobutton { - textFg: color; - textBg: color; - - checkBg: color; - checkFg: color; - checkFgOver: color; - checkFgActive: color; - - width: pixels; - height: pixels; - - textPosition: point; - diameter: pixels; - thickness: pixels; - checkSkip: pixels; - - font: font; - duration: int; + rippleAreaPosition: point; + rippleAreaSize: pixels; + rippleBg: color; + rippleBgActive: color; + ripple: RippleAnimation; } FlatScroll { @@ -674,44 +659,29 @@ defaultCheckboxIcon: icon {{ "default_checkbox_check", windowFgActive, point(4px defaultCheckbox: Checkbox { textFg: windowFg; - textBg: windowBg; - checkBg: #ffffff; + checkBg: transparent; checkFg: #b3b3b3; - checkFgOver: #b3b3b3; checkFgActive: windowBgActive; width: -44px; height: 22px; + margin: margins(8px, 8px, 8px, 8px); textPosition: point(32px, 2px); diameter: 22px; thickness: 2px; checkIcon: defaultCheckboxIcon; + radioSkip: 65px; // * 0.1 font: normalFont; duration: 120; -} -defaultRadiobutton: Radiobutton { - textFg: windowFg; - textBg: windowBg; - - checkBg: #ffffff; - checkFg: #b3b3b3; - checkFgOver: #bfbfbf; - checkFgActive: #4eb3ee; - - width: -46px; - height: 22px; - - textPosition: point(34px, 0px); - diameter: 22px; - thickness: 2px; - checkSkip: 65px; // * 0.1 - - font: boxTextFont; - duration: 120; + rippleAreaSize: 38px; + rippleAreaPosition: point(0px, 0px); + rippleBg: windowBgOver; + rippleBgActive: #e0f2fa; + ripple: defaultRippleAnimation; } defaultIconButton: IconButton { @@ -736,6 +706,8 @@ SettingsSlider { labelFg: color; labelFgActive: color; duration: int; + rippleBottomSkip: pixels; + ripple: RippleAnimation; } defaultSettingsSlider: SettingsSlider { @@ -761,6 +733,10 @@ defaultTabsSlider: SettingsSlider(defaultSettingsSlider) { labelFont: semiboldFont; labelFg: #999999; labelFgActive: lightButtonFg; + rippleBottomSkip: 1px; + ripple: RippleAnimation(defaultRippleAnimation) { + color: windowBgOver; + } } defaultRoundShadow: Shadow {