mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-03-25 04:38:23 +00:00
Closed beta 10019008: Some more ripple animations added.
This commit is contained in:
parent
cdef9fa14f
commit
07689476a6
@ -53,6 +53,11 @@ lightButtonBgRipple: #c9e4f6;
|
|||||||
lightButtonFg: #2b99d5;
|
lightButtonFg: #2b99d5;
|
||||||
lightButtonFgOver: lightButtonFg;
|
lightButtonFgOver: lightButtonFg;
|
||||||
|
|
||||||
|
attentionButtonFg: #d14e4e;
|
||||||
|
attentionButtonFgOver: #d14e4e;
|
||||||
|
attentionButtonBgOver: #fcdfde;
|
||||||
|
attentionButtonBgRipple: #f4c3c2;
|
||||||
|
|
||||||
menuBg: windowBg;
|
menuBg: windowBg;
|
||||||
menuBgOver: windowBgOver;
|
menuBgOver: windowBgOver;
|
||||||
menuBgRipple: windowBgRipple;
|
menuBgRipple: windowBgRipple;
|
||||||
@ -99,11 +104,6 @@ boxBlockTitleAdditionalFg: #808080;
|
|||||||
boxBlockTitleCloseFg: cancelIconFg;
|
boxBlockTitleCloseFg: cancelIconFg;
|
||||||
boxBlockTitleCloseFgOver: cancelIconFgOver;
|
boxBlockTitleCloseFgOver: cancelIconFgOver;
|
||||||
|
|
||||||
attentionBoxButtonFg: #d14e4e;
|
|
||||||
attentionBoxButtonFgOver: #d14e4e;
|
|
||||||
attentionBoxButtonBgOver: #fcdfde;
|
|
||||||
attentionBoxButtonBgRipple: #f4c3c2;
|
|
||||||
|
|
||||||
membersAboutLimitFg: windowSubTextFgOver;
|
membersAboutLimitFg: windowSubTextFgOver;
|
||||||
|
|
||||||
contactsBg: windowBg;
|
contactsBg: windowBg;
|
||||||
@ -228,6 +228,7 @@ mediaviewFileExtFg: activeButtonFg;
|
|||||||
|
|
||||||
mediaviewMenuBg: #383838;
|
mediaviewMenuBg: #383838;
|
||||||
mediaviewMenuBgOver: #505050;
|
mediaviewMenuBgOver: #505050;
|
||||||
|
mediaviewMenuBgRipple: #676767;
|
||||||
mediaviewMenuFg: #ffffff;
|
mediaviewMenuFg: #ffffff;
|
||||||
|
|
||||||
mediaviewBg: #222222eb;
|
mediaviewBg: #222222eb;
|
||||||
|
@ -49,6 +49,10 @@ lightButtonBgOver: #e3f1fa;
|
|||||||
lightButtonBgRipple: #c9e4f6;
|
lightButtonBgRipple: #c9e4f6;
|
||||||
lightButtonFg: #2b99d5;
|
lightButtonFg: #2b99d5;
|
||||||
lightButtonFgOver: lightButtonFg;
|
lightButtonFgOver: lightButtonFg;
|
||||||
|
attentionButtonFg: #d14e4e;
|
||||||
|
attentionButtonFgOver: #d14e4e;
|
||||||
|
attentionButtonBgOver: #fcdfde;
|
||||||
|
attentionButtonBgRipple: #f4c3c2;
|
||||||
menuBg: windowBg;
|
menuBg: windowBg;
|
||||||
menuBgOver: windowBgOver;
|
menuBgOver: windowBgOver;
|
||||||
menuBgRipple: windowBgRipple;
|
menuBgRipple: windowBgRipple;
|
||||||
@ -84,10 +88,6 @@ boxBlockTitleFg: boxTitleFg;
|
|||||||
boxBlockTitleAdditionalFg: #808080;
|
boxBlockTitleAdditionalFg: #808080;
|
||||||
boxBlockTitleCloseFg: cancelIconFg;
|
boxBlockTitleCloseFg: cancelIconFg;
|
||||||
boxBlockTitleCloseFgOver: cancelIconFgOver;
|
boxBlockTitleCloseFgOver: cancelIconFgOver;
|
||||||
attentionBoxButtonFg: #d14e4e;
|
|
||||||
attentionBoxButtonFgOver: #d14e4e;
|
|
||||||
attentionBoxButtonBgOver: #fcdfde;
|
|
||||||
attentionBoxButtonBgRipple: #f4c3c2;
|
|
||||||
membersAboutLimitFg: windowSubTextFgOver;
|
membersAboutLimitFg: windowSubTextFgOver;
|
||||||
contactsBg: windowBg;
|
contactsBg: windowBg;
|
||||||
contactsBgOver: windowBgOver;
|
contactsBgOver: windowBgOver;
|
||||||
@ -189,6 +189,7 @@ mediaviewFileBlueCornerFg: #599dcf;
|
|||||||
mediaviewFileExtFg: activeButtonFg;
|
mediaviewFileExtFg: activeButtonFg;
|
||||||
mediaviewMenuBg: #383838;
|
mediaviewMenuBg: #383838;
|
||||||
mediaviewMenuBgOver: #505050;
|
mediaviewMenuBgOver: #505050;
|
||||||
|
mediaviewMenuBgRipple: #676767;
|
||||||
mediaviewMenuFg: #ffffff;
|
mediaviewMenuFg: #ffffff;
|
||||||
mediaviewBg: #222222eb;
|
mediaviewBg: #222222eb;
|
||||||
mediaviewVideoBg: #000000;
|
mediaviewVideoBg: #000000;
|
||||||
|
@ -34,8 +34,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
|
|||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 0,10,19,7
|
FILEVERSION 0,10,19,8
|
||||||
PRODUCTVERSION 0,10,19,7
|
PRODUCTVERSION 0,10,19,8
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
@ -51,10 +51,10 @@ BEGIN
|
|||||||
BLOCK "040904b0"
|
BLOCK "040904b0"
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "Telegram Messenger LLP"
|
VALUE "CompanyName", "Telegram Messenger LLP"
|
||||||
VALUE "FileVersion", "0.10.19.7"
|
VALUE "FileVersion", "0.10.19.8"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
|
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
|
||||||
VALUE "ProductName", "Telegram Desktop"
|
VALUE "ProductName", "Telegram Desktop"
|
||||||
VALUE "ProductVersion", "0.10.19.7"
|
VALUE "ProductVersion", "0.10.19.8"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
|||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 0,10,19,7
|
FILEVERSION 0,10,19,8
|
||||||
PRODUCTVERSION 0,10,19,7
|
PRODUCTVERSION 0,10,19,8
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
@ -43,10 +43,10 @@ BEGIN
|
|||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "Telegram Messenger LLP"
|
VALUE "CompanyName", "Telegram Messenger LLP"
|
||||||
VALUE "FileDescription", "Telegram Updater"
|
VALUE "FileDescription", "Telegram Updater"
|
||||||
VALUE "FileVersion", "0.10.19.7"
|
VALUE "FileVersion", "0.10.19.8"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
|
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
|
||||||
VALUE "ProductName", "Telegram Desktop"
|
VALUE "ProductName", "Telegram Desktop"
|
||||||
VALUE "ProductVersion", "0.10.19.7"
|
VALUE "ProductVersion", "0.10.19.8"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "abstractbox.h"
|
#include "boxes/abstractbox.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class Radiobutton;
|
class Radiobutton;
|
||||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "abstractbox.h"
|
#include "boxes/abstractbox.h"
|
||||||
#include "core/lambda_wrap.h"
|
#include "core/lambda_wrap.h"
|
||||||
|
|
||||||
class BackgroundBox : public ItemListBox {
|
class BackgroundBox : public ItemListBox {
|
||||||
|
@ -37,7 +37,6 @@ defaultBoxButton: RoundButton {
|
|||||||
padding: margins(0px, 0px, 0px, 0px);
|
padding: margins(0px, 0px, 0px, 0px);
|
||||||
|
|
||||||
textTop: 8px;
|
textTop: 8px;
|
||||||
downTextTop: 8px;
|
|
||||||
|
|
||||||
font: boxButtonFont;
|
font: boxButtonFont;
|
||||||
|
|
||||||
@ -51,12 +50,12 @@ cancelBoxButton: RoundButton(defaultBoxButton) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
attentionBoxButton: RoundButton(defaultBoxButton) {
|
attentionBoxButton: RoundButton(defaultBoxButton) {
|
||||||
textFg: attentionBoxButtonFg;
|
textFg: attentionButtonFg;
|
||||||
textFgOver: attentionBoxButtonFgOver;
|
textFgOver: attentionButtonFgOver;
|
||||||
textBgOver: attentionBoxButtonBgOver;
|
textBgOver: attentionButtonBgOver;
|
||||||
|
|
||||||
ripple: RippleAnimation(defaultRippleAnimation) {
|
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||||
color: attentionBoxButtonBgRipple;
|
color: attentionButtonBgRipple;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,12 +197,21 @@ contactUserIcon: icon {{ "add_contact_user", #999999 }};
|
|||||||
contactPhoneIcon: icon {{ "add_contact_phone", #999999 }};
|
contactPhoneIcon: icon {{ "add_contact_phone", #999999 }};
|
||||||
contactIconTop: 10px;
|
contactIconTop: 10px;
|
||||||
|
|
||||||
contactsAdd: IconButton {
|
contactsAddIconAbove: icon {{ "contacts_add", activeButtonFg, point(18px, 18px) }};
|
||||||
|
contactsAdd: TwoIconButton {
|
||||||
width: 52px;
|
width: 52px;
|
||||||
height: 52px;
|
height: 52px;
|
||||||
|
|
||||||
icon: contactsAddIcon;
|
iconBelow: contactsAddIconBelow;
|
||||||
iconOver: contactsAddIconOver;
|
iconBelowOver: contactsAddIconBelowOver;
|
||||||
|
iconAbove: contactsAddIconAbove;
|
||||||
|
iconAboveOver: contactsAddIconAbove;
|
||||||
|
|
||||||
|
rippleAreaPosition: point(5px, 5px);
|
||||||
|
rippleAreaSize: 42px;
|
||||||
|
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||||
|
color: activeButtonBgRipple;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
contactsAddPosition: point(14px, 8px);
|
contactsAddPosition: point(14px, 8px);
|
||||||
|
|
||||||
@ -289,9 +297,7 @@ contactsMultiSelect: MultiSelect {
|
|||||||
|
|
||||||
icon: boxSearchCancelIcon;
|
icon: boxSearchCancelIcon;
|
||||||
iconOver: boxSearchCancelIconOver;
|
iconOver: boxSearchCancelIconOver;
|
||||||
|
|
||||||
iconPosition: point(8px, 18px);
|
iconPosition: point(8px, 18px);
|
||||||
iconPositionDown: point(8px, 18px);
|
|
||||||
}
|
}
|
||||||
fieldCancelSkip: 34px;
|
fieldCancelSkip: 34px;
|
||||||
}
|
}
|
||||||
@ -370,9 +376,7 @@ sessionTerminate: IconButton {
|
|||||||
|
|
||||||
icon: simpleCloseIcon;
|
icon: simpleCloseIcon;
|
||||||
iconOver: simpleCloseIconOver;
|
iconOver: simpleCloseIconOver;
|
||||||
|
|
||||||
iconPosition: point(3px, 3px);
|
iconPosition: point(3px, 3px);
|
||||||
iconPositionDown: point(3px, 4px);
|
|
||||||
}
|
}
|
||||||
sessionTerminateAllButton: LinkButton(boxLinkButton) {
|
sessionTerminateAllButton: LinkButton(boxLinkButton) {
|
||||||
color: #d15948;
|
color: #d15948;
|
||||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "abstractbox.h"
|
#include "boxes/abstractbox.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class InputField;
|
class InputField;
|
||||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "abstractbox.h"
|
#include "boxes/abstractbox.h"
|
||||||
#include "core/single_timer.h"
|
#include "core/single_timer.h"
|
||||||
#include "ui/effects/round_image_checkbox.h"
|
#include "ui/effects/round_image_checkbox.h"
|
||||||
#include "boxes/members_box.h"
|
#include "boxes/members_box.h"
|
||||||
@ -93,7 +93,7 @@ private:
|
|||||||
class Inner;
|
class Inner;
|
||||||
ChildWidget<Inner> _inner;
|
ChildWidget<Inner> _inner;
|
||||||
ChildWidget<Ui::WidgetSlideWrap<Ui::MultiSelect>> _select;
|
ChildWidget<Ui::WidgetSlideWrap<Ui::MultiSelect>> _select;
|
||||||
ChildWidget<Ui::IconButton> _add = { nullptr };
|
ChildWidget<MembersAddButton> _add = { nullptr };
|
||||||
|
|
||||||
ChildWidget<Ui::RoundButton> _next;
|
ChildWidget<Ui::RoundButton> _next;
|
||||||
ChildWidget<Ui::RoundButton> _cancel;
|
ChildWidget<Ui::RoundButton> _cancel;
|
||||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "abstractbox.h"
|
#include "boxes/abstractbox.h"
|
||||||
#include "core/observer.h"
|
#include "core/observer.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "abstractbox.h"
|
#include "boxes/abstractbox.h"
|
||||||
|
|
||||||
class EmojiBox : public AbstractBox {
|
class EmojiBox : public AbstractBox {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "abstractbox.h"
|
#include "boxes/abstractbox.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class Radiobutton;
|
class Radiobutton;
|
||||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "abstractbox.h"
|
#include "boxes/abstractbox.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class RoundButton;
|
class RoundButton;
|
||||||
|
@ -30,8 +30,36 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
#include "boxes/confirmbox.h"
|
#include "boxes/confirmbox.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/widgets/scroll_area.h"
|
#include "ui/widgets/scroll_area.h"
|
||||||
|
#include "ui/effects/ripple_animation.h"
|
||||||
#include "observer_peer.h"
|
#include "observer_peer.h"
|
||||||
|
|
||||||
|
|
||||||
|
MembersAddButton::MembersAddButton(QWidget *parent, const style::TwoIconButton &st) : RippleButton(parent, st.ripple)
|
||||||
|
, _st(st) {
|
||||||
|
resize(_st.width, _st.height);
|
||||||
|
setCursor(style::cur_pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MembersAddButton::paintEvent(QPaintEvent *e) {
|
||||||
|
Painter p(this);
|
||||||
|
|
||||||
|
auto ms = getms();
|
||||||
|
auto over = (_state & StateOver);
|
||||||
|
auto down = (_state & StateDown);
|
||||||
|
|
||||||
|
((over || down) ? _st.iconBelowOver : _st.iconBelow).paint(p, _st.iconPosition, width());
|
||||||
|
paintRipple(p, _st.rippleAreaPosition.x(), _st.rippleAreaPosition.y(), ms);
|
||||||
|
((over || down) ? _st.iconAboveOver : _st.iconAbove).paint(p, _st.iconPosition, width());
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage MembersAddButton::prepareRippleMask() const {
|
||||||
|
return Ui::RippleAnimation::ellipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
QPoint MembersAddButton::prepareRippleStartPosition() const {
|
||||||
|
return mapFromGlobal(QCursor::pos()) - _st.rippleAreaPosition;
|
||||||
|
}
|
||||||
|
|
||||||
MembersBox::MembersBox(ChannelData *channel, MembersFilter filter) : ItemListBox(st::boxScroll)
|
MembersBox::MembersBox(ChannelData *channel, MembersFilter filter) : ItemListBox(st::boxScroll)
|
||||||
, _inner(this, channel, filter) {
|
, _inner(this, channel, filter) {
|
||||||
ItemListBox::init(_inner);
|
ItemListBox::init(_inner);
|
||||||
|
@ -20,9 +20,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "abstractbox.h"
|
#include "boxes/abstractbox.h"
|
||||||
#include "core/single_timer.h"
|
#include "core/single_timer.h"
|
||||||
#include "ui/effects/round_image_checkbox.h"
|
#include "ui/effects/round_image_checkbox.h"
|
||||||
|
#include "ui/widgets/buttons.h"
|
||||||
|
|
||||||
class ContactsBox;
|
class ContactsBox;
|
||||||
class ConfirmBox;
|
class ConfirmBox;
|
||||||
@ -33,6 +34,21 @@ enum class MembersFilter {
|
|||||||
};
|
};
|
||||||
using MembersAlreadyIn = OrderedSet<UserData*>;
|
using MembersAlreadyIn = OrderedSet<UserData*>;
|
||||||
|
|
||||||
|
class MembersAddButton : public Ui::RippleButton {
|
||||||
|
public:
|
||||||
|
MembersAddButton(QWidget *parent, const style::TwoIconButton &st);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
|
||||||
|
QImage prepareRippleMask() const override;
|
||||||
|
QPoint prepareRippleStartPosition() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const style::TwoIconButton &_st;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
class MembersBox : public ItemListBox {
|
class MembersBox : public ItemListBox {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@ -54,7 +70,7 @@ private:
|
|||||||
|
|
||||||
class Inner;
|
class Inner;
|
||||||
ChildWidget<Inner> _inner;
|
ChildWidget<Inner> _inner;
|
||||||
ChildWidget<Ui::IconButton> _add = { nullptr };
|
ChildWidget<MembersAddButton> _add = { nullptr };
|
||||||
|
|
||||||
ContactsBox *_addBox = nullptr;
|
ContactsBox *_addBox = nullptr;
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "abstractbox.h"
|
#include "boxes/abstractbox.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class RoundButton;
|
class RoundButton;
|
||||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "abstractbox.h"
|
#include "boxes/abstractbox.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class InputField;
|
class InputField;
|
||||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "abstractbox.h"
|
#include "boxes/abstractbox.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class RoundButton;
|
class RoundButton;
|
||||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "abstractbox.h"
|
#include "boxes/abstractbox.h"
|
||||||
#include "localimageloader.h"
|
#include "localimageloader.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "abstractbox.h"
|
#include "boxes/abstractbox.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class Radiobutton;
|
class Radiobutton;
|
||||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "abstractbox.h"
|
#include "boxes/abstractbox.h"
|
||||||
#include "core/single_timer.h"
|
#include "core/single_timer.h"
|
||||||
|
|
||||||
class ConfirmBox;
|
class ConfirmBox;
|
||||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "abstractbox.h"
|
#include "boxes/abstractbox.h"
|
||||||
#include "core/lambda_wrap.h"
|
#include "core/lambda_wrap.h"
|
||||||
#include "core/observer.h"
|
#include "core/observer.h"
|
||||||
#include "core/vector_of_moveable.h"
|
#include "core/vector_of_moveable.h"
|
||||||
|
@ -33,6 +33,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
#include "styles/style_stickers.h"
|
#include "styles/style_stickers.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/widgets/scroll_area.h"
|
#include "ui/widgets/scroll_area.h"
|
||||||
|
#include "ui/effects/ripple_animation.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@ -563,6 +564,7 @@ void StickersBox::Inner::paintEvent(QPaintEvent *e) {
|
|||||||
|
|
||||||
_a_shifting.step();
|
_a_shifting.step();
|
||||||
|
|
||||||
|
auto ms = getms();
|
||||||
p.fillRect(r, st::boxBg);
|
p.fillRect(r, st::boxBg);
|
||||||
p.setClipRect(r);
|
p.setClipRect(r);
|
||||||
|
|
||||||
@ -591,19 +593,26 @@ void StickersBox::Inner::paintEvent(QPaintEvent *e) {
|
|||||||
p.translate(0, from * _rowHeight);
|
p.translate(0, from * _rowHeight);
|
||||||
for (int32 i = from; i < to; ++i) {
|
for (int32 i = from; i < to; ++i) {
|
||||||
if (i != _above) {
|
if (i != _above) {
|
||||||
paintRow(p, i);
|
paintRow(p, i, ms);
|
||||||
}
|
}
|
||||||
p.translate(0, _rowHeight);
|
p.translate(0, _rowHeight);
|
||||||
}
|
}
|
||||||
if (from <= _above && _above < to) {
|
if (from <= _above && _above < to) {
|
||||||
p.translate(0, (_above - to) * _rowHeight);
|
p.translate(0, (_above - to) * _rowHeight);
|
||||||
paintRow(p, _above);
|
paintRow(p, _above, ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickersBox::Inner::paintRow(Painter &p, int32 index) {
|
QRect StickersBox::Inner::relativeAddButtonRect() const {
|
||||||
const StickerSetRow *s(_rows.at(index));
|
int addw = st::stickersAddSize.width();
|
||||||
|
int addx = width() - st::contactsPadding.right() - st::contactsCheckPosition.x() - addw;
|
||||||
|
int addy = st::contactsPadding.top() + (st::contactsPhotoSize - st::stickersAddSize.height()) / 2;
|
||||||
|
return QRect(addx, addy, addw, st::stickersAddSize.height());
|
||||||
|
}
|
||||||
|
|
||||||
|
void StickersBox::Inner::paintRow(Painter &p, int32 index, uint64 ms) {
|
||||||
|
auto s = _rows.at(index);
|
||||||
|
|
||||||
int32 xadd = 0, yadd = s->yadd.current();
|
int32 xadd = 0, yadd = s->yadd.current();
|
||||||
if (xadd || yadd) p.translate(xadd, yadd);
|
if (xadd || yadd) p.translate(xadd, yadd);
|
||||||
@ -639,17 +648,23 @@ void StickersBox::Inner::paintRow(Painter &p, int32 index) {
|
|||||||
int checkx = width() - (st::contactsPadding.right() + st::contactsCheckPosition.x() + (addw + st::stickersFeaturedInstalled.width()) / 2);
|
int checkx = width() - (st::contactsPadding.right() + st::contactsCheckPosition.x() + (addw + st::stickersFeaturedInstalled.width()) / 2);
|
||||||
int checky = st::contactsPadding.top() + (st::contactsPhotoSize - st::stickersFeaturedInstalled.height()) / 2;
|
int checky = st::contactsPadding.top() + (st::contactsPhotoSize - st::stickersFeaturedInstalled.height()) / 2;
|
||||||
st::stickersFeaturedInstalled.paint(p, QPoint(checkx, checky), width());
|
st::stickersFeaturedInstalled.paint(p, QPoint(checkx, checky), width());
|
||||||
|
if (s->ripple) {
|
||||||
|
s->ripple.reset();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
int addw = st::stickersAddSize.width();
|
auto relativeAdd = relativeAddButtonRect();
|
||||||
int addx = width() - st::contactsPadding.right() - st::contactsCheckPosition.x() - addw;
|
auto add = myrtlrect(relativeAdd);
|
||||||
int addy = st::contactsPadding.top() + (st::contactsPhotoSize - st::stickersAddSize.height()) / 2;
|
|
||||||
QRect add(myrtlrect(addx, addy, addw, st::stickersAddSize.height()));
|
|
||||||
|
|
||||||
auto &textBg = (_actionSel == index) ? st::defaultActiveButton.textBgOver : st::defaultActiveButton.textBg;
|
auto &textBg = (_actionSel == index || _actionDown == index) ? st::defaultActiveButton.textBgOver : st::defaultActiveButton.textBg;
|
||||||
App::roundRect(p, add, textBg, ImageRoundRadius::Small);
|
App::roundRect(p, add, textBg, ImageRoundRadius::Small);
|
||||||
int iconx = addx + (st::stickersAddSize.width() - st::stickersAddIcon.width()) / 2;
|
if (s->ripple) {
|
||||||
int icony = addy + (st::stickersAddSize.height() - st::stickersAddIcon.height()) / 2;
|
s->ripple->paint(p, relativeAdd.x(), relativeAdd.y(), width(), ms);
|
||||||
icony += (_actionSel == index && _actionDown == index) ? (st::defaultActiveButton.downTextTop - st::defaultActiveButton.textTop) : 0;
|
if (s->ripple->empty()) {
|
||||||
|
s->ripple.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int iconx = relativeAdd.x() + (st::stickersAddSize.width() - st::stickersAddIcon.width()) / 2;
|
||||||
|
int icony = relativeAdd.y() + (st::stickersAddSize.height() - st::stickersAddIcon.height()) / 2;
|
||||||
st::stickersAddIcon.paint(p, QPoint(iconx, icony), width());
|
st::stickersAddIcon.paint(p, QPoint(iconx, icony), width());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -696,7 +711,7 @@ void StickersBox::Inner::mousePressEvent(QMouseEvent *e) {
|
|||||||
|
|
||||||
_pressed = _selected;
|
_pressed = _selected;
|
||||||
if (_actionSel >= 0) {
|
if (_actionSel >= 0) {
|
||||||
_actionDown = _actionSel;
|
setActionDown(_actionSel);
|
||||||
update(0, _itemsTop + _actionSel * _rowHeight, width(), _rowHeight);
|
update(0, _itemsTop + _actionSel * _rowHeight, width(), _rowHeight);
|
||||||
} else if (_selected >= 0 && _section == Section::Installed && !_rows.at(_selected)->recent) {
|
} else if (_selected >= 0 && _section == Section::Installed && !_rows.at(_selected)->recent) {
|
||||||
_above = _dragging = _started = _selected;
|
_above = _dragging = _started = _selected;
|
||||||
@ -704,6 +719,33 @@ void StickersBox::Inner::mousePressEvent(QMouseEvent *e) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StickersBox::Inner::setActionDown(int newActionDown) {
|
||||||
|
if (_actionDown == newActionDown) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_actionDown >= 0 && _actionDown < _rows.size()) {
|
||||||
|
update(0, _itemsTop + _actionDown * _rowHeight, width(), _rowHeight);
|
||||||
|
auto set = _rows[_actionDown];
|
||||||
|
if (set->ripple) {
|
||||||
|
set->ripple->lastStop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_actionDown = newActionDown;
|
||||||
|
if (_actionDown >= 0 && _actionDown < _rows.size()) {
|
||||||
|
update(0, _itemsTop + _actionDown * _rowHeight, width(), _rowHeight);
|
||||||
|
auto set = _rows[_actionDown];
|
||||||
|
if (!set->ripple) {
|
||||||
|
auto mask = Ui::RippleAnimation::roundRectMask(st::stickersAddSize, st::buttonRadius);
|
||||||
|
set->ripple = MakeShared<Ui::RippleAnimation>(st::defaultActiveButton.ripple, std_::move(mask), [this, index = _actionDown] {
|
||||||
|
update(0, _itemsTop + index * _rowHeight, width(), _rowHeight);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
auto relativeAdd = relativeAddButtonRect();
|
||||||
|
auto add = myrtlrect(relativeAdd);
|
||||||
|
set->ripple->add(mapFromGlobal(QCursor::pos()) - QPoint(add.x(), _itemsTop + _actionDown * _rowHeight + add.y()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void StickersBox::Inner::mouseMoveEvent(QMouseEvent *e) {
|
void StickersBox::Inner::mouseMoveEvent(QMouseEvent *e) {
|
||||||
if (_saving) return;
|
if (_saving) return;
|
||||||
_mouse = e->globalPos();
|
_mouse = e->globalPos();
|
||||||
@ -762,10 +804,8 @@ void StickersBox::Inner::onUpdateSelected() {
|
|||||||
} else if (_rows.at(selected)->installed && !_rows.at(selected)->disabled) {
|
} else if (_rows.at(selected)->installed && !_rows.at(selected)->disabled) {
|
||||||
actionSel = -1;
|
actionSel = -1;
|
||||||
} else {
|
} else {
|
||||||
int addw = st::stickersAddSize.width();
|
auto relativeAdd = relativeAddButtonRect();
|
||||||
int addx = width() - st::contactsPadding.right() - st::contactsCheckPosition.x() - addw;
|
auto add = myrtlrect(relativeAdd);
|
||||||
int addy = st::contactsPadding.top() + (st::contactsPhotoSize - st::stickersAddSize.height()) / 2;
|
|
||||||
QRect add(myrtlrect(addx, addy, addw, st::stickersAddSize.height()));
|
|
||||||
actionSel = add.contains(local.x(), local.y() - _itemsTop - selected * _rowHeight) ? selected : -1;
|
actionSel = add.contains(local.x(), local.y() - _itemsTop - selected * _rowHeight) ? selected : -1;
|
||||||
}
|
}
|
||||||
} else if (_hasFeaturedButton && QRect(0, st::membersPadding.top(), width(), _buttonHeight).contains(local)) {
|
} else if (_hasFeaturedButton && QRect(0, st::membersPadding.top(), width(), _buttonHeight).contains(local)) {
|
||||||
@ -878,10 +918,7 @@ void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_actionDown >= 0) {
|
setActionDown(-1);
|
||||||
update(0, _itemsTop + _actionDown * _rowHeight, width(), _rowHeight);
|
|
||||||
_actionDown = -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StickersBox::Inner::leaveEvent(QEvent *e) {
|
void StickersBox::Inner::leaveEvent(QEvent *e) {
|
||||||
|
@ -20,13 +20,14 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "abstractbox.h"
|
#include "boxes/abstractbox.h"
|
||||||
|
|
||||||
class ConfirmBox;
|
class ConfirmBox;
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class PlainShadow;
|
class PlainShadow;
|
||||||
class RoundButton;
|
class RoundButton;
|
||||||
|
class RippleAnimation;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
class StickersBox : public ItemListBox, public RPCSender {
|
class StickersBox : public ItemListBox, public RPCSender {
|
||||||
@ -150,11 +151,13 @@ private slots:
|
|||||||
void onImageLoaded();
|
void onImageLoaded();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void setActionDown(int newActionDown);
|
||||||
void setup();
|
void setup();
|
||||||
|
QRect relativeAddButtonRect() const;
|
||||||
void paintButton(Painter &p, int y, bool selected, const QString &text, int badgeCounter) const;
|
void paintButton(Painter &p, int y, bool selected, const QString &text, int badgeCounter) const;
|
||||||
|
|
||||||
void step_shifting(uint64 ms, bool timer);
|
void step_shifting(uint64 ms, bool timer);
|
||||||
void paintRow(Painter &p, int32 index);
|
void paintRow(Painter &p, int32 index, uint64 ms);
|
||||||
void clear();
|
void clear();
|
||||||
void setActionSel(int32 actionSel);
|
void setActionSel(int32 actionSel);
|
||||||
float64 aboveShadowOpacity() const;
|
float64 aboveShadowOpacity() const;
|
||||||
@ -192,6 +195,7 @@ private:
|
|||||||
bool installed, official, unread, disabled, recent;
|
bool installed, official, unread, disabled, recent;
|
||||||
int32 pixw, pixh;
|
int32 pixw, pixh;
|
||||||
anim::ivalue yadd;
|
anim::ivalue yadd;
|
||||||
|
QSharedPointer<Ui::RippleAnimation> ripple;
|
||||||
};
|
};
|
||||||
using StickerSetRows = QList<StickerSetRow*>;
|
using StickerSetRows = QList<StickerSetRow*>;
|
||||||
|
|
||||||
@ -236,5 +240,6 @@ private:
|
|||||||
|
|
||||||
Ui::RectShadow _aboveShadow;
|
Ui::RectShadow _aboveShadow;
|
||||||
|
|
||||||
int32 _scrollbar = 0;
|
int _scrollbar = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "abstractbox.h"
|
#include "boxes/abstractbox.h"
|
||||||
#include "core/vector_of_moveable.h"
|
#include "core/vector_of_moveable.h"
|
||||||
|
|
||||||
class ConfirmBox;
|
class ConfirmBox;
|
||||||
|
@ -20,7 +20,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "abstractbox.h"
|
#include "boxes/abstractbox.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class UsernameInput;
|
class UsernameInput;
|
||||||
|
@ -22,7 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
|
|
||||||
#include "core/utils.h"
|
#include "core/utils.h"
|
||||||
|
|
||||||
#define BETA_VERSION_MACRO (10019007ULL)
|
#define BETA_VERSION_MACRO (10019008ULL)
|
||||||
|
|
||||||
constexpr int AppVersion = 10020;
|
constexpr int AppVersion = 10020;
|
||||||
constexpr str_const AppVersionStr = "0.10.20";
|
constexpr str_const AppVersionStr = "0.10.20";
|
||||||
|
@ -84,7 +84,6 @@ dialogsMenuToggle: IconButton {
|
|||||||
icon: icon {{ "dialogs_menu", dialogsMenuIconFg }};
|
icon: icon {{ "dialogs_menu", dialogsMenuIconFg }};
|
||||||
iconOver: icon {{ "dialogs_menu", dialogsMenuIconFgOver }};
|
iconOver: icon {{ "dialogs_menu", dialogsMenuIconFgOver }};
|
||||||
iconPosition: point(10px, 10px);
|
iconPosition: point(10px, 10px);
|
||||||
iconPositionDown: point(10px, 10px);
|
|
||||||
|
|
||||||
rippleAreaPosition: point(0px, 0px);
|
rippleAreaPosition: point(0px, 0px);
|
||||||
rippleAreaSize: 40px;
|
rippleAreaSize: 40px;
|
||||||
@ -112,18 +111,14 @@ dialogsFilter: FlatInput(defaultFlatInput) {
|
|||||||
dialogsCancelSearchInPeer: IconButton(dialogsMenuToggle) {
|
dialogsCancelSearchInPeer: IconButton(dialogsMenuToggle) {
|
||||||
icon: icon {{ "dialogs_cancel_search", dialogsMenuIconFg }};
|
icon: icon {{ "dialogs_cancel_search", dialogsMenuIconFg }};
|
||||||
iconOver: icon {{ "dialogs_cancel_search", dialogsMenuIconFgOver }};
|
iconOver: icon {{ "dialogs_cancel_search", dialogsMenuIconFgOver }};
|
||||||
|
|
||||||
iconPosition: point(11px, 11px);
|
iconPosition: point(11px, 11px);
|
||||||
iconPositionDown: point(11px, 11px);
|
|
||||||
}
|
}
|
||||||
dialogsCancelSearch: IconButton(dialogsCancelSearchInPeer) {
|
dialogsCancelSearch: IconButton(dialogsCancelSearchInPeer) {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
|
|
||||||
iconPosition: point(7px, 7px);
|
iconPosition: point(7px, 7px);
|
||||||
iconPositionDown: point(7px, 7px);
|
|
||||||
|
|
||||||
rippleAreaSize: 0px;
|
ripple: emptyRippleAnimation;
|
||||||
}
|
}
|
||||||
|
|
||||||
dialogsChatTypeSkip: 22px;
|
dialogsChatTypeSkip: 22px;
|
||||||
@ -177,8 +172,6 @@ dialogsUpdateButton: FlatButton {
|
|||||||
height: 46px;
|
height: 46px;
|
||||||
|
|
||||||
textTop: 14px;
|
textTop: 14px;
|
||||||
overTextTop: 14px;
|
|
||||||
downTextTop: 15px;
|
|
||||||
|
|
||||||
font: semiboldFont;
|
font: semiboldFont;
|
||||||
overFont: semiboldFont;
|
overFont: semiboldFont;
|
||||||
@ -197,8 +190,6 @@ dialogsForwardCancel: IconButton {
|
|||||||
|
|
||||||
icon: dialogsForwardCancelIcon;
|
icon: dialogsForwardCancelIcon;
|
||||||
iconOver: dialogsForwardCancelIcon;
|
iconOver: dialogsForwardCancelIcon;
|
||||||
|
|
||||||
iconPosition: point(12px, 11px);
|
iconPosition: point(12px, 11px);
|
||||||
iconPositionDown: point(12px, 11px);
|
|
||||||
}
|
}
|
||||||
dialogsForwardFont: semiboldFont;
|
dialogsForwardFont: semiboldFont;
|
||||||
|
@ -22,14 +22,6 @@ using "basic.style";
|
|||||||
using "dialogs/dialogs.style";
|
using "dialogs/dialogs.style";
|
||||||
using "ui/widgets/widgets.style";
|
using "ui/widgets/widgets.style";
|
||||||
|
|
||||||
BotKeyboardButton {
|
|
||||||
margin: pixels;
|
|
||||||
padding: pixels;
|
|
||||||
height: pixels;
|
|
||||||
textTop: pixels;
|
|
||||||
downTextTop: pixels;
|
|
||||||
}
|
|
||||||
|
|
||||||
historyScroll: FlatScroll(defaultFlatScroll) {
|
historyScroll: FlatScroll(defaultFlatScroll) {
|
||||||
barColor: #89a0b47a;
|
barColor: #89a0b47a;
|
||||||
bgColor: #89a0b44c;
|
bgColor: #89a0b44c;
|
||||||
@ -47,13 +39,28 @@ historyScroll: FlatScroll(defaultFlatScroll) {
|
|||||||
bottomsh: -1px;
|
bottomsh: -1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
historyPaddingBottom: 10px;
|
historyPaddingBottom: 8px;
|
||||||
|
|
||||||
historyToDownPosition: point(12px, 10px);
|
historyToDownPosition: point(12px, 10px);
|
||||||
historyToDownArrow: icon {
|
historyToDownAbove: icon {{ "history_down_arrow", #b9b9b9, point(17px, 23px) }};
|
||||||
{ "history_down_arrow", #b9b9b9, point(17px, 23px) },
|
historyToDownAboveOver: icon {{ "history_down_arrow", #a3a3a3, point(17px, 23px) }};
|
||||||
};
|
|
||||||
historyToDownPaddingTop: 10px;
|
historyToDownPaddingTop: 10px;
|
||||||
|
historyToDown: TwoIconButton {
|
||||||
|
width: 52px;
|
||||||
|
height: 62px;
|
||||||
|
|
||||||
|
iconBelow: historyToDownBelow;
|
||||||
|
iconBelowOver: historyToDownBelowOver;
|
||||||
|
iconAbove: historyToDownAbove;
|
||||||
|
iconAboveOver: historyToDownAboveOver;
|
||||||
|
iconPosition: point(0px, historyToDownPaddingTop);
|
||||||
|
|
||||||
|
rippleAreaPosition: point(5px, 15px);
|
||||||
|
rippleAreaSize: 42px;
|
||||||
|
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||||
|
color: windowBgRipple;
|
||||||
|
}
|
||||||
|
}
|
||||||
historyToDownBadgeFont: semiboldFont;
|
historyToDownBadgeFont: semiboldFont;
|
||||||
historyToDownBadgeSize: 22px;
|
historyToDownBadgeSize: 22px;
|
||||||
|
|
||||||
@ -196,8 +203,6 @@ historyComposeButton: FlatButton {
|
|||||||
height: 46px;
|
height: 46px;
|
||||||
|
|
||||||
textTop: 14px;
|
textTop: 14px;
|
||||||
overTextTop: 14px;
|
|
||||||
downTextTop: 14px;
|
|
||||||
|
|
||||||
font: semiboldFont;
|
font: semiboldFont;
|
||||||
overFont: semiboldFont;
|
overFont: semiboldFont;
|
||||||
@ -217,9 +222,7 @@ historySend: IconButton {
|
|||||||
|
|
||||||
icon: icon {{ "send_control_send", historySendIconFg }};
|
icon: icon {{ "send_control_send", historySendIconFg }};
|
||||||
iconOver: icon {{ "send_control_send", historySendIconFgOver }};
|
iconOver: icon {{ "send_control_send", historySendIconFgOver }};
|
||||||
|
|
||||||
iconPosition: point(11px, 11px);
|
iconPosition: point(11px, 11px);
|
||||||
iconPositionDown: point(11px, 11px);
|
|
||||||
}
|
}
|
||||||
historyEditSaveIcon: icon {{ "send_control_save", historySendIconFg, point(3px, 7px) }};
|
historyEditSaveIcon: icon {{ "send_control_save", historySendIconFg, point(3px, 7px) }};
|
||||||
historyEditSaveIconOver: icon {{ "send_control_save", historySendIconFgOver, point(3px, 7px) }};
|
historyEditSaveIconOver: icon {{ "send_control_save", historySendIconFgOver, point(3px, 7px) }};
|
||||||
@ -242,11 +245,9 @@ historyAttachPhotoIconOver: icon {{ "media_type_photo", historyComposeIconFgOver
|
|||||||
historyAttachEmoji: IconButton(historyAttach) {
|
historyAttachEmoji: IconButton(historyAttach) {
|
||||||
icon: icon {{ "send_control_emoji", historyComposeIconFg }};
|
icon: icon {{ "send_control_emoji", historyComposeIconFg }};
|
||||||
iconOver: icon {{ "send_control_emoji", historyComposeIconFgOver }};
|
iconOver: icon {{ "send_control_emoji", historyComposeIconFgOver }};
|
||||||
|
|
||||||
iconPosition: point(15px, 15px);
|
iconPosition: point(15px, 15px);
|
||||||
iconPositionDown: point(15px, 15px);
|
|
||||||
|
|
||||||
rippleAreaSize: 0px;
|
ripple: emptyRippleAnimation;
|
||||||
}
|
}
|
||||||
historyEmojiCircle: size(20px, 20px);
|
historyEmojiCircle: size(20px, 20px);
|
||||||
historyEmojiCirclePeriod: 1500;
|
historyEmojiCirclePeriod: 1500;
|
||||||
@ -263,9 +264,7 @@ historyBotKeyboardShow: IconButton(historySend) {
|
|||||||
historyBotKeyboardHide: IconButton(historySend) {
|
historyBotKeyboardHide: IconButton(historySend) {
|
||||||
icon: icon {{ "send_control_bot_keyboard_hide", historyComposeIconFg }};
|
icon: icon {{ "send_control_bot_keyboard_hide", historyComposeIconFg }};
|
||||||
iconOver: icon {{ "send_control_bot_keyboard_hide", historyComposeIconFgOver }};
|
iconOver: icon {{ "send_control_bot_keyboard_hide", historyComposeIconFgOver }};
|
||||||
|
|
||||||
iconPosition: point(11px, 16px);
|
iconPosition: point(11px, 16px);
|
||||||
iconPositionDown: point(11px, 16px);
|
|
||||||
}
|
}
|
||||||
historyBotCommandStart: IconButton(historySend) {
|
historyBotCommandStart: IconButton(historySend) {
|
||||||
icon: icon {{ "send_control_bot_command", historyComposeIconFg }};
|
icon: icon {{ "send_control_bot_command", historyComposeIconFg }};
|
||||||
@ -319,9 +318,7 @@ historyReplyCancel: IconButton {
|
|||||||
|
|
||||||
icon: historyReplyCancelIcon;
|
icon: historyReplyCancelIcon;
|
||||||
iconOver: historyReplyCancelIconOver;
|
iconOver: historyReplyCancelIconOver;
|
||||||
|
|
||||||
iconPosition: point(-1px, -1px);
|
iconPosition: point(-1px, -1px);
|
||||||
iconPositionDown: point(-1px, -1px);
|
|
||||||
|
|
||||||
rippleAreaPosition: point(4px, 4px);
|
rippleAreaPosition: point(4px, 4px);
|
||||||
rippleAreaSize: 40px;
|
rippleAreaSize: 40px;
|
||||||
@ -349,8 +346,6 @@ reportSpamHide: FlatButton {
|
|||||||
height: 46px;
|
height: 46px;
|
||||||
|
|
||||||
textTop: 15px;
|
textTop: 15px;
|
||||||
overTextTop: 15px;
|
|
||||||
downTextTop: 16px;
|
|
||||||
|
|
||||||
font: font(fsize);
|
font: font(fsize);
|
||||||
overFont: font(fsize underline);
|
overFont: font(fsize underline);
|
||||||
@ -361,7 +356,7 @@ reportSpamFg: #000000;
|
|||||||
|
|
||||||
msgBotKbDuration: 200;
|
msgBotKbDuration: 200;
|
||||||
msgBotKbFont: semiboldFont;
|
msgBotKbFont: semiboldFont;
|
||||||
msgBotKbOverBg: #ffffff1a;
|
msgBotKbOverBg: #ffffff20;
|
||||||
msgBotKbIconPadding: 2px;
|
msgBotKbIconPadding: 2px;
|
||||||
msgBotKbUrlIcon: icon {{ "inline_button_url", #ffffff }};
|
msgBotKbUrlIcon: icon {{ "inline_button_url", #ffffff }};
|
||||||
msgBotKbSwitchPmIcon: icon {{ "inline_button_switch", #ffffff }};
|
msgBotKbSwitchPmIcon: icon {{ "inline_button_switch", #ffffff }};
|
||||||
@ -370,28 +365,30 @@ msgBotKbButton: BotKeyboardButton {
|
|||||||
padding: 10px;
|
padding: 10px;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
textTop: 8px;
|
textTop: 8px;
|
||||||
downTextTop: 9px;
|
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||||
|
color: #00000020;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
botKbDuration: 200;
|
botKbDuration: 200;
|
||||||
botKbBg: #edf1f5;
|
botKbBg: menuBgOver;
|
||||||
botKbOverBg: #d8e2ec;
|
botKbOverBg: menuBgOver;
|
||||||
botKbDownBg: #d8e2ec;
|
botKbDownBg: menuBgRipple;
|
||||||
botKbColor: #4b565f;
|
botKbColor: windowBoldFgOver;
|
||||||
botKbFont: font(15px semibold);
|
botKbFont: font(15px semibold);
|
||||||
botKbButton: BotKeyboardButton {
|
botKbButton: BotKeyboardButton {
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
height: 38px;
|
height: 38px;
|
||||||
textTop: 9px;
|
textTop: 9px;
|
||||||
downTextTop: 9px;
|
ripple: defaultRippleAnimation;
|
||||||
}
|
}
|
||||||
botKbTinyButton: BotKeyboardButton {
|
botKbTinyButton: BotKeyboardButton {
|
||||||
margin: 4px;
|
margin: 4px;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
height: 25px;
|
height: 25px;
|
||||||
textTop: 2px;
|
textTop: 2px;
|
||||||
downTextTop: 2px;
|
ripple: defaultRippleAnimation;
|
||||||
}
|
}
|
||||||
botKbScroll: FlatScroll(defaultSolidScroll) {
|
botKbScroll: FlatScroll(defaultSolidScroll) {
|
||||||
deltax: 3px;
|
deltax: 3px;
|
||||||
|
@ -27,6 +27,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
#include "media/media_clip_reader.h"
|
#include "media/media_clip_reader.h"
|
||||||
#include "styles/style_dialogs.h"
|
#include "styles/style_dialogs.h"
|
||||||
#include "styles/style_history.h"
|
#include "styles/style_history.h"
|
||||||
|
#include "ui/effects/ripple_animation.h"
|
||||||
#include "fileuploader.h"
|
#include "fileuploader.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -221,7 +222,7 @@ int ReplyKeyboard::naturalHeight() const {
|
|||||||
return (_rows.size() - 1) * _st->buttonSkip() + _rows.size() * _st->buttonHeight();
|
return (_rows.size() - 1) * _st->buttonSkip() + _rows.size() * _st->buttonHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReplyKeyboard::paint(Painter &p, int outerWidth, const QRect &clip) const {
|
void ReplyKeyboard::paint(Painter &p, int outerWidth, const QRect &clip, uint64 ms) const {
|
||||||
t_assert(_st != nullptr);
|
t_assert(_st != nullptr);
|
||||||
t_assert(_width > 0);
|
t_assert(_width > 0);
|
||||||
|
|
||||||
@ -235,7 +236,7 @@ void ReplyKeyboard::paint(Painter &p, int outerWidth, const QRect &clip) const {
|
|||||||
// just ignore the buttons that didn't layout well
|
// just ignore the buttons that didn't layout well
|
||||||
if (rect.x() + rect.width() > _width) break;
|
if (rect.x() + rect.width() > _width) break;
|
||||||
|
|
||||||
_st->paintButton(p, outerWidth, button);
|
_st->paintButton(p, outerWidth, button, ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -251,6 +252,7 @@ ClickHandlerPtr ReplyKeyboard::getState(int x, int y) const {
|
|||||||
if (rect.x() + rect.width() > _width) break;
|
if (rect.x() + rect.width() > _width) break;
|
||||||
|
|
||||||
if (rect.contains(x, y)) {
|
if (rect.contains(x, y)) {
|
||||||
|
_savedCoords = QPoint(x, y);
|
||||||
return button.link;
|
return button.link;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -261,34 +263,63 @@ ClickHandlerPtr ReplyKeyboard::getState(int x, int y) const {
|
|||||||
void ReplyKeyboard::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
|
void ReplyKeyboard::clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) {
|
||||||
if (!p) return;
|
if (!p) return;
|
||||||
|
|
||||||
bool startAnimation = false;
|
_savedActive = active ? p : ClickHandlerPtr();
|
||||||
|
auto coords = findButtonCoordsByClickHandler(p);
|
||||||
|
if (coords.i >= 0 && _savedPressed != p) {
|
||||||
|
startAnimation(coords.i, coords.j, active ? 1 : -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ReplyKeyboard::ButtonCoords ReplyKeyboard::findButtonCoordsByClickHandler(const ClickHandlerPtr &p) {
|
||||||
for (int i = 0, rows = _rows.size(); i != rows; ++i) {
|
for (int i = 0, rows = _rows.size(); i != rows; ++i) {
|
||||||
auto &row = _rows.at(i);
|
auto &row = _rows[i];
|
||||||
for (int j = 0, cols = row.size(); j != cols; ++j) {
|
for (int j = 0, cols = row.size(); j != cols; ++j) {
|
||||||
if (row.at(j).link == p) {
|
if (row[j].link == p) {
|
||||||
bool startAnimation = _animations.isEmpty();
|
return { i, j };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { -1, -1 };
|
||||||
|
}
|
||||||
|
|
||||||
int indexForAnimation = i * MatrixRowShift + j + 1;
|
void ReplyKeyboard::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) {
|
||||||
if (!active) {
|
if (!p) return;
|
||||||
indexForAnimation = -indexForAnimation;
|
|
||||||
}
|
|
||||||
|
|
||||||
_animations.remove(-indexForAnimation);
|
_savedPressed = pressed ? p : ClickHandlerPtr();
|
||||||
if (!_animations.contains(indexForAnimation)) {
|
auto coords = findButtonCoordsByClickHandler(p);
|
||||||
_animations.insert(indexForAnimation, getms());
|
if (coords.i >= 0) {
|
||||||
}
|
auto &button = _rows[coords.i][coords.j];
|
||||||
|
if (pressed) {
|
||||||
if (startAnimation && !_a_selected.animating()) {
|
if (!button.ripple) {
|
||||||
_a_selected.start();
|
auto mask = Ui::RippleAnimation::roundRectMask(button.rect.size(), _st->buttonRadius());
|
||||||
}
|
button.ripple = MakeShared<Ui::RippleAnimation>(_st->_st->ripple, std_::move(mask), [this] { _st->repaint(_item); });
|
||||||
return;
|
}
|
||||||
|
button.ripple->add(_savedCoords - button.rect.topLeft());
|
||||||
|
} else {
|
||||||
|
if (button.ripple) {
|
||||||
|
button.ripple->lastStop();
|
||||||
|
}
|
||||||
|
if (_savedActive != p) {
|
||||||
|
startAnimation(coords.i, coords.j, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReplyKeyboard::clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) {
|
void ReplyKeyboard::startAnimation(int i, int j, int direction) {
|
||||||
_st->repaint(_item);
|
auto notStarted = _animations.isEmpty();
|
||||||
|
|
||||||
|
int indexForAnimation = (i * MatrixRowShift + j + 1) * direction;
|
||||||
|
|
||||||
|
_animations.remove(-indexForAnimation);
|
||||||
|
if (!_animations.contains(indexForAnimation)) {
|
||||||
|
_animations.insert(indexForAnimation, getms());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notStarted && !_a_selected.animating()) {
|
||||||
|
_a_selected.start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReplyKeyboard::step_selected(uint64 ms, bool timer) {
|
void ReplyKeyboard::step_selected(uint64 ms, bool timer) {
|
||||||
@ -330,11 +361,15 @@ int ReplyKeyboard::Style::buttonHeight() const {
|
|||||||
return _st->height;
|
return _st->height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReplyKeyboard::Style::paintButton(Painter &p, int outerWidth, const ReplyKeyboard::Button &button) const {
|
void ReplyKeyboard::Style::paintButton(Painter &p, int outerWidth, const ReplyKeyboard::Button &button, uint64 ms) const {
|
||||||
const QRect &rect = button.rect;
|
const QRect &rect = button.rect;
|
||||||
bool pressed = ClickHandler::showAsPressed(button.link);
|
paintButtonBg(p, rect, button.howMuchOver);
|
||||||
|
if (button.ripple) {
|
||||||
paintButtonBg(p, rect, pressed, button.howMuchOver);
|
button.ripple->paint(p, rect.x(), rect.y(), outerWidth, ms);
|
||||||
|
if (button.ripple->empty()) {
|
||||||
|
button.ripple.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
paintButtonIcon(p, rect, outerWidth, button.type);
|
paintButtonIcon(p, rect, outerWidth, button.type);
|
||||||
if (button.type == HistoryMessageReplyMarkup::Button::Type::Callback
|
if (button.type == HistoryMessageReplyMarkup::Button::Type::Callback
|
||||||
|| button.type == HistoryMessageReplyMarkup::Button::Type::Game) {
|
|| button.type == HistoryMessageReplyMarkup::Button::Type::Game) {
|
||||||
@ -353,8 +388,7 @@ void ReplyKeyboard::Style::paintButton(Painter &p, int outerWidth, const ReplyKe
|
|||||||
tx += (tw - st::botKbFont->elidew) / 2;
|
tx += (tw - st::botKbFont->elidew) / 2;
|
||||||
tw = st::botKbFont->elidew;
|
tw = st::botKbFont->elidew;
|
||||||
}
|
}
|
||||||
int textTop = rect.y() + (pressed ? _st->downTextTop : _st->textTop);
|
button.text.drawElided(p, tx, rect.y() + _st->textTop + ((rect.height() - _st->height) / 2), tw, 1, style::al_top);
|
||||||
button.text.drawElided(p, tx, textTop + ((rect.height() - _st->height) / 2), tw, 1, style::al_top);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryMessageReplyMarkup::createFromButtonRows(const QVector<MTPKeyboardButtonRow> &v) {
|
void HistoryMessageReplyMarkup::createFromButtonRows(const QVector<MTPKeyboardButtonRow> &v) {
|
||||||
|
@ -22,8 +22,13 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
|
|
||||||
#include "core/runtime_composer.h"
|
#include "core/runtime_composer.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class RippleAnimation;
|
||||||
|
} // namespace Ui
|
||||||
|
|
||||||
namespace style {
|
namespace style {
|
||||||
struct BotKeyboardButton;
|
struct BotKeyboardButton;
|
||||||
|
struct RippleAnimation;
|
||||||
} // namespace style
|
} // namespace style
|
||||||
|
|
||||||
class HistoryElement {
|
class HistoryElement {
|
||||||
@ -294,13 +299,14 @@ public:
|
|||||||
int buttonSkip() const;
|
int buttonSkip() const;
|
||||||
int buttonPadding() const;
|
int buttonPadding() const;
|
||||||
int buttonHeight() const;
|
int buttonHeight() const;
|
||||||
|
virtual int buttonRadius() const = 0;
|
||||||
|
|
||||||
virtual void repaint(const HistoryItem *item) const = 0;
|
virtual void repaint(const HistoryItem *item) const = 0;
|
||||||
virtual ~Style() {
|
virtual ~Style() {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void paintButtonBg(Painter &p, const QRect &rect, bool pressed, float64 howMuchOver) const = 0;
|
virtual void paintButtonBg(Painter &p, const QRect &rect, float64 howMuchOver) const = 0;
|
||||||
virtual void paintButtonIcon(Painter &p, const QRect &rect, int outerWidth, HistoryMessageReplyMarkup::Button::Type type) const = 0;
|
virtual void paintButtonIcon(Painter &p, const QRect &rect, int outerWidth, HistoryMessageReplyMarkup::Button::Type type) const = 0;
|
||||||
virtual void paintButtonLoading(Painter &p, const QRect &rect) const = 0;
|
virtual void paintButtonLoading(Painter &p, const QRect &rect) const = 0;
|
||||||
virtual int minButtonWidth(HistoryMessageReplyMarkup::Button::Type type) const = 0;
|
virtual int minButtonWidth(HistoryMessageReplyMarkup::Button::Type type) const = 0;
|
||||||
@ -308,7 +314,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
const style::BotKeyboardButton *_st;
|
const style::BotKeyboardButton *_st;
|
||||||
|
|
||||||
void paintButton(Painter &p, int outerWidth, const ReplyKeyboard::Button &button) const;
|
void paintButton(Painter &p, int outerWidth, const ReplyKeyboard::Button &button, uint64 ms) const;
|
||||||
friend class ReplyKeyboard;
|
friend class ReplyKeyboard;
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -326,7 +332,7 @@ public:
|
|||||||
int naturalWidth() const;
|
int naturalWidth() const;
|
||||||
int naturalHeight() const;
|
int naturalHeight() const;
|
||||||
|
|
||||||
void paint(Painter &p, int outerWidth, const QRect &clip) const;
|
void paint(Painter &p, int outerWidth, const QRect &clip, uint64 ms) const;
|
||||||
ClickHandlerPtr getState(int x, int y) const;
|
ClickHandlerPtr getState(int x, int y) const;
|
||||||
|
|
||||||
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active);
|
void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active);
|
||||||
@ -336,8 +342,7 @@ public:
|
|||||||
void updateMessageId();
|
void updateMessageId();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const HistoryItem *_item;
|
void startAnimation(int i, int j, int direction);
|
||||||
int _width = 0;
|
|
||||||
|
|
||||||
friend class Style;
|
friend class Style;
|
||||||
using ReplyMarkupClickHandlerPtr = QSharedPointer<ReplyMarkupClickHandler>;
|
using ReplyMarkupClickHandlerPtr = QSharedPointer<ReplyMarkupClickHandler>;
|
||||||
@ -348,17 +353,33 @@ private:
|
|||||||
float64 howMuchOver = 0.;
|
float64 howMuchOver = 0.;
|
||||||
HistoryMessageReplyMarkup::Button::Type type;
|
HistoryMessageReplyMarkup::Button::Type type;
|
||||||
ReplyMarkupClickHandlerPtr link;
|
ReplyMarkupClickHandlerPtr link;
|
||||||
|
mutable QSharedPointer<Ui::RippleAnimation> ripple;
|
||||||
};
|
};
|
||||||
using ButtonRow = QVector<Button>;
|
using ButtonRow = QVector<Button>;
|
||||||
using ButtonRows = QVector<ButtonRow>;
|
using ButtonRows = QVector<ButtonRow>;
|
||||||
ButtonRows _rows;
|
|
||||||
|
struct ButtonCoords {
|
||||||
|
int i, j;
|
||||||
|
};
|
||||||
|
ButtonCoords findButtonCoordsByClickHandler(const ClickHandlerPtr &p);
|
||||||
|
|
||||||
using Animations = QMap<int, uint64>;
|
using Animations = QMap<int, uint64>;
|
||||||
Animations _animations;
|
|
||||||
Animation _a_selected;
|
|
||||||
void step_selected(uint64 ms, bool timer);
|
void step_selected(uint64 ms, bool timer);
|
||||||
|
|
||||||
|
const HistoryItem *_item;
|
||||||
|
int _width = 0;
|
||||||
|
|
||||||
|
ButtonRows _rows;
|
||||||
|
|
||||||
|
Animations _animations;
|
||||||
|
Animation _a_selected;
|
||||||
|
|
||||||
StylePtr _st;
|
StylePtr _st;
|
||||||
|
|
||||||
|
ClickHandlerPtr _savedPressed;
|
||||||
|
ClickHandlerPtr _savedActive;
|
||||||
|
mutable QPoint _savedCoords;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// any HistoryItem can have this Interface for
|
// any HistoryItem can have this Interface for
|
||||||
|
@ -310,11 +310,12 @@ void HistoryMessage::KeyboardStyle::repaint(const HistoryItem *item) const {
|
|||||||
Ui::repaintHistoryItem(item);
|
Ui::repaintHistoryItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryMessage::KeyboardStyle::paintButtonBg(Painter &p, const QRect &rect, bool down, float64 howMuchOver) const {
|
int HistoryMessage::KeyboardStyle::buttonRadius() const {
|
||||||
|
return st::dateRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistoryMessage::KeyboardStyle::paintButtonBg(Painter &p, const QRect &rect, float64 howMuchOver) const {
|
||||||
App::roundRect(p, rect, st::msgServiceBg, StickerCorners);
|
App::roundRect(p, rect, st::msgServiceBg, StickerCorners);
|
||||||
if (down) {
|
|
||||||
howMuchOver = 1.;
|
|
||||||
}
|
|
||||||
if (howMuchOver > 0) {
|
if (howMuchOver > 0) {
|
||||||
auto o = p.opacity();
|
auto o = p.opacity();
|
||||||
p.setOpacity(o * howMuchOver);
|
p.setOpacity(o * howMuchOver);
|
||||||
@ -1278,7 +1279,7 @@ void HistoryMessage::draw(Painter &p, const QRect &r, TextSelection selection, u
|
|||||||
height -= h;
|
height -= h;
|
||||||
int top = height + st::msgBotKbButton.margin - marginBottom();
|
int top = height + st::msgBotKbButton.margin - marginBottom();
|
||||||
p.translate(left, top);
|
p.translate(left, top);
|
||||||
keyboard->paint(p, width, r.translated(-left, -top));
|
keyboard->paint(p, width, r.translated(-left, -top), ms);
|
||||||
p.translate(-left, -top);
|
p.translate(-left, -top);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,12 +208,14 @@ private:
|
|||||||
public:
|
public:
|
||||||
using ReplyKeyboard::Style::Style;
|
using ReplyKeyboard::Style::Style;
|
||||||
|
|
||||||
|
int buttonRadius() const override;
|
||||||
|
|
||||||
void startPaint(Painter &p) const override;
|
void startPaint(Painter &p) const override;
|
||||||
style::font textFont() const override;
|
style::font textFont() const override;
|
||||||
void repaint(const HistoryItem *item) const override;
|
void repaint(const HistoryItem *item) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintButtonBg(Painter &p, const QRect &rect, bool down, float64 howMuchOver) const override;
|
void paintButtonBg(Painter &p, const QRect &rect, float64 howMuchOver) const override;
|
||||||
void paintButtonIcon(Painter &p, const QRect &rect, int outerWidth, HistoryMessageReplyMarkup::Button::Type type) const override;
|
void paintButtonIcon(Painter &p, const QRect &rect, int outerWidth, HistoryMessageReplyMarkup::Button::Type type) const override;
|
||||||
void paintButtonLoading(Painter &p, const QRect &rect) const override;
|
void paintButtonLoading(Painter &p, const QRect &rect) const override;
|
||||||
int minButtonWidth(HistoryMessageReplyMarkup::Button::Type type) const override;
|
int minButtonWidth(HistoryMessageReplyMarkup::Button::Type type) const override;
|
||||||
|
@ -2437,7 +2437,7 @@ void BotKeyboard::paintEvent(QPaintEvent *e) {
|
|||||||
if (_impl) {
|
if (_impl) {
|
||||||
int x = rtl() ? st::botKbScroll.width : _st->margin;
|
int x = rtl() ? st::botKbScroll.width : _st->margin;
|
||||||
p.translate(x, st::botKbScroll.deltat);
|
p.translate(x, st::botKbScroll.deltat);
|
||||||
_impl->paint(p, width(), clip.translated(-x, -st::botKbScroll.deltat));
|
_impl->paint(p, width(), clip.translated(-x, -st::botKbScroll.deltat), getms());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2454,17 +2454,12 @@ void BotKeyboard::Style::repaint(const HistoryItem *item) const {
|
|||||||
_parent->update();
|
_parent->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BotKeyboard::Style::paintButtonBg(Painter &p, const QRect &rect, bool down, float64 howMuchOver) const {
|
int BotKeyboard::Style::buttonRadius() const {
|
||||||
if (down) {
|
return st::buttonRadius;
|
||||||
App::roundRect(p, rect, st::botKbDownBg, BotKeyboardDownCorners);
|
}
|
||||||
} else {
|
|
||||||
App::roundRect(p, rect, st::botKbBg, BotKeyboardCorners);
|
void BotKeyboard::Style::paintButtonBg(Painter &p, const QRect &rect, float64 howMuchOver) const {
|
||||||
if (howMuchOver > 0) {
|
App::roundRect(p, rect, st::botKbBg, BotKeyboardCorners);
|
||||||
p.setOpacity(howMuchOver);
|
|
||||||
App::roundRect(p, rect, st::botKbOverBg, BotKeyboardOverCorners);
|
|
||||||
p.setOpacity(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BotKeyboard::Style::paintButtonIcon(Painter &p, const QRect &rect, int outerWidth, HistoryMessageReplyMarkup::Button::Type type) const {
|
void BotKeyboard::Style::paintButtonIcon(Painter &p, const QRect &rect, int outerWidth, HistoryMessageReplyMarkup::Button::Type type) const {
|
||||||
@ -3018,7 +3013,7 @@ TextWithTags::Tags textTagsFromEntities(const EntitiesInText &entities) {
|
|||||||
HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
|
HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent)
|
||||||
, _fieldBarCancel(this, st::historyReplyCancel)
|
, _fieldBarCancel(this, st::historyReplyCancel)
|
||||||
, _scroll(this, st::historyScroll, false)
|
, _scroll(this, st::historyScroll, false)
|
||||||
, _historyToEnd(this)
|
, _historyToEnd(this, st::historyToDown)
|
||||||
, _fieldAutocomplete(this)
|
, _fieldAutocomplete(this)
|
||||||
, _reportSpamPanel(this)
|
, _reportSpamPanel(this)
|
||||||
, _send(this, st::historySend)
|
, _send(this, st::historySend)
|
||||||
|
@ -427,12 +427,14 @@ private:
|
|||||||
Style(BotKeyboard *parent, const style::BotKeyboardButton &st) : ReplyKeyboard::Style(st), _parent(parent) {
|
Style(BotKeyboard *parent, const style::BotKeyboardButton &st) : ReplyKeyboard::Style(st), _parent(parent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int buttonRadius() const override;
|
||||||
|
|
||||||
void startPaint(Painter &p) const override;
|
void startPaint(Painter &p) const override;
|
||||||
style::font textFont() const override;
|
style::font textFont() const override;
|
||||||
void repaint(const HistoryItem *item) const override;
|
void repaint(const HistoryItem *item) const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintButtonBg(Painter &p, const QRect &rect, bool down, float64 howMuchOver) const override;
|
void paintButtonBg(Painter &p, const QRect &rect, float64 howMuchOver) const override;
|
||||||
void paintButtonIcon(Painter &p, const QRect &rect, int outerWidth, HistoryMessageReplyMarkup::Button::Type type) const override;
|
void paintButtonIcon(Painter &p, const QRect &rect, int outerWidth, HistoryMessageReplyMarkup::Button::Type type) const override;
|
||||||
void paintButtonLoading(Painter &p, const QRect &rect) const override;
|
void paintButtonLoading(Painter &p, const QRect &rect) const override;
|
||||||
int minButtonWidth(HistoryMessageReplyMarkup::Button::Type type) const override;
|
int minButtonWidth(HistoryMessageReplyMarkup::Button::Type type) const override;
|
||||||
|
@ -83,7 +83,6 @@ introNextButton: RoundButton(defaultActiveButton) {
|
|||||||
height: 56px;
|
height: 56px;
|
||||||
|
|
||||||
textTop: 16px;
|
textTop: 16px;
|
||||||
downTextTop: 17px;
|
|
||||||
|
|
||||||
font: font(17px);
|
font: font(17px);
|
||||||
}
|
}
|
||||||
@ -147,8 +146,6 @@ introBackButton: IconButton {
|
|||||||
{ size(40px, 40px), #eeeeee },
|
{ size(40px, 40px), #eeeeee },
|
||||||
{ "title_back", #969696, point(12px, 12px) },
|
{ "title_back", #969696, point(12px, 12px) },
|
||||||
};
|
};
|
||||||
|
|
||||||
iconPosition: point(0px, 0px);
|
iconPosition: point(0px, 0px);
|
||||||
iconPositionDown: point(0px, 0px);
|
|
||||||
}
|
}
|
||||||
introBackPosition: point(32px, 32px);
|
introBackPosition: point(32px, 32px);
|
||||||
|
@ -76,7 +76,6 @@ mediaPlayerRepeatButton: IconButton {
|
|||||||
{ "player_repeat", mediaPlayerActiveFg, point(9px, 11px) }
|
{ "player_repeat", mediaPlayerActiveFg, point(9px, 11px) }
|
||||||
};
|
};
|
||||||
iconPosition: point(0px, 0px);
|
iconPosition: point(0px, 0px);
|
||||||
iconPositionDown: point(0px, 0px);
|
|
||||||
}
|
}
|
||||||
mediaPlayerRepeatDisabledIcon: icon {
|
mediaPlayerRepeatDisabledIcon: icon {
|
||||||
{ "player_repeat", #c8c8c8, point(9px, 11px)}
|
{ "player_repeat", #c8c8c8, point(9px, 11px)}
|
||||||
@ -103,7 +102,6 @@ mediaPlayerVolumeToggle: IconButton {
|
|||||||
|
|
||||||
icon: mediaPlayerVolumeIcon0;
|
icon: mediaPlayerVolumeIcon0;
|
||||||
iconPosition: point(8px, 11px);
|
iconPosition: point(8px, 11px);
|
||||||
iconPositionDown: point(8px, 11px);
|
|
||||||
}
|
}
|
||||||
mediaPlayerVolumeMargin: 10px;
|
mediaPlayerVolumeMargin: 10px;
|
||||||
mediaPlayerVolumeSize: size(27px, 100px);
|
mediaPlayerVolumeSize: size(27px, 100px);
|
||||||
|
@ -51,9 +51,7 @@ mediaviewPlayButton: IconButton {
|
|||||||
|
|
||||||
icon: icon {{ "media_play", #c7c7c7, point(3px, 0px) }};
|
icon: icon {{ "media_play", #c7c7c7, point(3px, 0px) }};
|
||||||
iconOver: icon {{ "media_play", #ffffff, point(3px, 0px) }};
|
iconOver: icon {{ "media_play", #ffffff, point(3px, 0px) }};
|
||||||
|
|
||||||
iconPosition: point(3px, 1px);
|
iconPosition: point(3px, 1px);
|
||||||
iconPositionDown: point(3px, 1px);
|
|
||||||
|
|
||||||
duration: mediaviewOverDuration;
|
duration: mediaviewOverDuration;
|
||||||
}
|
}
|
||||||
@ -67,7 +65,6 @@ mediaviewFullScreenButton: IconButton(mediaviewPlayButton) {
|
|||||||
icon: icon {{ "media_fullscreen_to", #c7c7c7, point(0px, 0px) }};
|
icon: icon {{ "media_fullscreen_to", #c7c7c7, point(0px, 0px) }};
|
||||||
iconOver: icon {{ "media_fullscreen_to", #ffffff, point(0px, 0px) }};
|
iconOver: icon {{ "media_fullscreen_to", #ffffff, point(0px, 0px) }};
|
||||||
iconPosition: point(0px, 1px);
|
iconPosition: point(0px, 1px);
|
||||||
iconPositionDown: point(0px, 1px);
|
|
||||||
}
|
}
|
||||||
mediaviewFullScreenOutIcon: icon {{ "media_fullscreen_from", #c7c7c7, point(0px, 0px) }};
|
mediaviewFullScreenOutIcon: icon {{ "media_fullscreen_from", #c7c7c7, point(0px, 0px) }};
|
||||||
mediaviewFullScreenOutIconOver: icon {{ "media_fullscreen_from", #ffffff, point(0px, 0px) }};
|
mediaviewFullScreenOutIconOver: icon {{ "media_fullscreen_from", #ffffff, point(0px, 0px) }};
|
||||||
@ -136,6 +133,10 @@ mediaviewMenu: Menu(defaultMenu) {
|
|||||||
itemFgShortcutDisabled: mediaviewMenuFg;
|
itemFgShortcutDisabled: mediaviewMenuFg;
|
||||||
|
|
||||||
separatorFg: mediaviewMenuFg;
|
separatorFg: mediaviewMenuFg;
|
||||||
|
|
||||||
|
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||||
|
color: mediaviewMenuBgRipple;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mediaviewMenuShadow: Shadow(defaultEmptyShadow) {
|
mediaviewMenuShadow: Shadow(defaultEmptyShadow) {
|
||||||
fallback: mediaviewMenuBg;
|
fallback: mediaviewMenuBg;
|
||||||
|
@ -23,7 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
|
|
||||||
#include "styles/style_profile.h"
|
#include "styles/style_profile.h"
|
||||||
#include "styles/style_boxes.h"
|
#include "styles/style_boxes.h"
|
||||||
#include "ui/buttons/left_outline_button.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "boxes/confirmbox.h"
|
#include "boxes/confirmbox.h"
|
||||||
#include "boxes/report_box.h"
|
#include "boxes/report_box.h"
|
||||||
#include "mainwidget.h"
|
#include "mainwidget.h"
|
||||||
|
@ -23,7 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
|
|
||||||
#include "styles/style_profile.h"
|
#include "styles/style_profile.h"
|
||||||
#include "mtproto/file_download.h"
|
#include "mtproto/file_download.h"
|
||||||
#include "ui/buttons/left_outline_button.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/widgets/labels.h"
|
#include "ui/widgets/labels.h"
|
||||||
#include "boxes/contactsbox.h"
|
#include "boxes/contactsbox.h"
|
||||||
#include "boxes/confirmbox.h"
|
#include "boxes/confirmbox.h"
|
||||||
|
@ -22,7 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
#include "profile/profile_settings_widget.h"
|
#include "profile/profile_settings_widget.h"
|
||||||
|
|
||||||
#include "styles/style_profile.h"
|
#include "styles/style_profile.h"
|
||||||
#include "ui/buttons/left_outline_button.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/widgets/checkbox.h"
|
#include "ui/widgets/checkbox.h"
|
||||||
#include "boxes/confirmbox.h"
|
#include "boxes/confirmbox.h"
|
||||||
#include "boxes/contactsbox.h"
|
#include "boxes/contactsbox.h"
|
||||||
|
@ -23,7 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
|
|
||||||
#include "styles/style_profile.h"
|
#include "styles/style_profile.h"
|
||||||
#include "observer_peer.h"
|
#include "observer_peer.h"
|
||||||
#include "ui/buttons/left_outline_button.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "mainwidget.h"
|
#include "mainwidget.h"
|
||||||
#include "lang.h"
|
#include "lang.h"
|
||||||
|
|
||||||
|
@ -76,7 +76,6 @@ settingsEditButton: IconButton {
|
|||||||
|
|
||||||
icon: icon {{ "settings_edit_name", #b7b7b7 }};
|
icon: icon {{ "settings_edit_name", #b7b7b7 }};
|
||||||
iconPosition: point(3px, 9px);
|
iconPosition: point(3px, 9px);
|
||||||
iconPositionDown: point(3px, 10px);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
settingsBlocksTop: 7px;
|
settingsBlocksTop: 7px;
|
||||||
|
@ -24,6 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
#include "styles/style_stickers.h"
|
#include "styles/style_stickers.h"
|
||||||
#include "ui/widgets/buttons.h"
|
#include "ui/widgets/buttons.h"
|
||||||
#include "ui/widgets/shadow.h"
|
#include "ui/widgets/shadow.h"
|
||||||
|
#include "ui/effects/ripple_animation.h"
|
||||||
#include "boxes/confirmbox.h"
|
#include "boxes/confirmbox.h"
|
||||||
#include "boxes/stickersetbox.h"
|
#include "boxes/stickersetbox.h"
|
||||||
#include "boxes/stickers_box.h"
|
#include "boxes/stickers_box.h"
|
||||||
@ -1003,13 +1004,13 @@ void StickerPanInner::paintStickers(Painter &p, const QRect &r) {
|
|||||||
tocol = StickerPanPerRow - tocol;
|
tocol = StickerPanPerRow - tocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
int y, tilly = 0;
|
auto tilly = 0;
|
||||||
|
auto ms = getms();
|
||||||
auto &sets = shownSets();
|
auto &sets = shownSets();
|
||||||
if (_section == Section::Featured) {
|
if (_section == Section::Featured) {
|
||||||
tilly += st::emojiPanHeader;
|
tilly += st::emojiPanHeader;
|
||||||
for (int c = 0, l = sets.size(); c < l; ++c) {
|
for (int c = 0, l = sets.size(); c < l; ++c) {
|
||||||
y = tilly;
|
auto y = tilly;
|
||||||
auto &set = sets[c];
|
auto &set = sets[c];
|
||||||
tilly = y + featuredRowHeight();
|
tilly = y + featuredRowHeight();
|
||||||
if (r.top() >= tilly) continue;
|
if (r.top() >= tilly) continue;
|
||||||
@ -1020,14 +1021,19 @@ void StickerPanInner::paintStickers(Painter &p, const QRect &r) {
|
|||||||
int widthForTitle = featuredContentWidth() - (st::emojiPanHeaderLeft - st::buttonRadius);
|
int widthForTitle = featuredContentWidth() - (st::emojiPanHeaderLeft - st::buttonRadius);
|
||||||
if (featuredHasAddButton(c)) {
|
if (featuredHasAddButton(c)) {
|
||||||
auto add = featuredAddRect(c);
|
auto add = featuredAddRect(c);
|
||||||
auto selected = (_selectedFeaturedSetAdd == c);
|
auto selected = (_selectedFeaturedSetAdd == c) || (_pressedFeaturedSetAdd == c);
|
||||||
auto &textBg = selected ? st::stickersTrendingAdd.textBgOver : st::stickersTrendingAdd.textBg;
|
auto &textBg = selected ? st::stickersTrendingAdd.textBgOver : st::stickersTrendingAdd.textBg;
|
||||||
auto textTop = (selected && _selectedFeaturedSetAdd == _pressedFeaturedSetAdd) ? st::stickersTrendingAdd.downTextTop : st::stickersTrendingAdd.textTop;
|
|
||||||
|
|
||||||
App::roundRect(p, myrtlrect(add), textBg, ImageRoundRadius::Small);
|
App::roundRect(p, myrtlrect(add), textBg, ImageRoundRadius::Small);
|
||||||
|
if (set.ripple) {
|
||||||
|
set.ripple->paint(p, add.x(), add.y(), width(), ms);
|
||||||
|
if (set.ripple->empty()) {
|
||||||
|
set.ripple.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
p.setFont(st::stickersTrendingAdd.font);
|
p.setFont(st::stickersTrendingAdd.font);
|
||||||
p.setPen(selected ? st::stickersTrendingAdd.textFgOver : st::stickersTrendingAdd.textFg);
|
p.setPen(selected ? st::stickersTrendingAdd.textFgOver : st::stickersTrendingAdd.textFg);
|
||||||
p.drawTextLeft(add.x() - (st::stickersTrendingAdd.width / 2), add.y() + textTop, width(), _addText, _addWidth);
|
p.drawTextLeft(add.x() - (st::stickersTrendingAdd.width / 2), add.y() + st::stickersTrendingAdd.textTop, width(), _addText, _addWidth);
|
||||||
|
|
||||||
widthForTitle -= add.width() - (st::stickersTrendingAdd.width / 2);
|
widthForTitle -= add.width() - (st::stickersTrendingAdd.width / 2);
|
||||||
} else {
|
} else {
|
||||||
@ -1075,10 +1081,10 @@ void StickerPanInner::paintStickers(Painter &p, const QRect &r) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int c = 0, l = sets.size(); c < l; ++c) {
|
for (int c = 0, l = sets.size(); c < l; ++c) {
|
||||||
y = tilly;
|
auto y = tilly;
|
||||||
auto &set = sets[c];
|
auto &set = sets[c];
|
||||||
int32 size = set.pack.size();
|
auto size = set.pack.size();
|
||||||
int32 rows = (size / StickerPanPerRow) + ((size % StickerPanPerRow) ? 1 : 0);
|
auto rows = (size / StickerPanPerRow) + ((size % StickerPanPerRow) ? 1 : 0);
|
||||||
tilly = y + st::emojiPanHeader + (rows * st::stickerPanSize.height());
|
tilly = y + st::emojiPanHeader + (rows * st::stickerPanSize.height());
|
||||||
if (r.y() >= tilly) continue;
|
if (r.y() >= tilly) continue;
|
||||||
|
|
||||||
@ -1175,25 +1181,45 @@ void StickerPanInner::mousePressEvent(QMouseEvent *e) {
|
|||||||
|
|
||||||
_pressed = _selected;
|
_pressed = _selected;
|
||||||
_pressedFeaturedSet = _selectedFeaturedSet;
|
_pressedFeaturedSet = _selectedFeaturedSet;
|
||||||
_pressedFeaturedSetAdd = _selectedFeaturedSetAdd;
|
setPressedFeaturedSetAdd(_selectedFeaturedSetAdd);
|
||||||
ClickHandler::pressed();
|
ClickHandler::pressed();
|
||||||
_previewTimer.start(QApplication::startDragTime());
|
_previewTimer.start(QApplication::startDragTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StickerPanInner::setPressedFeaturedSetAdd(int newPressedFeaturedSetAdd) {
|
||||||
|
if (_pressedFeaturedSetAdd >= 0 && _pressedFeaturedSetAdd < _featuredSets.size()) {
|
||||||
|
auto &set = _featuredSets[_pressedFeaturedSetAdd];
|
||||||
|
if (set.ripple) {
|
||||||
|
set.ripple->lastStop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_pressedFeaturedSetAdd = newPressedFeaturedSetAdd;
|
||||||
|
if (_pressedFeaturedSetAdd >= 0 && _pressedFeaturedSetAdd < _featuredSets.size()) {
|
||||||
|
auto &set = _featuredSets[_pressedFeaturedSetAdd];
|
||||||
|
if (!set.ripple) {
|
||||||
|
auto maskSize = QSize(_addWidth - st::stickersTrendingAdd.width, st::stickersTrendingAdd.height);
|
||||||
|
auto mask = Ui::RippleAnimation::roundRectMask(maskSize, st::buttonRadius);
|
||||||
|
set.ripple = MakeShared<Ui::RippleAnimation>(st::stickersTrendingAdd.ripple, std_::move(mask), [this, index = _pressedFeaturedSetAdd] {
|
||||||
|
update(myrtlrect(featuredAddRect(index)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
auto rect = myrtlrect(featuredAddRect(_pressedFeaturedSetAdd));
|
||||||
|
set.ripple->add(mapFromGlobal(QCursor::pos()) - rect.topLeft());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void StickerPanInner::mouseReleaseEvent(QMouseEvent *e) {
|
void StickerPanInner::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
_previewTimer.stop();
|
_previewTimer.stop();
|
||||||
|
|
||||||
auto pressed = _pressed;
|
auto pressed = base::take(_pressed, -1);
|
||||||
_pressed = -1;
|
auto pressedFeaturedSet = base::take(_pressedFeaturedSet, -1);
|
||||||
auto pressedFeaturedSet = _pressedFeaturedSet;
|
|
||||||
_pressedFeaturedSet = -1;
|
|
||||||
auto pressedFeaturedSetAdd = _pressedFeaturedSetAdd;
|
auto pressedFeaturedSetAdd = _pressedFeaturedSetAdd;
|
||||||
if (_pressedFeaturedSetAdd != _selectedFeaturedSetAdd) {
|
setPressedFeaturedSetAdd(-1);
|
||||||
|
if (pressedFeaturedSetAdd != _selectedFeaturedSetAdd) {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
_pressedFeaturedSetAdd = -1;
|
|
||||||
|
|
||||||
ClickHandlerPtr activated = ClickHandler::unpressed();
|
auto activated = ClickHandler::unpressed();
|
||||||
|
|
||||||
if (_previewShown) {
|
if (_previewShown) {
|
||||||
_previewShown = false;
|
_previewShown = false;
|
||||||
@ -1360,7 +1386,8 @@ void StickerPanInner::clearSelection(bool fast) {
|
|||||||
}
|
}
|
||||||
_selected = _pressed = -1;
|
_selected = _pressed = -1;
|
||||||
_selectedFeaturedSet = _pressedFeaturedSet = -1;
|
_selectedFeaturedSet = _pressedFeaturedSet = -1;
|
||||||
_selectedFeaturedSetAdd = _pressedFeaturedSetAdd = -1;
|
_selectedFeaturedSetAdd = -1;
|
||||||
|
setPressedFeaturedSetAdd(-1);
|
||||||
_a_selected.stop();
|
_a_selected.stop();
|
||||||
update();
|
update();
|
||||||
} else {
|
} else {
|
||||||
|
@ -37,6 +37,7 @@ class ScrollArea;
|
|||||||
class IconButton;
|
class IconButton;
|
||||||
class LinkButton;
|
class LinkButton;
|
||||||
class RoundButton;
|
class RoundButton;
|
||||||
|
class RippleAnimation;
|
||||||
} // namesapce Ui
|
} // namesapce Ui
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
@ -307,6 +308,8 @@ private:
|
|||||||
static constexpr bool kRefreshIconsScrollAnimation = true;
|
static constexpr bool kRefreshIconsScrollAnimation = true;
|
||||||
static constexpr bool kRefreshIconsNoAnimation = false;
|
static constexpr bool kRefreshIconsNoAnimation = false;
|
||||||
|
|
||||||
|
void setPressedFeaturedSetAdd(int newPressedFeaturedSetAdd);
|
||||||
|
|
||||||
struct Set {
|
struct Set {
|
||||||
Set(uint64 id, MTPDstickerSet::Flags flags, const QString &title, int32 hoversSize, const StickerPack &pack = StickerPack()) : id(id), flags(flags), title(title), hovers(hoversSize, 0), pack(pack) {
|
Set(uint64 id, MTPDstickerSet::Flags flags, const QString &title, int32 hoversSize, const StickerPack &pack = StickerPack()) : id(id), flags(flags), title(title), hovers(hoversSize, 0), pack(pack) {
|
||||||
}
|
}
|
||||||
@ -315,6 +318,7 @@ private:
|
|||||||
QString title;
|
QString title;
|
||||||
QVector<float64> hovers;
|
QVector<float64> hovers;
|
||||||
StickerPack pack;
|
StickerPack pack;
|
||||||
|
QSharedPointer<Ui::RippleAnimation> ripple;
|
||||||
};
|
};
|
||||||
using Sets = QList<Set>;
|
using Sets = QList<Set>;
|
||||||
Sets &shownSets() {
|
Sets &shownSets() {
|
||||||
|
@ -27,7 +27,6 @@ switchPmButton: RoundButton(defaultBoxButton) {
|
|||||||
width: 320px;
|
width: 320px;
|
||||||
height: 34px;
|
height: 34px;
|
||||||
textTop: 7px;
|
textTop: 7px;
|
||||||
downTextTop: 8px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stickersTrendingHeader: 45px;
|
stickersTrendingHeader: 45px;
|
||||||
@ -45,7 +44,6 @@ stickersTrendingAdd: RoundButton(defaultActiveButton) {
|
|||||||
width: -17px;
|
width: -17px;
|
||||||
height: 26px;
|
height: 26px;
|
||||||
textTop: 4px;
|
textTop: 4px;
|
||||||
downTextTop: 5px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stickerEmojiSkip: 5px;
|
stickerEmojiSkip: 5px;
|
||||||
@ -113,7 +111,6 @@ emojiCategory: IconButton {
|
|||||||
height: 46px;
|
height: 46px;
|
||||||
|
|
||||||
iconPosition: point(11px, 12px);
|
iconPosition: point(11px, 12px);
|
||||||
iconPositionDown: point(11px, 12px);
|
|
||||||
}
|
}
|
||||||
emojiCategoryRecent: IconButton(emojiCategory) { icon: emojiRecent; }
|
emojiCategoryRecent: IconButton(emojiCategory) { icon: emojiRecent; }
|
||||||
emojiCategoryPeople: IconButton(emojiCategory) { icon: emojiPeople; }
|
emojiCategoryPeople: IconButton(emojiCategory) { icon: emojiPeople; }
|
||||||
@ -174,7 +171,5 @@ hashtagClose: IconButton {
|
|||||||
|
|
||||||
icon: simpleCloseIcon;
|
icon: simpleCloseIcon;
|
||||||
iconOver: simpleCloseIconOver;
|
iconOver: simpleCloseIconOver;
|
||||||
|
|
||||||
iconPosition: point(10px, 10px);
|
iconPosition: point(10px, 10px);
|
||||||
iconPositionDown: point(10px, 11px);
|
|
||||||
}
|
}
|
||||||
|
@ -23,46 +23,43 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
|
|
||||||
#include "styles/style_history.h"
|
#include "styles/style_history.h"
|
||||||
#include "dialogs/dialogs_layout.h"
|
#include "dialogs/dialogs_layout.h"
|
||||||
|
#include "ui/effects/ripple_animation.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
|
||||||
HistoryDownButton::HistoryDownButton(QWidget *parent) : AbstractButton(parent)
|
HistoryDownButton::HistoryDownButton(QWidget *parent, const style::TwoIconButton &st) : RippleButton(parent, st.ripple)
|
||||||
|
, _st(st)
|
||||||
//, a_arrowOpacity(st::historyAttachEmoji.opacity, st::historyAttachEmoji.opacity)
|
//, a_arrowOpacity(st::historyAttachEmoji.opacity, st::historyAttachEmoji.opacity)
|
||||||
, _a_arrowOver(animation(this, &HistoryDownButton::step_arrowOver)) {
|
, _a_arrowOver(animation(this, &HistoryDownButton::step_arrowOver)) {
|
||||||
|
resize(_st.width, _st.height);
|
||||||
setCursor(style::cur_pointer);
|
setCursor(style::cur_pointer);
|
||||||
|
|
||||||
int iconWidth = st::historyToDown.width();
|
|
||||||
int iconHeight = st::historyToDown.height();
|
|
||||||
int retina = cIntRetinaFactor();
|
|
||||||
resize(iconWidth, st::historyToDownPaddingTop + iconHeight);
|
|
||||||
|
|
||||||
QImage cache(iconWidth * retina, iconHeight * retina, QImage::Format_ARGB32_Premultiplied);
|
|
||||||
cache.setDevicePixelRatio(cRetinaFactor());
|
|
||||||
{
|
|
||||||
Painter p(&cache);
|
|
||||||
p.setCompositionMode(QPainter::CompositionMode_Source);
|
|
||||||
p.fillRect(0, 0, iconWidth, iconHeight, Qt::transparent);
|
|
||||||
st::historyToDown.paint(p, QPoint(0, 0), st::historyToDown.width());
|
|
||||||
}
|
|
||||||
_cache = App::pixmapFromImageInPlace(std_::move(cache));
|
|
||||||
_cache.setDevicePixelRatio(cRetinaFactor());
|
|
||||||
|
|
||||||
hide();
|
hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QImage HistoryDownButton::prepareRippleMask() const {
|
||||||
|
return Ui::RippleAnimation::ellipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
QPoint HistoryDownButton::prepareRippleStartPosition() const {
|
||||||
|
return mapFromGlobal(QCursor::pos()) - _st.rippleAreaPosition;
|
||||||
|
}
|
||||||
|
|
||||||
void HistoryDownButton::paintEvent(QPaintEvent *e) {
|
void HistoryDownButton::paintEvent(QPaintEvent *e) {
|
||||||
Painter p(this);
|
Painter p(this);
|
||||||
|
|
||||||
if (_a_show.animating(getms())) {
|
auto ms = getms();
|
||||||
p.setOpacity(_a_show.current());
|
auto opacity = _a_show.current(ms, _shown ? 1. : 0.);
|
||||||
p.drawPixmap(0, st::historyToDownPaddingTop, _cache);
|
if (opacity == 0.) {
|
||||||
} else if (!_shown) {
|
if (!_shown) hide();
|
||||||
hide();
|
|
||||||
return;
|
return;
|
||||||
} else {
|
|
||||||
st::historyToDown.paint(p, QPoint(0, st::historyToDownPaddingTop), width());
|
|
||||||
}
|
}
|
||||||
st::historyToDownArrow.paint(p, QPoint(0, st::historyToDownPaddingTop), width());
|
p.setOpacity(opacity);
|
||||||
|
auto over = (_state & StateOver);
|
||||||
|
auto down = (_state & StateDown);
|
||||||
|
((over || down) ? _st.iconBelowOver : _st.iconBelow).paint(p, _st.iconPosition, width());
|
||||||
|
paintRipple(p, _st.rippleAreaPosition.x(), _st.rippleAreaPosition.y(), ms);
|
||||||
|
((over || down) ? _st.iconAboveOver : _st.iconAbove).paint(p, _st.iconPosition, width());
|
||||||
if (_unreadCount > 0) {
|
if (_unreadCount > 0) {
|
||||||
auto unreadString = QString::number(_unreadCount);
|
auto unreadString = QString::number(_unreadCount);
|
||||||
if (unreadString.size() > 4) {
|
if (unreadString.size() > 4) {
|
||||||
@ -78,18 +75,6 @@ void HistoryDownButton::paintEvent(QPaintEvent *e) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryDownButton::onStateChanged(int oldState, StateChangeSource source) {
|
|
||||||
//a_arrowOpacity.start((_state & (StateOver | StateDown)) ? st::historyAttachEmoji.overOpacity : st::historyAttachEmoji.opacity);
|
|
||||||
|
|
||||||
if (source == StateChangeSource::ByUser || source == StateChangeSource::ByPress) {
|
|
||||||
_a_arrowOver.stop();
|
|
||||||
a_arrowOpacity.finish();
|
|
||||||
update();
|
|
||||||
} else {
|
|
||||||
_a_arrowOver.start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HistoryDownButton::setUnreadCount(int unreadCount) {
|
void HistoryDownButton::setUnreadCount(int unreadCount) {
|
||||||
_unreadCount = unreadCount;
|
_unreadCount = unreadCount;
|
||||||
update();
|
update();
|
||||||
@ -152,7 +137,7 @@ void EmojiButton::paintEvent(QPaintEvent *e) {
|
|||||||
|
|
||||||
auto over = (_state & StateOver);
|
auto over = (_state & StateOver);
|
||||||
auto icon = &(over ? _st.iconOver : _st.icon);
|
auto icon = &(over ? _st.iconOver : _st.icon);
|
||||||
icon->paint(p, (_state & StateDown) ? _st.iconPositionDown : _st.iconPosition, width());
|
icon->paint(p, _st.iconPosition, width());
|
||||||
|
|
||||||
p.setOpacity(1.);
|
p.setOpacity(1.);
|
||||||
p.setPen(QPen(over ? st::historyEmojiCircleFgOver : st::historyEmojiCircleFg, st::historyEmojiCircleLine));
|
p.setPen(QPen(over ? st::historyEmojiCircleFgOver : st::historyEmojiCircleFg, st::historyEmojiCircleLine));
|
||||||
|
@ -20,14 +20,14 @@ 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 HistoryDownButton : public AbstractButton {
|
class HistoryDownButton : public RippleButton {
|
||||||
public:
|
public:
|
||||||
HistoryDownButton(QWidget *parent);
|
HistoryDownButton(QWidget *parent, const style::TwoIconButton &st);
|
||||||
|
|
||||||
void setUnreadCount(int unreadCount);
|
void setUnreadCount(int unreadCount);
|
||||||
int unreadCount() const {
|
int unreadCount() const {
|
||||||
@ -44,13 +44,15 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
|
||||||
void onStateChanged(int oldState, StateChangeSource source) override;
|
QImage prepareRippleMask() const override;
|
||||||
|
QPoint prepareRippleStartPosition() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void toggleAnimated();
|
void toggleAnimated();
|
||||||
void step_arrowOver(float64 ms, bool timer);
|
void step_arrowOver(float64 ms, bool timer);
|
||||||
|
|
||||||
QPixmap _cache;
|
const style::TwoIconButton &_st;
|
||||||
|
|
||||||
bool _shown = false;
|
bool _shown = false;
|
||||||
|
|
||||||
anim::fvalue a_arrowOpacity;
|
anim::fvalue a_arrowOpacity;
|
||||||
|
@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Telegram Desktop,
|
|
||||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
|
||||||
|
|
||||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
It is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
In addition, as a special exception, the copyright holders give permission
|
|
||||||
to link the code of portions of this program with the OpenSSL library.
|
|
||||||
|
|
||||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
|
||||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|
||||||
*/
|
|
||||||
#include "stdafx.h"
|
|
||||||
#include "ui/buttons/left_outline_button.h"
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
|
|
||||||
LeftOutlineButton::LeftOutlineButton(QWidget *parent, const QString &text, const style::OutlineButton &st) : AbstractButton(parent)
|
|
||||||
, _text(text)
|
|
||||||
, _fullText(text)
|
|
||||||
, _textWidth(st.font->width(_text))
|
|
||||||
, _fullTextWidth(_textWidth)
|
|
||||||
, _st(st) {
|
|
||||||
resizeToWidth(_textWidth + _st.padding.left() + _st.padding.right());
|
|
||||||
|
|
||||||
setCursor(style::cur_pointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LeftOutlineButton::setText(const QString &text) {
|
|
||||||
_text = text;
|
|
||||||
_fullText = text;
|
|
||||||
_fullTextWidth = _textWidth = _st.font->width(_text);
|
|
||||||
resizeToWidth(width());
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
int LeftOutlineButton::resizeGetHeight(int newWidth) {
|
|
||||||
int availableWidth = qMax(newWidth - _st.padding.left() - _st.padding.right(), 1);
|
|
||||||
if ((availableWidth < _fullTextWidth) || (_textWidth < availableWidth)) {
|
|
||||||
_text = _st.font->elided(_fullText, availableWidth);
|
|
||||||
_textWidth = _st.font->width(_text);
|
|
||||||
}
|
|
||||||
return _st.padding.top() + _st.font->height + _st.padding.bottom();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LeftOutlineButton::paintEvent(QPaintEvent *e) {
|
|
||||||
Painter p(this);
|
|
||||||
|
|
||||||
bool over = (_state & StateOver);
|
|
||||||
if (width() > _st.outlineWidth) {
|
|
||||||
p.fillRect(rtlrect(0, 0, _st.outlineWidth, height(), width()), over ? _st.outlineFgOver : _st.outlineFg);
|
|
||||||
p.fillRect(rtlrect(_st.outlineWidth, 0, width() - _st.outlineWidth, height(), width()), over ? _st.textBgOver : _st.textBg);
|
|
||||||
}
|
|
||||||
p.setFont(_st.font);
|
|
||||||
p.setPen(over ? _st.textFgOver : _st.textFg);
|
|
||||||
p.drawTextLeft(_st.padding.left(), _st.padding.top(), width(), _text, _textWidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LeftOutlineButton::onStateChanged(int oldState, StateChangeSource source) {
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Ui
|
|
@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of Telegram Desktop,
|
|
||||||
the official desktop version of Telegram messaging app, see https://telegram.org
|
|
||||||
|
|
||||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
It is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
In addition, as a special exception, the copyright holders give permission
|
|
||||||
to link the code of portions of this program with the OpenSSL library.
|
|
||||||
|
|
||||||
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
|
||||||
Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "ui/abstract_button.h"
|
|
||||||
#include "styles/style_widgets.h"
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
|
|
||||||
class LeftOutlineButton : public AbstractButton {
|
|
||||||
public:
|
|
||||||
LeftOutlineButton(QWidget *parent, const QString &text, const style::OutlineButton &st = st::defaultLeftOutlineButton);
|
|
||||||
|
|
||||||
void setText(const QString &text);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void paintEvent(QPaintEvent *e) override;
|
|
||||||
|
|
||||||
void onStateChanged(int oldState, StateChangeSource source) override;
|
|
||||||
|
|
||||||
int resizeGetHeight(int newWidth) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString _text, _fullText;
|
|
||||||
int _textWidth, _fullTextWidth;
|
|
||||||
|
|
||||||
const style::OutlineButton &_st;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Ui
|
|
@ -190,6 +190,35 @@ void RippleAnimation::paint(QPainter &p, int x, int y, int outerWidth, uint64 ms
|
|||||||
clearFinished();
|
clearFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QImage RippleAnimation::maskByDrawer(QSize size, bool filled, base::lambda_unique<void(QPainter &p)> drawer) {
|
||||||
|
auto result = QImage(size * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
||||||
|
result.fill(filled ? QColor(255, 255, 255) : Qt::transparent);
|
||||||
|
if (drawer) {
|
||||||
|
Painter p(&result);
|
||||||
|
p.setRenderHint(QPainter::HighQualityAntialiasing);
|
||||||
|
p.setPen(Qt::NoPen);
|
||||||
|
p.setBrush(QColor(255, 255, 255));
|
||||||
|
drawer(p);
|
||||||
|
}
|
||||||
|
return std_::move(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage RippleAnimation::rectMask(QSize size) {
|
||||||
|
return maskByDrawer(size, true, base::lambda_unique<void(QPainter&)>());
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage RippleAnimation::roundRectMask(QSize size, int radius) {
|
||||||
|
return maskByDrawer(size, false, [size, radius](QPainter &p) {
|
||||||
|
p.drawRoundedRect(0, 0, size.width(), size.height(), radius, radius);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage RippleAnimation::ellipseMask(QSize size) {
|
||||||
|
return maskByDrawer(size, false, [size](QPainter &p) {
|
||||||
|
p.drawEllipse(0, 0, size.width(), size.height());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void RippleAnimation::clearFinished() {
|
void RippleAnimation::clearFinished() {
|
||||||
while (!_ripples.isEmpty() && _ripples.front()->finished()) {
|
while (!_ripples.isEmpty() && _ripples.front()->finished()) {
|
||||||
delete base::take(_ripples.front());
|
delete base::take(_ripples.front());
|
||||||
|
@ -45,6 +45,11 @@ public:
|
|||||||
return _ripples.isEmpty();
|
return _ripples.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QImage maskByDrawer(QSize size, bool filled, base::lambda_unique<void(QPainter &p)> drawer);
|
||||||
|
static QImage rectMask(QSize size);
|
||||||
|
static QImage roundRectMask(QSize size, int radius);
|
||||||
|
static QImage ellipseMask(QSize size);
|
||||||
|
|
||||||
~RippleAnimation() {
|
~RippleAnimation() {
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,111 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
|
||||||
FlatButton::FlatButton(QWidget *parent, const QString &text, const style::FlatButton &st) : AbstractButton(parent)
|
LinkButton::LinkButton(QWidget *parent, const QString &text, const style::LinkButton &st) : AbstractButton(parent)
|
||||||
|
, _text(text)
|
||||||
|
, _textWidth(st.font->width(_text))
|
||||||
|
, _st(st) {
|
||||||
|
resize(_textWidth, _st.font->height);
|
||||||
|
setCursor(style::cur_pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int LinkButton::naturalWidth() const {
|
||||||
|
return _textWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinkButton::paintEvent(QPaintEvent *e) {
|
||||||
|
Painter p(this);
|
||||||
|
auto &font = ((_state & StateOver) ? _st.overFont : _st.font);
|
||||||
|
auto &pen = ((_state & StateDown) ? _st.downColor : ((_state & StateOver) ? _st.overColor : _st.color));
|
||||||
|
p.setFont(font);
|
||||||
|
p.setPen(pen);
|
||||||
|
if (_textWidth > width()) {
|
||||||
|
p.drawText(0, font->ascent, font->elided(_text, width()));
|
||||||
|
} else {
|
||||||
|
p.drawText(0, font->ascent, _text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinkButton::setText(const QString &text) {
|
||||||
|
_text = text;
|
||||||
|
_textWidth = _st.font->width(_text);
|
||||||
|
resize(_textWidth, _st.font->height);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinkButton::onStateChanged(int oldState, StateChangeSource source) {
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
RippleButton::RippleButton(QWidget *parent, const style::RippleAnimation &st) : AbstractButton(parent)
|
||||||
|
, _st(st) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void RippleButton::setForceRippled(bool rippled, SetForceRippledWay way) {
|
||||||
|
if (_forceRippled != rippled) {
|
||||||
|
_forceRippled = rippled;
|
||||||
|
if (_forceRippled) {
|
||||||
|
ensureRipple();
|
||||||
|
if (_ripple->empty()) {
|
||||||
|
_ripple->addFading();
|
||||||
|
} else {
|
||||||
|
_ripple->lastUnstop();
|
||||||
|
}
|
||||||
|
} else if (_ripple) {
|
||||||
|
_ripple->lastStop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (way == SetForceRippledWay::SkipAnimation && _ripple) {
|
||||||
|
_ripple->lastFinish();
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RippleButton::paintRipple(QPainter &p, int x, int y, uint64 ms) {
|
||||||
|
if (_ripple) {
|
||||||
|
_ripple->paint(p, x, y, width(), ms);
|
||||||
|
if (_ripple->empty()) {
|
||||||
|
_ripple.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RippleButton::onStateChanged(int oldState, StateChangeSource source) {
|
||||||
|
update();
|
||||||
|
|
||||||
|
auto wasDown = (oldState & StateDown);
|
||||||
|
auto down = (_state & StateDown);
|
||||||
|
if (!_st.showDuration || down == wasDown || _forceRippled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (down && (source == StateChangeSource::ByPress)) {
|
||||||
|
// Start a ripple only from mouse press.
|
||||||
|
ensureRipple();
|
||||||
|
_ripple->add(prepareRippleStartPosition());
|
||||||
|
} else if (!down && _ripple) {
|
||||||
|
// Finish ripple anyway.
|
||||||
|
_ripple->lastStop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RippleButton::ensureRipple() {
|
||||||
|
if (!_ripple) {
|
||||||
|
_ripple = std_::make_unique<RippleAnimation>(_st, prepareRippleMask(), [this] { update(); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage RippleButton::prepareRippleMask() const {
|
||||||
|
return RippleAnimation::rectMask(size());
|
||||||
|
}
|
||||||
|
|
||||||
|
QPoint RippleButton::prepareRippleStartPosition() const {
|
||||||
|
return mapFromGlobal(QCursor::pos());
|
||||||
|
}
|
||||||
|
|
||||||
|
RippleButton::~RippleButton() = default;
|
||||||
|
|
||||||
|
FlatButton::FlatButton(QWidget *parent, const QString &text, const style::FlatButton &st) : RippleButton(parent, st.ripple)
|
||||||
, _text(text)
|
, _text(text)
|
||||||
, _st(st)
|
, _st(st)
|
||||||
, a_over(0)
|
, a_over(0)
|
||||||
@ -81,6 +185,8 @@ void FlatButton::step_appearance(float64 ms, bool timer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FlatButton::onStateChanged(int oldState, StateChangeSource source) {
|
void FlatButton::onStateChanged(int oldState, StateChangeSource source) {
|
||||||
|
RippleButton::onStateChanged(oldState, source);
|
||||||
|
|
||||||
a_over.start((_state & StateOver) ? 1. : 0.);
|
a_over.start((_state & StateOver) ? 1. : 0.);
|
||||||
if (source == StateChangeSource::ByUser || source == StateChangeSource::ByPress) {
|
if (source == StateChangeSource::ByUser || source == StateChangeSource::ByPress) {
|
||||||
_a_appearance.stop();
|
_a_appearance.stop();
|
||||||
@ -89,27 +195,6 @@ void FlatButton::onStateChanged(int oldState, StateChangeSource source) {
|
|||||||
} else {
|
} else {
|
||||||
_a_appearance.start();
|
_a_appearance.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
handleRipples(oldState & StateDown, (source == StateChangeSource::ByPress));
|
|
||||||
}
|
|
||||||
|
|
||||||
void FlatButton::handleRipples(bool wasDown, bool wasPress) {
|
|
||||||
auto down = static_cast<bool>(_state & StateDown);
|
|
||||||
if (!_st.ripple.showDuration || down == wasDown) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (down && wasPress) {
|
|
||||||
// Start a ripple only from mouse press.
|
|
||||||
if (!_ripple) {
|
|
||||||
_ripple = std_::make_unique<Ui::RippleAnimation>(_st.ripple, prepareRippleMask(), [this] { update(); });
|
|
||||||
}
|
|
||||||
auto clickPosition = mapFromGlobal(QCursor::pos());
|
|
||||||
_ripple->add(clickPosition);
|
|
||||||
} else if (!down && _ripple) {
|
|
||||||
// Finish ripple anyway.
|
|
||||||
_ripple->lastStop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlatButton::paintEvent(QPaintEvent *e) {
|
void FlatButton::paintEvent(QPaintEvent *e) {
|
||||||
@ -121,69 +206,17 @@ void FlatButton::paintEvent(QPaintEvent *e) {
|
|||||||
p.fillRect(r, anim::brush(_st.bgColor, _st.overBgColor, a_over.current()));
|
p.fillRect(r, anim::brush(_st.bgColor, _st.overBgColor, a_over.current()));
|
||||||
|
|
||||||
auto ms = getms();
|
auto ms = getms();
|
||||||
if (_ripple) {
|
paintRipple(p, 0, 0, ms);
|
||||||
_ripple->paint(p, 0, 0, width(), ms);
|
|
||||||
if (_ripple->empty()) {
|
|
||||||
_ripple.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p.setFont((_state & StateOver) ? _st.overFont : _st.font);
|
p.setFont((_state & StateOver) ? _st.overFont : _st.font);
|
||||||
p.setRenderHint(QPainter::TextAntialiasing);
|
p.setRenderHint(QPainter::TextAntialiasing);
|
||||||
p.setPen(anim::pen(_st.color, _st.overColor, a_over.current()));
|
p.setPen(anim::pen(_st.color, _st.overColor, a_over.current()));
|
||||||
|
|
||||||
auto top = (_state & StateDown) ? _st.downTextTop : ((_state & StateOver) ? _st.overTextTop : _st.textTop);
|
r.setTop(_st.textTop);
|
||||||
r.setTop(top);
|
|
||||||
|
|
||||||
p.drawText(r, _text, style::al_top);
|
p.drawText(r, _text, style::al_top);
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage FlatButton::prepareRippleMask() const {
|
RoundButton::RoundButton(QWidget *parent, const QString &text, const style::RoundButton &st) : RippleButton(parent, st.ripple)
|
||||||
auto result = QImage(size() * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
|
||||||
result.setDevicePixelRatio(cRetinaFactor());
|
|
||||||
result.fill(QColor(255, 255, 255));
|
|
||||||
return std_::move(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
FlatButton::~FlatButton() = default;
|
|
||||||
|
|
||||||
LinkButton::LinkButton(QWidget *parent, const QString &text, const style::LinkButton &st) : AbstractButton(parent)
|
|
||||||
, _text(text)
|
|
||||||
, _textWidth(st.font->width(_text))
|
|
||||||
, _st(st) {
|
|
||||||
resize(_textWidth, _st.font->height);
|
|
||||||
setCursor(style::cur_pointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
int LinkButton::naturalWidth() const {
|
|
||||||
return _textWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LinkButton::paintEvent(QPaintEvent *e) {
|
|
||||||
Painter p(this);
|
|
||||||
auto &font = ((_state & StateOver) ? _st.overFont : _st.font);
|
|
||||||
auto &pen = ((_state & StateDown) ? _st.downColor : ((_state & StateOver) ? _st.overColor : _st.color));
|
|
||||||
p.setFont(font);
|
|
||||||
p.setPen(pen);
|
|
||||||
if (_textWidth > width()) {
|
|
||||||
p.drawText(0, font->ascent, font->elided(_text, width()));
|
|
||||||
} else {
|
|
||||||
p.drawText(0, font->ascent, _text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LinkButton::setText(const QString &text) {
|
|
||||||
_text = text;
|
|
||||||
_textWidth = _st.font->width(_text);
|
|
||||||
resize(_textWidth, _st.font->height);
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LinkButton::onStateChanged(int oldState, StateChangeSource source) {
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
RoundButton::RoundButton(QWidget *parent, const QString &text, const style::RoundButton &st) : AbstractButton(parent)
|
|
||||||
, _fullText(text)
|
, _fullText(text)
|
||||||
, _st(st) {
|
, _st(st) {
|
||||||
setCursor(style::cur_pointer);
|
setCursor(style::cur_pointer);
|
||||||
@ -264,20 +297,14 @@ void RoundButton::paintEvent(QPaintEvent *e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto ms = getms();
|
auto ms = getms();
|
||||||
if (_ripple) {
|
paintRipple(p, rounded.x(), rounded.y(), ms);
|
||||||
_ripple->paint(p, rounded.x(), rounded.y(), width(), ms);
|
|
||||||
if (_ripple->empty()) {
|
|
||||||
_ripple.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p.setFont(_st.font);
|
p.setFont(_st.font);
|
||||||
int textLeft = _st.padding.left() + ((width() - innerWidth - _st.padding.left() - _st.padding.right()) / 2);
|
int textLeft = _st.padding.left() + ((width() - innerWidth - _st.padding.left() - _st.padding.right()) / 2);
|
||||||
if (_fullWidthOverride < 0) {
|
if (_fullWidthOverride < 0) {
|
||||||
textLeft = -_fullWidthOverride / 2;
|
textLeft = -_fullWidthOverride / 2;
|
||||||
}
|
}
|
||||||
int textTopDelta = (_state & StateDown) ? (_st.downTextTop - _st.textTop) : 0;
|
int textTop = _st.padding.top() + _st.textTop;
|
||||||
int textTop = _st.padding.top() + _st.textTop + textTopDelta;
|
|
||||||
if (!_text.isEmpty()) {
|
if (!_text.isEmpty()) {
|
||||||
p.setPen((over || down) ? _st.textFgOver : _st.textFg);
|
p.setPen((over || down) ? _st.textFgOver : _st.textFg);
|
||||||
p.drawTextLeft(textLeft, textTop, width(), _text);
|
p.drawTextLeft(textLeft, textTop, width(), _text);
|
||||||
@ -287,32 +314,7 @@ void RoundButton::paintEvent(QPaintEvent *e) {
|
|||||||
p.setPen((over || down) ? _st.secondaryTextFgOver : _st.secondaryTextFg);
|
p.setPen((over || down) ? _st.secondaryTextFgOver : _st.secondaryTextFg);
|
||||||
p.drawTextLeft(textLeft, textTop, width(), _secondaryText);
|
p.drawTextLeft(textLeft, textTop, width(), _secondaryText);
|
||||||
}
|
}
|
||||||
_st.icon.paint(p, QPoint(_st.padding.left(), _st.padding.right() + textTopDelta), width());
|
_st.icon.paint(p, QPoint(_st.padding.left(), _st.padding.right()), width());
|
||||||
}
|
|
||||||
|
|
||||||
void RoundButton::onStateChanged(int oldState, StateChangeSource source) {
|
|
||||||
update();
|
|
||||||
|
|
||||||
handleRipples(oldState & StateDown, (source == StateChangeSource::ByPress));
|
|
||||||
}
|
|
||||||
|
|
||||||
void RoundButton::handleRipples(bool wasDown, bool wasPress) {
|
|
||||||
auto down = static_cast<bool>(_state & StateDown);
|
|
||||||
if (!_st.ripple.showDuration || down == wasDown) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (down && wasPress) {
|
|
||||||
// Start a ripple only from mouse press.
|
|
||||||
if (!_ripple) {
|
|
||||||
_ripple = std_::make_unique<Ui::RippleAnimation>(_st.ripple, prepareRippleMask(), [this] { update(); });
|
|
||||||
}
|
|
||||||
auto clickPosition = mapFromGlobal(QCursor::pos()) - QPoint(_st.padding.left(), _st.padding.top());
|
|
||||||
_ripple->add(clickPosition);
|
|
||||||
} else if (!down && _ripple) {
|
|
||||||
// Finish ripple anyway.
|
|
||||||
_ripple->lastStop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage RoundButton::prepareRippleMask() const {
|
QImage RoundButton::prepareRippleMask() const {
|
||||||
@ -321,22 +323,14 @@ QImage RoundButton::prepareRippleMask() const {
|
|||||||
if (_fullWidthOverride < 0) {
|
if (_fullWidthOverride < 0) {
|
||||||
rounded = QRect(0, rounded.top(), innerWidth - _fullWidthOverride, rounded.height());
|
rounded = QRect(0, rounded.top(), innerWidth - _fullWidthOverride, rounded.height());
|
||||||
}
|
}
|
||||||
|
return RippleAnimation::roundRectMask(rounded.size(), st::buttonRadius);
|
||||||
auto result = QImage(rounded.size() * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
|
||||||
result.setDevicePixelRatio(cRetinaFactor());
|
|
||||||
result.fill(Qt::transparent);
|
|
||||||
{
|
|
||||||
Painter p(&result);
|
|
||||||
p.setPen(Qt::NoPen);
|
|
||||||
p.setBrush(QColor(255, 255, 255));
|
|
||||||
p.drawRoundedRect(rounded.translated(-rounded.topLeft()), st::buttonRadius, st::buttonRadius);
|
|
||||||
}
|
|
||||||
return std_::move(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RoundButton::~RoundButton() = default;
|
QPoint RoundButton::prepareRippleStartPosition() const {
|
||||||
|
return mapFromGlobal(QCursor::pos()) - QPoint(_st.padding.left(), _st.padding.top());
|
||||||
|
}
|
||||||
|
|
||||||
IconButton::IconButton(QWidget *parent, const style::IconButton &st) : AbstractButton(parent)
|
IconButton::IconButton(QWidget *parent, const style::IconButton &st) : RippleButton(parent, st.ripple)
|
||||||
, _st(st) {
|
, _st(st) {
|
||||||
resize(_st.width, _st.height);
|
resize(_st.width, _st.height);
|
||||||
setCursor(style::cur_pointer);
|
setCursor(style::cur_pointer);
|
||||||
@ -348,40 +342,15 @@ void IconButton::setIcon(const style::icon *icon, const style::icon *iconOver) {
|
|||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IconButton::setActiveState(bool activeState, SetStateWay way) {
|
|
||||||
if (_activeState != activeState) {
|
|
||||||
_activeState = activeState;
|
|
||||||
if (_activeState) {
|
|
||||||
ensureRipple();
|
|
||||||
if (_ripple->empty()) {
|
|
||||||
_ripple->addFading();
|
|
||||||
} else {
|
|
||||||
_ripple->lastUnstop();
|
|
||||||
}
|
|
||||||
} else if (_ripple) {
|
|
||||||
_ripple->lastStop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (way == SetStateWay::SkipAnimation && _ripple) {
|
|
||||||
_ripple->lastFinish();
|
|
||||||
}
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IconButton::paintEvent(QPaintEvent *e) {
|
void IconButton::paintEvent(QPaintEvent *e) {
|
||||||
Painter p(this);
|
Painter p(this);
|
||||||
|
|
||||||
auto ms = getms();
|
auto ms = getms();
|
||||||
|
|
||||||
if (_ripple) {
|
paintRipple(p, _st.rippleAreaPosition.x(), _st.rippleAreaPosition.y(), ms);
|
||||||
_ripple->paint(p, _st.rippleAreaPosition.x(), _st.rippleAreaPosition.y(), width(), ms);
|
|
||||||
if (_ripple->empty()) {
|
|
||||||
_ripple.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto down = (_state & StateDown);
|
auto down = (_state & StateDown);
|
||||||
auto overIconOpacity = (down || _activeState) ? 1. : _a_over.current(getms(), (_state & StateOver) ? 1. : 0.);
|
auto overIconOpacity = (down || forceRippled()) ? 1. : _a_over.current(getms(), (_state & StateOver) ? 1. : 0.);
|
||||||
auto overIcon = [this] {
|
auto overIcon = [this] {
|
||||||
if (_iconOverrideOver) {
|
if (_iconOverrideOver) {
|
||||||
return _iconOverrideOver;
|
return _iconOverrideOver;
|
||||||
@ -399,7 +368,7 @@ void IconButton::paintEvent(QPaintEvent *e) {
|
|||||||
return &_st.icon;
|
return &_st.icon;
|
||||||
};
|
};
|
||||||
auto icon = (overIconOpacity == 1.) ? overIcon() : justIcon();
|
auto icon = (overIconOpacity == 1.) ? overIcon() : justIcon();
|
||||||
auto position = (_state & StateDown) ? _st.iconPositionDown : _st.iconPosition;
|
auto position = _st.iconPosition;
|
||||||
if (position.x() < 0) {
|
if (position.x() < 0) {
|
||||||
position.setX((width() - icon->width()) / 2);
|
position.setX((width() - icon->width()) / 2);
|
||||||
}
|
}
|
||||||
@ -417,6 +386,8 @@ void IconButton::paintEvent(QPaintEvent *e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IconButton::onStateChanged(int oldState, StateChangeSource source) {
|
void IconButton::onStateChanged(int oldState, StateChangeSource source) {
|
||||||
|
RippleButton::onStateChanged(oldState, source);
|
||||||
|
|
||||||
auto over = (_state & StateOver);
|
auto over = (_state & StateOver);
|
||||||
if (over != (oldState & StateOver)) {
|
if (over != (oldState & StateOver)) {
|
||||||
if (_st.duration) {
|
if (_st.duration) {
|
||||||
@ -427,54 +398,56 @@ void IconButton::onStateChanged(int oldState, StateChangeSource source) {
|
|||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleRipples(oldState & StateDown, (source == StateChangeSource::ByPress));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IconButton::handleRipples(bool wasDown, bool wasPress) {
|
QPoint IconButton::prepareRippleStartPosition() const {
|
||||||
auto down = static_cast<bool>(_state & StateDown);
|
return mapFromGlobal(QCursor::pos()) - _st.rippleAreaPosition;
|
||||||
if (!_st.ripple.showDuration || _st.rippleAreaSize <= 0 || down == wasDown) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (down && wasPress && !_activeState) {
|
|
||||||
// Start a ripple only from mouse press.
|
|
||||||
ensureRipple();
|
|
||||||
auto clickPosition = mapFromGlobal(QCursor::pos());
|
|
||||||
auto rippleCenter = QRect(_st.rippleAreaPosition, QSize(_st.rippleAreaSize, _st.rippleAreaSize)).center();
|
|
||||||
auto clickRadiusSquare = style::point::dotProduct(clickPosition - rippleCenter, clickPosition - rippleCenter);
|
|
||||||
auto startRadius = 0;
|
|
||||||
if (clickRadiusSquare * 4 > _st.rippleAreaSize * _st.rippleAreaSize) {
|
|
||||||
startRadius = sqrt(clickRadiusSquare) - (_st.rippleAreaSize / 2);
|
|
||||||
}
|
|
||||||
_ripple->add(clickPosition - _st.rippleAreaPosition, startRadius);
|
|
||||||
} else if (!down && _ripple && !_activeState) {
|
|
||||||
// Finish ripple anyway.
|
|
||||||
_ripple->lastStop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void IconButton::ensureRipple() {
|
|
||||||
if (!_ripple) {
|
|
||||||
_ripple = std_::make_unique<Ui::RippleAnimation>(_st.ripple, prepareRippleMask(), [this] { update(); });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage IconButton::prepareRippleMask() const {
|
QImage IconButton::prepareRippleMask() const {
|
||||||
auto size = _st.rippleAreaSize * cIntRetinaFactor();
|
return RippleAnimation::ellipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize));
|
||||||
auto result = QImage(size, size, QImage::Format_ARGB32_Premultiplied);
|
|
||||||
result.setDevicePixelRatio(cRetinaFactor());
|
|
||||||
result.fill(Qt::transparent);
|
|
||||||
{
|
|
||||||
Painter p(&result);
|
|
||||||
p.setRenderHint(QPainter::HighQualityAntialiasing);
|
|
||||||
p.setPen(Qt::NoPen);
|
|
||||||
p.setBrush(QColor(255, 255, 255));
|
|
||||||
p.drawEllipse(0, 0, _st.rippleAreaSize, _st.rippleAreaSize);
|
|
||||||
}
|
|
||||||
return std_::move(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IconButton::~IconButton() = default;
|
LeftOutlineButton::LeftOutlineButton(QWidget *parent, const QString &text, const style::OutlineButton &st) : RippleButton(parent, st.ripple)
|
||||||
|
, _text(text)
|
||||||
|
, _fullText(text)
|
||||||
|
, _textWidth(st.font->width(_text))
|
||||||
|
, _fullTextWidth(_textWidth)
|
||||||
|
, _st(st) {
|
||||||
|
resizeToWidth(_textWidth + _st.padding.left() + _st.padding.right());
|
||||||
|
|
||||||
|
setCursor(style::cur_pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LeftOutlineButton::setText(const QString &text) {
|
||||||
|
_text = text;
|
||||||
|
_fullText = text;
|
||||||
|
_fullTextWidth = _textWidth = _st.font->width(_text);
|
||||||
|
resizeToWidth(width());
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
int LeftOutlineButton::resizeGetHeight(int newWidth) {
|
||||||
|
int availableWidth = qMax(newWidth - _st.padding.left() - _st.padding.right(), 1);
|
||||||
|
if ((availableWidth < _fullTextWidth) || (_textWidth < availableWidth)) {
|
||||||
|
_text = _st.font->elided(_fullText, availableWidth);
|
||||||
|
_textWidth = _st.font->width(_text);
|
||||||
|
}
|
||||||
|
return _st.padding.top() + _st.font->height + _st.padding.bottom();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LeftOutlineButton::paintEvent(QPaintEvent *e) {
|
||||||
|
Painter p(this);
|
||||||
|
|
||||||
|
bool over = (_state & StateOver), down = (_state & StateDown);
|
||||||
|
if (width() > _st.outlineWidth) {
|
||||||
|
p.fillRect(rtlrect(_st.outlineWidth, 0, width() - _st.outlineWidth, height(), width()), (over || down) ? _st.textBgOver : _st.textBg);
|
||||||
|
paintRipple(p, 0, 0, getms());
|
||||||
|
p.fillRect(rtlrect(0, 0, _st.outlineWidth, height(), width()), (over || down) ? _st.outlineFgOver : _st.outlineFg);
|
||||||
|
}
|
||||||
|
p.setFont(_st.font);
|
||||||
|
p.setPen((over || down) ? _st.textFgOver : _st.textFg);
|
||||||
|
p.drawTextLeft(_st.padding.left(), _st.padding.top(), width(), _text, _textWidth);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
@ -27,44 +27,6 @@ namespace Ui {
|
|||||||
|
|
||||||
class RippleAnimation;
|
class RippleAnimation;
|
||||||
|
|
||||||
class FlatButton : public AbstractButton {
|
|
||||||
public:
|
|
||||||
FlatButton(QWidget *parent, const QString &text, const style::FlatButton &st);
|
|
||||||
|
|
||||||
void step_appearance(float64 ms, bool timer);
|
|
||||||
void setOpacity(float64 o);
|
|
||||||
float64 opacity() const;
|
|
||||||
|
|
||||||
void setText(const QString &text);
|
|
||||||
void setWidth(int32 w);
|
|
||||||
|
|
||||||
int32 textWidth() const;
|
|
||||||
|
|
||||||
~FlatButton();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void paintEvent(QPaintEvent *e) override;
|
|
||||||
|
|
||||||
void onStateChanged(int oldState, StateChangeSource source) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
QImage prepareRippleMask() const;
|
|
||||||
void handleRipples(bool wasDown, bool wasPress);
|
|
||||||
|
|
||||||
QString _text, _textForAutoSize;
|
|
||||||
int _width;
|
|
||||||
|
|
||||||
const style::FlatButton &_st;
|
|
||||||
|
|
||||||
anim::fvalue a_over;
|
|
||||||
Animation _a_appearance;
|
|
||||||
|
|
||||||
float64 _opacity = 1.;
|
|
||||||
|
|
||||||
std_::unique_ptr<RippleAnimation> _ripple;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class LinkButton : public AbstractButton {
|
class LinkButton : public AbstractButton {
|
||||||
public:
|
public:
|
||||||
LinkButton(QWidget *parent, const QString &text, const style::LinkButton &st = st::defaultLinkButton);
|
LinkButton(QWidget *parent, const QString &text, const style::LinkButton &st = st::defaultLinkButton);
|
||||||
@ -85,7 +47,73 @@ private:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class RoundButton : public AbstractButton {
|
class RippleButton : public AbstractButton {
|
||||||
|
public:
|
||||||
|
RippleButton(QWidget *parent, const style::RippleAnimation &st);
|
||||||
|
|
||||||
|
// Displays full ripple circle constantly.
|
||||||
|
enum class SetForceRippledWay {
|
||||||
|
Default,
|
||||||
|
SkipAnimation,
|
||||||
|
};
|
||||||
|
void setForceRippled(bool rippled, SetForceRippledWay way = SetForceRippledWay::Default);
|
||||||
|
bool forceRippled() const {
|
||||||
|
return _forceRippled;
|
||||||
|
}
|
||||||
|
|
||||||
|
~RippleButton();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintRipple(QPainter &p, int x, int y, uint64 ms);
|
||||||
|
|
||||||
|
void onStateChanged(int oldState, StateChangeSource source) override;
|
||||||
|
|
||||||
|
virtual QImage prepareRippleMask() const;
|
||||||
|
virtual QPoint prepareRippleStartPosition() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ensureRipple();
|
||||||
|
void handleRipples(bool wasDown, bool wasPress);
|
||||||
|
|
||||||
|
const style::RippleAnimation &_st;
|
||||||
|
std_::unique_ptr<RippleAnimation> _ripple;
|
||||||
|
bool _forceRippled = false;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class FlatButton : public RippleButton {
|
||||||
|
public:
|
||||||
|
FlatButton(QWidget *parent, const QString &text, const style::FlatButton &st);
|
||||||
|
|
||||||
|
void step_appearance(float64 ms, bool timer);
|
||||||
|
|
||||||
|
void setText(const QString &text);
|
||||||
|
void setWidth(int32 w);
|
||||||
|
|
||||||
|
int32 textWidth() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
|
||||||
|
void onStateChanged(int oldState, StateChangeSource source) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setOpacity(float64 o);
|
||||||
|
float64 opacity() const;
|
||||||
|
|
||||||
|
QString _text, _textForAutoSize;
|
||||||
|
int _width;
|
||||||
|
|
||||||
|
const style::FlatButton &_st;
|
||||||
|
|
||||||
|
anim::fvalue a_over;
|
||||||
|
Animation _a_appearance;
|
||||||
|
|
||||||
|
float64 _opacity = 1.;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class RoundButton : public RippleButton {
|
||||||
public:
|
public:
|
||||||
RoundButton(QWidget *parent, const QString &text, const style::RoundButton &st);
|
RoundButton(QWidget *parent, const QString &text, const style::RoundButton &st);
|
||||||
|
|
||||||
@ -102,17 +130,13 @@ public:
|
|||||||
};
|
};
|
||||||
void setTextTransform(TextTransform transform);
|
void setTextTransform(TextTransform transform);
|
||||||
|
|
||||||
~RoundButton();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
|
||||||
void onStateChanged(int oldState, StateChangeSource source) override;
|
QImage prepareRippleMask() const override;
|
||||||
|
QPoint prepareRippleStartPosition() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QImage prepareRippleMask() const;
|
|
||||||
void handleRipples(bool wasDown, bool wasPress);
|
|
||||||
|
|
||||||
void updateText();
|
void updateText();
|
||||||
void resizeToText();
|
void resizeToText();
|
||||||
|
|
||||||
@ -128,44 +152,48 @@ private:
|
|||||||
|
|
||||||
TextTransform _transform = TextTransform::ToUpper;
|
TextTransform _transform = TextTransform::ToUpper;
|
||||||
|
|
||||||
std_::unique_ptr<RippleAnimation> _ripple;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class IconButton : public AbstractButton {
|
class IconButton : public RippleButton {
|
||||||
public:
|
public:
|
||||||
IconButton(QWidget *parent, const style::IconButton &st);
|
IconButton(QWidget *parent, const style::IconButton &st);
|
||||||
|
|
||||||
// Pass nullptr to restore the default icon.
|
// Pass nullptr to restore the default icon.
|
||||||
void setIcon(const style::icon *icon, const style::icon *iconOver = nullptr);
|
void setIcon(const style::icon *icon, const style::icon *iconOver = nullptr);
|
||||||
|
|
||||||
// Displays full ripple circle constantly.
|
|
||||||
enum class SetStateWay {
|
|
||||||
Default,
|
|
||||||
SkipAnimation,
|
|
||||||
};
|
|
||||||
void setActiveState(bool activeState, SetStateWay way = SetStateWay::Default);
|
|
||||||
|
|
||||||
~IconButton();
|
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
private:
|
QImage prepareRippleMask() const override;
|
||||||
void ensureRipple();
|
QPoint prepareRippleStartPosition() const override;
|
||||||
QImage prepareRippleMask() const;
|
|
||||||
void handleRipples(bool wasDown, bool wasPress);
|
|
||||||
|
|
||||||
|
private:
|
||||||
const style::IconButton &_st;
|
const style::IconButton &_st;
|
||||||
const style::icon *_iconOverride = nullptr;
|
const style::icon *_iconOverride = nullptr;
|
||||||
const style::icon *_iconOverrideOver = nullptr;
|
const style::icon *_iconOverrideOver = nullptr;
|
||||||
|
|
||||||
FloatAnimation _a_over;
|
FloatAnimation _a_over;
|
||||||
|
|
||||||
std_::unique_ptr<RippleAnimation> _ripple;
|
};
|
||||||
bool _activeState = false;
|
|
||||||
|
class LeftOutlineButton : public RippleButton {
|
||||||
|
public:
|
||||||
|
LeftOutlineButton(QWidget *parent, const QString &text, const style::OutlineButton &st = st::defaultLeftOutlineButton);
|
||||||
|
|
||||||
|
void setText(const QString &text);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
|
||||||
|
int resizeGetHeight(int newWidth) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString _text, _fullText;
|
||||||
|
int _textWidth, _fullTextWidth;
|
||||||
|
|
||||||
|
const style::OutlineButton &_st;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,6 +58,7 @@ void DropdownMenu::init() {
|
|||||||
_menu->setKeyPressDelegate([this](int key) { return handleKeyPress(key); });
|
_menu->setKeyPressDelegate([this](int key) { return handleKeyPress(key); });
|
||||||
_menu->setMouseMoveDelegate([this](QPoint globalPosition) { handleMouseMove(globalPosition); });
|
_menu->setMouseMoveDelegate([this](QPoint globalPosition) { handleMouseMove(globalPosition); });
|
||||||
_menu->setMousePressDelegate([this](QPoint globalPosition) { handleMousePress(globalPosition); });
|
_menu->setMousePressDelegate([this](QPoint globalPosition) { handleMousePress(globalPosition); });
|
||||||
|
_menu->setMouseReleaseDelegate([this](QPoint globalPosition) { handleMouseRelease(globalPosition); });
|
||||||
|
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
|
|
||||||
@ -176,6 +177,14 @@ void DropdownMenu::handleMousePress(QPoint globalPosition) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DropdownMenu::handleMouseRelease(QPoint globalPosition) {
|
||||||
|
if (_parent) {
|
||||||
|
_parent->forwardMouseRelease(globalPosition);
|
||||||
|
} else {
|
||||||
|
hideMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DropdownMenu::focusOutEvent(QFocusEvent *e) {
|
void DropdownMenu::focusOutEvent(QFocusEvent *e) {
|
||||||
hideMenu();
|
hideMenu();
|
||||||
}
|
}
|
||||||
|
@ -88,6 +88,10 @@ private:
|
|||||||
_menu->handleMousePress(globalPosition);
|
_menu->handleMousePress(globalPosition);
|
||||||
}
|
}
|
||||||
void handleMousePress(QPoint globalPosition);
|
void handleMousePress(QPoint globalPosition);
|
||||||
|
void forwardMouseRelease(QPoint globalPosition) {
|
||||||
|
_menu->handleMouseRelease(globalPosition);
|
||||||
|
}
|
||||||
|
void handleMouseRelease(QPoint globalPosition);
|
||||||
|
|
||||||
using SubmenuPointer = QPointer<DropdownMenu>;
|
using SubmenuPointer = QPointer<DropdownMenu>;
|
||||||
bool popupSubmenuFromAction(QAction *action, int actionTop, TriggeredSource source);
|
bool popupSubmenuFromAction(QAction *action, int actionTop, TriggeredSource source);
|
||||||
|
@ -18,6 +18,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "ui/widgets/menu.h"
|
#include "ui/widgets/menu.h"
|
||||||
|
|
||||||
|
#include "ui/effects/ripple_animation.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
|
||||||
Menu::Menu(QWidget *parent, const style::Menu &st) : TWidget(parent)
|
Menu::Menu(QWidget *parent, const style::Menu &st) : TWidget(parent)
|
||||||
@ -150,6 +152,7 @@ void Menu::actionChanged() {
|
|||||||
void Menu::paintEvent(QPaintEvent *e) {
|
void Menu::paintEvent(QPaintEvent *e) {
|
||||||
Painter p(this);
|
Painter p(this);
|
||||||
|
|
||||||
|
auto ms = getms();
|
||||||
auto clip = e->rect();
|
auto clip = e->rect();
|
||||||
|
|
||||||
auto topskip = QRect(0, 0, width(), _st.skip);
|
auto topskip = QRect(0, 0, width(), _st.skip);
|
||||||
@ -172,8 +175,15 @@ void Menu::paintEvent(QPaintEvent *e) {
|
|||||||
p.fillRect(0, 0, width(), actionHeight, _st.itemBg);
|
p.fillRect(0, 0, width(), actionHeight, _st.itemBg);
|
||||||
p.fillRect(_st.separatorPadding.left(), _st.separatorPadding.top(), width() - _st.separatorPadding.left() - _st.separatorPadding.right(), _st.separatorWidth, _st.separatorFg);
|
p.fillRect(_st.separatorPadding.left(), _st.separatorPadding.top(), width() - _st.separatorPadding.left() - _st.separatorPadding.right(), _st.separatorWidth, _st.separatorFg);
|
||||||
} else {
|
} else {
|
||||||
auto enabled = action->isEnabled(), selected = (i == _selected && enabled);
|
auto enabled = action->isEnabled();
|
||||||
|
auto selected = ((i == _selected || i == _pressed) && enabled);
|
||||||
p.fillRect(0, 0, width(), actionHeight, selected ? _st.itemBgOver : _st.itemBg);
|
p.fillRect(0, 0, width(), actionHeight, selected ? _st.itemBgOver : _st.itemBg);
|
||||||
|
if (data.ripple) {
|
||||||
|
data.ripple->paint(p, 0, 0, width(), ms);
|
||||||
|
if (data.ripple->empty()) {
|
||||||
|
data.ripple.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
if (auto icon = (selected ? data.iconOver : data.icon)) {
|
if (auto icon = (selected ? data.iconOver : data.icon)) {
|
||||||
icon->paint(p, _st.itemIconPosition, width());
|
icon->paint(p, _st.itemIconPosition, width());
|
||||||
}
|
}
|
||||||
@ -207,9 +217,29 @@ void Menu::itemPressed(TriggeredSource source) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_selected >= 0 && _selected < _actions.size() && _actions[_selected]->isEnabled()) {
|
if (_selected >= 0 && _selected < _actions.size() && _actions[_selected]->isEnabled()) {
|
||||||
if (_triggeredCallback) {
|
_pressed = _selected;
|
||||||
auto actionTop = _st.skip + itemTop(_selected);
|
if (source == TriggeredSource::Mouse) {
|
||||||
_triggeredCallback(_actions[_selected], actionTop, source);
|
if (!_actionsData[_pressed].ripple) {
|
||||||
|
auto mask = RippleAnimation::rectMask(QSize(width(), _itemHeight));
|
||||||
|
_actionsData[_pressed].ripple = MakeShared<RippleAnimation>(_st.ripple, std_::move(mask), [this, selected = _pressed] {
|
||||||
|
updateItem(selected);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_actionsData[_pressed].ripple->add(mapFromGlobal(QCursor::pos()) - QPoint(0, itemTop(_pressed)));
|
||||||
|
} else {
|
||||||
|
itemReleased(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Menu::itemReleased(TriggeredSource source) {
|
||||||
|
auto pressed = base::take(_pressed, -1);
|
||||||
|
if (pressed >= 0 && pressed < _actions.size()) {
|
||||||
|
if (source == TriggeredSource::Mouse && _actionsData[pressed].ripple) {
|
||||||
|
_actionsData[pressed].ripple->lastStop();
|
||||||
|
}
|
||||||
|
if (pressed == _selected && _triggeredCallback) {
|
||||||
|
_triggeredCallback(_actions[_selected], itemTop(_selected), source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -290,9 +320,8 @@ void Menu::setSelected(int selected) {
|
|||||||
_selected = selected;
|
_selected = selected;
|
||||||
updateSelectedItem();
|
updateSelectedItem();
|
||||||
if (_activatedCallback) {
|
if (_activatedCallback) {
|
||||||
auto actionTop = _st.skip + itemTop(_selected);
|
|
||||||
auto source = _mouseSelection ? TriggeredSource::Mouse : TriggeredSource::Keyboard;
|
auto source = _mouseSelection ? TriggeredSource::Mouse : TriggeredSource::Keyboard;
|
||||||
_activatedCallback((_selected >= 0) ? _actions[_selected] : nullptr, actionTop, source);
|
_activatedCallback((_selected >= 0) ? _actions[_selected] : nullptr, itemTop(_selected), source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -301,19 +330,23 @@ int Menu::itemTop(int index) {
|
|||||||
if (index > _actions.size()) {
|
if (index > _actions.size()) {
|
||||||
index = _actions.size();
|
index = _actions.size();
|
||||||
}
|
}
|
||||||
int top = 0;
|
int top = _st.skip;
|
||||||
for (int i = 0; i < index; ++i) {
|
for (int i = 0; i < index; ++i) {
|
||||||
top += _actions.at(i)->isSeparator() ? _separatorHeight : _itemHeight;
|
top += _actions.at(i)->isSeparator() ? _separatorHeight : _itemHeight;
|
||||||
}
|
}
|
||||||
return top;
|
return top;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::updateSelectedItem() {
|
void Menu::updateItem(int index) {
|
||||||
if (_selected >= 0) {
|
if (index >= 0 && index < _actions.size()) {
|
||||||
update(0, _st.skip + itemTop(_selected), width(), _actions.at(_selected)->isSeparator() ? _separatorHeight : _itemHeight);
|
update(0, itemTop(index), width(), _actions[index]->isSeparator() ? _separatorHeight : _itemHeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Menu::updateSelectedItem() {
|
||||||
|
updateItem(_selected);
|
||||||
|
}
|
||||||
|
|
||||||
void Menu::mouseMoveEvent(QMouseEvent *e) {
|
void Menu::mouseMoveEvent(QMouseEvent *e) {
|
||||||
handleMouseMove(e->globalPos());
|
handleMouseMove(e->globalPos());
|
||||||
}
|
}
|
||||||
@ -336,6 +369,10 @@ void Menu::mousePressEvent(QMouseEvent *e) {
|
|||||||
handleMousePress(e->globalPos());
|
handleMousePress(e->globalPos());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Menu::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
|
handleMouseRelease(e->globalPos());
|
||||||
|
}
|
||||||
|
|
||||||
void Menu::handleMousePress(QPoint globalPosition) {
|
void Menu::handleMousePress(QPoint globalPosition) {
|
||||||
handleMouseMove(globalPosition);
|
handleMouseMove(globalPosition);
|
||||||
if (rect().contains(mapFromGlobal(globalPosition))) {
|
if (rect().contains(mapFromGlobal(globalPosition))) {
|
||||||
@ -345,4 +382,12 @@ void Menu::handleMousePress(QPoint globalPosition) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Menu::handleMouseRelease(QPoint globalPosition) {
|
||||||
|
handleMouseMove(globalPosition);
|
||||||
|
itemReleased(TriggeredSource::Mouse);
|
||||||
|
if (!rect().contains(mapFromGlobal(globalPosition)) && _mouseReleaseDelegate) {
|
||||||
|
_mouseReleaseDelegate(globalPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
@ -24,6 +24,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
|
|||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
|
||||||
|
class RippleAnimation;
|
||||||
|
|
||||||
class Menu : public TWidget {
|
class Menu : public TWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@ -76,11 +78,17 @@ public:
|
|||||||
}
|
}
|
||||||
void handleMousePress(QPoint globalPosition);
|
void handleMousePress(QPoint globalPosition);
|
||||||
|
|
||||||
|
void setMouseReleaseDelegate(base::lambda_unique<void(QPoint globalPosition)> delegate) {
|
||||||
|
_mouseReleaseDelegate = std_::move(delegate);
|
||||||
|
}
|
||||||
|
void handleMouseRelease(QPoint globalPosition);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
void keyPressEvent(QKeyEvent *e) override;
|
void keyPressEvent(QKeyEvent *e) override;
|
||||||
void mouseMoveEvent(QMouseEvent *e) override;
|
void mouseMoveEvent(QMouseEvent *e) override;
|
||||||
void mousePressEvent(QMouseEvent *e) override;
|
void mousePressEvent(QMouseEvent *e) override;
|
||||||
|
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||||
void enterEvent(QEvent *e) override;
|
void enterEvent(QEvent *e) override;
|
||||||
void leaveEvent(QEvent *e) override;
|
void leaveEvent(QEvent *e) override;
|
||||||
|
|
||||||
@ -99,8 +107,10 @@ private:
|
|||||||
void clearMouseSelection();
|
void clearMouseSelection();
|
||||||
|
|
||||||
int itemTop(int index);
|
int itemTop(int index);
|
||||||
|
void updateItem(int index);
|
||||||
void updateSelectedItem();
|
void updateSelectedItem();
|
||||||
void itemPressed(TriggeredSource source);
|
void itemPressed(TriggeredSource source);
|
||||||
|
void itemReleased(TriggeredSource source);
|
||||||
|
|
||||||
const style::Menu &_st;
|
const style::Menu &_st;
|
||||||
|
|
||||||
@ -110,6 +120,7 @@ private:
|
|||||||
base::lambda_unique<bool(int key)> _keyPressDelegate;
|
base::lambda_unique<bool(int key)> _keyPressDelegate;
|
||||||
base::lambda_unique<void(QPoint globalPosition)> _mouseMoveDelegate;
|
base::lambda_unique<void(QPoint globalPosition)> _mouseMoveDelegate;
|
||||||
base::lambda_unique<void(QPoint globalPosition)> _mousePressDelegate;
|
base::lambda_unique<void(QPoint globalPosition)> _mousePressDelegate;
|
||||||
|
base::lambda_unique<void(QPoint globalPosition)> _mouseReleaseDelegate;
|
||||||
|
|
||||||
struct ActionData {
|
struct ActionData {
|
||||||
bool hasSubmenu = false;
|
bool hasSubmenu = false;
|
||||||
@ -117,6 +128,7 @@ private:
|
|||||||
QString shortcut;
|
QString shortcut;
|
||||||
const style::icon *icon = nullptr;
|
const style::icon *icon = nullptr;
|
||||||
const style::icon *iconOver = nullptr;
|
const style::icon *iconOver = nullptr;
|
||||||
|
QSharedPointer<RippleAnimation> ripple;
|
||||||
};
|
};
|
||||||
using ActionsData = QList<ActionData>;
|
using ActionsData = QList<ActionData>;
|
||||||
|
|
||||||
@ -129,6 +141,7 @@ private:
|
|||||||
bool _mouseSelection = false;
|
bool _mouseSelection = false;
|
||||||
|
|
||||||
int _selected = -1;
|
int _selected = -1;
|
||||||
|
int _pressed = -1;
|
||||||
bool _childShown = false;
|
bool _childShown = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -55,6 +55,7 @@ void PopupMenu::init() {
|
|||||||
_menu->setKeyPressDelegate([this](int key) { return handleKeyPress(key); });
|
_menu->setKeyPressDelegate([this](int key) { return handleKeyPress(key); });
|
||||||
_menu->setMouseMoveDelegate([this](QPoint globalPosition) { handleMouseMove(globalPosition); });
|
_menu->setMouseMoveDelegate([this](QPoint globalPosition) { handleMouseMove(globalPosition); });
|
||||||
_menu->setMousePressDelegate([this](QPoint globalPosition) { handleMousePress(globalPosition); });
|
_menu->setMousePressDelegate([this](QPoint globalPosition) { handleMousePress(globalPosition); });
|
||||||
|
_menu->setMouseReleaseDelegate([this](QPoint globalPosition) { handleMouseRelease(globalPosition); });
|
||||||
|
|
||||||
handleCompositingUpdate();
|
handleCompositingUpdate();
|
||||||
|
|
||||||
@ -224,6 +225,14 @@ void PopupMenu::handleMousePress(QPoint globalPosition) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PopupMenu::handleMouseRelease(QPoint globalPosition) {
|
||||||
|
if (_parent) {
|
||||||
|
_parent->forwardMouseRelease(globalPosition);
|
||||||
|
} else {
|
||||||
|
hideMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PopupMenu::focusOutEvent(QFocusEvent *e) {
|
void PopupMenu::focusOutEvent(QFocusEvent *e) {
|
||||||
hideMenu();
|
hideMenu();
|
||||||
}
|
}
|
||||||
|
@ -93,6 +93,10 @@ private:
|
|||||||
_menu->handleMousePress(globalPosition);
|
_menu->handleMousePress(globalPosition);
|
||||||
}
|
}
|
||||||
void handleMousePress(QPoint globalPosition);
|
void handleMousePress(QPoint globalPosition);
|
||||||
|
void forwardMouseRelease(QPoint globalPosition) {
|
||||||
|
_menu->handleMouseRelease(globalPosition);
|
||||||
|
}
|
||||||
|
void handleMouseRelease(QPoint globalPosition);
|
||||||
|
|
||||||
using SubmenuPointer = QPointer<PopupMenu>;
|
using SubmenuPointer = QPointer<PopupMenu>;
|
||||||
bool popupSubmenuFromAction(QAction *action, int actionTop, TriggeredSource source);
|
bool popupSubmenuFromAction(QAction *action, int actionTop, TriggeredSource source);
|
||||||
|
@ -61,8 +61,6 @@ FlatButton {
|
|||||||
height: pixels;
|
height: pixels;
|
||||||
|
|
||||||
textTop: pixels;
|
textTop: pixels;
|
||||||
overTextTop: pixels;
|
|
||||||
downTextTop: pixels;
|
|
||||||
|
|
||||||
font: font;
|
font: font;
|
||||||
overFont: font;
|
overFont: font;
|
||||||
@ -87,7 +85,6 @@ RoundButton {
|
|||||||
padding: margins;
|
padding: margins;
|
||||||
|
|
||||||
textTop: pixels;
|
textTop: pixels;
|
||||||
downTextTop: pixels;
|
|
||||||
|
|
||||||
icon: icon;
|
icon: icon;
|
||||||
|
|
||||||
@ -272,6 +269,8 @@ OutlineButton {
|
|||||||
|
|
||||||
font: font;
|
font: font;
|
||||||
padding: margins;
|
padding: margins;
|
||||||
|
|
||||||
|
ripple: RippleAnimation;
|
||||||
}
|
}
|
||||||
|
|
||||||
IconButton {
|
IconButton {
|
||||||
@ -280,9 +279,7 @@ IconButton {
|
|||||||
|
|
||||||
icon: icon;
|
icon: icon;
|
||||||
iconOver: icon;
|
iconOver: icon;
|
||||||
|
|
||||||
iconPosition: point;
|
iconPosition: point;
|
||||||
iconPositionDown: point;
|
|
||||||
|
|
||||||
duration: int;
|
duration: int;
|
||||||
|
|
||||||
@ -394,6 +391,8 @@ Menu {
|
|||||||
|
|
||||||
widthMin: pixels;
|
widthMin: pixels;
|
||||||
widthMax: pixels;
|
widthMax: pixels;
|
||||||
|
|
||||||
|
ripple: RippleAnimation;
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelAnimation {
|
PanelAnimation {
|
||||||
@ -487,7 +486,6 @@ defaultActiveButton: RoundButton {
|
|||||||
padding: margins(0px, 0px, 0px, 0px);
|
padding: margins(0px, 0px, 0px, 0px);
|
||||||
|
|
||||||
textTop: 8px;
|
textTop: 8px;
|
||||||
downTextTop: 8px;
|
|
||||||
|
|
||||||
font: semiboldFont;
|
font: semiboldFont;
|
||||||
|
|
||||||
@ -589,14 +587,22 @@ defaultLeftOutlineButton: OutlineButton {
|
|||||||
|
|
||||||
font: normalFont;
|
font: normalFont;
|
||||||
padding: margins(11px, 5px, 11px, 5px);
|
padding: margins(11px, 5px, 11px, 5px);
|
||||||
|
|
||||||
|
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||||
|
color: lightButtonBgRipple;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
attentionLeftOutlineButton: OutlineButton(defaultLeftOutlineButton) {
|
attentionLeftOutlineButton: OutlineButton(defaultLeftOutlineButton) {
|
||||||
outlineFgOver: attentionBoxButtonFg;
|
outlineFgOver: attentionButtonFg;
|
||||||
|
|
||||||
textBgOver: attentionBoxButtonBgOver;
|
textBgOver: attentionButtonBgOver;
|
||||||
|
|
||||||
textFg: attentionBoxButtonFg;
|
textFg: attentionButtonFg;
|
||||||
textFgOver: attentionBoxButtonFg;
|
textFgOver: attentionButtonFg;
|
||||||
|
|
||||||
|
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||||
|
color: attentionButtonBgRipple;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultInputArea: InputArea {
|
defaultInputArea: InputArea {
|
||||||
@ -697,7 +703,6 @@ defaultRadiobutton: Radiobutton {
|
|||||||
|
|
||||||
defaultIconButton: IconButton {
|
defaultIconButton: IconButton {
|
||||||
iconPosition: point(-1px, -1px);
|
iconPosition: point(-1px, -1px);
|
||||||
iconPositionDown: point(-1px, -1px);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
widgetSlideDuration: 200;
|
widgetSlideDuration: 200;
|
||||||
@ -756,8 +761,8 @@ defaultMenu: Menu {
|
|||||||
itemFg: windowFg;
|
itemFg: windowFg;
|
||||||
itemFgOver: windowFgOver;
|
itemFgOver: windowFgOver;
|
||||||
itemFgDisabled: #cccccc;
|
itemFgDisabled: #cccccc;
|
||||||
itemFgShortcut: #999999;
|
itemFgShortcut: windowSubTextFg;
|
||||||
itemFgShortcutOver: #7c99b2;
|
itemFgShortcutOver: windowSubTextFgOver;
|
||||||
itemFgShortcutDisabled: #cccccc;
|
itemFgShortcutDisabled: #cccccc;
|
||||||
itemIconPosition: point(0px, 0px);
|
itemIconPosition: point(0px, 0px);
|
||||||
itemPadding: margins(17px, 8px, 17px, 7px);
|
itemPadding: margins(17px, 8px, 17px, 7px);
|
||||||
@ -771,6 +776,8 @@ defaultMenu: Menu {
|
|||||||
|
|
||||||
widthMin: 180px;
|
widthMin: 180px;
|
||||||
widthMax: 300px;
|
widthMax: 300px;
|
||||||
|
|
||||||
|
ripple: defaultRippleAnimation;
|
||||||
}
|
}
|
||||||
defaultPopupMenu: PopupMenu {
|
defaultPopupMenu: PopupMenu {
|
||||||
shadow: defaultRoundShadow;
|
shadow: defaultRoundShadow;
|
||||||
@ -801,18 +808,42 @@ defaultDropdownMenu: DropdownMenu {
|
|||||||
menu: defaultMenu;
|
menu: defaultMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
historyToDown: icon {
|
historyToDownBelow: icon {
|
||||||
{ "history_down_shadow", #00000040 },
|
{ "history_down_shadow", #00000040 },
|
||||||
{ "history_down_circle", #ffffff, point(4px, 4px) },
|
{ "history_down_circle", windowBg, point(4px, 4px) },
|
||||||
|
};
|
||||||
|
historyToDownBelowOver: icon {
|
||||||
|
{ "history_down_shadow", #00000040 },
|
||||||
|
{ "history_down_circle", windowBgOver, point(4px, 4px) },
|
||||||
|
};
|
||||||
|
contactsAddIconBelow: icon {
|
||||||
|
{ "history_down_shadow", #00000040 },
|
||||||
|
{ "history_down_circle", activeButtonBg, point(4px, 4px) },
|
||||||
|
};
|
||||||
|
contactsAddIconBelowOver: icon {
|
||||||
|
{ "history_down_shadow", #00000040 },
|
||||||
|
{ "history_down_circle", activeButtonBgOver, point(4px, 4px) },
|
||||||
};
|
};
|
||||||
|
|
||||||
contactsAddIcon: icon {
|
BotKeyboardButton {
|
||||||
{ "history_down_shadow", #00000020 },
|
margin: pixels;
|
||||||
{ "history_down_circle", activeButtonBg, point(4px, 4px) },
|
padding: pixels;
|
||||||
{ "contacts_add", activeButtonFg, point(18px, 18px) },
|
height: pixels;
|
||||||
};
|
textTop: pixels;
|
||||||
contactsAddIconOver: icon {
|
ripple: RippleAnimation;
|
||||||
{ "history_down_shadow", #00000020 },
|
}
|
||||||
{ "history_down_circle", activeButtonBgOver, point(4px, 4px) },
|
|
||||||
{ "contacts_add", activeButtonFg, point(18px, 18px) },
|
TwoIconButton {
|
||||||
};
|
width: pixels;
|
||||||
|
height: pixels;
|
||||||
|
|
||||||
|
iconBelow: icon;
|
||||||
|
iconAbove: icon;
|
||||||
|
iconBelowOver: icon;
|
||||||
|
iconAboveOver: icon;
|
||||||
|
iconPosition: point;
|
||||||
|
|
||||||
|
rippleAreaPosition: point;
|
||||||
|
rippleAreaSize: pixels;
|
||||||
|
ripple: RippleAnimation;
|
||||||
|
}
|
||||||
|
@ -56,10 +56,10 @@ TopBarWidget::TopBarWidget(MainWidget *w) : TWidget(w)
|
|||||||
subscribe(w->searchInPeerChanged(), [this](PeerData *peer) {
|
subscribe(w->searchInPeerChanged(), [this](PeerData *peer) {
|
||||||
_searchInPeer = peer;
|
_searchInPeer = peer;
|
||||||
auto historyPeer = App::main() ? App::main()->historyPeer() : nullptr;
|
auto historyPeer = App::main() ? App::main()->historyPeer() : nullptr;
|
||||||
_search->setActiveState(historyPeer && historyPeer == _searchInPeer);
|
_search->setForceRippled(historyPeer && historyPeer == _searchInPeer);
|
||||||
});
|
});
|
||||||
subscribe(w->historyPeerChanged(), [this](PeerData *peer) {
|
subscribe(w->historyPeerChanged(), [this](PeerData *peer) {
|
||||||
_search->setActiveState(peer && peer == _searchInPeer, Ui::IconButton::SetStateWay::SkipAnimation);
|
_search->setForceRippled(peer && peer == _searchInPeer, Ui::IconButton::SetForceRippledWay::SkipAnimation);
|
||||||
update();
|
update();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -115,17 +115,17 @@ void TopBarWidget::showMenu() {
|
|||||||
data->menu->deleteLater();
|
data->menu->deleteLater();
|
||||||
if (data->that && _menu == data->menu) {
|
if (data->that && _menu == data->menu) {
|
||||||
_menu = nullptr;
|
_menu = nullptr;
|
||||||
_menuToggle->setActiveState(false);
|
_menuToggle->setForceRippled(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
_menu->setShowStartCallback([this, data] {
|
_menu->setShowStartCallback([this, data] {
|
||||||
if (data->that && _menu == data->menu) {
|
if (data->that && _menu == data->menu) {
|
||||||
_menuToggle->setActiveState(true);
|
_menuToggle->setForceRippled(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
_menu->setHideStartCallback([this, data] {
|
_menu->setHideStartCallback([this, data] {
|
||||||
if (data->that && _menu == data->menu) {
|
if (data->that && _menu == data->menu) {
|
||||||
_menuToggle->setActiveState(false);
|
_menuToggle->setForceRippled(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
_menuToggle->installEventFilter(_menu);
|
_menuToggle->installEventFilter(_menu);
|
||||||
|
@ -47,7 +47,6 @@ notifyClose: IconButton {
|
|||||||
iconOver: simpleCloseIconOver;
|
iconOver: simpleCloseIconOver;
|
||||||
|
|
||||||
iconPosition: point(10px, 10px);
|
iconPosition: point(10px, 10px);
|
||||||
iconPositionDown: point(10px, 11px);
|
|
||||||
}
|
}
|
||||||
notifyItemTop: 12px;
|
notifyItemTop: 12px;
|
||||||
notifyTextLeft: 12px;
|
notifyTextLeft: 12px;
|
||||||
@ -77,7 +76,6 @@ notifySendReply: IconButton {
|
|||||||
|
|
||||||
icon: icon {{ "notification_send", lightButtonFg, point(3px, 9px) }};
|
icon: icon {{ "notification_send", lightButtonFg, point(3px, 9px) }};
|
||||||
iconPosition: point(0px, 0px);
|
iconPosition: point(0px, 0px);
|
||||||
iconPositionDown: point(0px, 1px);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
titleUnreadCounterTop: 5px;
|
titleUnreadCounterTop: 5px;
|
||||||
@ -96,6 +94,8 @@ mainMenuCoverNameTop: 88px;
|
|||||||
mainMenuCoverStatusTop: 106px;
|
mainMenuCoverStatusTop: 106px;
|
||||||
mainMenuSkip: 13px;
|
mainMenuSkip: 13px;
|
||||||
mainMenu: Menu(defaultMenu) {
|
mainMenu: Menu(defaultMenu) {
|
||||||
|
itemFg: windowBoldFg;
|
||||||
|
itemFgOver: windowBoldFgOver;
|
||||||
itemFont: semiboldFont;
|
itemFont: semiboldFont;
|
||||||
itemIconPosition: point(28px, 11px);
|
itemIconPosition: point(28px, 11px);
|
||||||
itemPadding: margins(76px, 14px, 28px, 14px);
|
itemPadding: margins(76px, 14px, 28px, 14px);
|
||||||
@ -144,9 +144,7 @@ titleButtonMinimize: IconButton {
|
|||||||
{ size(24px, 21px), titleButtonBgOver },
|
{ size(24px, 21px), titleButtonBgOver },
|
||||||
{ "title_button_minimize", titleButtonFgOver, point(4px, 4px) },
|
{ "title_button_minimize", titleButtonFgOver, point(4px, 4px) },
|
||||||
};
|
};
|
||||||
|
|
||||||
iconPosition: point(0px, 0px);
|
iconPosition: point(0px, 0px);
|
||||||
iconPositionDown: point(0px, 0px);
|
|
||||||
}
|
}
|
||||||
titleButtonMaximize: IconButton(titleButtonMinimize) {
|
titleButtonMaximize: IconButton(titleButtonMinimize) {
|
||||||
icon: icon {{ "title_button_maximize", titleButtonFg, point(4px, 4px) }};
|
icon: icon {{ "title_button_maximize", titleButtonFg, point(4px, 4px) }};
|
||||||
@ -195,7 +193,6 @@ topBarButton: RoundButton {
|
|||||||
padding: margins(0px, 14px, 12px, 12px);
|
padding: margins(0px, 14px, 12px, 12px);
|
||||||
|
|
||||||
textTop: 6px;
|
textTop: 6px;
|
||||||
downTextTop: 6px;
|
|
||||||
|
|
||||||
font: font(fsize);
|
font: font(fsize);
|
||||||
|
|
||||||
@ -212,9 +209,7 @@ topBarSearch: IconButton {
|
|||||||
|
|
||||||
icon: icon {{ "title_search", menuIconFg }};
|
icon: icon {{ "title_search", menuIconFg }};
|
||||||
iconOver: icon {{ "title_search", menuIconFgOver }};
|
iconOver: icon {{ "title_search", menuIconFgOver }};
|
||||||
|
|
||||||
iconPosition: point(15px, 18px);
|
iconPosition: point(15px, 18px);
|
||||||
iconPositionDown: point(15px, 18px);
|
|
||||||
|
|
||||||
rippleAreaPosition: point(4px, 7px);
|
rippleAreaPosition: point(4px, 7px);
|
||||||
rippleAreaSize: 40px;
|
rippleAreaSize: 40px;
|
||||||
@ -225,9 +220,7 @@ topBarSearch: IconButton {
|
|||||||
topBarMenuToggle: IconButton(topBarSearch) {
|
topBarMenuToggle: IconButton(topBarSearch) {
|
||||||
icon: icon {{ "title_menu_dots", menuIconFg }};
|
icon: icon {{ "title_menu_dots", menuIconFg }};
|
||||||
iconOver: icon {{ "title_menu_dots", menuIconFgOver }};
|
iconOver: icon {{ "title_menu_dots", menuIconFgOver }};
|
||||||
|
|
||||||
iconPosition: point(16px, 17px);
|
iconPosition: point(16px, 17px);
|
||||||
iconPositionDown: point(16px, 17px);
|
|
||||||
|
|
||||||
rippleAreaPosition: point(0px, 7px);
|
rippleAreaPosition: point(0px, 7px);
|
||||||
}
|
}
|
||||||
|
@ -80,6 +80,7 @@ void MainMenu::checkSelf() {
|
|||||||
_userpicButton->setClickedCallback([] {
|
_userpicButton->setClickedCallback([] {
|
||||||
App::wnd()->showSettings();
|
App::wnd()->showSettings();
|
||||||
});
|
});
|
||||||
|
_userpicButton->show();
|
||||||
updateControlsGeometry();
|
updateControlsGeometry();
|
||||||
if (_showFinished) {
|
if (_showFinished) {
|
||||||
_userpicButton->showFinished();
|
_userpicButton->showFinished();
|
||||||
|
@ -3,4 +3,4 @@ AppVersionStrMajor 0.10
|
|||||||
AppVersionStrSmall 0.10.20
|
AppVersionStrSmall 0.10.20
|
||||||
AppVersionStr 0.10.20
|
AppVersionStr 0.10.20
|
||||||
AlphaChannel 0
|
AlphaChannel 0
|
||||||
BetaVersion 10019007
|
BetaVersion 10019008
|
||||||
|
@ -452,8 +452,6 @@
|
|||||||
'<(src_loc)/stickers/stickers.h',
|
'<(src_loc)/stickers/stickers.h',
|
||||||
'<(src_loc)/ui/buttons/history_down_button.cpp',
|
'<(src_loc)/ui/buttons/history_down_button.cpp',
|
||||||
'<(src_loc)/ui/buttons/history_down_button.h',
|
'<(src_loc)/ui/buttons/history_down_button.h',
|
||||||
'<(src_loc)/ui/buttons/left_outline_button.cpp',
|
|
||||||
'<(src_loc)/ui/buttons/left_outline_button.h',
|
|
||||||
'<(src_loc)/ui/buttons/peer_avatar_button.cpp',
|
'<(src_loc)/ui/buttons/peer_avatar_button.cpp',
|
||||||
'<(src_loc)/ui/buttons/peer_avatar_button.h',
|
'<(src_loc)/ui/buttons/peer_avatar_button.h',
|
||||||
'<(src_loc)/ui/effects/panel_animation.cpp',
|
'<(src_loc)/ui/effects/panel_animation.cpp',
|
||||||
|
Loading…
Reference in New Issue
Block a user