Some more ripple animations.

This commit is contained in:
John Preston 2016-12-02 22:16:35 +03:00
parent 8958ae0377
commit 2796c53542
50 changed files with 518 additions and 537 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 B

After

Width:  |  Height:  |  Size: 106 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 155 B

After

Width:  |  Height:  |  Size: 130 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 B

View file

@ -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_image" = "Do you want to send this image?";
"lng_really_send_file" = "Do you want to send this file?"; "lng_really_send_file" = "Do you want to send this file?";
"lng_really_share_contact" = "Do you want to share this contact?"; "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_non_local" = "Could not send a non local file: {name}";
"lng_send_image_empty" = "Could not send an empty 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}"; "lng_send_image_too_large" = "Could not send a file, because it is larger than 1500 MB: {name}";

View file

@ -426,9 +426,9 @@ void GroupInfoBox::onPhotoReady(const QImage &img) {
SetupChannelBox::SetupChannelBox(ChannelData *channel, bool existing) : AbstractBox() SetupChannelBox::SetupChannelBox(ChannelData *channel, bool existing) : AbstractBox()
, _channel(channel) , _channel(channel)
, _existing(existing) , _existing(existing)
, _public(this, qsl("channel_privacy"), 0, lang(channel->isMegagroup() ? lng_create_public_group_title : lng_create_public_channel_title), true) , _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)) , _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::defaultRadiobutton.textPosition.x()) , _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) , _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) , _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) , _link(this, st::defaultInputField, QString(), channel->username, true)
@ -467,9 +467,9 @@ void SetupChannelBox::doSetInnerFocus() {
void SetupChannelBox::updateMaxHeight() { void SetupChannelBox::updateMaxHeight() {
if (!_channel->isMegagroup() || _public->checked()) { 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 { } 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.fillRect(e->rect(), st::boxBg);
p.setPen(st::newGroupAboutFg); 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()); _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()); _aboutPrivate.drawLeft(p, aboutPrivate.x(), aboutPrivate.y(), aboutPrivate.width(), width());
if (!_channel->isMegagroup() || !_link->isHidden()) { if (!_channel->isMegagroup() || !_link->isHidden()) {
@ -536,10 +536,10 @@ void SetupChannelBox::paintEvent(QPaintEvent *e) {
void SetupChannelBox::resizeEvent(QResizeEvent *e) { void SetupChannelBox::resizeEvent(QResizeEvent *e) {
_public->moveToLeft(st::boxPadding.left() + st::newGroupPadding.left(), st::boxPadding.top() + st::newGroupPadding.top()); _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->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); _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()); _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(); int32 h = titleHeight() + st::newGroupInfoPadding.top() + _title->height();
h += st::newGroupDescriptionPadding.top() + _description->height() + st::newGroupDescriptionPadding.bottom(); h += st::newGroupDescriptionPadding.top() + _description->height() + st::newGroupDescriptionPadding.bottom();
if (!_channel->isMegagroup()) { if (!_channel->isMegagroup()) {
h += st::newGroupPublicLinkPadding.top() + _sign->height() + st::newGroupPublicLinkPadding.bottom(); h += st::newGroupPublicLinkPadding.top() + _sign->heightNoMargins() + st::newGroupPublicLinkPadding.bottom();
} }
if (_channel->canEditUsername()) { if (_channel->canEditUsername()) {
h += st::newGroupPublicLinkPadding.top() + _publicLink->height() + st::newGroupPublicLinkPadding.bottom(); h += st::newGroupPublicLinkPadding.top() + _publicLink->height() + st::newGroupPublicLinkPadding.bottom();
@ -1026,7 +1026,7 @@ void EditChannelBox::resizeEvent(QResizeEvent *e) {
if (_channel->isMegagroup()) { if (_channel->isMegagroup()) {
_publicLink->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _description->y() + _description->height() + st::newGroupDescriptionPadding.bottom() + st::newGroupPublicLinkPadding.top()); _publicLink->moveToLeft(st::boxPadding.left() + st::newGroupInfoPadding.left(), _description->y() + _description->height() + st::newGroupDescriptionPadding.bottom() + st::newGroupPublicLinkPadding.top());
} else { } 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()); _save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height());

View file

@ -170,7 +170,8 @@ private:
ChannelData *_channel; ChannelData *_channel;
bool _existing; bool _existing;
ChildWidget<Ui::Radiobutton> _public, _private; ChildWidget<Ui::Radiobutton> _public;
ChildWidget<Ui::Radiobutton> _private;
int32 _aboutPublicWidth, _aboutPublicHeight; int32 _aboutPublicWidth, _aboutPublicHeight;
Text _aboutPublic, _aboutPrivate; Text _aboutPublic, _aboutPrivate;

View file

@ -45,7 +45,7 @@ AutoLockBox::AutoLockBox() : _close(this, lang(lng_box_ok), st::defaultBoxButton
int32 v = opts[i]; 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.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); _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())); connect(_options.back(), SIGNAL(changed()), this, SLOT(onChange()));
} }

View file

@ -233,17 +233,12 @@ contactsNameFont: semiboldFont;
contactsStatusTop: 23px; contactsStatusTop: 23px;
contactsStatusFont: font(fsize); contactsStatusFont: font(fsize);
contactsCheckPosition: point(8px, 16px); contactsCheckPosition: point(8px, 16px);
contactsAllAdminsTop: 18px; contactsAllAdminsTop: 15px;
contactsAboutBg: #f7f7f7; contactsAboutBg: windowBgOver;
contactsAboutFg: windowSubTextFgOver;
contactsAboutShadow: #0000001F; contactsAboutShadow: #0000001F;
contactsAdminCheckbox: Checkbox(defaultBoxCheckbox) { contactsAboutTop: 60px;
font: semiboldFont; contactsAboutBottom: 19px;
textBg: #f7f7f7;
textPosition: point(34px, 1px);
}
contactsAboutSkip: 53px;
contactsAboutHeight: 42px;
contactsAboutTop: 9px;
contactsScroll: FlatScroll(boxScroll) { contactsScroll: FlatScroll(boxScroll) {
deltab: 0px; deltab: 0px;
} }
@ -489,7 +484,7 @@ connectionPasswordInputField: InputField(defaultInputField) {
connectionIPv6Skip: 11px; connectionIPv6Skip: 11px;
langsWidth: 256px; langsWidth: 256px;
langsButton: Radiobutton(defaultRadiobutton) { langsButton: Checkbox(defaultBoxCheckbox) {
width: 200px; width: 200px;
} }

View file

@ -380,7 +380,7 @@ PinMessageBox::PinMessageBox(ChannelData *channel, MsgId msgId) : AbstractBox(st
, _pin(this, lang(lng_pinned_pin), st::defaultBoxButton) , _pin(this, lang(lng_pinned_pin), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) { , _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
_text->resizeToWidth(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()); _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(_pin, SIGNAL(clicked()), this, SLOT(onPin()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
@ -430,7 +430,7 @@ RichDeleteMessageBox::RichDeleteMessageBox(ChannelData *channel, UserData *from,
t_assert(_channel != nullptr); t_assert(_channel != nullptr);
_text->resizeToWidth(st::boxWidth - st::boxPadding.left() - st::boxButtonPadding.right()); _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(_delete, SIGNAL(clicked()), this, SLOT(onDelete()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
@ -438,9 +438,9 @@ RichDeleteMessageBox::RichDeleteMessageBox(ChannelData *channel, UserData *from,
void RichDeleteMessageBox::resizeEvent(QResizeEvent *e) { void RichDeleteMessageBox::resizeEvent(QResizeEvent *e) {
_text->moveToLeft(st::boxPadding.left(), st::boxPadding.top()); _text->moveToLeft(st::boxPadding.left(), st::boxPadding.top());
_banUser->moveToLeft(st::boxPadding.left(), _text->y() + _text->height() + st::boxMediumSkip); _banUser->moveToLeft(st::boxPadding.left(), _text->bottomNoMargins() + st::boxMediumSkip);
_reportSpam->moveToLeft(st::boxPadding.left(), _banUser->y() + _banUser->height() + st::boxLittleSkip); _reportSpam->moveToLeft(st::boxPadding.left(), _banUser->bottomNoMargins() + st::boxLittleSkip);
_deleteAll->moveToLeft(st::boxPadding.left(), _reportSpam->y() + _reportSpam->height() + st::boxLittleSkip); _deleteAll->moveToLeft(st::boxPadding.left(), _reportSpam->bottomNoMargins() + st::boxLittleSkip);
_delete->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _delete->height()); _delete->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _delete->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _delete->width() + st::boxButtonPadding.left(), _delete->y()); _cancel->moveToRight(st::boxButtonPadding.right() + _delete->width() + st::boxButtonPadding.left(), _delete->y());
AbstractBox::resizeEvent(e); AbstractBox::resizeEvent(e);

View file

@ -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)) , _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) , _userInput(this, st::connectionUserInputField, lang(lng_connection_user_ph), Global::ConnectionProxy().user)
, _passwordInput(this, st::connectionPasswordInputField, lang(lng_connection_password_ph), Global::ConnectionProxy().password) , _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)) , _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)) , _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)) , _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) , _tryIPv6(this, lang(lng_connection_try_ipv6), Global::TryIPv6(), st::defaultBoxCheckbox)
, _save(this, lang(lng_connection_save), st::defaultBoxButton) , _save(this, lang(lng_connection_save), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) { , _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
@ -59,7 +59,7 @@ ConnectionBox::ConnectionBox() : AbstractBox(st::boxWidth, lang(lng_connection_h
} }
void ConnectionBox::updateControlsVisibility() { 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()) { if (_httpProxyRadio->checked() || _tcpProxyRadio->checked()) {
h += 2 * st::boxOptionListPadding.top() + 2 * _hostInput->height(); h += 2 * st::boxOptionListPadding.top() + 2 * _hostInput->height();
_hostInput->show(); _hostInput->show();
@ -85,27 +85,27 @@ void ConnectionBox::doSetInnerFocus() {
void ConnectionBox::resizeEvent(QResizeEvent *e) { void ConnectionBox::resizeEvent(QResizeEvent *e) {
_autoRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), titleHeight() + st::boxOptionListPadding.top()); _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; int32 inputy = 0;
if (_httpProxyRadio->checked()) { 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()); _tcpProxyRadio->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), inputy + st::boxOptionListPadding.top() + 2 * _hostInput->height() + st::boxOptionListPadding.top());
} else { } 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()) { if (_tcpProxyRadio->checked()) {
inputy = _tcpProxyRadio->y() + _tcpProxyRadio->height() + st::boxOptionListPadding.top(); inputy = _tcpProxyRadio->bottomNoMargins() + st::boxOptionListPadding.top();
} }
} }
if (inputy) { 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); _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()); _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); _tryIPv6->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), tryipv6y);
_save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height()); _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) , _save(this, lang(lng_connection_save), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) { , _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(_save, SIGNAL(clicked()), this, SLOT(onSave()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose())); connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
@ -232,14 +232,14 @@ void AutoDownloadBox::paintEvent(QPaintEvent *e) {
void AutoDownloadBox::resizeEvent(QResizeEvent *e) { void AutoDownloadBox::resizeEvent(QResizeEvent *e) {
_photoPrivate->moveToLeft(st::boxTitlePosition.x(), titleHeight() + st::setLittleSkip); _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); _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); _gifPrivate->moveToLeft(st::boxTitlePosition.x(), 2 * _sectionHeight + titleHeight() + st::setLittleSkip);
_gifGroups->moveToLeft(st::boxTitlePosition.x(), _gifPrivate->y() + _gifPrivate->height() + st::setLittleSkip); _gifGroups->moveToLeft(st::boxTitlePosition.x(), _gifPrivate->bottomNoMargins() + st::setLittleSkip);
_gifPlay->moveToLeft(st::boxTitlePosition.x(), _gifGroups->y() + _gifGroups->height() + st::setLittleSkip); _gifPlay->moveToLeft(st::boxTitlePosition.x(), _gifGroups->bottomNoMargins() + st::setLittleSkip);
_save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height()); _save->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _save->height());
_cancel->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y()); _cancel->moveToRight(st::boxButtonPadding.right() + _save->width() + st::boxButtonPadding.left(), _save->y());

View file

@ -25,6 +25,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "styles/style_dialogs.h" #include "styles/style_dialogs.h"
#include "styles/style_history.h" #include "styles/style_history.h"
#include "styles/style_profile.h"
#include "lang.h" #include "lang.h"
#include "boxes/addcontactbox.h" #include "boxes/addcontactbox.h"
#include "mainwidget.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) ContactsBox::Inner::Inner(QWidget *parent, CreatingGroupType creating) : TWidget(parent)
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) , _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
, _creating(creating) , _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()) , _contacts(App::main()->contactsList())
, _addContactLnk(this, lang(lng_add_contact_button)) { , _addContactLnk(this, lang(lng_add_contact_button)) {
init(); init();
@ -564,7 +565,7 @@ ContactsBox::Inner::Inner(QWidget *parent, ChannelData *channel, MembersFilter m
, _membersFilter(membersFilter) , _membersFilter(membersFilter)
, _creating(CreatingGroupChannel) , _creating(CreatingGroupChannel)
, _already(already) , _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()) , _contacts(App::main()->contactsList())
, _addContactLnk(this, lang(lng_add_contact_button)) { , _addContactLnk(this, lang(lng_add_contact_button)) {
init(); init();
@ -580,16 +581,16 @@ ContactsBox::Inner::Inner(QWidget *parent, ChatData *chat, MembersFilter members
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) , _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
, _chat(chat) , _chat(chat)
, _membersFilter(membersFilter) , _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()) , _aboutWidth(st::boxWideWidth - st::contactsPadding.left() - st::contactsPadding.right())
, _aboutAllAdmins(st::boxTextFont, lang(lng_chat_about_all_admins), _defaultOptions, _aboutWidth) , _aboutAllAdmins(st::normalFont, lang(lng_chat_about_all_admins), _defaultOptions, _aboutWidth)
, _aboutAdmins(st::boxTextFont, lang(lng_chat_about_admins), _defaultOptions, _aboutWidth) , _aboutAdmins(st::normalFont, lang(lng_chat_about_admins), _defaultOptions, _aboutWidth)
, _customList((membersFilter == MembersFilter::Recent) ? std_::unique_ptr<Dialogs::IndexedList>() : std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Add)) , _customList((membersFilter == MembersFilter::Recent) ? std_::unique_ptr<Dialogs::IndexedList>() : std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Add))
, _contacts((membersFilter == MembersFilter::Recent) ? App::main()->contactsList() : _customList.get()) , _contacts((membersFilter == MembersFilter::Recent) ? App::main()->contactsList() : _customList.get())
, _addContactLnk(this, lang(lng_add_contact_button)) { , _addContactLnk(this, lang(lng_add_contact_button)) {
initList(); initList();
if (membersFilter == MembersFilter::Admins) { 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()) { if (_contacts->isEmpty()) {
App::api()->requestFullPeer(_chat); App::api()->requestFullPeer(_chat);
} }
@ -611,7 +612,7 @@ void ContactsBox::Inner::addDialogsToList(FilterCallback callback) {
ContactsBox::Inner::Inner(QWidget *parent, UserData *bot) : TWidget(parent) ContactsBox::Inner::Inner(QWidget *parent, UserData *bot) : TWidget(parent)
, _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom()) , _rowHeight(st::contactsPadding.top() + st::contactsPhotoSize + st::contactsPadding.bottom())
, _bot(bot) , _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::IndexedList>(Dialogs::SortMode::Add)) , _customList(std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Add))
, _contacts(_customList.get()) , _contacts(_customList.get())
, _addContactLnk(this, lang(lng_add_contact_button)) { , _addContactLnk(this, lang(lng_add_contact_button)) {
@ -667,7 +668,7 @@ void ContactsBox::Inner::initList() {
others.reserve(_chat->participants.size()); 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 (i.key()->id == peerFromUser(_chat->creator)) continue;
if (!_allAdmins->checked() && _chat->admins.contains(i.key())) { if (!_allAdmins->checked() && _chat->admins.contains(i.key())) {
admins.push_back(i.key()); admins.push_back(i.key());
@ -680,16 +681,16 @@ void ContactsBox::Inner::initList() {
} }
std::sort(admins.begin(), admins.end(), _sortByName); std::sort(admins.begin(), admins.end(), _sortByName);
std::sort(others.begin(), others.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)) { if (_chat->participants.contains(creator)) {
admins.push_front(creator); admins.push_front(creator);
} }
} }
for (int32 i = 0, l = admins.size(); i < l; ++i) { for_const (auto user, admins) {
_contacts->addToEnd(App::history(admins.at(i)->id)); _contacts->addToEnd(App::history(user->id));
} }
for (int32 i = 0, l = others.size(); i < l; ++i) { for_const (auto user, others) {
_contacts->addToEnd(App::history(others.at(i)->id)); _contacts->addToEnd(App::history(user->id));
} }
} }
@ -1039,12 +1040,18 @@ void ContactsBox::Inner::paintEvent(QPaintEvent *e) {
if (_filter.isEmpty()) { if (_filter.isEmpty()) {
if (!_contacts->isEmpty() || !_byUsername.isEmpty()) { if (!_contacts->isEmpty() || !_byUsername.isEmpty()) {
if (_aboutHeight) { if (_aboutHeight) {
p.fillRect(0, 0, width(), _aboutHeight - st::contactsPadding.bottom() - st::lineWidth, st::contactsAboutBg); auto infoTop = _allAdmins->bottomNoMargins() + st::contactsAllAdminsTop - st::lineWidth;
p.fillRect(0, _aboutHeight - st::contactsPadding.bottom() - st::lineWidth, width(), st::lineWidth, st::shadowColor);
p.setPen(st::boxTextFg); auto infoRect = rtlrect(0, infoTop, width(), _aboutHeight - infoTop - st::contactsPadding.bottom(), width());
p.drawTextLeft(st::contactsPadding.left(), st::contactsAllAdminsTop, width(), lang(lng_chat_all_members_admins)); 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(); 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; yFrom -= _aboutHeight;
yTo -= _aboutHeight; yTo -= _aboutHeight;
@ -1090,10 +1097,9 @@ void ContactsBox::Inner::paintEvent(QPaintEvent *e) {
text = lang(lng_contacts_loading); text = lang(lng_contacts_loading);
p.fillRect(0, 0, width(), _aboutHeight - st::contactsPadding.bottom() - st::lineWidth, st::contactsAboutBg); 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.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(); 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); p.translate(0, _aboutHeight);
} else if (cContactsReceived() && !_searching) { } else if (cContactsReceived() && !_searching) {
text = lang(lng_no_contacts); text = lang(lng_no_contacts);

View file

@ -32,9 +32,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
DownloadPathBox::DownloadPathBox() : AbstractBox() DownloadPathBox::DownloadPathBox() : AbstractBox()
, _path(Global::DownloadPath()) , _path(Global::DownloadPath())
, _pathBookmark(Global::DownloadPathBookmark()) , _pathBookmark(Global::DownloadPathBookmark())
, _default(this, qsl("dir_type"), 0, lang(lng_download_path_default_radio), _path.isEmpty()) , _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")) , _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")) , _dir(this, qsl("dir_type"), 2, lang(lng_download_path_dir_radio), (!_path.isEmpty() && _path != qsl("tmp")), st::defaultBoxCheckbox)
, _pathLink(this, QString(), st::boxLinkButton) , _pathLink(this, QString(), st::boxLinkButton)
, _save(this, lang(lng_connection_save), st::defaultBoxButton) , _save(this, lang(lng_connection_save), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) { , _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
@ -57,7 +57,7 @@ DownloadPathBox::DownloadPathBox() : AbstractBox()
void DownloadPathBox::updateControlsVisibility() { void DownloadPathBox::updateControlsVisibility() {
_pathLink->setVisible(_dir->checked()); _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(); if (_dir->checked()) h += st::downloadPathSkip + _pathLink->height();
h += st::boxOptionListPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom(); h += st::boxOptionListPadding.bottom() + st::boxButtonPadding.top() + _save->height() + st::boxButtonPadding.bottom();
@ -66,10 +66,10 @@ void DownloadPathBox::updateControlsVisibility() {
void DownloadPathBox::resizeEvent(QResizeEvent *e) { void DownloadPathBox::resizeEvent(QResizeEvent *e) {
_default->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), titleHeight() + st::boxOptionListPadding.top()); _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()); _temp->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _default->bottomNoMargins() + st::boxOptionListPadding.top());
_dir->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _temp->y() + _temp->height() + 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::defaultRadiobutton.textPosition.x(); int32 inputx = st::boxPadding.left() + st::boxOptionListPadding.left() + st::defaultBoxCheckbox.textPosition.x();
int32 inputy = _dir->y() + _dir->height() + st::downloadPathSkip; int32 inputy = _dir->bottomNoMargins() + st::downloadPathSkip;
_pathLink->moveToLeft(inputx, inputy); _pathLink->moveToLeft(inputx, inputy);
@ -123,6 +123,6 @@ void DownloadPathBox::onSave() {
} }
void DownloadPathBox::setPathText(const QString &text) { 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)); _pathLink->setText(st::boxTextFont->elided(text, availw));
} }

View file

@ -42,7 +42,7 @@ _close(this, lang(lng_box_ok), st::defaultBoxButton) {
if (haveTestLang) { if (haveTestLang) {
_langs.push_back(new Ui::Radiobutton(this, qsl("lang"), languageTest, qsl("Custom Lang"), (cLang() == languageTest), st::langsButton)); _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); _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())); connect(_langs.back(), SIGNAL(changed()), this, SLOT(onChange()));
} }
for (int32 i = 0; i < languageCount; ++i) { 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.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); _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())); connect(_langs.back(), SIGNAL(changed()), this, SLOT(onChange()));
} }

View file

@ -32,10 +32,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
ReportBox::ReportBox(ChannelData *channel) : AbstractBox(st::boxWidth) ReportBox::ReportBox(ChannelData *channel) : AbstractBox(st::boxWidth)
, _channel(channel) , _channel(channel)
, _reasonSpam(this, qsl("report_reason"), ReasonSpam, lang(lng_report_reason_spam), true) , _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)) , _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)) , _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)) , _reasonOther(this, qsl("report_reason"), ReasonOther, lang(lng_report_reason_other), false, st::defaultBoxCheckbox)
, _report(this, lang(lng_report_button), st::defaultBoxButton) , _report(this, lang(lng_report_button), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton) { , _cancel(this, lang(lng_cancel), st::cancelBoxButton) {
setTitleText(lang(_channel->isMegagroup() ? lng_report_group_title : lng_report_title)); 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) { void ReportBox::resizeEvent(QResizeEvent *e) {
_reasonSpam->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), titleHeight() + st::boxOptionListPadding.top()); _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()); _reasonViolence->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonSpam->bottomNoMargins() + st::boxOptionListPadding.top());
_reasonPornography->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonViolence->y() + _reasonViolence->height() + 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->y() + _reasonPornography->height() + st::boxOptionListPadding.top()); _reasonOther->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), _reasonPornography->bottomNoMargins() + st::boxOptionListPadding.top());
if (_reasonOtherText) { 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()); _report->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _report->height());
@ -138,7 +138,7 @@ bool ReportBox::reportFail(const RPCError &error) {
} }
void ReportBox::updateMaxHeight() { 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) { if (_reasonOtherText) {
h += st::newGroupDescriptionPadding.top() + _reasonOtherText->height() + st::newGroupDescriptionPadding.bottom(); h += st::newGroupDescriptionPadding.top() + _reasonOtherText->height() + st::newGroupDescriptionPadding.bottom();
} }

View file

@ -204,7 +204,7 @@ void SendFilesBox::updateBoxSize() {
newHeight += st::boxPhotoPadding.top() + st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom(); newHeight += st::boxPhotoPadding.top() + st::msgFilePadding.top() + st::msgFileSize + st::msgFilePadding.bottom();
} }
if (_compressed) { if (_compressed) {
newHeight += st::boxPhotoCompressedSkip + _compressed->height(); newHeight += st::boxPhotoCompressedSkip + _compressed->heightNoMargins();
} }
if (_caption) { if (_caption) {
newHeight += st::boxPhotoCaptionSkip + _caption->height(); newHeight += st::boxPhotoCaptionSkip + _caption->height();
@ -318,8 +318,8 @@ void SendFilesBox::updateControlsGeometry() {
bottom -= st::boxPhotoCaptionSkip + _caption->height(); bottom -= st::boxPhotoCaptionSkip + _caption->height();
} }
if (_compressed) { if (_compressed) {
_compressed->moveToLeft(st::boxPhotoPadding.left(), bottom - _compressed->height()); _compressed->moveToLeft(st::boxPhotoPadding.left(), bottom - _compressed->heightNoMargins());
bottom -= st::boxPhotoCompressedSkip + _compressed->height(); bottom -= st::boxPhotoCompressedSkip + _compressed->heightNoMargins();
} }
} }

View file

@ -217,7 +217,6 @@ void StickersBox::setup() {
preloadArchivedSets(); preloadArchivedSets();
} }
if (_tabs) { if (_tabs) {
_tabs->setSelectOnPress(false);
_tabs->setSectionActivatedCallback([this] { _tabs->setSectionActivatedCallback([this] {
switchTab(); switchTab();
}); });

View file

@ -38,6 +38,10 @@ Q_DECLARE_METATYPE(Ui::ShowWay);
namespace App { namespace App {
void LambdaDelayed(int duration, base::lambda<void()> &&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) { void sendBotCommand(PeerData *peer, UserData *bot, const QString &cmd, MsgId replyTo) {
if (auto m = main()) { if (auto m = main()) {
m->sendBotCommand(peer, bot, cmd, replyTo); m->sendBotCommand(peer, bot, cmd, replyTo);

View file

@ -33,6 +33,8 @@ class ItemBase;
namespace App { namespace App {
void LambdaDelayed(int duration, base::lambda<void()> &&lambda);
void sendBotCommand(PeerData *peer, UserData *bot, const QString &cmd, MsgId replyTo = 0); void sendBotCommand(PeerData *peer, UserData *bot, const QString &cmd, MsgId replyTo = 0);
bool insertBotCommand(const QString &cmd, bool specialGif = false); bool insertBotCommand(const QString &cmd, bool specialGif = false);
void activateBotCommand(const HistoryItem *msg, int row, int col); void activateBotCommand(const HistoryItem *msg, int row, int col);

View file

@ -3101,7 +3101,11 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
connect(audioCapture(), SIGNAL(done(QByteArray,VoiceWaveform,qint32)), this, SLOT(onRecordDone(QByteArray,VoiceWaveform,qint32))); 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) { subscribe(FileDialog::QueryDone(), [this](const FileDialog::QueryUpdate &update) {
notifyFileQueryUpdated(update); notifyFileQueryUpdated(update);
}); });

View file

@ -362,7 +362,7 @@ void FileLoadTask::process() {
{ {
QBuffer buffer(&filedata); QBuffer buffer(&filedata);
full.save(&buffer, "JPG", 77); full.save(&buffer, "JPG", 87);
} }
MTPDphoto::Flags photoFlags = 0; MTPDphoto::Flags photoFlags = 0;

View file

@ -72,9 +72,11 @@ profileDropAreaBorderFg: profileDropAreaFg;
profileDropAreaBorderWidth: 3px; profileDropAreaBorderWidth: 3px;
profileDropAreaDuration: 200; profileDropAreaDuration: 200;
profileDividerBg: windowBgOver;
profileDividerFg: windowShadowFg; profileDividerFg: windowShadowFg;
profileDividerLeft: icon {{ "profile_divider_left", profileDividerFg }}; 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; profileBlocksTop: 7px;
profileBlocksBottom: 20px; profileBlocksBottom: 20px;

View file

@ -139,7 +139,7 @@ int CoverWidget::resizeGetHeight(int newWidth) {
newHeight += st::profileMarginBottom; newHeight += st::profileMarginBottom;
_dividerTop = newHeight; _dividerTop = newHeight;
newHeight += st::profileDividerFill.height(); newHeight += st::profileDividerLeft.height();
newHeight += st::profileBlocksTop; newHeight += st::profileBlocksTop;
@ -319,12 +319,18 @@ void CoverWidget::dropEvent(QDropEvent *e) {
} }
void CoverWidget::paintDivider(Painter &p) { void CoverWidget::paintDivider(Painter &p) {
auto dividerLeft = (Adaptive::OneColumn() ? 0 : st::lineWidth); auto dividerHeight = st::profileDividerLeft.height();
st::profileDividerLeft.paint(p, QPoint(dividerLeft, _dividerTop), width()); auto dividerLeft = Adaptive::OneColumn() ? 0 : st::lineWidth;
auto divider = rtlrect(dividerLeft, _dividerTop, width() - dividerLeft, dividerHeight, width());
int toFillLeft = dividerLeft + st::profileDividerLeft.width(); p.fillRect(divider, st::profileDividerBg);
QRect toFill = rtlrect(toFillLeft, _dividerTop, width() - toFillLeft, st::profileDividerFill.height(), width()); if (!Adaptive::OneColumn()) {
st::profileDividerFill.fill(p, toFill); 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) { void CoverWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) {

View file

@ -83,7 +83,7 @@ int SettingsWidget::resizeGetHeight(int newWidth) {
int newHeight = contentTop() + st::profileEnableNotificationsTop; int newHeight = contentTop() + st::profileEnableNotificationsTop;
_enableNotifications->moveToLeft(st::profileBlockTitlePosition.x(), newHeight); _enableNotifications->moveToLeft(st::profileBlockTitlePosition.x(), newHeight);
newHeight += _enableNotifications->height() + st::profileSettingsBlockSkip; newHeight += _enableNotifications->heightNoMargins() + st::profileSettingsBlockSkip;
auto moveLink = [&newHeight, newWidth](Ui::LeftOutlineButton *button) { auto moveLink = [&newHeight, newWidth](Ui::LeftOutlineButton *button) {
if (!button) return; if (!button) return;

View file

@ -44,14 +44,15 @@ int BlockWidget::resizeGetHeight(int newWidth) {
int x = contentLeft(), result = contentTop(); int x = contentLeft(), result = contentTop();
int availw = newWidth - x; int availw = newWidth - x;
for_const (auto &row, _rows) { for_const (auto &row, _rows) {
auto childMargins = row.child->getMargins();
row.child->moveToLeft(x + row.margin.left(), result + row.margin.top(), newWidth); row.child->moveToLeft(x + row.margin.left(), result + row.margin.top(), newWidth);
auto availRowWidth = availw - row.margin.left() - row.margin.right() - x; auto availRowWidth = availw - row.margin.left() - row.margin.right() - x;
auto natural = row.child->naturalWidth(); auto natural = row.child->naturalWidth();
auto rowWidth = (natural < 0) ? availRowWidth : qMin(natural, availRowWidth); auto rowWidth = (natural < 0) ? availRowWidth : qMin(natural, availRowWidth);
if (row.child->width() != rowWidth) { if (row.child->widthNoMargins() != rowWidth) {
row.child->resizeToWidth(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; result += st::settingsBlockMarginBottom;
return result; return result;
@ -91,7 +92,7 @@ void BlockWidget::createChildRow(ChildWidget<Ui::Checkbox> &child, style::margin
} }
void BlockWidget::createChildRow(ChildWidget<Ui::Radiobutton> &child, style::margins &margin, const QString &group, int value, const QString &text, const char *slot, bool checked) { void BlockWidget::createChildRow(ChildWidget<Ui::Radiobutton> &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); connect(child, SIGNAL(changed()), this, slot);
} }

View file

@ -121,7 +121,7 @@ int CoverWidget::resizeGetHeight(int newWidth) {
newHeight += st::settingsMarginBottom; newHeight += st::settingsMarginBottom;
_dividerTop = newHeight; _dividerTop = newHeight;
newHeight += st::profileDividerFill.height(); newHeight += st::profileDividerLeft.height();
newHeight += st::settingsBlocksTop; newHeight += st::settingsBlocksTop;
@ -247,11 +247,13 @@ void CoverWidget::dropEvent(QDropEvent *e) {
} }
void CoverWidget::paintDivider(Painter &p) { void CoverWidget::paintDivider(Painter &p) {
st::profileDividerLeft.paint(p, QPoint(0, _dividerTop), width()); auto dividerHeight = st::profileDividerLeft.height();
auto divider = rtlrect(0, _dividerTop, width(), dividerHeight, width());
int toFillLeft = st::profileDividerLeft.width(); p.fillRect(divider, st::profileDividerBg);
QRect toFill = rtlrect(toFillLeft, _dividerTop, width() - toFillLeft, st::profileDividerFill.height(), width()); auto dividerFillTop = rtlrect(0, _dividerTop, width(), st::profileDividerTop.height(), width());
st::profileDividerFill.fill(p, toFill); 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) { void CoverWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) {

View file

@ -21,6 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "stdafx.h" #include "stdafx.h"
#include "settings/settings_scale_widget.h" #include "settings/settings_scale_widget.h"
#include "styles/style_boxes.h"
#include "styles/style_settings.h" #include "styles/style_settings.h"
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
#include "lang.h" #include "lang.h"
@ -126,7 +127,9 @@ void ScaleWidget::onRestartNow() {
} }
void ScaleWidget::onCancel() { void ScaleWidget::onCancel() {
setScale(cRealScale()); App::LambdaDelayed(st::boxDuration, base::lambda_guarded(this, [this] {
setScale(cRealScale());
}));
} }
} // namespace Settings } // namespace Settings

View file

@ -27,13 +27,12 @@ void AbstractButton::leaveEvent(QEvent *e) {
if (_state & StateDown) return; if (_state & StateDown) return;
setOver(false, StateChangeSource::ByHover); setOver(false, StateChangeSource::ByHover);
setMouseTracking(false);
return TWidget::leaveEvent(e); return TWidget::leaveEvent(e);
} }
void AbstractButton::enterEvent(QEvent *e) { void AbstractButton::enterEvent(QEvent *e) {
setOver(true, StateChangeSource::ByHover); auto over = rect().marginsRemoved(getMargins()).contains(mapFromGlobal(QCursor::pos()));
setMouseTracking(true); setOver(over, StateChangeSource::ByHover);
return TWidget::enterEvent(e); return TWidget::enterEvent(e);
} }
@ -42,11 +41,8 @@ void AbstractButton::setAcceptBoth(bool acceptBoth) {
} }
void AbstractButton::mousePressEvent(QMouseEvent *e) { void AbstractButton::mousePressEvent(QMouseEvent *e) {
if (_acceptBoth || e->buttons() & Qt::LeftButton) { if (_acceptBoth || (e->buttons() & Qt::LeftButton)) {
if (!(_state & StateOver)) { if ((_state & StateOver) && !(_state & StateDown)) {
enterEvent(0);
}
if (!(_state & StateDown)) {
int oldState = _state; int oldState = _state;
_state |= StateDown; _state |= StateDown;
onStateChanged(oldState, StateChangeSource::ByPress); onStateChanged(oldState, StateChangeSource::ByPress);
@ -57,7 +53,7 @@ void AbstractButton::mousePressEvent(QMouseEvent *e) {
} }
void AbstractButton::mouseMoveEvent(QMouseEvent *e) { void AbstractButton::mouseMoveEvent(QMouseEvent *e) {
if (rect().contains(e->pos())) { if (rect().marginsRemoved(getMargins()).contains(e->pos())) {
setOver(true, StateChangeSource::ByHover); setOver(true, StateChangeSource::ByHover);
} else { } else {
setOver(false, StateChangeSource::ByHover); setOver(false, StateChangeSource::ByHover);
@ -83,6 +79,7 @@ void AbstractButton::mouseReleaseEvent(QMouseEvent *e) {
} }
void AbstractButton::setOver(bool over, StateChangeSource source) { void AbstractButton::setOver(bool over, StateChangeSource source) {
setCursor(over ? style::cur_pointer : style::cur_default);
if (over && !(_state & StateOver)) { if (over && !(_state & StateOver)) {
int oldState = _state; int oldState = _state;
_state |= StateOver; _state |= StateOver;

View file

@ -35,7 +35,7 @@ public:
}; };
AbstractButton(QWidget *parent) : TWidget(parent) { AbstractButton(QWidget *parent) : TWidget(parent) {
setCursor(style::cur_pointer); setMouseTracking(true);
} }
enum { enum {

View file

@ -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, QPoint origin, int startRadius, const QPixmap &mask, const UpdateCallback &update);
Ripple(const style::RippleAnimation &st, 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 stop();
void unstop(); void unstop();
@ -86,7 +86,7 @@ RippleAnimation::Ripple::Ripple(const style::RippleAnimation &st, const QPixmap
_hide.start(UpdateCallback(_update), 0., 1., _st.hideDuration); _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.); auto opacity = _hide.current(ms, _hiding ? 0. : 1.);
if (opacity == 0.) { if (opacity == 0.) {
return; return;
@ -99,7 +99,11 @@ void RippleAnimation::Ripple::paint(QPainter &p, const QPixmap &mask, TimeMs ms)
Painter p(&_frame); Painter p(&_frame);
p.setRenderHint(QPainter::HighQualityAntialiasing); p.setRenderHint(QPainter::HighQualityAntialiasing);
p.setPen(Qt::NoPen); p.setPen(Qt::NoPen);
p.setBrush(_st.color); if (colorOverride) {
p.setBrush(*colorOverride);
} else {
p.setBrush(_st.color);
}
p.drawEllipse(_origin, radius, radius); p.drawEllipse(_origin, radius, radius);
p.setCompositionMode(QPainter::CompositionMode_DestinationIn); 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()) { if (_ripples.isEmpty()) {
return; 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()); if (rtl()) x = outerWidth - x - (_mask.width() / cIntRetinaFactor());
p.translate(x, y); p.translate(x, y);
for (auto ripple : _ripples) { for (auto ripple : _ripples) {
ripple->paint(p, _mask, ms); ripple->paint(p, _mask, ms, colorOverride);
} }
p.translate(-x, -y); p.translate(-x, -y);
clearFinished(); clearFinished();

View file

@ -37,7 +37,7 @@ public:
void lastUnstop(); void lastUnstop();
void lastFinish(); 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 { bool empty() const {
return _ripples.isEmpty(); return _ripples.isEmpty();

View file

@ -98,6 +98,13 @@ public:
return _entity; return _entity;
} }
QMargins getMargins() const override {
return _entity->getMargins();
}
int naturalWidth() const override {
return _entity->naturalWidth();
}
protected: protected:
bool eventFilter(QObject *object, QEvent *event) override; bool eventFilter(QObject *object, QEvent *event) override;
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;

View file

@ -34,16 +34,17 @@ WidgetSlideWrap<TWidget>::WidgetSlideWrap(QWidget *parent
, _updateCallback(std_::move(updateCallback)) , _updateCallback(std_::move(updateCallback))
, _a_height(animation(this, &WidgetSlideWrap<TWidget>::step_height)) { , _a_height(animation(this, &WidgetSlideWrap<TWidget>::step_height)) {
_entity->setParent(this); _entity->setParent(this);
_entity->moveToLeft(_padding.left(), _padding.top()); auto margins = getMargins();
_realSize = _entity->rect().marginsAdded(_padding).size(); _entity->moveToLeft(margins.left() + _padding.left(), margins.top() + _padding.top());
_realSize = _entity->rectNoMargins().marginsAdded(_padding).size();
_entity->installEventFilter(this); _entity->installEventFilter(this);
resize(_realSize); resizeToWidth(_realSize.width());
} }
void WidgetSlideWrap<TWidget>::slideUp() { void WidgetSlideWrap<TWidget>::slideUp() {
if (isHidden()) { if (isHidden()) {
_forceHeight = 0; _forceHeight = 0;
resize(_realSize.width(), _forceHeight); resizeToWidth(_realSize.width());
if (_updateCallback) _updateCallback(); if (_updateCallback) _updateCallback();
return; return;
} }
@ -77,7 +78,8 @@ void WidgetSlideWrap<TWidget>::slideDown() {
void WidgetSlideWrap<TWidget>::showFast() { void WidgetSlideWrap<TWidget>::showFast() {
show(); show();
_a_height.stop(); _a_height.stop();
resize(_realSize); _forceHeight = -1;
resizeToWidth(_realSize.width());
if (_updateCallback) { if (_updateCallback) {
_updateCallback(); _updateCallback();
} }
@ -87,13 +89,21 @@ void WidgetSlideWrap<TWidget>::hideFast() {
_a_height.stop(); _a_height.stop();
a_height = anim::ivalue(0); a_height = anim::ivalue(0);
_forceHeight = 0; _forceHeight = 0;
resize(_realSize.width(), 0); resizeToWidth(_realSize.width());
hide(); hide();
if (_updateCallback) { if (_updateCallback) {
_updateCallback(); _updateCallback();
} }
} }
QMargins WidgetSlideWrap<TWidget>::getMargins() const {
auto entityMargins = _entity->getMargins();
if (_forceHeight < 0) {
return entityMargins;
}
return QMargins(entityMargins.left(), 0, entityMargins.right(), 0);
}
int WidgetSlideWrap<TWidget>::naturalWidth() const { int WidgetSlideWrap<TWidget>::naturalWidth() const {
auto inner = _entity->naturalWidth(); auto inner = _entity->naturalWidth();
return (inner < 0) ? inner : (_padding.left() + inner + _padding.right()); return (inner < 0) ? inner : (_padding.left() + inner + _padding.right());
@ -101,9 +111,9 @@ int WidgetSlideWrap<TWidget>::naturalWidth() const {
bool WidgetSlideWrap<TWidget>::eventFilter(QObject *object, QEvent *event) { bool WidgetSlideWrap<TWidget>::eventFilter(QObject *object, QEvent *event) {
if (object == _entity && event->type() == QEvent::Resize) { if (object == _entity && event->type() == QEvent::Resize) {
_realSize = _entity->rect().marginsAdded(_padding).size(); _realSize = _entity->rectNoMargins().marginsAdded(_padding).size();
if (!_inResizeToWidth) { if (!_inResizeToWidth) {
resize(_realSize.width(), (_forceHeight >= 0) ? _forceHeight : _realSize.height()); resizeToWidth(_realSize.width());
if (_updateCallback) { if (_updateCallback) {
_updateCallback(); _updateCallback();
} }
@ -114,9 +124,15 @@ bool WidgetSlideWrap<TWidget>::eventFilter(QObject *object, QEvent *event) {
int WidgetSlideWrap<TWidget>::resizeGetHeight(int newWidth) { int WidgetSlideWrap<TWidget>::resizeGetHeight(int newWidth) {
_inResizeToWidth = true; _inResizeToWidth = true;
auto resized = (_forceHeight >= 0);
_entity->resizeToWidth(newWidth - _padding.left() - _padding.right()); _entity->resizeToWidth(newWidth - _padding.left() - _padding.right());
auto margins = getMargins();
_entity->moveToLeft(margins.left() + _padding.left(), margins.top() + _padding.top());
_inResizeToWidth = false; _inResizeToWidth = false;
return (_forceHeight >= 0) ? _forceHeight : _realSize.height(); if (resized) {
return _forceHeight;
}
return _realSize.height();
} }
void WidgetSlideWrap<TWidget>::step_height(float64 ms, bool timer) { void WidgetSlideWrap<TWidget>::step_height(float64 ms, bool timer) {
@ -130,7 +146,7 @@ void WidgetSlideWrap<TWidget>::step_height(float64 ms, bool timer) {
a_height.update(dt, anim::linear); a_height.update(dt, anim::linear);
_forceHeight = a_height.current(); _forceHeight = a_height.current();
} }
resize(_realSize.width(), (_forceHeight >= 0) ? _forceHeight : _realSize.height()); resizeToWidth(_realSize.width());
if (_updateCallback) { if (_updateCallback) {
_updateCallback(); _updateCallback();
} }

View file

@ -48,6 +48,7 @@ public:
return _entity; return _entity;
} }
QMargins getMargins() const override;
int naturalWidth() const override; int naturalWidth() const override;
protected: protected:

View file

@ -90,15 +90,31 @@ public: \
virtual void enterFromChildEvent(QEvent *e, QWidget *child) { /* e -- from leaveEvent() of child TWidget */ \ virtual void enterFromChildEvent(QEvent *e, QWidget *child) { /* e -- from leaveEvent() of child TWidget */ \
} \ } \
void moveToLeft(int x, int y, int outerw = 0) { \ 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); \ move(rtl() ? ((outerw > 0 ? outerw : parentWidget()->width()) - x - width()) : x, y); \
} \ } \
void moveToRight(int x, int y, int outerw = 0) { \ 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); \ move(rtl() ? x : ((outerw > 0 ? outerw : parentWidget()->width()) - x - width()), y); \
} \ } \
void setGeometryToLeft(int x, int y, int w, int h, int outerw = 0) { \ 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); \ 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) { \ 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); \ setGeometry(rtl() ? x : ((outerw > 0 ? outerw : parentWidget()->width()) - x - w), y, w, h); \
} \ } \
QPoint myrtlpoint(int x, int y) const { \ 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. // Get the size of the widget as it should be.
// Negative return value means no default width. // Negative return value means no default width.
virtual int naturalWidth() const { virtual int naturalWidth() const {
@ -168,13 +188,37 @@ public:
// Count new height for width=newWidth and resize to it. // Count new height for width=newWidth and resize to it.
void resizeToWidth(int newWidth) { 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()) { if (newSize != size()) {
resize(newSize); resize(newSize);
update(); 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. // Updates the area that is visible inside the scroll container.
virtual void setVisibleTopBottom(int visibleTop, int visibleBottom) { virtual void setVisibleTopBottom(int visibleTop, int visibleBottom) {
} }

View file

@ -86,9 +86,9 @@ void RippleButton::setForceRippled(bool rippled, SetForceRippledWay way) {
update(); 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) { if (_ripple) {
_ripple->paint(p, x, y, width(), ms); _ripple->paint(p, x, y, width(), ms, colorOverride);
if (_ripple->empty()) { if (_ripple->empty()) {
_ripple.reset(); _ripple.reset();
} }
@ -106,8 +106,11 @@ void RippleButton::onStateChanged(int oldState, StateChangeSource source) {
if (down && (source == StateChangeSource::ByPress)) { if (down && (source == StateChangeSource::ByPress)) {
// Start a ripple only from mouse press. // Start a ripple only from mouse press.
ensureRipple(); auto position = prepareRippleStartPosition();
_ripple->add(prepareRippleStartPosition()); if (position != disabledRippleStartPosition()) {
ensureRipple();
_ripple->add(position);
}
} else if (!down && _ripple) { } else if (!down && _ripple) {
// Finish ripple anyway. // Finish ripple anyway.
_ripple->lastStop(); _ripple->lastStop();

View file

@ -64,12 +64,15 @@ public:
~RippleButton(); ~RippleButton();
protected: 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; void onStateChanged(int oldState, StateChangeSource source) override;
virtual QImage prepareRippleMask() const; virtual QImage prepareRippleMask() const;
virtual QPoint prepareRippleStartPosition() const; virtual QPoint prepareRippleStartPosition() const;
QPoint disabledRippleStartPosition() const {
return QPoint(-0x3FFFFFFF, -0x3FFFFFFF);
}
private: private:
void ensureRipple(); void ensureRipple();

View file

@ -22,6 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
#include "lang.h" #include "lang.h"
#include "ui/effects/ripple_animation.h"
namespace Ui { namespace Ui {
namespace { 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) , _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) , _text(text)
, _fullText(text) , _fullText(text)
, _textWidth(st.font->width(text)) , _textWidth(st.font->width(text))
, _checked(checked) { , _checked(checked) {
if (_st.width <= 0) { if (_st.width <= 0) {
resize(_textWidth - _st.width, _st.height); resizeToWidth(_textWidth - _st.width);
} else { } else {
if (_st.width < _st.textPosition.x() + _textWidth + (_st.textPosition.x() - _st.diameter)) { 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)); _text = _st.font->elided(_fullText, qMax(_st.width - (_st.textPosition.x() + (_st.textPosition.x() - _st.diameter)), 1));
_textWidth = _st.font->width(_text); _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())); connect(this, SIGNAL(clicked()), this, SLOT(onClicked()));
setCursor(style::cur_pointer); setCursor(style::cur_pointer);
setAttribute(Qt::WA_OpaquePaintEvent);
} }
bool Checkbox::checked() const { bool Checkbox::checked() const {
@ -122,12 +117,7 @@ bool Checkbox::checked() const {
void Checkbox::setChecked(bool checked, NotifyAboutChange notify) { void Checkbox::setChecked(bool checked, NotifyAboutChange notify) {
if (_checked != checked) { if (_checked != checked) {
_checked = checked; _checked = checked;
if (_checked) { _a_checked.start([this] { update(_checkRect); }, _checked ? 0. : 1., _checked ? 1. : 0., _st.duration);
a_checked.start(1);
} else {
a_checked.start(0);
}
_a_checked.start();
if (notify == NotifyAboutChange::Notify) { if (notify == NotifyAboutChange::Notify) {
emit changed(); emit changed();
} }
@ -135,30 +125,7 @@ void Checkbox::setChecked(bool checked, NotifyAboutChange notify) {
} }
void Checkbox::finishAnimations() { void Checkbox::finishAnimations() {
a_checked.finish(); _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);
} }
int Checkbox::naturalWidth() const { int Checkbox::naturalWidth() const {
@ -168,52 +135,31 @@ int Checkbox::naturalWidth() const {
void Checkbox::paintEvent(QPaintEvent *e) { void Checkbox::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
float64 over = a_over.current(), checked = a_checked.current(); auto ms = getms();
bool cnone = (over == 0. && checked == 0.), cover = (over == 1. && checked == 0.), cchecked = (checked == 1.); auto active = _a_checked.current(ms, _checked ? 1. : 0.);
bool cbad = !cnone && !cover && !cchecked; auto color = anim::color(_st.rippleBg, _st.rippleBgActive, active);
QColor color; paintRipple(p, _st.rippleAreaPosition.x(), _st.rippleAreaPosition.y(), ms, &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);
}
QRect r(e->rect()); if (_checkRect.intersects(e->rect())) {
p.setClipRect(r);
p.fillRect(r, _st.textBg);
if (_checkRect.intersects(r)) {
p.setRenderHint(QPainter::HighQualityAntialiasing); p.setRenderHint(QPainter::HighQualityAntialiasing);
QPen pen; auto pen = anim::pen(_st.checkFg, _st.checkFgActive, active);
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;
}
pen.setWidth(_st.thickness); pen.setWidth(_st.thickness);
p.setPen(pen); p.setPen(pen);
if (checked > 0) { p.setBrush(anim::brush(_st.checkBg, anim::color(_st.checkFg, _st.checkFgActive, active), active));
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.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.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); p.setRenderHint(QPainter::HighQualityAntialiasing, false);
if (checked > 0) { if (active > 0) {
_st.checkIcon.paint(p, QPoint(0, 0), width()); _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.setPen(_st.textFg);
p.setFont(_st.font); 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() { void Checkbox::onClicked() {
@ -222,13 +168,8 @@ void Checkbox::onClicked() {
} }
void Checkbox::onStateChanged(int oldState, StateChangeSource source) { void Checkbox::onStateChanged(int oldState, StateChangeSource source) {
if ((_state & StateOver) && !(oldState & StateOver)) { RippleButton::onStateChanged(oldState, source);
a_over.start(1);
_a_over.start();
} else if (!(_state & StateOver) && (oldState & StateOver)) {
a_over.start(0);
_a_over.start();
}
if ((_state & StateDisabled) && !(oldState & StateDisabled)) { if ((_state & StateDisabled) && !(oldState & StateDisabled)) {
setCursor(style::cur_default); setCursor(style::cur_default);
} else if (!(_state & StateDisabled) && (oldState & StateDisabled)) { } 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) , _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) , _text(text)
, _fullText(text) , _fullText(text)
, _textWidth(st.font->width(text)) , _textWidth(st.font->width(text))
@ -249,22 +202,20 @@ Radiobutton::Radiobutton(QWidget *parent, const QString &group, int32 value, con
, _group(radiobuttons.reg(group)) , _group(radiobuttons.reg(group))
, _value(value) { , _value(value) {
if (_st.width <= 0) { if (_st.width <= 0) {
resize(_textWidth - _st.width, _st.height); resizeToWidth(_textWidth - _st.width);
} else { } else {
if (_st.width < _st.textPosition.x() + _textWidth + (_st.textPosition.x() - _st.diameter)) { 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)); _text = _st.font->elided(_fullText, qMax(_st.width - (_st.textPosition.x() + (_st.textPosition.x() - _st.diameter)), 1));
_textWidth = _st.font->width(_text); _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())); connect(this, SIGNAL(clicked()), this, SLOT(onClicked()));
setCursor(style::cur_pointer); setCursor(style::cur_pointer);
setAttribute(Qt::WA_OpaquePaintEvent);
reinterpret_cast<RadiobuttonGroup*>(_group)->insert(this, true); reinterpret_cast<RadiobuttonGroup*>(_group)->insert(this, true);
if (_checked) onChanged(); if (_checked) onChanged();
} }
@ -276,66 +227,29 @@ bool Radiobutton::checked() const {
void Radiobutton::setChecked(bool checked) { void Radiobutton::setChecked(bool checked) {
if (_checked != checked) { if (_checked != checked) {
_checked = checked; _checked = checked;
if (_checked) { _a_checked.start([this] { update(_checkRect); }, _checked ? 0. : 1., _checked ? 1. : 0., _st.duration);
a_checked.start(1);
} else {
a_checked.start(0);
}
_a_checked.start();
onChanged(); onChanged();
emit changed(); emit changed();
} }
} }
void Radiobutton::step_over(float64 ms, bool timer) { int Radiobutton::naturalWidth() const {
float64 dt = ms / _st.duration; return _st.textPosition.x() + _st.font->width(_fullText);
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);
} }
void Radiobutton::paintEvent(QPaintEvent *e) { void Radiobutton::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
float64 over = a_over.current(), checked = a_checked.current(); auto ms = getms();
bool cnone = (over == 0. && checked == 0.), cover = (over == 1. && checked == 0.), cchecked = (checked == 1.); auto active = _a_checked.current(ms, _checked ? 1. : 0.);
bool cbad = !cnone && !cover && !cchecked; auto color = anim::color(_st.rippleBg, _st.rippleBgActive, active);
QColor color; paintRipple(p, _st.rippleAreaPosition.x(), _st.rippleAreaPosition.y(), ms, &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);
}
QRect r(e->rect()); if (_checkRect.intersects(e->rect())) {
p.setClipRect(r);
p.fillRect(r, _st.textBg->b);
if (_checkRect.intersects(r)) {
p.setRenderHint(QPainter::HighQualityAntialiasing); p.setRenderHint(QPainter::HighQualityAntialiasing);
QPen pen; auto pen = anim::pen(_st.checkFg, _st.checkFgActive, active);
if (cbad) {
pen = QPen(color);
} else {
pen = (cnone ? _st.checkFg : (cover ? _st.checkFgOver : _st.checkFgActive))->p;
}
pen.setWidth(_st.thickness); pen.setWidth(_st.thickness);
p.setPen(pen); p.setPen(pen);
p.setBrush(_st.checkBg); p.setBrush(_st.checkBg);
@ -343,14 +257,11 @@ void Radiobutton::paintEvent(QPaintEvent *e) {
//p.drawEllipse(_checkRect.marginsRemoved(QMargins(skip, skip, skip, skip))); //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.))); 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); p.setPen(Qt::NoPen);
if (cbad) { p.setBrush(anim::brush(_st.checkFg, _st.checkFgActive, active));
p.setBrush(color);
} else { auto skip0 = _checkRect.width() / 2., skip1 = _st.radioSkip / 10., checkSkip = skip0 * (1. - active) + skip1 * active;
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.drawEllipse(QRectF(_checkRect).marginsRemoved(QMarginsF(checkSkip, checkSkip, checkSkip, checkSkip))); p.drawEllipse(QRectF(_checkRect).marginsRemoved(QMarginsF(checkSkip, checkSkip, checkSkip, checkSkip)));
//int32 fskip = qFloor(checkSkip), cskip = qCeil(checkSkip); //int32 fskip = qFloor(checkSkip), cskip = qCeil(checkSkip);
//if (2 * fskip < _checkRect.width()) { //if (2 * fskip < _checkRect.width()) {
@ -367,11 +278,11 @@ void Radiobutton::paintEvent(QPaintEvent *e) {
p.setRenderHint(QPainter::HighQualityAntialiasing, false); p.setRenderHint(QPainter::HighQualityAntialiasing, false);
} }
if (_checkRect.contains(r)) return; if (_checkRect.contains(e->rect())) return;
p.setPen(_st.textFg); p.setPen(_st.textFg);
p.setFont(_st.font); 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() { void Radiobutton::onClicked() {
@ -380,13 +291,8 @@ void Radiobutton::onClicked() {
} }
void Radiobutton::onStateChanged(int oldState, StateChangeSource source) { void Radiobutton::onStateChanged(int oldState, StateChangeSource source) {
if ((_state & StateOver) && !(oldState & StateOver)) { RippleButton::onStateChanged(oldState, source);
a_over.start(1);
_a_over.start();
} else if (!(_state & StateOver) && (oldState & StateOver)) {
a_over.start(0);
_a_over.start();
}
if ((_state & StateDisabled) && !(oldState & StateDisabled)) { if ((_state & StateDisabled) && !(oldState & StateDisabled)) {
setCursor(style::cur_default); setCursor(style::cur_default);
} else if (!(_state & StateDisabled) && (oldState & StateDisabled)) { } 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() { void Radiobutton::onChanged() {
RadiobuttonGroup *group = reinterpret_cast<RadiobuttonGroup*>(_group); RadiobuttonGroup *group = reinterpret_cast<RadiobuttonGroup*>(_group);
if (checked()) { if (checked()) {

View file

@ -20,12 +20,12 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/ */
#pragma once #pragma once
#include "ui/abstract_button.h" #include "ui/widgets/buttons.h"
#include "styles/style_widgets.h" #include "styles/style_widgets.h"
namespace Ui { namespace Ui {
class Checkbox : public AbstractButton { class Checkbox : public RippleButton {
Q_OBJECT Q_OBJECT
public: public:
@ -40,12 +40,19 @@ public:
void finishAnimations(); void finishAnimations();
QMargins getMargins() const override {
return _st.margin;
}
int naturalWidth() const override; int naturalWidth() const override;
protected: protected:
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
void onStateChanged(int oldState, StateChangeSource source) override; void onStateChanged(int oldState, StateChangeSource source) override;
int resizeGetHeight(int newWidth) override;
QImage prepareRippleMask() const override;
QPoint prepareRippleStartPosition() const override;
public slots: public slots:
void onClicked(); void onClicked();
@ -54,26 +61,22 @@ signals:
void changed(); void changed();
private: private:
void step_over(float64 ms, bool timer);
void step_checked(float64 ms, bool timer);
const style::Checkbox &_st; const style::Checkbox &_st;
anim::fvalue a_over, a_checked;
Animation _a_over, _a_checked;
QString _text, _fullText; QString _text, _fullText;
int32 _textWidth; int32 _textWidth;
QRect _checkRect; QRect _checkRect;
bool _checked; bool _checked;
FloatAnimation _a_checked;
}; };
class Radiobutton : public AbstractButton { class Radiobutton : public RippleButton {
Q_OBJECT Q_OBJECT
public: 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; bool checked() const;
void setChecked(bool checked); void setChecked(bool checked);
@ -82,8 +85,10 @@ public:
return _value; return _value;
} }
void step_over(float64 ms, bool timer); QMargins getMargins() const override {
void step_checked(float64 ms, bool timer); return _st.margin;
}
int naturalWidth() const override;
~Radiobutton(); ~Radiobutton();
@ -91,6 +96,10 @@ protected:
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
void onStateChanged(int oldState, StateChangeSource source) override; void onStateChanged(int oldState, StateChangeSource source) override;
int resizeGetHeight(int newWidth) override;
QImage prepareRippleMask() const override;
QPoint prepareRippleStartPosition() const override;
public slots: public slots:
void onClicked(); void onClicked();
@ -101,15 +110,14 @@ signals:
private: private:
void onChanged(); void onChanged();
const style::Radiobutton &_st; const style::Checkbox &_st;
anim::fvalue a_over, a_checked;
Animation _a_over, _a_checked;
QString _text, _fullText; QString _text, _fullText;
int32 _textWidth; int32 _textWidth;
QRect _checkRect; QRect _checkRect;
bool _checked; bool _checked;
FloatAnimation _a_checked;
void *_group; void *_group;
int32 _value; int32 _value;

View file

@ -21,6 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "stdafx.h" #include "stdafx.h"
#include "ui/widgets/discrete_sliders.h" #include "ui/widgets/discrete_sliders.h"
#include "ui/effects/ripple_animation.h"
#include "styles/style_widgets.h" #include "styles/style_widgets.h"
namespace Ui { namespace Ui {
@ -36,11 +37,27 @@ void DiscreteSlider::setSectionActivatedCallback(SectionActivatedCallback &&call
void DiscreteSlider::setActiveSection(int index) { void DiscreteSlider::setActiveSection(int index) {
if (_activeIndex != index) { if (_activeIndex != index) {
_activeIndex = index; _activeIndex = index;
activateCallback();
}
setSelectedSection(index);
}
void DiscreteSlider::activateCallback() {
if (_timerId >= 0) {
killTimer(_timerId);
}
auto ms = getms();
if (ms >= _callbackAfterMs) {
if (_callback) { if (_callback) {
_callback(); _callback();
} }
} else {
_timerId = startTimer(_callbackAfterMs - ms, Qt::PreciseTimer);
} }
setSelectedSection(index); }
void DiscreteSlider::timerEvent(QTimerEvent *e) {
activateCallback();
} }
void DiscreteSlider::setActiveSectionFast(int index) { void DiscreteSlider::setActiveSectionFast(int index) {
@ -82,14 +99,18 @@ int DiscreteSlider::getCurrentActiveLeft(TimeMs ms) {
template <typename Lambda> template <typename Lambda>
void DiscreteSlider::enumerateSections(Lambda callback) { void DiscreteSlider::enumerateSections(Lambda callback) {
for (auto &section : _sections) { for (auto &section : _sections) {
callback(section); if (!callback(section)) {
return;
}
} }
} }
void DiscreteSlider::mousePressEvent(QMouseEvent *e) { void DiscreteSlider::mousePressEvent(QMouseEvent *e) {
auto index = getIndexFromPosition(e->pos());
if (_selectOnPress) { if (_selectOnPress) {
setSelectedSection(getIndexFromPosition(e->pos())); setSelectedSection(index);
} }
startRipple(index);
_pressed = true; _pressed = true;
} }
@ -101,9 +122,14 @@ void DiscreteSlider::mouseMoveEvent(QMouseEvent *e) {
} }
void DiscreteSlider::mouseReleaseEvent(QMouseEvent *e) { void DiscreteSlider::mouseReleaseEvent(QMouseEvent *e) {
if (!_pressed) return; if (!base::take(_pressed)) return;
_pressed = false; auto index = getIndexFromPosition(e->pos());
setActiveSection(getIndexFromPosition(e->pos())); if (index >= 0 && index < _sections.size()) {
if (_sections[index].ripple) {
_sections[index].ripple->lastStop();
}
}
setActiveSection(index);
} }
void DiscreteSlider::setSelectedSection(int index) { void DiscreteSlider::setSelectedSection(int index) {
@ -113,7 +139,9 @@ void DiscreteSlider::setSelectedSection(int index) {
auto from = _sections[_selected].left; auto from = _sections[_selected].left;
_selected = index; _selected = index;
auto to = _sections[_selected].left; 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) SettingsSlider::SettingsSlider(QWidget *parent, const style::SettingsSlider &st) : DiscreteSlider(parent)
, _st(st) { , _st(st) {
setSelectOnPress(_st.ripple.showDuration == 0);
} }
const style::font &SettingsSlider::getLabelFont() const { const style::font &SettingsSlider::getLabelFont() const {
@ -157,6 +186,7 @@ void SettingsSlider::resizeSections(int newWidth) {
x += sectionWidth; x += sectionWidth;
section.width = qRound(x) - (section.left - skip); section.width = qRound(x) - (section.left - skip);
skip += _st.barSkip; skip += _st.barSkip;
return true;
}); });
stopAnimation(); stopAnimation();
} }
@ -166,13 +196,35 @@ int SettingsSlider::resizeGetHeight(int newWidth) {
return _st.height; return _st.height;
} }
void SettingsSlider::startRipple(int index) {
if (!_st.ripple.showDuration) return;
enumerateSections([this, &index](Section &section) {
if (!index--) {
if (!section.ripple) {
auto mask = RippleAnimation::rectMask(QSize(section.width, height() - _st.rippleBottomSkip));
section.ripple = MakeShared<RippleAnimation>(_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) { void SettingsSlider::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
auto activeLeft = getCurrentActiveLeft(getms()); auto ms = getms();
auto activeLeft = getCurrentActiveLeft(ms);
p.setFont(_st.labelFont); p.setFont(_st.labelFont);
enumerateSections([this, &p, activeLeft](Section &section) { enumerateSections([this, &p, activeLeft, ms](Section &section) {
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; auto from = section.left, tofill = section.width;
if (activeLeft > from) { if (activeLeft > from) {
auto fill = qMin(tofill, 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.setPen(anim::pen(_st.labelFg, _st.labelFgActive, active));
p.drawTextLeft(section.left + (section.width - section.labelWidth) / 2, _st.labelTop, width(), section.label, section.labelWidth); p.drawTextLeft(section.left + (section.width - section.labelWidth) / 2, _st.labelTop, width(), section.label, section.labelWidth);
return true;
}); });
} }

View file

@ -24,6 +24,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Ui { namespace Ui {
class RippleAnimation;
class DiscreteSlider : public TWidget { class DiscreteSlider : public TWidget {
public: public:
DiscreteSlider(QWidget *parent); DiscreteSlider(QWidget *parent);
@ -35,12 +37,12 @@ public:
} }
void setActiveSection(int index); void setActiveSection(int index);
void setActiveSectionFast(int index); void setActiveSectionFast(int index);
void setSelectOnPress(bool selectOnPress);
using SectionActivatedCallback = base::lambda<void()>; using SectionActivatedCallback = base::lambda<void()>;
void setSectionActivatedCallback(SectionActivatedCallback &&callback); void setSectionActivatedCallback(SectionActivatedCallback &&callback);
protected: protected:
void timerEvent(QTimerEvent *e) override;
void mousePressEvent(QMouseEvent *e) override; void mousePressEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override; void mouseMoveEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override; void mouseReleaseEvent(QMouseEvent *e) override;
@ -53,6 +55,7 @@ protected:
int left, width; int left, width;
QString label; QString label;
int labelWidth; int labelWidth;
QSharedPointer<RippleAnimation> ripple;
}; };
int getCurrentActiveLeft(TimeMs ms); int getCurrentActiveLeft(TimeMs ms);
@ -64,11 +67,17 @@ protected:
template <typename Lambda> template <typename Lambda>
void enumerateSections(Lambda callback); void enumerateSections(Lambda callback);
virtual void startRipple(int index) {
}
void stopAnimation() { void stopAnimation() {
_a_left.finish(); _a_left.finish();
} }
void setSelectOnPress(bool selectOnPress);
private: private:
void activateCallback();
virtual const style::font &getLabelFont() const = 0; virtual const style::font &getLabelFont() const = 0;
virtual int getAnimationDuration() const = 0; virtual int getAnimationDuration() const = 0;
@ -85,6 +94,9 @@ private:
int _selected = 0; int _selected = 0;
FloatAnimation _a_left; FloatAnimation _a_left;
int _timerId = -1;
TimeMs _callbackAfterMs = 0;
}; };
class SettingsSlider : public DiscreteSlider { class SettingsSlider : public DiscreteSlider {
@ -96,6 +108,8 @@ protected:
int resizeGetHeight(int newWidth) override; int resizeGetHeight(int newWidth) override;
void startRipple(int index) override;
private: private:
const style::font &getLabelFont() const override; const style::font &getLabelFont() const override;
int getAnimationDuration() const override; int getAnimationDuration() const override;
@ -104,6 +118,7 @@ private:
const style::SettingsSlider &_st; const style::SettingsSlider &_st;
}; };
} // namespace Ui } // namespace Ui

View file

@ -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) FlatTextarea::FlatTextarea(QWidget *parent, const style::FlatTextarea &st, const QString &pholder, const QString &v, const TagList &tags) : QTextEdit(parent)
, _phVisible(!v.length()) , _placeholderVisible(!v.length())
, a_phLeft(_phVisible ? 0 : st.phShift)
, a_phAlpha(_phVisible ? 1 : 0)
, a_phColorFocused(0)
, _a_appearance(animation(this, &FlatTextarea::step_appearance))
, _lastTextWithTags { v, tags } , _lastTextWithTags { v, tags }
, _st(st) { , _st(st) {
setCursor(style::cur_text); setCursor(style::cur_text);
@ -217,12 +213,9 @@ void FlatTextarea::setTextWithTags(const TextWithTags &textWithTags, UndoHistory
} }
void FlatTextarea::finishPlaceholder() { void FlatTextarea::finishPlaceholder() {
if (_a_appearance.animating()) { _a_placeholderFocused.finish();
a_phLeft.finish(); _a_placeholderVisible.finish();
a_phAlpha.finish(); update();
_a_appearance.stop();
update();
}
} }
void FlatTextarea::setMaxLength(int32 maxLength) { void FlatTextarea::setMaxLength(int32 maxLength) {
@ -323,24 +316,25 @@ int32 FlatTextarea::fakeMargin() const {
} }
void FlatTextarea::paintEvent(QPaintEvent *e) { void FlatTextarea::paintEvent(QPaintEvent *e) {
QPainter p(viewport()); Painter p(viewport());
QRect r(rect().intersected(e->rect())); auto ms = getms();
p.fillRect(r, _st.bgColor->b); auto r = rect().intersected(e->rect());
bool phDraw = _phVisible; p.fillRect(r, _st.bgColor);
if (_a_appearance.animating()) { auto placeholderOpacity = _a_placeholderVisible.current(ms, _placeholderVisible ? 1. : 0.);
p.setOpacity(a_phAlpha.current()); if (placeholderOpacity > 0.) {
phDraw = true; p.setOpacity(placeholderOpacity);
}
if (phDraw) { auto placeholderLeft = anim::interpolate(_st.phShift, 0, placeholderOpacity);
p.save(); p.save();
p.setClipRect(r); p.setClipRect(r);
p.setFont(_st.font); 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) { if (_st.phAlign == style::al_topleft && _phAfter > 0) {
int skipWidth = placeholderSkipWidth(); 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 { } 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.drawText(phRect, _ph, QTextOption(_st.phAlign));
} }
p.restore(); p.restore();
@ -362,14 +356,12 @@ int FlatTextarea::placeholderSkipWidth() const {
} }
void FlatTextarea::focusInEvent(QFocusEvent *e) { void FlatTextarea::focusInEvent(QFocusEvent *e) {
a_phColorFocused.start(1.); _a_placeholderFocused.start([this] { update(); }, 0., 1., _st.phDuration);
_a_appearance.start();
QTextEdit::focusInEvent(e); QTextEdit::focusInEvent(e);
} }
void FlatTextarea::focusOutEvent(QFocusEvent *e) { void FlatTextarea::focusOutEvent(QFocusEvent *e) {
a_phColorFocused.start(0.); _a_placeholderFocused.start([this] { update(); }, 1., 0., _st.phDuration);
_a_appearance.start();
QTextEdit::focusOutEvent(e); QTextEdit::focusOutEvent(e);
} }
@ -1313,24 +1305,6 @@ void FlatTextarea::onRedoAvailable(bool avail) {
if (App::wnd()) App::wnd()->updateGlobalMenu(); 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) { void FlatTextarea::setPlaceholder(const QString &ph, int32 afterSymbols) {
_ph = ph; _ph = ph;
if (_phAfter != afterSymbols) { if (_phAfter != afterSymbols) {
@ -1339,18 +1313,15 @@ void FlatTextarea::setPlaceholder(const QString &ph, int32 afterSymbols) {
} }
int skipWidth = placeholderSkipWidth(); int skipWidth = placeholderSkipWidth();
_phelided = _st.font->elided(_ph, width() - _st.textMrg.left() - _st.textMrg.right() - _st.phPos.x() - 1 - skipWidth); _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() { void FlatTextarea::updatePlaceholder() {
bool vis = (getTextWithTags().text.size() <= _phAfter); auto placeholderVisible = (getTextWithTags().text.size() <= _phAfter);
if (vis == _phVisible) return; if (_placeholderVisible != placeholderVisible) {
_placeholderVisible = placeholderVisible;
a_phLeft.start(vis ? 0 : _st.phShift); _a_placeholderVisible.start([this] { update(); }, _placeholderVisible ? 0. : 1., _placeholderVisible ? 1. : 0., _st.phDuration);
a_phAlpha.start(vis ? 1 : 0); }
_a_appearance.start();
_phVisible = vis;
} }
QMimeData *FlatTextarea::createMimeDataFromSelection() const { 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) FlatInput::FlatInput(QWidget *parent, const style::FlatInput &st, const QString &pholder, const QString &v) : QLineEdit(v, parent)
, _oldtext(v) , _oldtext(v)
, _fullph(pholder) , _fullph(pholder)
, _fastph(false) , _placeholderVisible(!v.length())
, _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)
, _st(st) { , _st(st) {
setCursor(style::cur_text); setCursor(style::cur_text);
resize(_st.width, _st.height); resize(_st.width, _st.height);
@ -1578,12 +1539,14 @@ QRect FlatInput::getTextRect() const {
void FlatInput::paintEvent(QPaintEvent *e) { void FlatInput::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
auto ms = getms();
auto placeholderFocused = _a_placeholderFocused.current(ms, hasFocus() ? 1. : 0.);
p.setRenderHint(QPainter::HighQualityAntialiasing); p.setRenderHint(QPainter::HighQualityAntialiasing);
auto borderColor = anim::color(_st.borderColor, _st.borderActive, a_borderColorActive.current()); auto pen = anim::pen(_st.borderColor, _st.borderActive, placeholderFocused);
auto pen = anim::pen(borderColor, _st.borderError, a_borderColorError.current());
pen.setWidth(_st.borderWidth); pen.setWidth(_st.borderWidth);
p.setPen(pen); 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.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); p.setRenderHint(QPainter::HighQualityAntialiasing, false);
@ -1591,17 +1554,17 @@ void FlatInput::paintEvent(QPaintEvent *e) {
_st.icon.paint(p, 0, 0, width()); _st.icon.paint(p, 0, 0, width());
} }
bool phDraw = _phVisible; auto placeholderOpacity = _a_placeholderVisible.current(ms, _placeholderVisible ? 1. : 0.);
if (_a_appearance.animating()) { if (placeholderOpacity > 0.) {
p.setOpacity(a_phAlpha.current()); p.setOpacity(placeholderOpacity);
phDraw = true;
} auto left = anim::interpolate(_st.phShift, 0, placeholderOpacity);
if (phDraw) {
p.save(); p.save();
p.setClipRect(rect()); p.setClipRect(rect());
QRect phRect(placeholderRect()); QRect phRect(placeholderRect());
phRect.moveLeft(phRect.left() + a_phLeft.current()); phRect.moveLeft(phRect.left() + left);
phPrepare(p); phPrepare(p, placeholderFocused);
p.drawText(phRect, _ph, QTextOption(_st.phAlign)); p.drawText(phRect, _ph, QTextOption(_st.phAlign));
p.restore(); p.restore();
} }
@ -1609,21 +1572,13 @@ void FlatInput::paintEvent(QPaintEvent *e) {
} }
void FlatInput::focusInEvent(QFocusEvent *e) { void FlatInput::focusInEvent(QFocusEvent *e) {
a_phColorFocus.start(1.); _a_placeholderFocused.start([this] { update(); }, 0., 1., _st.phDuration);
a_borderColorActive.start(1.);
a_borderColorError.restart();
a_bgColorActive.start(1);
_a_appearance.start();
QLineEdit::focusInEvent(e); QLineEdit::focusInEvent(e);
emit focused(); emit focused();
} }
void FlatInput::focusOutEvent(QFocusEvent *e) { void FlatInput::focusOutEvent(QFocusEvent *e) {
a_phColorFocus.start(0.); _a_placeholderFocused.start([this] { update(); }, 1., 0., _st.phDuration);
a_borderColorActive.start(0.);
a_borderColorError.restart();
a_bgColorActive.start(0);
_a_appearance.start();
QLineEdit::focusOutEvent(e); QLineEdit::focusOutEvent(e);
emit blurred(); emit blurred();
} }
@ -1645,16 +1600,6 @@ void FlatInput::updatePlaceholderText() {
void FlatInput::contextMenuEvent(QContextMenuEvent *e) { void FlatInput::contextMenuEvent(QContextMenuEvent *e) {
if (auto menu = createStandardContextMenu()) { 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()); (new Ui::PopupMenu(menu))->popup(e->globalPos());
} }
} }
@ -1667,35 +1612,6 @@ QSize FlatInput::minimumSizeHint() const {
return geometry().size(); 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) { void FlatInput::setPlaceholder(const QString &ph) {
_fullph = ph; _fullph = ph;
updatePlaceholderText(); updatePlaceholderText();
@ -1704,26 +1620,21 @@ void FlatInput::setPlaceholder(const QString &ph) {
void FlatInput::setPlaceholderFast(bool fast) { void FlatInput::setPlaceholderFast(bool fast) {
_fastph = fast; _fastph = fast;
if (_fastph) { if (_fastph) {
a_phLeft = anim::ivalue(_phVisible ? 0 : _st.phShift, _phVisible ? 0 : _st.phShift); _a_placeholderVisible.finish();
a_phAlpha = anim::fvalue(_phVisible ? 1 : 0, _phVisible ? 1 : 0);
update(); update();
} }
} }
void FlatInput::updatePlaceholder() { void FlatInput::updatePlaceholder() {
bool vis = !text().length(); auto placeholderVisible = text().isEmpty();
if (vis == _phVisible) return; if (_placeholderVisible != placeholderVisible) {
_placeholderVisible = placeholderVisible;
if (_fastph) { if (_fastph) {
a_phLeft = anim::ivalue(vis ? 0 : _st.phShift, vis ? 0 : _st.phShift); update();
a_phAlpha = anim::fvalue(vis ? 1 : 0, vis ? 1 : 0); } else {
update(); _a_placeholderVisible.start([this] { update(); }, _placeholderVisible ? 0. : 1., _placeholderVisible ? 1. : 0., _st.phDuration);
} else { }
a_phLeft.start(vis ? 0 : _st.phShift);
a_phAlpha.start(vis ? 1 : 0);
_a_appearance.start();
} }
_phVisible = vis;
} }
const QString &FlatInput::placeholder() const { const QString &FlatInput::placeholder() const {
@ -1737,9 +1648,9 @@ QRect FlatInput::placeholderRect() const {
void FlatInput::correctValue(const QString &was, QString &now) { 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.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) { void FlatInput::keyPressEvent(QKeyEvent *e) {
@ -1790,14 +1701,6 @@ void FlatInput::onTextChange(const QString &text) {
if (App::wnd()) App::wnd()->updateGlobalMenu(); 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) InputArea::InputArea(QWidget *parent, const style::InputArea &st, const QString &ph, const QString &val) : TWidget(parent)
, _maxLength(-1) , _maxLength(-1)
, _inner(this) , _inner(this)

View file

@ -52,8 +52,6 @@ public:
QRect getTextRect() const; QRect getTextRect() const;
int32 fakeMargin() const; int32 fakeMargin() const;
void step_appearance(float64 ms, bool timer);
QSize sizeHint() const override; QSize sizeHint() const override;
QSize minimumSizeHint() const override; QSize minimumSizeHint() const override;
@ -114,6 +112,10 @@ public:
}; };
void setTagMimeProcessor(std_::unique_ptr<TagMimeProcessor> &&processor); void setTagMimeProcessor(std_::unique_ptr<TagMimeProcessor> &&processor);
QMargins getMargins() const {
return QMargins();
}
public slots: public slots:
void onTouchTimer(); void onTouchTimer();
@ -187,11 +189,9 @@ private:
QString _ph, _phelided; QString _ph, _phelided;
int _phAfter = 0; int _phAfter = 0;
bool _phVisible; bool _placeholderVisible = true;
anim::ivalue a_phLeft; FloatAnimation _a_placeholderFocused;
anim::fvalue a_phAlpha; FloatAnimation _a_placeholderVisible;
anim::fvalue a_phColorFocused;
Animation _a_appearance;
TextWithTags _lastTextWithTags; TextWithTags _lastTextWithTags;
@ -247,8 +247,6 @@ class FlatInput : public QLineEdit {
public: public:
FlatInput(QWidget *parent, const style::FlatInput &st, const QString &ph = QString(), const QString &val = QString()); FlatInput(QWidget *parent, const style::FlatInput &st, const QString &ph = QString(), const QString &val = QString());
void notaBene();
void setPlaceholder(const QString &ph); void setPlaceholder(const QString &ph);
void setPlaceholderFast(bool fast); void setPlaceholderFast(bool fast);
void updatePlaceholder(); void updatePlaceholder();
@ -257,8 +255,6 @@ public:
QRect getTextRect() const; QRect getTextRect() const;
void step_appearance(float64 ms, bool timer);
QSize sizeHint() const override; QSize sizeHint() const override;
QSize minimumSizeHint() const override; QSize minimumSizeHint() const override;
@ -267,6 +263,10 @@ public:
return _oldtext; return _oldtext;
} }
QMargins getMargins() const {
return QMargins();
}
public slots: public slots:
void onTextChange(const QString &text); void onTextChange(const QString &text);
void onTextEdited(); void onTextEdited();
@ -303,26 +303,20 @@ protected:
return _st.font; return _st.font;
} }
void phPrepare(Painter &p); void phPrepare(Painter &p, float64 placeholderFocused);
private: private:
void updatePlaceholderText(); void updatePlaceholderText();
QString _oldtext, _ph, _fullph; QString _oldtext, _ph, _fullph;
bool _fastph; bool _fastph = false;
bool _customUpDown; bool _customUpDown = false;
bool _phVisible; bool _placeholderVisible = true;
anim::ivalue a_phLeft; FloatAnimation _a_placeholderFocused;
anim::fvalue a_phAlpha; FloatAnimation _a_placeholderVisible;
anim::fvalue a_phColorFocus;
anim::fvalue a_borderColorActive;
anim::fvalue a_borderColorError;
anim::fvalue a_bgColorActive;
Animation _a_appearance;
int _notingBene;
const style::FlatInput &_st; const style::FlatInput &_st;
QTimer _touchTimer; QTimer _touchTimer;
@ -702,6 +696,10 @@ public:
updatePlaceholder(); updatePlaceholder();
} }
QMargins getMargins() const {
return QMargins();
}
public slots: public slots:
void onTextChange(const QString &text); void onTextChange(const QString &text);
void onCursorPositionChanged(int oldPosition, int position); void onCursorPositionChanged(int oldPosition, int position);

View file

@ -350,6 +350,8 @@ MultiSelect::MultiSelect(QWidget *parent, const style::MultiSelect &st, const QS
}); });
setAttribute(Qt::WA_OpaquePaintEvent); 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) { bool MultiSelect::eventFilter(QObject *o, QEvent *e) {

View file

@ -186,6 +186,10 @@ public:
bool viewportEvent(QEvent *e) override; bool viewportEvent(QEvent *e) override;
void keyPressEvent(QKeyEvent *e) override; void keyPressEvent(QKeyEvent *e) override;
QMargins getMargins() const {
return QMargins();
}
~ScrollArea(); ~ScrollArea();
protected: protected:

View file

@ -94,44 +94,29 @@ RoundButton {
Checkbox { Checkbox {
textFg: color; textFg: color;
textBg: color;
checkBg: color; checkBg: color;
checkFg: color; checkFg: color;
checkFgOver: color;
checkFgActive: color; checkFgActive: color;
width: pixels; width: pixels;
height: pixels; height: pixels;
margin: margins;
textPosition: point; textPosition: point;
diameter: pixels; diameter: pixels;
thickness: pixels; thickness: pixels;
radioSkip: pixels;
checkIcon: icon; checkIcon: icon;
font: font; font: font;
duration: int; duration: int;
}
Radiobutton { rippleAreaPosition: point;
textFg: color; rippleAreaSize: pixels;
textBg: color; rippleBg: color;
rippleBgActive: color;
checkBg: color; ripple: RippleAnimation;
checkFg: color;
checkFgOver: color;
checkFgActive: color;
width: pixels;
height: pixels;
textPosition: point;
diameter: pixels;
thickness: pixels;
checkSkip: pixels;
font: font;
duration: int;
} }
FlatScroll { FlatScroll {
@ -674,44 +659,29 @@ defaultCheckboxIcon: icon {{ "default_checkbox_check", windowFgActive, point(4px
defaultCheckbox: Checkbox { defaultCheckbox: Checkbox {
textFg: windowFg; textFg: windowFg;
textBg: windowBg;
checkBg: #ffffff; checkBg: transparent;
checkFg: #b3b3b3; checkFg: #b3b3b3;
checkFgOver: #b3b3b3;
checkFgActive: windowBgActive; checkFgActive: windowBgActive;
width: -44px; width: -44px;
height: 22px; height: 22px;
margin: margins(8px, 8px, 8px, 8px);
textPosition: point(32px, 2px); textPosition: point(32px, 2px);
diameter: 22px; diameter: 22px;
thickness: 2px; thickness: 2px;
checkIcon: defaultCheckboxIcon; checkIcon: defaultCheckboxIcon;
radioSkip: 65px; // * 0.1
font: normalFont; font: normalFont;
duration: 120; duration: 120;
}
defaultRadiobutton: Radiobutton { rippleAreaSize: 38px;
textFg: windowFg; rippleAreaPosition: point(0px, 0px);
textBg: windowBg; rippleBg: windowBgOver;
rippleBgActive: #e0f2fa;
checkBg: #ffffff; ripple: defaultRippleAnimation;
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;
} }
defaultIconButton: IconButton { defaultIconButton: IconButton {
@ -736,6 +706,8 @@ SettingsSlider {
labelFg: color; labelFg: color;
labelFgActive: color; labelFgActive: color;
duration: int; duration: int;
rippleBottomSkip: pixels;
ripple: RippleAnimation;
} }
defaultSettingsSlider: SettingsSlider { defaultSettingsSlider: SettingsSlider {
@ -761,6 +733,10 @@ defaultTabsSlider: SettingsSlider(defaultSettingsSlider) {
labelFont: semiboldFont; labelFont: semiboldFont;
labelFg: #999999; labelFg: #999999;
labelFgActive: lightButtonFg; labelFgActive: lightButtonFg;
rippleBottomSkip: 1px;
ripple: RippleAnimation(defaultRippleAnimation) {
color: windowBgOver;
}
} }
defaultRoundShadow: Shadow { defaultRoundShadow: Shadow {