Ripple animations done for IconButton, FlatButton and RoundButton.

Also moved input field classes to ui/widgets/input_fields module.
This commit is contained in:
John Preston 2016-11-15 14:56:49 +03:00
parent 48eb72a9c2
commit 3186e1e495
94 changed files with 2970 additions and 2449 deletions

View File

@ -57,156 +57,12 @@ boxTitlePosition: point(26px, 28px);
boxTitleHeight: 54px;
boxButtonFont: font(boxFontSize semibold);
defaultBoxButton: RoundButton {
textFg: #2f9fea;
textFgOver: #2f9fea;
secondaryTextFg: #2f9fea;
secondaryTextFgOver: #2f9fea;
textBg: boxBg;
textBgOver: lightButtonBgOver;
width: -24px;
height: 36px;
padding: margins(0px, 0px, 0px, 0px);
textTop: 8px;
downTextTop: 9px;
font: boxButtonFont;
}
cancelBoxButton: RoundButton(defaultBoxButton) {
textFg: #aeaeae;
}
attentionBoxButton: RoundButton(defaultBoxButton) {
textFg: #ea4b2f;
textFgOver: #ea4b2f;
textBgOver: #fff0ed;
}
boxButtonPadding: margins(12px, 16px, 22px, 16px);
boxLabel: flatLabel(labelDefFlat) {
font: font(boxFontSize);
align: align(topleft);
}
defaultLeftOutlineButton: OutlineButton {
outlineWidth: 3px;
outlineFg: windowBg;
outlineFgOver: windowActiveBg;
textBg: windowBg;
textBgOver: #f2f7fa;
textFg: windowActiveTextFg;
textFgOver: windowActiveTextFg;
font: normalFont;
padding: margins(11px, 5px, 11px, 5px);
}
attentionLeftOutlineButton: OutlineButton(defaultLeftOutlineButton) {
outlineFgOver: #e43f3f;
textBgOver: #faf2f2;
textFg: #d15948;
textFgOver: #d15948;
}
defaultInputArea: InputArea {
textBg: windowBg;
textFg: windowTextFg;
textMargins: margins(5px, 6px, 5px, 4px);
placeholderFg: #999999;
placeholderFgActive: #aaaaaa;
placeholderMargins: margins(2px, 0px, 2px, 0px);
placeholderAlign: align(topleft);
placeholderShift: 50px;
duration: 120;
borderFg: #e0e0e0;
borderFgActive: #62c0f7;
borderFgError: #e48383;
border: 1px;
borderActive: 2px;
borderError: 2px;
font: boxTextFont;
heightMin: 32px;
heightMax: 128px;
}
defaultInputField: InputField {
textBg: windowBg;
textFg: windowTextFg;
textMargins: margins(0px, 6px, 0px, 4px);
textAlign: align(topleft);
placeholderFg: #999999;
placeholderFgActive: #aaaaaa;
placeholderMargins: margins(2px, 0px, 2px, 0px);
placeholderAlign: align(topleft);
placeholderShift: 50px;
duration: 120;
borderFg: #e0e0e0;
borderFgActive: #62c0f7;
borderFgError: #e48383;
border: 1px;
borderActive: 2px;
borderError: 2px;
font: boxTextFont;
height: 32px;
}
defaultCheckboxIcon: icon {{ "default_checkbox_check", windowActiveFg, point(4px, 7px) }};
defaultCheckbox: Checkbox {
textFg: windowTextFg;
textBg: windowBg;
checkBg: #ffffff;
checkFg: #b3b3b3;
checkFgOver: #b3b3b3;
checkFgActive: windowActiveBg;
width: -44px;
height: 22px;
textPosition: point(32px, 2px);
diameter: 22px;
thickness: 2px;
checkIcon: defaultCheckboxIcon;
font: normalFont;
duration: 120;
}
defaultBoxCheckbox: Checkbox(defaultCheckbox) {
width: -46px;
textPosition: point(34px, 1px);
font: boxTextFont;
}
defaultRadiobutton: Radiobutton {
textFg: windowTextFg;
textBg: windowBg;
checkBg: #ffffff;
checkFg: #b3b3b3;
checkFgOver: #bfbfbf;
checkFgActive: #4eb3ee;
width: -46px;
height: 22px;
textPosition: point(34px, 0px);
diameter: 22px;
thickness: 2px;
checkSkip: 65px; // * 0.1
font: boxTextFont;
duration: 120;
}
solidScroll: flatScroll {
barColor: #3f729734;
bgColor: #214f751a;
@ -279,40 +135,6 @@ linkCropLimit: 360px;
linkFont: normalFont;
linkOverFont: font(fsize underline);
inpDefFont: font(17px);
inpDefFlat: flatInput {
textColor: #000000;
bgColor: #ffffff;
bgActive: #ffffff;
width: 210px;
height: 40px;
align: align(left);
textMrg: margins(5px, 5px, 5px, 5px);
font: inpDefFont;
cursor: cursor(text);
borderWidth: 0px;
borderColor: transparent;
borderActive: transparent;
borderError: transparent;
phColor: #949494;
phFocusColor: #aaaaaa;
phAlign: align(left);
phPos: point(2px, 0px);
phShift: 50px;
phDuration: 100;
}
inpDefGray: flatInput(inpDefFlat) {
bgColor: #f2f2f2;
borderWidth: 2px;
borderColor: #f2f2f2;
borderActive: #54c3f3;
borderError: #ed8080;
phColor: #808080;
}
scrollDef: flatScroll {
barColor: #00000053;
bgColor: #0000001a;
@ -375,63 +197,6 @@ noContactsHeight: 100px;
noContactsFont: font(fsize);
noContactsColor: #777777;
topBarHeight: 54px;
topBarDuration: 200;
topBarBackward: icon {{ "title_back", #a3a3a3 }};
topBarForwardAlpha: 0.6;
topBarBack: icon {{ "title_back", #259fd8 }};
topBarBackAlpha: 0.8;
topBarBackColor: #005faf;
topBarBackFont: font(16px);
topBarArrowPadding: margins(39px, 8px, 17px, 8px);
topBarMinPadding: 5px;
topBarButton: RoundButton {
textFg: btnYesColor;
textFgOver: btnYesColor;
secondaryTextFg: btnYesColor;
secondaryTextFgOver: btnYesColor;
textBg: windowBg;
textBgOver: #edf4f7;
width: -22px;
height: 28px;
padding: margins(0px, 14px, 12px, 12px);
textTop: 6px;
downTextTop: 7px;
font: font(fsize);
}
defaultActiveButton: RoundButton {
textFg: activeButtonFg;
textFgOver: activeButtonFgOver;
secondaryTextFg: activeButtonSecondaryFg;
secondaryTextFgOver: activeButtonSecondaryFgOver;
textBg: activeButtonBg;
textBgOver: activeButtonBgOver;
secondarySkip: 7px;
width: -34px;
height: 34px;
padding: margins(0px, 0px, 0px, 0px);
textTop: 8px;
downTextTop: 9px;
font: semiboldFont;
}
defaultLightButton: RoundButton(defaultActiveButton) {
textFg: lightButtonFg;
textFgOver: lightButtonFgOver;
textBg: lightButtonBg;
textBgOver: lightButtonBgOver;
}
topBarClearButton: RoundButton(defaultLightButton) {
width: -18px;
}
topBarActionSkip: 10px;
activeFadeInDuration: 500;
activeFadeOutDuration: 3000;
@ -704,13 +469,6 @@ boxPhotoTextFg: #808080;
cropPointSize: 10px;
cropSkip: 13px;
cropMinSize: 20px;
confirmCaptionArea: InputArea(defaultInputArea) {
textMargins: margins(1px, 6px, 1px, 4px);
heightMax: 56px;
}
confirmBg: #f2f2f2;
confirmMaxHeight: 245px;
confirmCompressedSkip: 10px;
profileMaxWidth: 410px;
profilePadding: margins(28px, 30px, 28px, 0px);
@ -725,20 +483,6 @@ forwardFont: font(16px);
forwardBg: #0000004c;
forwardFg: #ffffff;
connectionHostInputField: InputField(defaultInputField) {
width: 160px;
}
connectionPortInputField: InputField(defaultInputField) {
width: 55px;
}
connectionUserInputField: InputField(defaultInputField) {
width: 95px;
}
connectionPasswordInputField: InputField(defaultInputField) {
width: 120px;
}
connectionIPv6Skip: 11px;
emojiTextFont: font(15px);
emojiReplaceWidth: 52px;
emojiReplaceHeight: 56px;
@ -784,12 +528,6 @@ botKbScroll: flatScroll(solidScroll) {
deltax: 3px;
width: 10px;
}
switchPmButton: RoundButton(defaultBoxButton) {
width: 320px;
height: 34px;
textTop: 7px;
downTextTop: 8px;
}
minPhotoSize: 100px;
maxMediaSize: 420px;
@ -867,23 +605,6 @@ videoIcon: icon {
};
locationSize: size(320px, 240px);
boxOptionListPadding: margins(2px, 20px, 2px, 2px);
langsWidth: 256px;
langsButton: Radiobutton(defaultRadiobutton) {
width: 200px;
}
backgroundPadding: 10px;
backgroundSize: size(108px, 193px);
backgroundScroll: flatScroll(boxScroll) {
round: 2px;
width: 10px;
deltax: 3px;
deltat: 10px;
deltab: 0px;
}
mentionHeight: 40px;
mentionScroll: flatScroll(scrollDef) {
topsh: 0px;
@ -934,11 +655,6 @@ inlineRowFileDescriptionTop: 23px;
inlineResultsMinWidth: 64px;
inlineDurationMargin: 3px;
editTextArea: InputArea(defaultInputArea) {
textMargins: margins(1px, 6px, 1px, 4px);
heightMax: 256px;
}
toastFont: normalFont;
toastMaxWidth: 480px;
toastMinMargin: 13px;
@ -948,11 +664,6 @@ toastPadding: margins(19px, 13px, 19px, 12px);
toastFadeInDuration: 200;
toastFadeOutDuration: 1000;
infoButton: PeerAvatarButton {
size: topBarHeight;
photoSize: 42px;
}
// forward declaration for single "title_back" usage.
profileTopBarBackIconFg: #0290d7;
profileTopBarBackIcon: icon {{ "title_back", profileTopBarBackIconFg }};

View File

@ -30,49 +30,6 @@ textStyle {
lineHeight: pixels;
}
flatInput {
textColor: color;
bgColor: color;
bgActive: color;
width: pixels;
height: pixels;
textMrg: margins;
align: align;
font: font;
cursor: cursor;
icon: icon;
borderWidth: pixels;
borderColor: color;
borderActive: color;
borderError: color;
phColor: color;
phFocusColor: color;
phPos: point;
phAlign: align;
phShift: pixels;
phDuration: int;
}
flatTextarea {
textColor: color;
bgColor: color;
width: pixels;
textMrg: margins;
align: align;
font: font;
cursor: cursor;
phColor: color;
phFocusColor: color;
phPos: point;
phAlign: align;
phShift: pixels;
phDuration: int;
}
flatScroll {
barColor: color;
bgColor: color;
@ -125,143 +82,3 @@ botKeyboardButton {
textTop: pixels;
downTextTop: pixels;
}
RoundButton {
textFg: color;
textFgOver: color;
textBg: color; // rect of textBg with rounded rect of textBgOver upon it
textBgOver: color;
secondaryTextFg: color;
secondaryTextFgOver: color;
secondarySkip: pixels;
width: pixels;
height: pixels;
padding: margins;
textTop: pixels;
downTextTop: pixels;
icon: icon;
font: font;
}
Checkbox {
textFg: color;
textBg: color;
checkBg: color;
checkFg: color;
checkFgOver: color;
checkFgActive: color;
width: pixels;
height: pixels;
textPosition: point;
diameter: pixels;
thickness: pixels;
checkIcon: icon;
font: font;
duration: int;
}
Radiobutton {
textFg: color;
textBg: color;
checkBg: color;
checkFg: color;
checkFgOver: color;
checkFgActive: color;
width: pixels;
height: pixels;
textPosition: point;
diameter: pixels;
thickness: pixels;
checkSkip: pixels;
font: font;
duration: int;
}
InputArea {
textBg: color;
textFg: color;
textMargins: margins;
placeholderFg: color;
placeholderFgActive: color;
placeholderMargins: margins;
placeholderAlign: align;
placeholderShift: pixels;
duration: int;
borderFg: color;
borderFgActive: color;
borderFgError: color;
border: pixels;
borderActive: pixels;
borderError: pixels;
font: font;
width: pixels;
heightMin: pixels;
heightMax: pixels;
}
InputField {
textBg: color;
textFg: color;
textMargins: margins;
textAlign: align;
placeholderFg: color;
placeholderFgActive: color;
placeholderMargins: margins;
placeholderAlign: align;
placeholderShift: pixels;
duration: int;
borderFg: color;
borderFgActive: color;
borderFgError: color;
border: pixels;
borderActive: pixels;
borderError: pixels;
font: font;
width: pixels;
height: pixels;
}
PeerAvatarButton {
size: pixels;
photoSize: pixels;
}
OutlineButton {
outlineWidth: pixels;
outlineFg: color;
outlineFgOver: color;
textBg: color;
textBgOver: color;
textFg: color;
textFgOver: color;
font: font;
padding: margins;
}

View File

@ -37,6 +37,7 @@ imageBgTransparent: #ffffff;
// widgets
activeButtonBg: windowActiveBg;
activeButtonBgOver: #46b4eb;
activeButtonBgRipple: #177eb2;
activeButtonFg: windowActiveFg;
activeButtonFgOver: activeButtonFg;
activeButtonSecondaryFg: #cceeff;
@ -44,6 +45,7 @@ activeButtonSecondaryFgOver: activeButtonSecondaryFg;
lightButtonBg: windowBg;
lightButtonBgOver: #edf7ff;
lightButtonBgRipple: #c7e1f6;
lightButtonFg: #2b99d5;
lightButtonFgOver: lightButtonFg;
@ -92,6 +94,11 @@ boxBlockTitleAdditionalFg: #808080;
boxBlockTitleCloseFg: cancelIconFg;
boxBlockTitleCloseFgOver: cancelIconFgOver;
attentionBoxButtonFg: #ea4b2f;
attentionBoxButtonFgOver: #ea4b2f;
attentionBoxButtonBgOver: #fff0ed;
attentionBoxButtonBgRipple: #efbcb2;
membersAboutLimitFg: windowSubTextFg;
contactsBg: windowBg;
@ -188,6 +195,7 @@ historyReplyCancelFgOver: cancelIconFgOver;
historyComposeButtonBg: historyComposeAreaBg;
historyComposeButtonBgOver: #f5f5f5;
historyComposeButtonBgRipple: #e7e7e7;
historyTextInFg: windowTextFg;
historyTextOutFg: windowTextFg;

View File

@ -35,12 +35,14 @@ imageBg: #000000;
imageBgTransparent: #ffffff;
activeButtonBg: windowActiveBg;
activeButtonBgOver: #46b4eb;
activeButtonBgRipple: #177eb2;
activeButtonFg: windowActiveFg;
activeButtonFgOver: activeButtonFg;
activeButtonSecondaryFg: #cceeff;
activeButtonSecondaryFgOver: activeButtonSecondaryFg;
lightButtonBg: windowBg;
lightButtonBgOver: #edf7ff;
lightButtonBgRipple: #c7e1f6;
lightButtonFg: #2b99d5;
lightButtonFgOver: lightButtonFg;
menuBg: windowBg;
@ -77,6 +79,10 @@ boxBlockTitleFg: boxTitleFg;
boxBlockTitleAdditionalFg: #808080;
boxBlockTitleCloseFg: cancelIconFg;
boxBlockTitleCloseFgOver: cancelIconFgOver;
attentionBoxButtonFg: #ea4b2f;
attentionBoxButtonFgOver: #ea4b2f;
attentionBoxButtonBgOver: #fff0ed;
attentionBoxButtonBgRipple: #efbcb2;
membersAboutLimitFg: windowSubTextFg;
contactsBg: windowBg;
contactsBgOver: windowOverBg;
@ -155,6 +161,7 @@ historyReplyCancelFg: cancelIconFg;
historyReplyCancelFgOver: cancelIconFgOver;
historyComposeButtonBg: historyComposeAreaBg;
historyComposeButtonBgOver: #f5f5f5;
historyComposeButtonBgRipple: #e7e7e7;
historyTextInFg: windowTextFg;
historyTextOutFg: windowTextFg;
historyCaptionInFg: historyTextInFg;

View File

@ -34,8 +34,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,10,19,6
PRODUCTVERSION 0,10,19,6
FILEVERSION 0,10,19,7
PRODUCTVERSION 0,10,19,7
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -51,10 +51,10 @@ BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Telegram Messenger LLP"
VALUE "FileVersion", "0.10.19.6"
VALUE "FileVersion", "0.10.19.7"
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "0.10.19.6"
VALUE "ProductVersion", "0.10.19.7"
END
END
BLOCK "VarFileInfo"

View File

@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,10,19,6
PRODUCTVERSION 0,10,19,6
FILEVERSION 0,10,19,7
PRODUCTVERSION 0,10,19,7
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -43,10 +43,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram Messenger LLP"
VALUE "FileDescription", "Telegram Updater"
VALUE "FileVersion", "0.10.19.6"
VALUE "FileVersion", "0.10.19.7"
VALUE "LegalCopyright", "Copyright (C) 2014-2016"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "0.10.19.6"
VALUE "ProductVersion", "0.10.19.7"
END
END
BLOCK "VarFileInfo"

View File

@ -1037,15 +1037,15 @@ void AppClass::uploadProfilePhoto(const QImage &tosend, const PeerId &peerId) {
PreparedPhotoThumbs photoThumbs;
QVector<MTPPhotoSize> photoSizes;
QPixmap thumb = App::pixmapFromImageInPlace(tosend.scaled(160, 160, Qt::KeepAspectRatio, Qt::SmoothTransformation));
auto thumb = App::pixmapFromImageInPlace(tosend.scaled(160, 160, Qt::KeepAspectRatio, Qt::SmoothTransformation));
photoThumbs.insert('a', thumb);
photoSizes.push_back(MTP_photoSize(MTP_string("a"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(thumb.width()), MTP_int(thumb.height()), MTP_int(0)));
QPixmap medium = App::pixmapFromImageInPlace(tosend.scaled(320, 320, Qt::KeepAspectRatio, Qt::SmoothTransformation));
auto medium = App::pixmapFromImageInPlace(tosend.scaled(320, 320, Qt::KeepAspectRatio, Qt::SmoothTransformation));
photoThumbs.insert('b', medium);
photoSizes.push_back(MTP_photoSize(MTP_string("b"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(medium.width()), MTP_int(medium.height()), MTP_int(0)));
QPixmap full = QPixmap::fromImage(tosend, Qt::ColorOnly);
auto full = QPixmap::fromImage(tosend, Qt::ColorOnly);
photoThumbs.insert('c', full);
photoSizes.push_back(MTP_photoSize(MTP_string("c"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0)));

View File

@ -31,6 +31,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/filedialog.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
#include "mainwidget.h"
#include "mainwindow.h"
#include "apiwrap.h"

View File

@ -28,6 +28,10 @@ class FlatLabel;
class ConfirmBox;
namespace Ui {
class InputField;
class PhoneInput;
class InputArea;
class UsernameInput;
class Checkbox;
class Radiobutton;
class LinkButton;
@ -64,9 +68,9 @@ private:
UserData *_user = nullptr;
QString _boxTitle;
ChildWidget<InputField> _first;
ChildWidget<InputField> _last;
ChildWidget<PhoneInput> _phone;
ChildWidget<Ui::InputField> _first;
ChildWidget<Ui::InputField> _last;
ChildWidget<Ui::PhoneInput> _phone;
ChildWidget<Ui::RoundButton> _save;
ChildWidget<Ui::RoundButton> _cancel;
@ -119,8 +123,8 @@ private:
Animation _a_photoOver;
bool _photoOver;
ChildWidget<InputField> _title;
ChildWidget<InputArea> _description;
ChildWidget<Ui::InputField> _title;
ChildWidget<Ui::InputArea> _description;
QImage _photoBig;
QPixmap _photoSmall;
@ -187,7 +191,7 @@ private:
int32 _aboutPublicWidth, _aboutPublicHeight;
Text _aboutPublic, _aboutPrivate;
ChildWidget<UsernameInput> _link;
ChildWidget<Ui::UsernameInput> _link;
QRect _invitationLink;
bool _linkOver;
@ -236,8 +240,8 @@ private:
PeerData *_peer;
QString _boxTitle;
ChildWidget<InputField> _first;
ChildWidget<InputField> _last;
ChildWidget<Ui::InputField> _first;
ChildWidget<Ui::InputField> _last;
ChildWidget<Ui::RoundButton> _save;
ChildWidget<Ui::RoundButton> _cancel;
@ -283,8 +287,8 @@ private:
ChannelData *_channel;
ChildWidget<InputField> _title;
ChildWidget<InputArea> _description;
ChildWidget<Ui::InputField> _title;
ChildWidget<Ui::InputArea> _description;
ChildWidget<Ui::Checkbox> _sign;
ChildWidget<Ui::LinkButton> _publicLink;

View File

@ -28,6 +28,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "mainwindow.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h"
#include "styles/style_boxes.h"
AutoLockBox::AutoLockBox() :
_close(this, lang(lng_box_ok), st::defaultBoxButton) {

View File

@ -26,6 +26,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "mainwindow.h"
#include "window/window_theme.h"
#include "styles/style_overview.h"
#include "styles/style_boxes.h"
BackgroundBox::BackgroundBox() : ItemListBox(st::backgroundScroll)
, _inner(this) {

View File

@ -23,6 +23,48 @@ using "basic.style";
using "ui/widgets/widgets.style";
using "intro/intro.style";
defaultBoxButton: RoundButton {
textFg: #2f9fea;
textFgOver: #2f9fea;
secondaryTextFg: #2f9fea;
secondaryTextFgOver: #2f9fea;
textBg: boxBg;
textBgOver: lightButtonBgOver;
width: -24px;
height: 36px;
padding: margins(0px, 0px, 0px, 0px);
textTop: 8px;
downTextTop: 8px;
font: boxButtonFont;
ripple: RippleAnimation(defaultRippleAnimation) {
color: lightButtonBgRipple;
}
}
cancelBoxButton: RoundButton(defaultBoxButton) {
textFg: #aeaeae;
}
attentionBoxButton: RoundButton(defaultBoxButton) {
textFg: attentionBoxButtonFg;
textFgOver: attentionBoxButtonFgOver;
textBgOver: attentionBoxButtonBgOver;
ripple: RippleAnimation(defaultRippleAnimation) {
color: attentionBoxButtonBgRipple;
}
}
defaultBoxCheckbox: Checkbox(defaultCheckbox) {
width: -46px;
textPosition: point(34px, 1px);
font: boxTextFont;
}
boxBlockTitleHeight: 48px;
boxBlockTitlePosition: point(18px, 14px);
boxBlockTitleFont: font(boxFontSize semibold);
@ -46,6 +88,8 @@ boxLinkButton: LinkButton {
overFont: font(boxFontSize underline);
}
boxOptionListPadding: margins(2px, 20px, 2px, 2px);
confirmInviteTitle: flatLabel(labelDefFlat) {
font: font(16px semibold);
align: align(center);
@ -281,7 +325,7 @@ sessionTerminateAllButton: LinkButton(boxLinkButton) {
passcodeHeaderFont: font(19px);
passcodeHeaderHeight: 80px;
passcodeInput: flatInput(inpIntroPhone) {
passcodeInput: FlatInput(introPhone) {
}
passcodeSubmit: RoundButton(introNextButton) {
width: 225px;
@ -340,3 +384,45 @@ aboutLabel: flatLabel(labelDefFlat) {
aboutTextStyle: textStyle(defaultTextStyle) {
lineHeight: 22px;
}
editTextArea: InputArea(defaultInputArea) {
textMargins: margins(1px, 6px, 1px, 4px);
heightMax: 256px;
}
confirmCaptionArea: InputArea(defaultInputArea) {
textMargins: margins(1px, 6px, 1px, 4px);
heightMax: 56px;
}
confirmBg: #f2f2f2;
confirmMaxHeight: 245px;
confirmCompressedSkip: 10px;
connectionHostInputField: InputField(defaultInputField) {
width: 160px;
}
connectionPortInputField: InputField(defaultInputField) {
width: 55px;
}
connectionUserInputField: InputField(defaultInputField) {
width: 95px;
}
connectionPasswordInputField: InputField(defaultInputField) {
width: 120px;
}
connectionIPv6Skip: 11px;
langsWidth: 256px;
langsButton: Radiobutton(defaultRadiobutton) {
width: 200px;
}
backgroundPadding: 10px;
backgroundSize: size(108px, 193px);
backgroundScroll: flatScroll(boxScroll) {
round: 2px;
width: 10px;
deltax: 3px;
deltat: 10px;
deltab: 0px;
}

View File

@ -29,6 +29,11 @@ class Checkbox;
class RoundButton;
} // namespace Ui
namespace st {
extern const style::RoundButton &defaultBoxButton;
extern const style::RoundButton &cancelBoxButton;
} // namespace style
class InformBox;
class ConfirmBox : public AbstractBox, public ClickHandlerHost {
Q_OBJECT

View File

@ -24,6 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "styles/style_boxes.h"
#include "boxes/confirmbox.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
#include "mainwidget.h"
#include "lang.h"
@ -106,7 +107,7 @@ void ConfirmPhoneBox::launch() {
}
_about->setMarkedText(aboutText);
_code = new InputField(this, st::confirmPhoneCodeField, lang(lng_code_ph));
_code.create(this, st::confirmPhoneCodeField, lang(lng_code_ph));
_send.create(this, lang(lng_confirm_phone_send), st::defaultBoxButton);
_cancel.create(this, lang(lng_cancel), st::cancelBoxButton);
@ -300,6 +301,10 @@ void ConfirmPhoneBox::resizeEvent(QResizeEvent *e) {
AbstractBox::resizeEvent(e);
}
void ConfirmPhoneBox::doSetInnerFocus() {
_code->setFocus();
}
ConfirmPhoneBox::~ConfirmPhoneBox() {
if (_sendCodeRequestId) {
MTP::cancel(_sendCodeRequestId);

View File

@ -25,6 +25,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
class FlatLabel;
namespace Ui {
class InputField;
class RoundButton;
} // namespace Ui
@ -47,9 +48,7 @@ protected:
void showAll() override {
showChildren();
}
void doSetInnerFocus() override {
_code->setFocus();
}
void doSetInnerFocus() override;
private:
ConfirmPhoneBox(QWidget *parent, const QString &phone, const QString &hash);
@ -96,7 +95,7 @@ private:
ChildWidget<FlatLabel> _about = { nullptr };
ChildWidget<Ui::RoundButton> _send = { nullptr };
ChildWidget<Ui::RoundButton> _cancel = { nullptr };
ChildWidget<InputField> _code = { nullptr };
ChildWidget<Ui::InputField> _code = { nullptr };
// Flag for not calling onTextChanged() recursively.
bool _fixing = false;

View File

@ -27,7 +27,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "mainwindow.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
#include "history/history_location_manager.h"
#include "styles/style_boxes.h"
ConnectionBox::ConnectionBox() : AbstractBox(st::boxWidth)
, _hostInput(this, st::connectionHostInputField, lang(lng_connection_host_ph), Global::ConnectionProxy().host)

View File

@ -23,6 +23,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "abstractbox.h"
namespace Ui {
class InputField;
class PortInput;
class PasswordInput;
class Checkbox;
class Radiobutton;
class RoundButton;
@ -47,10 +50,10 @@ protected:
void doSetInnerFocus() override;
private:
ChildWidget<InputField> _hostInput;
ChildWidget<PortInput> _portInput;
ChildWidget<InputField> _userInput;
ChildWidget<PasswordField> _passwordInput;
ChildWidget<Ui::InputField> _hostInput;
ChildWidget<Ui::PortInput> _portInput;
ChildWidget<Ui::InputField> _userInput;
ChildWidget<Ui::PasswordInput> _passwordInput;
ChildWidget<Ui::Radiobutton> _autoRadio;
ChildWidget<Ui::Radiobutton> _httpProxyRadio;
ChildWidget<Ui::Radiobutton> _tcpProxyRadio;

View File

@ -29,6 +29,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "mainwidget.h"
#include "mainwindow.h"
#include "langloaderplain.h"
#include "styles/style_boxes.h"
LanguageBox::LanguageBox() :
_close(this, lang(lng_box_ok), st::defaultBoxButton) {

View File

@ -27,6 +27,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "localstorage.h"
#include "styles/style_boxes.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
PasscodeBox::PasscodeBox(bool turningOff) : AbstractBox(st::boxWidth)
, _replacedBy(0)

View File

@ -23,6 +23,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "abstractbox.h"
namespace Ui {
class InputField;
class PasswordInput;
class LinkButton;
class RoundButton;
} // namespace Ui
@ -81,11 +83,11 @@ private:
ChildWidget<Ui::RoundButton> _saveButton;
ChildWidget<Ui::RoundButton> _cancelButton;
ChildWidget<PasswordField> _oldPasscode;
ChildWidget<PasswordField> _newPasscode;
ChildWidget<PasswordField> _reenterPasscode;
ChildWidget<InputField> _passwordHint;
ChildWidget<InputField> _recoverEmail;
ChildWidget<Ui::PasswordInput> _oldPasscode;
ChildWidget<Ui::PasswordInput> _newPasscode;
ChildWidget<Ui::PasswordInput> _reenterPasscode;
ChildWidget<Ui::InputField> _passwordHint;
ChildWidget<Ui::InputField> _recoverEmail;
ChildWidget<Ui::LinkButton> _recover;
QString _oldError, _newError, _emailError;
@ -123,7 +125,7 @@ private:
ChildWidget<Ui::RoundButton> _saveButton;
ChildWidget<Ui::RoundButton> _cancelButton;
ChildWidget<InputField> _recoverCode;
ChildWidget<Ui::InputField> _recoverCode;
QString _error;

View File

@ -27,6 +27,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "photocropbox.h"
#include "fileuploader.h"
#include "ui/widgets/buttons.h"
#include "styles/style_boxes.h"
PhotoCropBox::PhotoCropBox(const QImage &img, const PeerId &peer) : AbstractBox()
, _downState(0)

View File

@ -28,7 +28,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "history/history_media_types.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
#include "styles/style_history.h"
#include "styles/style_boxes.h"
PhotoSendBox::PhotoSendBox(const FileLoadResultPtr &file) : AbstractBox(st::boxWideWidth)
, _file(file)
@ -141,7 +143,7 @@ PhotoSendBox::PhotoSendBox(const FileLoadResultPtr &file) : AbstractBox(st::boxW
updateBoxSize();
_caption->setMaxLength(MaxPhotoCaption);
_caption->setCtrlEnterSubmit(CtrlEnterSubmitBoth);
_caption->setCtrlEnterSubmit(Ui::CtrlEnterSubmitBoth);
connect(_compressed, SIGNAL(changed()), this, SLOT(onCompressedChange()));
connect(_caption, SIGNAL(resized()), this, SLOT(onCaptionResized()));
connect(_caption, SIGNAL(submitted(bool)), this, SLOT(onSend(bool)));
@ -493,13 +495,13 @@ EditCaptionBox::EditCaptionBox(HistoryItem *msg) : AbstractBox(st::boxWideWidth)
if (_animated || _photo || _doc) {
_field.create(this, st::confirmCaptionArea, lang(lng_photo_caption), caption);
_field->setMaxLength(MaxPhotoCaption);
_field->setCtrlEnterSubmit(CtrlEnterSubmitBoth);
_field->setCtrlEnterSubmit(Ui::CtrlEnterSubmitBoth);
} else {
auto original = msg->originalText();
QString text = textApplyEntities(original.text, original.entities);
_field.create(this, st::editTextArea, lang(lng_photo_caption), text);
// _field->setMaxLength(MaxMessageSize); // entities can make text in input field larger but still valid
_field->setCtrlEnterSubmit(cCtrlEnter() ? CtrlEnterSubmitCtrlEnter : CtrlEnterSubmitEnter);
_field->setCtrlEnterSubmit(cCtrlEnter() ? Ui::CtrlEnterSubmitCtrlEnter : Ui::CtrlEnterSubmitEnter);
}
updateBoxSize();
connect(_field, SIGNAL(submitted(bool)), this, SLOT(onSave(bool)));

View File

@ -26,6 +26,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Ui {
class Checkbox;
class RoundButton;
class InputArea;
} // namespace Ui
class PhotoSendBox : public AbstractBox {
@ -57,7 +58,7 @@ private:
QPixmap _thumb;
ChildWidget<InputArea> _caption;
ChildWidget<Ui::InputArea> _caption;
bool _compressedFromSettings;
ChildWidget<Ui::Checkbox> _compressed;
@ -108,7 +109,7 @@ private:
QPixmap _thumb;
ChildWidget<InputArea> _field = { nullptr };
ChildWidget<Ui::InputArea> _field = { nullptr };
ChildWidget<Ui::RoundButton> _save;
ChildWidget<Ui::RoundButton> _cancel;

View File

@ -27,6 +27,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "boxes/confirmbox.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
#include "mainwindow.h"
ReportBox::ReportBox(ChannelData *channel) : AbstractBox(st::boxWidth)
@ -75,9 +76,9 @@ void ReportBox::resizeEvent(QResizeEvent *e) {
void ReportBox::onChange() {
if (_reasonOther->checked()) {
if (!_reasonOtherText) {
_reasonOtherText = new InputArea(this, st::profileReportReasonOther, lang(lng_report_reason_description));
_reasonOtherText.create(this, st::profileReportReasonOther, lang(lng_report_reason_description));
_reasonOtherText->show();
_reasonOtherText->setCtrlEnterSubmit(CtrlEnterSubmitBoth);
_reasonOtherText->setCtrlEnterSubmit(Ui::CtrlEnterSubmitBoth);
_reasonOtherText->setMaxLength(MaxPhotoCaption);
_reasonOtherText->resize(width() - (st::boxPadding.left() + st::boxOptionListPadding.left() + st::boxPadding.right()), _reasonOtherText->height());

View File

@ -25,6 +25,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Ui {
class Radiobutton;
class RoundButton;
class InputArea;
} // namespace Ui
class ReportBox : public AbstractBox, public RPCSender {
@ -59,7 +60,7 @@ private:
ChildWidget<Ui::Radiobutton> _reasonViolence;
ChildWidget<Ui::Radiobutton> _reasonPornography;
ChildWidget<Ui::Radiobutton> _reasonOther;
ChildWidget<InputArea> _reasonOtherText = { nullptr };
ChildWidget<Ui::InputArea> _reasonOtherText = { nullptr };
ChildWidget<Ui::RoundButton> _report, _cancel;

View File

@ -26,6 +26,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "mainwidget.h"
#include "mainwindow.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
#include "styles/style_boxes.h"
UsernameBox::UsernameBox() : AbstractBox(st::boxWidth),

View File

@ -23,6 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "abstractbox.h"
namespace Ui {
class UsernameInput;
class RoundButton;
class LinkButton;
} // namespace Ui
@ -60,7 +61,7 @@ private:
ChildWidget<Ui::RoundButton> _save;
ChildWidget<Ui::RoundButton> _cancel;
ChildWidget<UsernameInput> _username;
ChildWidget<Ui::UsernameInput> _username;
ChildWidget<Ui::LinkButton> _link;
mtpRequestId _saveRequestId, _checkRequestId;

View File

@ -651,10 +651,19 @@ bool Generator::writeIncludesInSource() {
return true;
}
bool result = module_.enumIncludes([this](const Module &module) -> bool {
source_->include(moduleBaseName(module) + ".h");
auto includes = QStringList();
std::function<bool(const Module&)> collector = [this, &collector, &includes](const Module &module) {
module.enumIncludes(collector);
auto base = moduleBaseName(module);
if (!includes.contains(base)) {
includes.push_back(base);
}
return true;
});
};
auto result = module_.enumIncludes(collector);
for (auto base : includes) {
source_->include(base + ".h");
}
source_->newline();
return result;
}

View File

@ -22,7 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "core/utils.h"
#define BETA_VERSION_MACRO (10019006ULL)
#define BETA_VERSION_MACRO (10019007ULL)
constexpr int AppVersion = 10020;
constexpr str_const AppVersionStr = "0.10.20";

View File

@ -21,6 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "stdafx.h"
#include "data/data_drafts.h"
#include "ui/widgets/input_fields.h"
#include "historywidget.h"
#include "mainwidget.h"
#include "localstorage.h"
@ -30,6 +31,13 @@ namespace {
} // namespace
Draft::Draft(const Ui::FlatTextarea *field, MsgId msgId, bool previewCancelled, mtpRequestId saveRequestId)
: textWithTags(field->getTextWithTags())
, msgId(msgId)
, cursor(field)
, previewCancelled(previewCancelled) {
}
void applyPeerCloudDraft(PeerId peerId, const MTPDdraftMessage &draft) {
auto history = App::history(peerId);
auto text = qs(draft.vmessage);

View File

@ -20,6 +20,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#pragma once
namespace Ui {
class FlatTextarea;
} // namespace Ui
namespace Data {
void applyPeerCloudDraft(PeerId peerId, const MTPDdraftMessage &draft);
@ -35,12 +39,8 @@ struct Draft {
, previewCancelled(previewCancelled)
, saveRequestId(saveRequestId) {
}
Draft(const FlatTextarea *field, MsgId msgId, bool previewCancelled, mtpRequestId saveRequestId = 0)
: textWithTags(field->getTextWithTags())
, msgId(msgId)
, cursor(field)
, previewCancelled(previewCancelled) {
}
Draft(const Ui::FlatTextarea *field, MsgId msgId, bool previewCancelled, mtpRequestId saveRequestId = 0);
QDateTime date;
TextWithTags textWithTags;
MsgId msgId = 0; // replyToId for message draft, editMsgId for edit draft

View File

@ -84,6 +84,10 @@ dialogsMenuToggle: IconButton {
iconOver: icon {{ "dialogs_menu", dialogsMenuIconFgOver }};
iconPosition: point(6px, 6px);
iconPositionDown: point(6px, 6px);
rippleAreaPosition: point(0px, 0px);
rippleAreaSize: 32px;
ripple: defaultRippleAnimation;
}
dialogsLock: IconButton(dialogsMenuToggle) {
icon: icon {{ "dialogs_lock", dialogsMenuIconFg }};
@ -92,7 +96,7 @@ dialogsLock: IconButton(dialogsMenuToggle) {
dialogsUnlockIcon: icon {{ "dialogs_unlock", dialogsMenuIconFg }};
dialogsUnlockIconOver: icon {{ "dialogs_unlock", dialogsMenuIconFgOver }};
dialogsFilter: flatInput(inpDefGray) {
dialogsFilter: FlatInput(defaultFlatInput) {
font: font(fsize);
bgColor: #f2f2f2;
phColor: #949494;
@ -102,9 +106,15 @@ dialogsFilter: flatInput(inpDefGray) {
height: 32px;
textMrg: margins(12px, 3px, 30px, 3px);
}
dialogsCancelSearch: IconButton(dialogsMenuToggle) {
icon: icon {{ "dialogs_cancel_search", dialogsMenuIconFg, point(0px, 1px) }};
iconOver: icon {{ "dialogs_cancel_search", dialogsMenuIconFgOver, point(0px, 1px) }};
dialogsCancelSearchInPeer: IconButton(dialogsMenuToggle) {
icon: icon {{ "dialogs_cancel_search", dialogsMenuIconFg }};
iconOver: icon {{ "dialogs_cancel_search", dialogsMenuIconFgOver }};
iconPosition: point(7px, 7px);
iconPositionDown: point(7px, 7px);
}
dialogsCancelSearch: IconButton(dialogsCancelSearchInPeer) {
rippleAreaSize: 0px;
}
dialogsMenu: Menu(defaultMenu) {
@ -183,6 +193,10 @@ dialogsUpdateButton: FlatButton {
font: semiboldFont;
overFont: semiboldFont;
ripple: RippleAnimation(defaultRippleAnimation) {
color: activeButtonBgRipple;
}
}
dialogsForwardHeight: 32px;

View File

@ -40,6 +40,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "localstorage.h"
#include "apiwrap.h"
#include "ui/widgets/dropdown_menu.h"
#include "ui/widgets/input_fields.h"
#include "autoupdater.h"
DialogsInner::DialogsInner(QWidget *parent, QWidget *main) : SplittedWidget(parent)
@ -47,7 +48,7 @@ DialogsInner::DialogsInner(QWidget *parent, QWidget *main) : SplittedWidget(pare
, contactsNoDialogs(std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Name))
, contacts(std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Name))
, _addContactLnk(this, lang(lng_add_contact_button))
, _cancelSearchInPeer(this, st::dialogsCancelSearch) {
, _cancelSearchInPeer(this, st::dialogsCancelSearchInPeer) {
if (Global::DialogsModeEnabled()) {
importantDialogs = std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Date);
}

View File

@ -34,6 +34,7 @@ class PopupMenu;
class DropdownMenu;
class FlatButton;
class LinkButton;
class FlatInput;
} // namespace Ui
enum DialogsSearchRequestType {
@ -332,7 +333,7 @@ private:
ChildWidget<Ui::IconButton> _forwardCancel = { nullptr };
ChildWidget<Ui::IconButton> _mainMenuToggle;
ChildWidget<Ui::DropdownMenu> _mainMenu = { nullptr };
ChildWidget<FlatInput> _filter;
ChildWidget<Ui::FlatInput> _filter;
ChildWidget<Ui::IconButton> _cancelSearch;
ChildWidget<Ui::IconButton> _lockUnlock;
ChildWidget<ScrollArea> _scroll;

View File

@ -152,7 +152,30 @@ struct SendAction {
int32 progress;
};
using TextWithTags = FlatTextarea::TextWithTags;
struct TextWithTags {
struct Tag {
int offset, length;
QString id;
};
using Tags = QVector<Tag>;
QString text;
Tags tags;
};
inline bool operator==(const TextWithTags::Tag &a, const TextWithTags::Tag &b) {
return (a.offset == b.offset) && (a.length == b.length) && (a.id == b.id);
}
inline bool operator!=(const TextWithTags::Tag &a, const TextWithTags::Tag &b) {
return !(a == b);
}
inline bool operator==(const TextWithTags &a, const TextWithTags &b) {
return (a.text == b.text) && (a.tags == b.tags);
}
inline bool operator!=(const TextWithTags &a, const TextWithTags &b) {
return !(a == b);
}
namespace Data {
struct Draft;

View File

@ -136,7 +136,7 @@ historyPeer8UserpicBg: #f7b37c;
historyPeer8UserpicFg: #de8d62;
historyPeer8UserpicPerson: icon {{ size(120px, 120px), historyPeer8UserpicBg }, { "userpic_person", historyPeer8UserpicFg }};
historyComposeField: flatTextarea {
historyComposeField: FlatTextarea {
textColor: #000000;
bgColor: historyComposeAreaBg;
align: align(left);
@ -170,12 +170,16 @@ historyComposeButton: FlatButton {
width: -32px;
height: 46px;
textTop: 12px;
overTextTop: 12px;
downTextTop: 13px;
textTop: 14px;
overTextTop: 14px;
downTextTop: 14px;
font: semiboldFont;
overFont: semiboldFont;
ripple: RippleAnimation(defaultRippleAnimation) {
color: historyComposeButtonBgRipple;
}
}
historyUnblock: FlatButton(historyComposeButton) {
color: #d15948;
@ -290,23 +294,6 @@ historyInlineBotCancel: IconButton(historyReplyCancel) {
height: 46px;
}
topBarSearch: IconButton {
width: 44px;
height: topBarHeight;
icon: icon {{ "title_search", menuIconFg }};
iconOver: icon {{ "title_search", menuIconFgOver }};
iconPosition: point(13px, 18px);
iconPositionDown: point(13px, 18px);
}
topBarMenuToggle: IconButton(topBarSearch) {
icon: icon {{ "title_menu_dots", menuIconFg }};
iconOver: icon {{ "title_menu_dots", menuIconFgOver }};
iconPosition: point(18px, 17px);
iconPositionDown: point(18px, 17px);
}
reportSpamHide: FlatButton {
duration: 200;
cursor: cursor(pointer);
@ -327,17 +314,6 @@ reportSpamHide: FlatButton {
font: font(fsize);
overFont: font(fsize underline);
}
reportSpamButton: FlatButton(reportSpamHide) {
textTop: 6px;
overTextTop: 6px;
downTextTop: 7px;
width: -50px;
height: 30px;
bgColor: #888888;
overBgColor: #7b7b7b;
}
reportSpamSeparator: 30px;
reportSpamBg: #fffffff0;
reportSpamFg: #000000;

View File

@ -23,6 +23,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "styles/style_history.h"
#include "styles/style_dialogs.h"
#include "styles/style_window.h"
#include "styles/style_boxes.h"
#include "boxes/confirmbox.h"
#include "boxes/photosendbox.h"
#include "boxes/sharebox.h"
@ -77,13 +79,13 @@ QMimeData *mimeDataFromTextWithEntities(const TextWithEntities &forClipboard) {
for (auto &tag : tags) {
tag.id = mimeTagFromTag(tag.id);
}
result->setData(FlatTextarea::tagsMimeType(), FlatTextarea::serializeTagsList(tags));
result->setData(Ui::FlatTextarea::tagsMimeType(), Ui::FlatTextarea::serializeTagsList(tags));
}
return result;
}
// For mention tags save and validate userId, ignore tags for different userId.
class FieldTagMimeProcessor : public FlatTextarea::TagMimeProcessor {
class FieldTagMimeProcessor : public Ui::FlatTextarea::TagMimeProcessor {
public:
QString mimeTagFromTag(const QString &tagId) override {
return ::mimeTagFromTag(tagId);
@ -2302,7 +2304,7 @@ void HistoryInner::onParentGeometryChanged() {
}
}
MessageField::MessageField(HistoryWidget *history, const style::flatTextarea &st, const QString &ph, const QString &val) : FlatTextarea(history, st, ph, val), history(history) {
MessageField::MessageField(HistoryWidget *history, const style::FlatTextarea &st, const QString &ph, const QString &val) : Ui::FlatTextarea(history, st, ph, val), history(history) {
setMinHeight(st::historySend.height - 2 * st::historySendPadding);
setMaxHeight(st::historyComposeFieldMaxHeight);
}
@ -2976,7 +2978,7 @@ QPoint SilentToggle::tooltipPos() const {
return QCursor::pos();
}
EntitiesInText entitiesFromTextTags(const FlatTextarea::TagList &tags) {
EntitiesInText entitiesFromTextTags(const TextWithTags::Tags &tags) {
EntitiesInText result;
if (tags.isEmpty()) {
return result;
@ -3229,14 +3231,14 @@ void HistoryWidget::updateInlineBotQuery() {
MTP::cancel(_inlineBotResolveRequestId);
_inlineBotResolveRequestId = 0;
}
if (bot == LookingUpInlineBot) {
_inlineBot = LookingUpInlineBot;
if (bot == Ui::LookingUpInlineBot) {
_inlineBot = Ui::LookingUpInlineBot;
// Notify::inlineBotRequesting(true);
_inlineBotResolveRequestId = MTP::send(MTPcontacts_ResolveUsername(MTP_string(_inlineBotUsername)), rpcDone(&HistoryWidget::inlineBotResolveDone), rpcFail(&HistoryWidget::inlineBotResolveFail, _inlineBotUsername));
return;
}
} else if (bot == LookingUpInlineBot) {
if (_inlineBot == LookingUpInlineBot) {
} else if (bot == Ui::LookingUpInlineBot) {
if (_inlineBot == Ui::LookingUpInlineBot) {
return;
}
bot = _inlineBot;
@ -4389,11 +4391,11 @@ void HistoryWidget::updateAfterDrag() {
}
void HistoryWidget::updateFieldSubmitSettings() {
FlatTextarea::SubmitSettings settings = FlatTextarea::SubmitSettings::Enter;
auto settings = Ui::FlatTextarea::SubmitSettings::Enter;
if (_inlineBotCancel) {
settings = FlatTextarea::SubmitSettings::None;
settings = Ui::FlatTextarea::SubmitSettings::None;
} else if (cCtrlEnter()) {
settings = FlatTextarea::SubmitSettings::CtrlEnter;
settings = Ui::FlatTextarea::SubmitSettings::CtrlEnter;
}
_field->setSubmitSettings(settings);
}
@ -5156,9 +5158,9 @@ void HistoryWidget::preloadHistoryIfNeeded() {
void HistoryWidget::onInlineBotCancel() {
auto &textWithTags = _field->getTextWithTags();
if (textWithTags.text.size() > _inlineBotUsername.size() + 2) {
setFieldText({ '@' + _inlineBotUsername + ' ', TextWithTags::Tags() }, TextUpdateEvent::SaveDraft, FlatTextarea::AddToUndoHistory);
setFieldText({ '@' + _inlineBotUsername + ' ', TextWithTags::Tags() }, TextUpdateEvent::SaveDraft, Ui::FlatTextarea::AddToUndoHistory);
} else {
clearFieldText(TextUpdateEvent::SaveDraft, FlatTextarea::AddToUndoHistory);
clearFieldText(TextUpdateEvent::SaveDraft, Ui::FlatTextarea::AddToUndoHistory);
}
}
@ -5883,7 +5885,7 @@ bool HistoryWidget::insertBotCommand(const QString &cmd, bool specialGif) {
auto &textWithTags = _field->getTextWithTags();
if (specialGif) {
if (textWithTags.text.trimmed() == '@' + cInlineGifBotUsername() && textWithTags.text.at(0) == '@') {
clearFieldText(TextUpdateEvent::SaveDraft, FlatTextarea::AddToUndoHistory);
clearFieldText(TextUpdateEvent::SaveDraft, Ui::FlatTextarea::AddToUndoHistory);
}
} else {
TextWithTags textWithTagsToSet;
@ -5905,7 +5907,7 @@ bool HistoryWidget::insertBotCommand(const QString &cmd, bool specialGif) {
}
} else {
if (!specialGif || _field->isEmpty()) {
setFieldText({ toInsert, TextWithTags::Tags() }, TextUpdateEvent::SaveDraft, FlatTextarea::AddToUndoHistory);
setFieldText({ toInsert, TextWithTags::Tags() }, TextUpdateEvent::SaveDraft, Ui::FlatTextarea::AddToUndoHistory);
_field->setFocus();
return true;
}
@ -6027,7 +6029,7 @@ void HistoryWidget::inlineBotResolveDone(const MTPcontacts_ResolvedPeer &result)
QString inlineBotUsername;
auto query = _field->getInlineBotQuery(&bot, &inlineBotUsername);
if (inlineBotUsername == _inlineBotUsername) {
if (bot == LookingUpInlineBot) {
if (bot == Ui::LookingUpInlineBot) {
bot = resolvedBot;
}
} else {
@ -6223,7 +6225,7 @@ void HistoryWidget::onKbToggle(bool manual) {
}
void HistoryWidget::onCmdStart() {
setFieldText({ qsl("/"), TextWithTags::Tags() }, 0, FlatTextarea::AddToUndoHistory);
setFieldText({ qsl("/"), TextWithTags::Tags() }, 0, Ui::FlatTextarea::AddToUndoHistory);
}
void HistoryWidget::contextMenuEvent(QContextMenuEvent *e) {
@ -6502,7 +6504,7 @@ void HistoryWidget::clearInlineBot() {
}
void HistoryWidget::inlineBotChanged() {
bool isInlineBot = _inlineBot && (_inlineBot != LookingUpInlineBot);
bool isInlineBot = _inlineBot && (_inlineBot != Ui::LookingUpInlineBot);
if (isInlineBot && !_inlineBotCancel) {
_inlineBotCancel = std_::make_unique<Ui::IconButton>(this, st::historyInlineBotCancel);
connect(_inlineBotCancel.get(), SIGNAL(clicked()), this, SLOT(onInlineBotCancel()));
@ -6532,7 +6534,7 @@ void HistoryWidget::onCheckFieldAutocomplete() {
if (!_history || _a_show.animating()) return;
bool start = false;
bool isInlineBot = _inlineBot && (_inlineBot != LookingUpInlineBot);
bool isInlineBot = _inlineBot && (_inlineBot != Ui::LookingUpInlineBot);
QString query = isInlineBot ? QString() : _field->getMentionHashtagBotCommandPart(start);
if (!query.isEmpty()) {
if (query.at(0) == '#' && cRecentWriteHashtags().isEmpty() && cRecentSearchHashtags().isEmpty()) Local::readRecentHashtagsAndBots();
@ -6547,7 +6549,7 @@ void HistoryWidget::updateFieldPlaceholder() {
_field->setPlaceholder(lang(lng_edit_message_text));
_send->setIcon(&st::historyEditSaveIcon, &st::historyEditSaveIconOver);
} else {
if (_inlineBot && _inlineBot != LookingUpInlineBot) {
if (_inlineBot && _inlineBot != Ui::LookingUpInlineBot) {
_field->setPlaceholder(_inlineBot->botInfo->inlinePlaceholder.mid(1), _inlineBot->username.size() + 2);
} else {
_field->setPlaceholder(lang((_history && _history->isChannel() && !_history->isMegagroup()) ? (_silent->checked() ? lng_broadcast_silent_ph : lng_broadcast_ph) : lng_message_ph));
@ -7770,7 +7772,7 @@ void HistoryWidget::sendExistingPhoto(PhotoData *photo, const QString &caption)
_field->setFocus();
}
void HistoryWidget::setFieldText(const TextWithTags &textWithTags, TextUpdateEvents events, FlatTextarea::UndoHistoryAction undoHistoryAction) {
void HistoryWidget::setFieldText(const TextWithTags &textWithTags, TextUpdateEvents events, Ui::FlatTextarea::UndoHistoryAction undoHistoryAction) {
_textUpdateEvents = events;
_field->setTextWithTags(textWithTags, undoHistoryAction);
_field->moveCursor(QTextCursor::End);

View File

@ -23,6 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "localimageloader.h"
#include "ui/effects/rect_shadow.h"
#include "ui/widgets/tooltip.h"
#include "ui/widgets/input_fields.h"
#include "history/history_common.h"
#include "history/field_autocomplete.h"
#include "window/section_widget.h"
@ -310,11 +311,11 @@ private:
};
class MessageField : public FlatTextarea {
class MessageField : public Ui::FlatTextarea {
Q_OBJECT
public:
MessageField(HistoryWidget *history, const style::flatTextarea &st, const QString &ph = QString(), const QString &val = QString());
MessageField(HistoryWidget *history, const style::FlatTextarea &st, const QString &ph = QString(), const QString &val = QString());
void dropEvent(QDropEvent *e);
bool canInsertFromMimeData(const QMimeData *source) const;
void insertFromMimeData(const QMimeData *source);
@ -1014,8 +1015,8 @@ private:
void writeDrafts(Data::Draft **localDraft, Data::Draft **editDraft);
void writeDrafts(History *history);
void setFieldText(const TextWithTags &textWithTags, TextUpdateEvents events = 0, FlatTextarea::UndoHistoryAction undoHistoryAction = FlatTextarea::ClearUndoHistory);
void clearFieldText(TextUpdateEvents events = 0, FlatTextarea::UndoHistoryAction undoHistoryAction = FlatTextarea::ClearUndoHistory) {
void setFieldText(const TextWithTags &textWithTags, TextUpdateEvents events = 0, Ui::FlatTextarea::UndoHistoryAction undoHistoryAction = Ui::FlatTextarea::ClearUndoHistory);
void clearFieldText(TextUpdateEvents events = 0, Ui::FlatTextarea::UndoHistoryAction undoHistoryAction = Ui::FlatTextarea::ClearUndoHistory) {
setFieldText(TextWithTags(), events, undoHistoryAction);
}

View File

@ -39,7 +39,7 @@ introCountry: countryInput {
bgColor: #f2f2f2;
ptrSize: size(15px, 8px);
textMrg: margins(16px, 5px, 16px, 15px);
font: inpDefFont;
font: defaultInputFont;
align: align(left);
}
@ -89,17 +89,17 @@ introNextButton: RoundButton(defaultActiveButton) {
}
introPhoneTop: 8px;
inpIntroCountryCode: flatInput(inpDefGray) {
introCountryCode: FlatInput(defaultFlatInput) {
width: 70px;
height: 41px;
align: align(center);
}
inpIntroPhone: flatInput(inpDefGray) {
introPhone: FlatInput(defaultFlatInput) {
textMrg: margins(12px, 5px, 12px, 6px);
width: 225px;
height: 41px;
}
inpIntroCode: flatInput(inpDefGray) {
introCode: FlatInput(defaultFlatInput) {
textMrg: margins(12px, 5px, 12px, 6px);
width: 106px;
height: 41px;
@ -109,10 +109,10 @@ inpIntroCode: flatInput(inpDefGray) {
phAlign: align(center);
phShift: 0px;
}
inpIntroName: flatInput(inpIntroPhone) {
introName: FlatInput(introPhone) {
width: 192px;
}
inpIntroPassword: flatInput(inpIntroPhone) {
introPassword: FlatInput(introPhone) {
width: 300px;
}

View File

@ -28,7 +28,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/widgets/buttons.h"
#include "styles/style_intro.h"
CodeInput::CodeInput(QWidget *parent, const style::flatInput &st, const QString &ph) : FlatInput(parent, st, ph) {
CodeInput::CodeInput(QWidget *parent, const style::FlatInput &st, const QString &ph) : Ui::FlatInput(parent, st, ph) {
}
void CodeInput::correctValue(const QString &was, QString &now) {
@ -80,7 +80,7 @@ IntroCode::IntroCode(IntroWidget *parent) : IntroStep(parent)
, _desc(st::introTextSize.width())
, _noTelegramCode(this, lang(lng_code_no_telegram), st::introLink)
, _noTelegramCodeRequestId(0)
, _code(this, st::inpIntroCode, lang(lng_code_ph))
, _code(this, st::introCode, lang(lng_code_ph))
, _callTimer(this)
, _callStatus(intro()->getCallStatus())
, _checkRequest(this) {

View File

@ -21,19 +21,18 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#pragma once
#include "intro/introwidget.h"
class FlatInput;
#include "ui/widgets/input_fields.h"
namespace Ui {
class RoundButton;
class LinkButton;
} // namespace Ui
class CodeInput final : public FlatInput {
class CodeInput final : public Ui::FlatInput {
Q_OBJECT
public:
CodeInput(QWidget *parent, const style::flatInput &st, const QString &ph);
CodeInput(QWidget *parent, const style::FlatInput &st, const QString &ph);
signals:
void codeEntered();

View File

@ -49,8 +49,8 @@ IntroPhone::IntroPhone(IntroWidget *parent) : IntroStep(parent)
, _a_error(animation(this, &IntroPhone::step_error))
, _next(this, lang(lng_intro_next), st::introNextButton)
, _country(this, st::introCountry)
, _phone(this, st::inpIntroPhone)
, _code(this, st::inpIntroCountryCode)
, _phone(this, st::introPhone)
, _code(this, st::introCountryCode)
, _signup(this, lng_phone_notreg(lt_signup_start, textcmdStartLink(1), lt_signup_end, textcmdStopLink()), FlatLabel::InitType::Rich, st::introErrorLabel, st::introErrorLabelTextStyle)
, _checkRequest(this) {
setVisible(false);
@ -110,7 +110,7 @@ void IntroPhone::resizeEvent(QResizeEvent *e) {
_next->move((width() - _next->width()) / 2, st::introBtnTop);
_country->move((width() - _country->width()) / 2, st::introTextTop + st::introTextSize.height() + st::introCountry.top);
int phoneTop = _country->y() + _country->height() + st::introPhoneTop;
_phone->move((width() - _country->width()) / 2 + _country->width() - st::inpIntroPhone.width, phoneTop);
_phone->move((width() - _country->width()) / 2 + _country->width() - st::introPhone.width, phoneTop);
_code->move((width() - _country->width()) / 2, phoneTop);
}
_signup->move((width() - _signup->width()) / 2, _next->y() + _next->height() + st::introErrorTop - ((st::introErrorLabelTextStyle.lineHeight - st::introErrorFont->height) / 2));

View File

@ -25,6 +25,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "intro/introwidget.h"
namespace Ui {
class PhonePartInput;
class CountryCodeInput;
class RoundButton;
} // namespace Ui
@ -76,8 +78,8 @@ private:
QRect _textRect;
ChildWidget<CountryInput> _country;
ChildWidget<PhonePartInput> _phone;
ChildWidget<CountryCodeInput> _code;
ChildWidget<Ui::PhonePartInput> _phone;
ChildWidget<Ui::CountryCodeInput> _code;
ChildWidget<FlatLabel> _signup;
QPixmap _signupCache;

View File

@ -22,12 +22,14 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "intro/intropwdcheck.h"
#include "styles/style_intro.h"
#include "styles/style_boxes.h"
#include "ui/filedialog.h"
#include "boxes/confirmbox.h"
#include "lang.h"
#include "application.h"
#include "intro/introsignup.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
IntroPwdCheck::IntroPwdCheck(IntroWidget *parent) : IntroStep(parent)
, a_errorAlpha(0)
@ -36,8 +38,8 @@ IntroPwdCheck::IntroPwdCheck(IntroWidget *parent) : IntroStep(parent)
, _salt(parent->getPwdSalt())
, _hasRecovery(parent->getHasRecovery())
, _hint(parent->getPwdHint())
, _pwdField(this, st::inpIntroPassword, lang(lng_signin_password))
, _codeField(this, st::inpIntroPassword, lang(lng_signin_code))
, _pwdField(this, st::introPassword, lang(lng_signin_password))
, _codeField(this, st::introPassword, lang(lng_signin_code))
, _toRecover(this, lang(lng_signin_recover))
, _toPassword(this, lang(lng_signin_try_password))
, _reset(this, lang(lng_signin_reset_account), st::introResetLink)

View File

@ -22,9 +22,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "intro/introwidget.h"
class FlatInput;
namespace Ui {
class FlatInput;
class RoundButton;
class LinkButton;
} // namespace Ui
@ -80,8 +79,8 @@ private:
bool _hasRecovery;
QString _hint, _emailPattern;
ChildWidget<FlatInput> _pwdField;
ChildWidget<FlatInput> _codeField;
ChildWidget<Ui::FlatInput> _pwdField;
ChildWidget<Ui::FlatInput> _codeField;
ChildWidget<Ui::LinkButton> _toRecover;
ChildWidget<Ui::LinkButton> _toPassword;
ChildWidget<Ui::LinkButton> _reset;

View File

@ -28,6 +28,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "lang.h"
#include "application.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
IntroSignup::IntroSignup(IntroWidget *parent) : IntroStep(parent)
, a_errorAlpha(0)
@ -35,8 +36,8 @@ IntroSignup::IntroSignup(IntroWidget *parent) : IntroStep(parent)
, _a_error(animation(this, &IntroSignup::step_error))
, _a_photo(animation(this, &IntroSignup::step_photo))
, _next(this, lang(lng_intro_finish), st::introNextButton)
, _first(this, st::inpIntroName, lang(lng_signup_firstname))
, _last(this, st::inpIntroName, lang(lng_signup_lastname))
, _first(this, st::introName, lang(lng_signup_firstname))
, _last(this, st::introName, lang(lng_signup_lastname))
, _invertOrder(langFirstNameGoesSecond())
, _checkRequest(this) {
setVisible(false);

View File

@ -20,11 +20,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "ui/flatinput.h"
#include "intro/introwidget.h"
namespace Ui {
class RoundButton;
class FlatInput;
} // namespace Ui
class IntroSignup final : public IntroStep {
@ -72,8 +72,8 @@ private:
QPixmap _photoSmall;
int32 _phLeft, _phTop;
ChildWidget<FlatInput> _first;
ChildWidget<FlatInput> _last;
ChildWidget<Ui::FlatInput> _first;
ChildWidget<Ui::FlatInput> _last;
QString _firstName, _lastName;
mtpRequestId _sentRequest = 0;

View File

@ -37,6 +37,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "styles/style_intro.h"
#include "autoupdater.h"
#include "window/slide_animation.h"
#include "styles/style_boxes.h"
IntroWidget::IntroWidget(QWidget *parent) : TWidget(parent)
, _a_stage(animation(this, &IntroWidget::step_stage))

View File

@ -353,22 +353,22 @@ void FileLoadTask::process() {
}
if (!fullimage.isNull() && fullimage.width() > 0 && !song && !gif && !voice) {
int32 w = fullimage.width(), h = fullimage.height();
auto w = fullimage.width(), h = fullimage.height();
attributes.push_back(MTP_documentAttributeImageSize(MTP_int(w), MTP_int(h)));
if (w < 20 * h && h < 20 * w) {
if (animated) {
attributes.push_back(MTP_documentAttributeAnimated());
} else if (_type != PrepareDocument) {
QPixmap thumb = (w > 100 || h > 100) ? App::pixmapFromImageInPlace(fullimage.scaled(100, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(fullimage);
auto thumb = (w > 100 || h > 100) ? App::pixmapFromImageInPlace(fullimage.scaled(100, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(fullimage);
photoThumbs.insert('s', thumb);
photoSizes.push_back(MTP_photoSize(MTP_string("s"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(thumb.width()), MTP_int(thumb.height()), MTP_int(0)));
QPixmap medium = (w > 320 || h > 320) ? App::pixmapFromImageInPlace(fullimage.scaled(320, 320, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(fullimage);
auto medium = (w > 320 || h > 320) ? App::pixmapFromImageInPlace(fullimage.scaled(320, 320, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(fullimage);
photoThumbs.insert('m', medium);
photoSizes.push_back(MTP_photoSize(MTP_string("m"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(medium.width()), MTP_int(medium.height()), MTP_int(0)));
QPixmap full = (w > 1280 || h > 1280) ? App::pixmapFromImageInPlace(fullimage.scaled(1280, 1280, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(fullimage);
auto full = (w > 1280 || h > 1280) ? App::pixmapFromImageInPlace(fullimage.scaled(1280, 1280, Qt::KeepAspectRatio, Qt::SmoothTransformation)) : QPixmap::fromImage(fullimage);
photoThumbs.insert('y', full);
photoSizes.push_back(MTP_photoSize(MTP_string("y"), MTP_fileLocationUnavailable(MTP_long(0), MTP_int(0), MTP_long(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0)));

View File

@ -32,6 +32,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "mainwindow.h"
#include "lang.h"
#include "media/media_audio.h"
#include "ui/widgets/input_fields.h"
#include "application.h"
#include "apiwrap.h"
@ -2369,8 +2370,8 @@ void writeDrafts(const PeerId &peer, const MessageDraft &localDraft, const Messa
_writeMap(WriteMapFast);
}
auto msgTags = FlatTextarea::serializeTagsList(localDraft.textWithTags.tags);
auto editTags = FlatTextarea::serializeTagsList(editDraft.textWithTags.tags);
auto msgTags = Ui::FlatTextarea::serializeTagsList(localDraft.textWithTags.tags);
auto editTags = Ui::FlatTextarea::serializeTagsList(editDraft.textWithTags.tags);
int size = sizeof(quint64);
size += Serialize::stringSize(localDraft.textWithTags.text) + Serialize::bytearraySize(msgTags) + 2 * sizeof(qint32);
@ -2476,8 +2477,8 @@ void readDraftsWithCursors(History *h) {
return;
}
msgData.tags = FlatTextarea::deserializeTagsList(msgTagsSerialized, msgData.text.size());
editData.tags = FlatTextarea::deserializeTagsList(editTagsSerialized, editData.text.size());
msgData.tags = Ui::FlatTextarea::deserializeTagsList(msgTagsSerialized, msgData.text.size());
editData.tags = Ui::FlatTextarea::deserializeTagsList(editTagsSerialized, editData.text.size());
MessageCursor msgCursor, editCursor;
_readDraftCursors(peer, msgCursor, editCursor);

View File

@ -84,7 +84,6 @@ int32 oldMapVersion();
int32 oldSettingsVersion();
using TextWithTags = FlatTextarea::TextWithTags;
struct MessageDraft {
MessageDraft(MsgId msgId = 0, TextWithTags textWithTags = TextWithTags(), bool previewCancelled = false)
: msgId(msgId)

View File

@ -22,6 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "mainwidget.h"
#include "styles/style_dialogs.h"
#include "styles/style_history.h"
#include "ui/buttons/peer_avatar_button.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/shadow.h"
@ -58,6 +59,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "core/qthelp_url.h"
#include "window/window_theme.h"
#include "window/player_wrap_widget.h"
#include "styles/style_boxes.h"
StackItemSection::StackItemSection(std_::unique_ptr<Window::SectionMemento> &&memento) : StackItem(nullptr)
, _memento(std_::move(memento)) {

View File

@ -24,6 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "dialogs/dialogs_layout.h"
#include "styles/style_dialogs.h"
#include "styles/style_window.h"
#include "styles/style_boxes.h"
#include "ui/widgets/popup_menu.h"
#include "ui/widgets/buttons.h"
#include "core/zlib_help.h"

View File

@ -78,11 +78,12 @@ public:
void start(int framew, int frameh, int outerw, int outerh, ImageRoundRadius radius);
QPixmap current(int framew, int frameh, int outerw, int outerh, uint64 ms);
QPixmap frameOriginal() const {
Frame *frame = frameToShow();
if (!frame) return QPixmap();
QPixmap result(frame ? QPixmap::fromImage(frame->original) : QPixmap());
result.detach();
return result;
if (auto frame = frameToShow()) {
auto result = QPixmap::fromImage(frame->original);
result.detach();
return result;
}
return QPixmap();
}
bool currentDisplayed() const {
Frame *frame = frameToShow();

View File

@ -118,7 +118,7 @@ overviewLinksChecked: icon {
{ "overview_links_check", #ffffff, point(4px, 5px) },
};
overviewFilter: flatInput(inpDefGray) {
overviewFilter: FlatInput(defaultFlatInput) {
font: font(fsize);
bgColor: #f2f2f2;
phColor: #949494;

View File

@ -30,6 +30,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/widgets/popup_menu.h"
#include "ui/widgets/tooltip.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
#include "window/top_bar_widget.h"
#include "window/window_theme.h"
#include "lang.h"
@ -77,17 +78,17 @@ OverviewInner::OverviewInner(OverviewWidget *overview, ScrollArea *scroll, PeerD
setMouseTracking(true);
connect(_cancelSearch, SIGNAL(clicked()), this, SLOT(onCancelSearch()));
connect(&_search, SIGNAL(cancelled()), this, SLOT(onCancel()));
connect(&_search, SIGNAL(changed()), this, SLOT(onSearchUpdate()));
connect(_search, SIGNAL(cancelled()), this, SLOT(onCancel()));
connect(_search, SIGNAL(changed()), this, SLOT(onSearchUpdate()));
_searchTimer.setSingleShot(true);
connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchMessages()));
_cancelSearch->hide();
if (_type == OverviewLinks || _type == OverviewFiles) {
_search.show();
_search->show();
} else {
_search.hide();
_search->hide();
}
}
@ -176,7 +177,7 @@ void OverviewInner::fixItemIndex(int32 &current, MsgId msgId) const {
}
void OverviewInner::searchReceived(SearchRequestType type, const MTPmessages_Messages &result, mtpRequestId req) {
if (!_search.text().isEmpty()) {
if (!_search->text().isEmpty()) {
if (type == SearchFromStart) {
SearchQueries::iterator i = _searchQueries.find(req);
if (i != _searchQueries.cend()) {
@ -683,7 +684,7 @@ QPoint OverviewInner::mapMouseToItem(QPoint p, MsgId itemId, int32 itemIndex) {
void OverviewInner::activate() {
if (_type == OverviewLinks || _type == OverviewFiles) {
_search.setFocus();
_search->setFocus();
} else {
setFocus();
}
@ -1111,7 +1112,7 @@ void OverviewInner::mouseReleaseEvent(QMouseEvent *e) {
}
void OverviewInner::keyPressEvent(QKeyEvent *e) {
if ((_search.isHidden() || !_search.hasFocus()) && !_overview->isHidden() && e->key() == Qt::Key_Escape) {
if ((_search->isHidden() || !_search->hasFocus()) && !_overview->isHidden() && e->key() == Qt::Key_Escape) {
onCancel();
} else if (e->key() == Qt::Key_Back) {
App::main()->showBackFromStack();
@ -1282,8 +1283,8 @@ int32 OverviewInner::resizeToWidth(int32 nwidth, int32 scrollTop, int32 minHeigh
}
_rowsLeft = (_width - _rowWidth) / 2;
_search.setGeometry(_rowsLeft, st::linksSearchMargin.top(), _rowWidth, _search.height());
_cancelSearch->moveToLeft(_rowsLeft + _rowWidth - _cancelSearch->width(), _search.y());
_search->setGeometry(_rowsLeft, st::linksSearchMargin.top(), _rowWidth, _search->height());
_cancelSearch->moveToLeft(_rowsLeft + _rowWidth - _cancelSearch->width(), _search->y());
if (_type == OverviewPhotos || _type == OverviewVideos) {
for (int32 i = 0, l = _items.size(); i < l; ++i) {
@ -1334,14 +1335,14 @@ void OverviewInner::switchType(MediaOverviewType type) {
_type = type;
_reversed = (_type != OverviewLinks && _type != OverviewFiles);
if (_type == OverviewLinks || _type == OverviewFiles) {
_search.show();
_search->show();
} else {
_search.hide();
_search->hide();
}
if (!_search.getLastText().isEmpty()) {
_search.setText(QString());
_search.updatePlaceholder();
if (!_search->getLastText().isEmpty()) {
_search->setText(QString());
_search->updatePlaceholder();
onSearchUpdate();
}
_cancelSearch->hide();
@ -1425,7 +1426,7 @@ void OverviewInner::saveContextFile() {
bool OverviewInner::onSearchMessages(bool searchCache) {
_searchTimer.stop();
QString q = _search.text().trimmed();
QString q = _search->text().trimmed();
if (q.isEmpty()) {
if (_searchRequest) {
_searchRequest = 0;
@ -1462,7 +1463,7 @@ void OverviewInner::onNeedSearchMessages() {
}
void OverviewInner::onSearchUpdate() {
QString filterText = (_type == OverviewLinks || _type == OverviewFiles) ? _search.text().trimmed() : QString();
QString filterText = (_type == OverviewLinks || _type == OverviewFiles) ? _search->text().trimmed() : QString();
bool inSearch = !filterText.isEmpty(), changed = (inSearch != _inSearch);
_inSearch = inSearch;
@ -1495,11 +1496,11 @@ void OverviewInner::onCancel() {
}
bool OverviewInner::onCancelSearch() {
if (_search.isHidden()) return false;
bool clearing = !_search.text().isEmpty();
if (_search->isHidden()) return false;
bool clearing = !_search->text().isEmpty();
_cancelSearch->hide();
_search.clear();
_search.updatePlaceholder();
_search->clear();
_search->updatePlaceholder();
onSearchUpdate();
return clearing;
}
@ -1796,7 +1797,7 @@ void OverviewInner::recountMargins() {
_marginTop = st::playlistPadding;
_marginBottom = qMax(_minHeight - _height - _marginTop, int32(st::playlistPadding));
} else if (_type == OverviewLinks || _type == OverviewFiles) {
_marginTop = st::linksSearchMargin.top() + _search.height() + st::linksSearchMargin.bottom();
_marginTop = st::linksSearchMargin.top() + _search->height() + st::linksSearchMargin.bottom();
_marginBottom = qMax(_minHeight - _height - _marginTop, int32(st::playlistPadding));
} else {
_marginBottom = st::playlistPadding;

View File

@ -35,6 +35,7 @@ namespace Ui {
class PlainShadow;
class PopupMenu;
class IconButton;
class FlatInput;
} // namespace Ui
class OverviewWidget;
@ -179,7 +180,7 @@ private:
Overview::Layout::AbstractItem *layoutPrepare(const QDate &date, bool month);
int32 setLayoutItem(int32 index, Overview::Layout::AbstractItem *item, int32 top);
FlatInput _search;
ChildWidget<Ui::FlatInput> _search;
ChildWidget<Ui::IconButton> _cancelSearch;
QVector<MsgId> _results;
int32 _itemsToBeLoaded;

View File

@ -27,6 +27,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "application.h"
#include "ui/text/text.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
#include "styles/style_boxes.h"
#include "window/slide_animation.h"

View File

@ -21,6 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#pragma once
namespace Ui {
class FlatInput;
class LinkButton;
class RoundButton;
} // namespace Ui
@ -55,7 +56,7 @@ private:
anim::ivalue a_coordUnder, a_coordOver;
anim::fvalue a_shadow;
ChildWidget<FlatInput> _passcode;
ChildWidget<Ui::FlatInput> _passcode;
ChildWidget<Ui::RoundButton> _submit;
ChildWidget<Ui::LinkButton> _logout;
QString _error;

View File

@ -436,7 +436,7 @@ void MainWindow::createGlobalMenu() {
namespace {
void _sendKeySequence(Qt::Key key, Qt::KeyboardModifiers modifiers = Qt::NoModifier) {
QWidget *focused = QApplication::focusWidget();
if (qobject_cast<QLineEdit*>(focused) || qobject_cast<FlatTextarea*>(focused) || qobject_cast<HistoryInner*>(focused)) {
if (qobject_cast<QLineEdit*>(focused) || qobject_cast<QTextEdit*>(focused) || qobject_cast<HistoryInner*>(focused)) {
QApplication::postEvent(focused, new QKeyEvent(QEvent::KeyPress, key, modifiers));
QApplication::postEvent(focused, new QKeyEvent(QEvent::KeyRelease, key, modifiers));
}
@ -498,11 +498,11 @@ void MainWindow::psMacUpdateMenu() {
canUndo = edit->isUndoAvailable();
canRedo = edit->isRedoAvailable();
canPaste = !Application::clipboard()->text().isEmpty();
} else if (auto edit = qobject_cast<FlatTextarea*>(focused)) {
} else if (auto edit = qobject_cast<QTextEdit*>(focused)) {
canCut = canCopy = canDelete = edit->textCursor().hasSelection();
canSelectAll = !edit->isEmpty();
canUndo = edit->isUndoAvailable();
canRedo = edit->isRedoAvailable();
canSelectAll = !edit->document()->isEmpty();
canUndo = edit->document()->isUndoAvailable();
canRedo = edit->document()->isRedoAvailable();
canPaste = !Application::clipboard()->text().isEmpty();
} else if (auto list = qobject_cast<HistoryInner*>(focused)) {
canCopy = list->canCopySelected();
@ -534,7 +534,7 @@ bool MainWindow::psFilterNativeEvent(void *event) {
bool MainWindow::eventFilter(QObject *obj, QEvent *evt) {
QEvent::Type t = evt->type();
if (t == QEvent::FocusIn || t == QEvent::FocusOut) {
if (qobject_cast<QLineEdit*>(obj) || qobject_cast<FlatTextarea*>(obj) || qobject_cast<HistoryInner*>(obj)) {
if (qobject_cast<QLineEdit*>(obj) || qobject_cast<QTextEdit*>(obj) || qobject_cast<HistoryInner*>(obj)) {
psMacUpdateMenu();
}
}

View File

@ -21,6 +21,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
using "basic.style";
using "basic_types.style";
using "window/window.style";
profileBg: windowBg;
profileTopBarHeight: topBarHeight;

View File

@ -22,6 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "profile/profile_actions_widget.h"
#include "styles/style_profile.h"
#include "styles/style_boxes.h"
#include "ui/buttons/left_outline_button.h"
#include "boxes/confirmbox.h"
#include "boxes/report_box.h"

View File

@ -22,6 +22,14 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "profile/profile_block_widget.h"
namespace style {
struct OutlineButton;
} // namespace style
namespace st {
extern const style::OutlineButton &defaultLeftOutlineButton;
} // namespace st
namespace Ui {
class LeftOutlineButton;
} // namespace Ui

View File

@ -22,6 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "profile/profile_block_widget.h"
#include "styles/style_profile.h"
#include "styles/style_widgets.h"
namespace Profile {

View File

@ -25,6 +25,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
class FlatLabel;
namespace style {
struct RoundButton;
} // namespace style
namespace Ui {
class RoundButton;
class LinkButton;

View File

@ -30,6 +30,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "boxes/confirmbox.h"
#include "observer_peer.h"
#include "window/top_bar_widget.h"
#include "styles/style_boxes.h"
namespace Profile {

View File

@ -129,7 +129,7 @@ void SettingsWidget::refreshManageAdminsButton() {
};
_manageAdmins.destroy();
if (hasManageAdmins()) {
_manageAdmins = new Ui::LeftOutlineButton(this, lang(lng_profile_manage_admins), st::defaultLeftOutlineButton);
_manageAdmins.create(this, lang(lng_profile_manage_admins), st::defaultLeftOutlineButton);
_manageAdmins->show();
connect(_manageAdmins, SIGNAL(clicked()), this, SLOT(onManageAdmins()));
}
@ -152,7 +152,7 @@ void SettingsWidget::refreshInviteLinkButton() {
if (inviteLinkText.isEmpty()) {
_inviteLink.destroy();
} else {
_inviteLink = new Ui::LeftOutlineButton(this, inviteLinkText, st::defaultLeftOutlineButton);
_inviteLink.create(this, inviteLinkText, st::defaultLeftOutlineButton);
_inviteLink->show();
connect(_inviteLink, SIGNAL(clicked()), this, SLOT(onInviteLink()));
}

View File

@ -70,8 +70,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "ui/animation.h"
#include "ui/twidget.h"
#include "ui/flatinput.h"
#include "ui/flattextarea.h"
#include "ui/scrollarea.h"
#include "ui/images.h"
#include "ui/text/text.h"

View File

@ -23,6 +23,13 @@ using "basic.style";
using "boxes/boxes.style";
using "ui/widgets/widgets.style";
switchPmButton: RoundButton(defaultBoxButton) {
width: 320px;
height: 34px;
textTop: 7px;
downTextTop: 8px;
}
stickersTrendingHeader: 45px;
stickersTrendingSkip: 15px;

View File

@ -21,6 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#pragma once
#include "ui/abstract_button.h"
#include "styles/style_widgets.h"
namespace Ui {

View File

@ -21,6 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#pragma once
#include "ui/abstract_button.h"
#include "styles/style_window.h"
class PeerData;

View File

@ -111,7 +111,7 @@ CountryInput::CountryInput(QWidget *parent, const style::countryInput &st) : QWi
}
_arrow = App::pixmapFromImageInPlace(std_::move(trImage));
_inner = QRect(0, 0, _st.width, _st.height);
_arrowRect = QRect((st::inpIntroCountryCode.width - _arrow.width() - 1) / 2, _st.height, _arrow.width(), _arrow.height());
_arrowRect = QRect((st::introCountryCode.width - _arrow.width() - 1) / 2, _st.height, _arrow.width(), _arrow.height());
}
void CountryInput::paintEvent(QPaintEvent *e) {

View File

@ -20,7 +20,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "ui/flatinput.h"
#include "ui/scrollarea.h"
#include "ui/effects/rect_shadow.h"
#include "boxes/abstractbox.h"

View File

@ -229,7 +229,7 @@ void RoundShadowAnimation::paintShadowHorizontal(int left, int right, int top, c
void PanelAnimation::setFinalImage(QImage &&finalImage, QRect inner) {
t_assert(!started());
_finalImage = QPixmap::fromImage(std_::move(finalImage).convertToFormat(QImage::Format_ARGB32_Premultiplied), Qt::ColorOnly);
_finalImage = App::pixmapFromImageInPlace(std_::move(finalImage).convertToFormat(QImage::Format_ARGB32_Premultiplied));
t_assert(!_finalImage.isNull());
_finalWidth = _finalImage.width();
@ -317,7 +317,7 @@ void PanelAnimation::createFadeMask() {
}
ints += intsPerLineAdded;
}
_fadeMask = QPixmap::fromImage(style::colorizeImage(result, _st.fadeBg), Qt::ColorOnly);
_fadeMask = App::pixmapFromImageInPlace(style::colorizeImage(result, _st.fadeBg));
_fadeHeight = _fadeMask.height();
}

View File

@ -0,0 +1,157 @@
/*
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/effects/ripple_animation.h"
namespace Ui {
class RippleAnimation::Ripple {
public:
Ripple(const style::RippleAnimation &st, QPoint origin, int startRadius, const QPixmap &mask, UpdateCallback update);
void paint(QPainter &p, const QPixmap &mask, uint64 ms);
void stop();
bool finished() const {
return _hiding && !_hide.animating();
}
private:
const style::RippleAnimation &_st;
UpdateCallback _update;
QPoint _origin;
int _radiusFrom = 0;
int _radiusTo = 0;
bool _hiding = false;
FloatAnimation _show;
FloatAnimation _hide;
QPixmap _cache;
QImage _frame;
};
RippleAnimation::Ripple::Ripple(const style::RippleAnimation &st, QPoint origin, int startRadius, const QPixmap &mask, UpdateCallback update)
: _st(st)
, _update(update)
, _origin(origin)
, _radiusFrom(startRadius)
, _frame(mask.size(), QImage::Format_ARGB32_Premultiplied) {
_frame.setDevicePixelRatio(mask.devicePixelRatio());
QPoint points[] = {
{ 0, 0 },
{ _frame.width() / cIntRetinaFactor(), 0 },
{ _frame.width() / cIntRetinaFactor(), _frame.height() / cIntRetinaFactor() },
{ 0, _frame.height() / cIntRetinaFactor() },
};
for (auto point : points) {
accumulate_max(_radiusTo, style::point::dotProduct(_origin - point, _origin - point));
}
_radiusTo = qRound(sqrt(_radiusTo));
_show.start(UpdateCallback(_update), 0., 1., _st.showDuration);
}
void RippleAnimation::Ripple::paint(QPainter &p, const QPixmap &mask, uint64 ms) {
auto opacity = _hide.current(ms, _hiding ? 0. : 1.);
if (opacity == 0.) {
return;
}
if (_cache.isNull()) {
auto radius = anim::interpolate(_radiusFrom, _radiusTo, _show.current(ms, 1.));
_frame.fill(Qt::transparent);
{
Painter p(&_frame);
p.setRenderHint(QPainter::HighQualityAntialiasing);
p.setPen(Qt::NoPen);
p.setBrush(_st.color);
p.drawEllipse(_origin, radius, radius);
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
p.drawPixmap(0, 0, mask);
}
if (radius == _radiusTo) {
_cache = App::pixmapFromImageInPlace(std_::move(_frame));
}
}
auto saved = p.opacity();
if (opacity != 1.) p.setOpacity(saved * opacity);
if (_cache.isNull()) {
p.drawImage(0, 0, _frame);
} else {
p.drawPixmap(0, 0, _cache);
}
if (opacity != 1.) p.setOpacity(saved);
}
void RippleAnimation::Ripple::stop() {
_hiding = true;
_hide.start(UpdateCallback(_update), 1., 0., _st.hideDuration);
}
RippleAnimation::RippleAnimation(const style::RippleAnimation &st, QImage mask, UpdateCallback callback)
: _st(st)
, _mask(App::pixmapFromImageInPlace(std_::move(mask)))
, _update(std_::move(callback)) {
}
void RippleAnimation::add(QPoint origin, int startRadius) {
_ripples.push_back(new Ripple(_st, origin, startRadius, _mask, _update));
}
void RippleAnimation::stopLast() {
if (!_ripples.isEmpty()) {
_ripples.back()->stop();
}
}
void RippleAnimation::paint(QPainter &p, int x, int y, int outerWidth, uint64 ms) {
if (_ripples.isEmpty()) {
return;
}
if (rtl()) x = outerWidth - x - (_mask.width() / cIntRetinaFactor());
p.translate(x, y);
for (auto ripple : _ripples) {
ripple->paint(p, _mask, ms);
}
p.translate(-x, -y);
clearFinished();
}
void RippleAnimation::clearFinished() {
while (!_ripples.isEmpty() && _ripples.front()->finished()) {
delete base::take(_ripples.front());
_ripples.pop_front();
}
}
void RippleAnimation::clear() {
for (auto ripple : base::take(_ripples)) {
delete ripple;
}
}
} // namespace Ui

View File

@ -0,0 +1,62 @@
/*
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 "styles/style_widgets.h"
namespace Ui {
class RippleAnimation {
public:
using UpdateCallback = base::lambda_wrap<void()>;
// White upon transparent mask, like colorizeImage(black-white-mask, white).
RippleAnimation(const style::RippleAnimation &st, QImage mask, UpdateCallback update);
void setMask(QImage &&mask);
void add(QPoint origin, int startRadius = 0);
void stopLast();
void paint(QPainter &p, int x, int y, int outerWidth, uint64 ms);
bool empty() const {
return _ripples.isEmpty();
}
~RippleAnimation() {
clear();
}
private:
void clear();
void clearFinished();
const style::RippleAnimation &_st;
QPixmap _mask;
UpdateCallback _update;
class Ripple;
QList<Ripple*> _ripples;
};
} // namespace Ui

File diff suppressed because it is too large Load Diff

View File

@ -1,261 +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 "animation.h"
class UserData;
static UserData * const LookingUpInlineBot = SharedMemoryLocation<UserData, 0>();
class FlatTextarea : public QTextEdit {
Q_OBJECT
T_WIDGET
public:
struct Tag {
int offset, length;
QString id;
};
using TagList = QVector<Tag>;
struct TextWithTags {
using Tags = FlatTextarea::TagList;
QString text;
Tags tags;
};
static QByteArray serializeTagsList(const TagList &tags);
static TagList deserializeTagsList(QByteArray data, int textLength);
static QString tagsMimeType();
FlatTextarea(QWidget *parent, const style::flatTextarea &st, const QString &ph = QString(), const QString &val = QString(), const TagList &tags = TagList());
void setMaxLength(int32 maxLength);
void setMinHeight(int32 minHeight);
void setMaxHeight(int32 maxHeight);
void setPlaceholder(const QString &ph, int32 afterSymbols = 0);
void updatePlaceholder();
void finishPlaceholder();
QRect getTextRect() const;
int32 fakeMargin() const;
void step_appearance(float64 ms, bool timer);
QSize sizeHint() const override;
QSize minimumSizeHint() const override;
EmojiPtr getSingleEmoji() const;
QString getMentionHashtagBotCommandPart(bool &start) const;
// Get the current inline bot and request string for it.
// The *outInlineBot can be filled by LookingUpInlineBot shared ptr.
// In that case the caller should lookup the bot by *outInlineBotUsername.
QString getInlineBotQuery(UserData **outInlineBot, QString *outInlineBotUsername) const;
void removeSingleEmoji();
bool hasText() const;
bool isUndoAvailable() const;
bool isRedoAvailable() const;
void parseLinks();
QStringList linksList() const;
void insertFromMimeData(const QMimeData *source) override;
QMimeData *createMimeDataFromSelection() const override;
enum class SubmitSettings {
None,
Enter,
CtrlEnter,
Both,
};
void setSubmitSettings(SubmitSettings settings);
const TextWithTags &getTextWithTags() const {
return _lastTextWithTags;
}
TextWithTags getTextWithTagsPart(int start, int end = -1);
void insertTag(const QString &text, QString tagId = QString());
bool isEmpty() const {
return _lastTextWithTags.text.isEmpty();
}
enum UndoHistoryAction {
AddToUndoHistory,
MergeWithUndoHistory,
ClearUndoHistory
};
void setTextWithTags(const TextWithTags &textWithTags, UndoHistoryAction undoHistoryAction = AddToUndoHistory);
// If you need to make some preparations of tags before putting them to QMimeData
// (and then to clipboard or to drag-n-drop object), here is a strategy for that.
class TagMimeProcessor {
public:
virtual QString mimeTagFromTag(const QString &tagId) = 0;
virtual QString tagFromMimeTag(const QString &mimeTag) = 0;
virtual ~TagMimeProcessor() {
}
};
void setTagMimeProcessor(std_::unique_ptr<TagMimeProcessor> &&processor);
public slots:
void onTouchTimer();
void onDocumentContentsChange(int position, int charsRemoved, int charsAdded);
void onDocumentContentsChanged();
void onUndoAvailable(bool avail);
void onRedoAvailable(bool avail);
signals:
void resized();
void changed();
void submitted(bool ctrlShiftEnter);
void cancelled();
void tabbed();
void spacedReturnedPasted();
void linksChanged();
protected:
void enterEventHook(QEvent *e) {
return QTextEdit::enterEvent(e);
}
void leaveEventHook(QEvent *e) {
return QTextEdit::leaveEvent(e);
}
bool viewportEvent(QEvent *e) override;
void touchEvent(QTouchEvent *e);
void paintEvent(QPaintEvent *e) override;
void focusInEvent(QFocusEvent *e) override;
void focusOutEvent(QFocusEvent *e) override;
void keyPressEvent(QKeyEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void dropEvent(QDropEvent *e) override;
void contextMenuEvent(QContextMenuEvent *e) override;
virtual void correctValue(const QString &was, QString &now, TagList &nowTags) {
}
void insertEmoji(EmojiPtr emoji, QTextCursor c);
QVariant loadResource(int type, const QUrl &name) override;
void checkContentHeight();
private:
// "start" and "end" are in coordinates of text where emoji are replaced
// by ObjectReplacementCharacter. If "end" = -1 means get text till the end.
QString getTextPart(int start, int end, TagList *outTagsList, bool *outTagsChanged = nullptr) const;
void getSingleEmojiFragment(QString &text, QTextFragment &fragment) const;
// After any characters added we must postprocess them. This includes:
// 1. Replacing font family to semibold for ~ characters, if we used Open Sans 13px.
// 2. Replacing font family from semibold for all non-~ characters, if we used ...
// 3. Replacing emoji code sequences by ObjectReplacementCharacters with emoji pics.
// 4. Interrupting tags in which the text was inserted by any char except a letter.
// 5. Applying tags from "_insertedTags" in case we pasted text with tags, not just text.
// Rule 4 applies only if we inserted chars not in the middle of a tag (but at the end).
void processFormatting(int changedPosition, int changedEnd);
bool heightAutoupdated();
int placeholderSkipWidth() const;
int _minHeight = -1; // < 0 - no autosize
int _maxHeight = -1;
int _maxLength = -1;
SubmitSettings _submitSettings = SubmitSettings::Enter;
QString _ph, _phelided;
int _phAfter = 0;
bool _phVisible;
anim::ivalue a_phLeft;
anim::fvalue a_phAlpha;
anim::fvalue a_phColorFocused;
Animation _a_appearance;
TextWithTags _lastTextWithTags;
// Tags list which we should apply while setText() call or insert from mime data.
TagList _insertedTags;
bool _insertedTagsAreFromMime;
// Override insert position and charsAdded from complex text editing
// (like drag-n-drop in the same text edit field).
int _realInsertPosition = -1;
int _realCharsAdded = 0;
std_::unique_ptr<TagMimeProcessor> _tagMimeProcessor;
const style::flatTextarea &_st;
bool _undoAvailable = false;
bool _redoAvailable = false;
bool _inDrop = false;
bool _inHeightCheck = false;
int _fakeMargin = 0;
QTimer _touchTimer;
bool _touchPress = false;
bool _touchRightButton = false;
bool _touchMove = false;
QPoint _touchStart;
bool _correcting = false;
struct LinkRange {
int start;
int length;
};
friend bool operator==(const LinkRange &a, const LinkRange &b);
friend bool operator!=(const LinkRange &a, const LinkRange &b);
using LinkRanges = QVector<LinkRange>;
LinkRanges _links;
};
inline bool operator==(const FlatTextarea::Tag &a, const FlatTextarea::Tag &b) {
return (a.offset == b.offset) && (a.length == b.length) && (a.id == b.id);
}
inline bool operator!=(const FlatTextarea::Tag &a, const FlatTextarea::Tag &b) {
return !(a == b);
}
inline bool operator==(const FlatTextarea::TextWithTags &a, const FlatTextarea::TextWithTags &b) {
return (a.text == b.text) && (a.tags == b.tags);
}
inline bool operator!=(const FlatTextarea::TextWithTags &a, const FlatTextarea::TextWithTags &b) {
return !(a == b);
}
inline bool operator==(const FlatTextarea::LinkRange &a, const FlatTextarea::LinkRange &b) {
return (a.start == b.start) && (a.length == b.length);
}
inline bool operator!=(const FlatTextarea::LinkRange &a, const FlatTextarea::LinkRange &b) {
return !(a == b);
}

View File

@ -21,6 +21,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "stdafx.h"
#include "ui/widgets/buttons.h"
#include "ui/effects/ripple_animation.h"
namespace Ui {
FlatButton::FlatButton(QWidget *parent, const QString &text, const style::FlatButton &st) : AbstractButton(parent)
@ -87,6 +89,27 @@ void FlatButton::onStateChanged(int oldState, StateChangeSource source) {
} else {
_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->stopLast();
}
}
void FlatButton::paintEvent(QPaintEvent *e) {
@ -97,6 +120,14 @@ void FlatButton::paintEvent(QPaintEvent *e) {
p.setOpacity(_opacity);
p.fillRect(r, anim::brush(_st.bgColor, _st.overBgColor, a_over.current()));
auto ms = getms();
if (_ripple) {
_ripple->paint(p, 0, 0, width(), ms);
if (_ripple->empty()) {
_ripple.reset();
}
}
p.setFont((_state & StateOver) ? _st.overFont : _st.font);
p.setRenderHint(QPainter::TextAntialiasing);
p.setPen(anim::pen(_st.color, _st.overColor, a_over.current()));
@ -107,6 +138,15 @@ void FlatButton::paintEvent(QPaintEvent *e) {
p.drawText(r, _text, style::al_top);
}
QImage FlatButton::prepareRippleMask() const {
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))
@ -210,16 +250,25 @@ int RoundButton::contentWidth() const {
void RoundButton::paintEvent(QPaintEvent *e) {
Painter p(this);
int innerWidth = contentWidth();
auto rounded = rtlrect(rect().marginsRemoved(_st.padding), width());
auto innerWidth = contentWidth();
auto rounded = rect().marginsRemoved(_st.padding);
if (_fullWidthOverride < 0) {
rounded = QRect(0, rounded.top(), innerWidth - _fullWidthOverride, rounded.height());
}
App::roundRect(p, rounded, _st.textBg, ImageRoundRadius::Small);
App::roundRect(p, myrtlrect(rounded), _st.textBg, ImageRoundRadius::Small);
auto over = (_state & StateOver);
auto down = (_state & StateDown);
if (over) {
App::roundRect(p, rounded, _st.textBgOver, ImageRoundRadius::Small);
App::roundRect(p, myrtlrect(rounded), _st.textBgOver, ImageRoundRadius::Small);
}
auto ms = getms();
if (_ripple) {
_ripple->paint(p, rounded.x(), rounded.y(), width(), ms);
if (_ripple->empty()) {
_ripple.reset();
}
}
p.setFont(_st.font);
@ -230,12 +279,12 @@ void RoundButton::paintEvent(QPaintEvent *e) {
int textTopDelta = (_state & StateDown) ? (_st.downTextTop - _st.textTop) : 0;
int textTop = _st.padding.top() + _st.textTop + textTopDelta;
if (!_text.isEmpty()) {
p.setPen(over ? _st.textFgOver : _st.textFg);
p.setPen((over || down) ? _st.textFgOver : _st.textFg);
p.drawTextLeft(textLeft, textTop, width(), _text);
}
if (!_secondaryText.isEmpty()) {
textLeft += _textWidth + (_textWidth ? _st.secondarySkip : 0);
p.setPen(over ? _st.secondaryTextFgOver : _st.secondaryTextFg);
p.setPen((over || down) ? _st.secondaryTextFgOver : _st.secondaryTextFg);
p.drawTextLeft(textLeft, textTop, width(), _secondaryText);
}
_st.icon.paint(p, QPoint(_st.padding.left(), _st.padding.right() + textTopDelta), width());
@ -243,8 +292,50 @@ void RoundButton::paintEvent(QPaintEvent *e) {
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->stopLast();
}
}
QImage RoundButton::prepareRippleMask() const {
auto innerWidth = contentWidth();
auto rounded = rtlrect(rect().marginsRemoved(_st.padding), width());
if (_fullWidthOverride < 0) {
rounded = QRect(0, rounded.top(), innerWidth - _fullWidthOverride, rounded.height());
}
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;
IconButton::IconButton(QWidget *parent, const style::IconButton &st) : AbstractButton(parent)
, _st(st) {
resize(_st.width, _st.height);
@ -260,6 +351,15 @@ void IconButton::setIcon(const style::icon *icon, const style::icon *iconOver) {
void IconButton::paintEvent(QPaintEvent *e) {
Painter p(this);
auto ms = getms();
if (_ripple) {
_ripple->paint(p, _st.rippleAreaPosition.x(), _st.rippleAreaPosition.y(), width(), ms);
if (_ripple->empty()) {
_ripple.reset();
}
}
auto over = _a_over.current(getms(), (_state & StateOver) ? 1. : 0.);
auto overIcon = [this] {
if (_iconOverrideOver) {
@ -306,6 +406,50 @@ void IconButton::onStateChanged(int oldState, StateChangeSource source) {
update();
}
}
handleRipples(oldState & StateDown, (source == StateChangeSource::ByPress));
}
void IconButton::handleRipples(bool wasDown, bool wasPress) {
auto down = static_cast<bool>(_state & StateDown);
if (!_st.ripple.showDuration || _st.rippleAreaSize <= 0 || 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());
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) {
// Finish ripple anyway.
_ripple->stopLast();
}
}
QImage IconButton::prepareRippleMask() const {
auto size = _st.rippleAreaSize * cIntRetinaFactor();
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;
} // namespace Ui

View File

@ -25,6 +25,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Ui {
class RippleAnimation;
class FlatButton : public AbstractButton {
public:
FlatButton(QWidget *parent, const QString &text, const style::FlatButton &st);
@ -38,12 +40,17 @@ public:
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;
@ -54,6 +61,8 @@ private:
float64 _opacity = 1.;
std_::unique_ptr<RippleAnimation> _ripple;
};
class LinkButton : public AbstractButton {
@ -93,12 +102,17 @@ public:
};
void setTextTransform(TextTransform transform);
~RoundButton();
protected:
void paintEvent(QPaintEvent *e) override;
void onStateChanged(int oldState, StateChangeSource source) override;
private:
QImage prepareRippleMask() const;
void handleRipples(bool wasDown, bool wasPress);
void updateText();
void resizeToText();
@ -114,6 +128,8 @@ private:
TextTransform _transform = TextTransform::ToUpper;
std_::unique_ptr<RippleAnimation> _ripple;
};
class IconButton : public AbstractButton {
@ -123,18 +139,25 @@ public:
// Pass nullptr to restore the default icon.
void setIcon(const style::icon *icon, const style::icon *iconOver = nullptr);
~IconButton();
protected:
void paintEvent(QPaintEvent *e) override;
void onStateChanged(int oldState, StateChangeSource source) override;
private:
QImage prepareRippleMask() const;
void handleRipples(bool wasDown, bool wasPress);
const style::IconButton &_st;
const style::icon *_iconOverride = nullptr;
const style::icon *_iconOverrideOver = nullptr;
FloatAnimation _a_over;
std_::unique_ptr<RippleAnimation> _ripple;
};
} // namespace Ui

View File

@ -21,6 +21,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#pragma once
#include "ui/abstract_button.h"
#include "styles/style_widgets.h"
namespace Ui {

View File

@ -20,14 +20,232 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "animation.h"
#include "styles/style_widgets.h"
class UserData;
namespace Ui {
static UserData * const LookingUpInlineBot = SharedMemoryLocation<UserData, 0>();
class FlatTextarea : public QTextEdit {
Q_OBJECT
T_WIDGET
public:
using TagList = TextWithTags::Tags;
static QByteArray serializeTagsList(const TagList &tags);
static TagList deserializeTagsList(QByteArray data, int textLength);
static QString tagsMimeType();
FlatTextarea(QWidget *parent, const style::FlatTextarea &st, const QString &ph = QString(), const QString &val = QString(), const TagList &tags = TagList());
void setMaxLength(int32 maxLength);
void setMinHeight(int32 minHeight);
void setMaxHeight(int32 maxHeight);
void setPlaceholder(const QString &ph, int32 afterSymbols = 0);
void updatePlaceholder();
void finishPlaceholder();
QRect getTextRect() const;
int32 fakeMargin() const;
void step_appearance(float64 ms, bool timer);
QSize sizeHint() const override;
QSize minimumSizeHint() const override;
EmojiPtr getSingleEmoji() const;
QString getMentionHashtagBotCommandPart(bool &start) const;
// Get the current inline bot and request string for it.
// The *outInlineBot can be filled by LookingUpInlineBot shared ptr.
// In that case the caller should lookup the bot by *outInlineBotUsername.
QString getInlineBotQuery(UserData **outInlineBot, QString *outInlineBotUsername) const;
void removeSingleEmoji();
bool hasText() const;
bool isUndoAvailable() const;
bool isRedoAvailable() const;
void parseLinks();
QStringList linksList() const;
void insertFromMimeData(const QMimeData *source) override;
QMimeData *createMimeDataFromSelection() const override;
enum class SubmitSettings {
None,
Enter,
CtrlEnter,
Both,
};
void setSubmitSettings(SubmitSettings settings);
const TextWithTags &getTextWithTags() const {
return _lastTextWithTags;
}
TextWithTags getTextWithTagsPart(int start, int end = -1);
void insertTag(const QString &text, QString tagId = QString());
bool isEmpty() const {
return _lastTextWithTags.text.isEmpty();
}
enum UndoHistoryAction {
AddToUndoHistory,
MergeWithUndoHistory,
ClearUndoHistory
};
void setTextWithTags(const TextWithTags &textWithTags, UndoHistoryAction undoHistoryAction = AddToUndoHistory);
// If you need to make some preparations of tags before putting them to QMimeData
// (and then to clipboard or to drag-n-drop object), here is a strategy for that.
class TagMimeProcessor {
public:
virtual QString mimeTagFromTag(const QString &tagId) = 0;
virtual QString tagFromMimeTag(const QString &mimeTag) = 0;
virtual ~TagMimeProcessor() {
}
};
void setTagMimeProcessor(std_::unique_ptr<TagMimeProcessor> &&processor);
public slots:
void onTouchTimer();
void onDocumentContentsChange(int position, int charsRemoved, int charsAdded);
void onDocumentContentsChanged();
void onUndoAvailable(bool avail);
void onRedoAvailable(bool avail);
signals:
void resized();
void changed();
void submitted(bool ctrlShiftEnter);
void cancelled();
void tabbed();
void spacedReturnedPasted();
void linksChanged();
protected:
void enterEventHook(QEvent *e) {
return QTextEdit::enterEvent(e);
}
void leaveEventHook(QEvent *e) {
return QTextEdit::leaveEvent(e);
}
bool viewportEvent(QEvent *e) override;
void touchEvent(QTouchEvent *e);
void paintEvent(QPaintEvent *e) override;
void focusInEvent(QFocusEvent *e) override;
void focusOutEvent(QFocusEvent *e) override;
void keyPressEvent(QKeyEvent *e) override;
void resizeEvent(QResizeEvent *e) override;
void mousePressEvent(QMouseEvent *e) override;
void dropEvent(QDropEvent *e) override;
void contextMenuEvent(QContextMenuEvent *e) override;
virtual void correctValue(const QString &was, QString &now, TagList &nowTags) {
}
void insertEmoji(EmojiPtr emoji, QTextCursor c);
QVariant loadResource(int type, const QUrl &name) override;
void checkContentHeight();
private:
// "start" and "end" are in coordinates of text where emoji are replaced
// by ObjectReplacementCharacter. If "end" = -1 means get text till the end.
QString getTextPart(int start, int end, TagList *outTagsList, bool *outTagsChanged = nullptr) const;
void getSingleEmojiFragment(QString &text, QTextFragment &fragment) const;
// After any characters added we must postprocess them. This includes:
// 1. Replacing font family to semibold for ~ characters, if we used Open Sans 13px.
// 2. Replacing font family from semibold for all non-~ characters, if we used ...
// 3. Replacing emoji code sequences by ObjectReplacementCharacters with emoji pics.
// 4. Interrupting tags in which the text was inserted by any char except a letter.
// 5. Applying tags from "_insertedTags" in case we pasted text with tags, not just text.
// Rule 4 applies only if we inserted chars not in the middle of a tag (but at the end).
void processFormatting(int changedPosition, int changedEnd);
bool heightAutoupdated();
int placeholderSkipWidth() const;
int _minHeight = -1; // < 0 - no autosize
int _maxHeight = -1;
int _maxLength = -1;
SubmitSettings _submitSettings = SubmitSettings::Enter;
QString _ph, _phelided;
int _phAfter = 0;
bool _phVisible;
anim::ivalue a_phLeft;
anim::fvalue a_phAlpha;
anim::fvalue a_phColorFocused;
Animation _a_appearance;
TextWithTags _lastTextWithTags;
// Tags list which we should apply while setText() call or insert from mime data.
TagList _insertedTags;
bool _insertedTagsAreFromMime;
// Override insert position and charsAdded from complex text editing
// (like drag-n-drop in the same text edit field).
int _realInsertPosition = -1;
int _realCharsAdded = 0;
std_::unique_ptr<TagMimeProcessor> _tagMimeProcessor;
const style::FlatTextarea &_st;
bool _undoAvailable = false;
bool _redoAvailable = false;
bool _inDrop = false;
bool _inHeightCheck = false;
int _fakeMargin = 0;
QTimer _touchTimer;
bool _touchPress = false;
bool _touchRightButton = false;
bool _touchMove = false;
QPoint _touchStart;
bool _correcting = false;
struct LinkRange {
int start;
int length;
};
friend bool operator==(const LinkRange &a, const LinkRange &b);
friend bool operator!=(const LinkRange &a, const LinkRange &b);
using LinkRanges = QVector<LinkRange>;
LinkRanges _links;
};
inline bool operator==(const FlatTextarea::LinkRange &a, const FlatTextarea::LinkRange &b) {
return (a.start == b.start) && (a.length == b.length);
}
inline bool operator!=(const FlatTextarea::LinkRange &a, const FlatTextarea::LinkRange &b) {
return !(a == b);
}
class FlatInput : public QLineEdit {
Q_OBJECT
T_WIDGET
public:
FlatInput(QWidget *parent, const style::flatInput &st, const QString &ph = QString(), const QString &val = QString());
FlatInput(QWidget *parent, const style::FlatInput &st, const QString &ph = QString(), const QString &val = QString());
void notaBene();
@ -49,7 +267,7 @@ public:
return _oldtext;
}
public slots:
public slots:
void onTextChange(const QString &text);
void onTextEdited();
@ -105,7 +323,7 @@ private:
Animation _a_appearance;
int _notingBene;
const style::flatInput &_st;
const style::FlatInput &_st;
QTimer _touchTimer;
bool _touchPress, _touchRightButton, _touchMove;
@ -116,9 +334,9 @@ class CountryCodeInput : public FlatInput {
Q_OBJECT
public:
CountryCodeInput(QWidget *parent, const style::flatInput &st);
CountryCodeInput(QWidget *parent, const style::FlatInput &st);
public slots:
public slots:
void startErasing(QKeyEvent *e);
void codeSelected(const QString &code);
@ -138,9 +356,9 @@ class PhonePartInput : public FlatInput {
Q_OBJECT
public:
PhonePartInput(QWidget *parent, const style::flatInput &st);
PhonePartInput(QWidget *parent, const style::FlatInput &st);
public slots:
public slots:
void addedToNumber(const QString &added);
void onChooseCode(const QString &code);
@ -221,7 +439,7 @@ public:
_inner.clearFocus();
}
public slots:
public slots:
void onTouchTimer();
void onDocumentContentsChange(int position, int charsRemoved, int charsAdded);
@ -392,7 +610,7 @@ public:
_inner.setTextCursor(c);
}
public slots:
public slots:
void onTouchTimer();
void onDocumentContentsChange(int position, int charsRemoved, int charsAdded);
@ -497,7 +715,7 @@ private:
class MaskedInputField : public QLineEdit {
Q_OBJECT
T_WIDGET
T_WIDGET
public:
MaskedInputField(QWidget *parent, const style::InputField &st, const QString &placeholder = QString(), const QString &val = QString());
@ -539,7 +757,7 @@ public:
updatePlaceholder();
}
public slots:
public slots:
void onTextChange(const QString &text);
void onCursorPositionChanged(int oldPosition, int position);
@ -610,9 +828,9 @@ private:
QPoint _touchStart;
};
class PasswordField : public MaskedInputField {
class PasswordInput : public MaskedInputField {
public:
PasswordField(QWidget *parent, const style::InputField &st, const QString &ph = QString(), const QString &val = QString());
PasswordInput(QWidget *parent, const style::InputField &st, const QString &ph = QString(), const QString &val = QString());
};
@ -655,3 +873,5 @@ private:
QVector<int> _pattern;
};
} // namespace Ui

View File

@ -23,6 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "styles/style_widgets.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
#include "lang.h"
namespace Ui {

View File

@ -22,10 +22,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "styles/style_widgets.h"
class InputField;
namespace Ui {
class InputField;
class IconButton;
class MultiSelect : public TWidget {
@ -153,7 +152,7 @@ private:
int _fieldLeft = 0;
int _fieldTop = 0;
int _fieldWidth = 0;
ChildWidget<InputField> _field;
ChildWidget<Ui::InputField> _field;
ChildWidget<Ui::IconButton> _cancel;
int _newHeight = 0;

View File

@ -35,6 +35,12 @@ LinkButton {
overFont: font;
}
RippleAnimation {
color: color;
showDuration: int;
hideDuration: int;
}
FlatButton {
color: color;
overColor: color;
@ -53,6 +59,188 @@ FlatButton {
overFont: font;
duration: int;
cursor: cursor;
ripple: RippleAnimation;
}
RoundButton {
textFg: color;
textFgOver: color;
textBg: color; // rect of textBg with rounded rect of textBgOver upon it
textBgOver: color;
secondaryTextFg: color;
secondaryTextFgOver: color;
secondarySkip: pixels;
width: pixels;
height: pixels;
padding: margins;
textTop: pixels;
downTextTop: pixels;
icon: icon;
font: font;
ripple: RippleAnimation;
}
Checkbox {
textFg: color;
textBg: color;
checkBg: color;
checkFg: color;
checkFgOver: color;
checkFgActive: color;
width: pixels;
height: pixels;
textPosition: point;
diameter: pixels;
thickness: pixels;
checkIcon: icon;
font: font;
duration: int;
}
Radiobutton {
textFg: color;
textBg: color;
checkBg: color;
checkFg: color;
checkFgOver: color;
checkFgActive: color;
width: pixels;
height: pixels;
textPosition: point;
diameter: pixels;
thickness: pixels;
checkSkip: pixels;
font: font;
duration: int;
}
FlatTextarea {
textColor: color;
bgColor: color;
width: pixels;
textMrg: margins;
align: align;
font: font;
cursor: cursor;
phColor: color;
phFocusColor: color;
phPos: point;
phAlign: align;
phShift: pixels;
phDuration: int;
}
FlatInput {
textColor: color;
bgColor: color;
bgActive: color;
width: pixels;
height: pixels;
textMrg: margins;
align: align;
font: font;
cursor: cursor;
icon: icon;
borderWidth: pixels;
borderColor: color;
borderActive: color;
borderError: color;
phColor: color;
phFocusColor: color;
phPos: point;
phAlign: align;
phShift: pixels;
phDuration: int;
}
InputArea {
textBg: color;
textFg: color;
textMargins: margins;
placeholderFg: color;
placeholderFgActive: color;
placeholderMargins: margins;
placeholderAlign: align;
placeholderShift: pixels;
duration: int;
borderFg: color;
borderFgActive: color;
borderFgError: color;
border: pixels;
borderActive: pixels;
borderError: pixels;
font: font;
width: pixels;
heightMin: pixels;
heightMax: pixels;
}
InputField {
textBg: color;
textFg: color;
textMargins: margins;
textAlign: align;
placeholderFg: color;
placeholderFgActive: color;
placeholderMargins: margins;
placeholderAlign: align;
placeholderShift: pixels;
duration: int;
borderFg: color;
borderFgActive: color;
borderFgError: color;
border: pixels;
borderActive: pixels;
borderError: pixels;
font: font;
width: pixels;
height: pixels;
}
OutlineButton {
outlineWidth: pixels;
outlineFg: color;
outlineFgOver: color;
textBg: color;
textBgOver: color;
textFg: color;
textFgOver: color;
font: font;
padding: margins;
}
IconButton {
@ -66,6 +254,10 @@ IconButton {
iconPositionDown: point;
duration: int;
rippleAreaPosition: point;
rippleAreaSize: pixels;
ripple: RippleAnimation;
}
Shadow {
@ -232,6 +424,194 @@ defaultLinkButton: LinkButton {
overFont: linkOverFont;
}
defaultRippleAnimation: RippleAnimation {
color: windowOverBg;
showDuration: 200;
hideDuration: 200;
}
emptyRippleAnimation: RippleAnimation {
}
defaultActiveButton: RoundButton {
textFg: activeButtonFg;
textFgOver: activeButtonFgOver;
secondaryTextFg: activeButtonSecondaryFg;
secondaryTextFgOver: activeButtonSecondaryFgOver;
textBg: activeButtonBg;
textBgOver: activeButtonBgOver;
secondarySkip: 7px;
width: -34px;
height: 34px;
padding: margins(0px, 0px, 0px, 0px);
textTop: 8px;
downTextTop: 8px;
font: semiboldFont;
ripple: RippleAnimation(defaultRippleAnimation) {
color: activeButtonBgRipple;
}
}
defaultLightButton: RoundButton(defaultActiveButton) {
textFg: lightButtonFg;
textFgOver: lightButtonFgOver;
textBg: lightButtonBg;
textBgOver: lightButtonBgOver;
ripple: RippleAnimation(defaultRippleAnimation) {
color: lightButtonBgRipple;
}
}
defaultInputFont: font(17px);
defaultFlatInput: FlatInput {
textColor: #000000;
bgColor: #f2f2f2;
bgActive: #ffffff;
width: 210px;
height: 40px;
align: align(left);
textMrg: margins(5px, 5px, 5px, 5px);
font: defaultInputFont;
cursor: cursor(text);
borderWidth: 2px;
borderColor: #f2f2f2;
borderActive: #54c3f3;
borderError: #ed8080;
phColor: #808080;
phFocusColor: #aaaaaa;
phAlign: align(left);
phPos: point(2px, 0px);
phShift: 50px;
phDuration: 100;
}
defaultLeftOutlineButton: OutlineButton {
outlineWidth: 3px;
outlineFg: windowBg;
outlineFgOver: windowActiveBg;
textBg: windowBg;
textBgOver: #f2f7fa;
textFg: windowActiveTextFg;
textFgOver: windowActiveTextFg;
font: normalFont;
padding: margins(11px, 5px, 11px, 5px);
}
attentionLeftOutlineButton: OutlineButton(defaultLeftOutlineButton) {
outlineFgOver: #e43f3f;
textBgOver: #faf2f2;
textFg: #d15948;
textFgOver: #d15948;
}
defaultInputArea: InputArea {
textBg: windowBg;
textFg: windowTextFg;
textMargins: margins(5px, 6px, 5px, 4px);
placeholderFg: #999999;
placeholderFgActive: #aaaaaa;
placeholderMargins: margins(2px, 0px, 2px, 0px);
placeholderAlign: align(topleft);
placeholderShift: 50px;
duration: 120;
borderFg: #e0e0e0;
borderFgActive: #62c0f7;
borderFgError: #e48383;
border: 1px;
borderActive: 2px;
borderError: 2px;
font: boxTextFont;
heightMin: 32px;
heightMax: 128px;
}
defaultInputField: InputField {
textBg: windowBg;
textFg: windowTextFg;
textMargins: margins(0px, 6px, 0px, 4px);
textAlign: align(topleft);
placeholderFg: #999999;
placeholderFgActive: #aaaaaa;
placeholderMargins: margins(2px, 0px, 2px, 0px);
placeholderAlign: align(topleft);
placeholderShift: 50px;
duration: 120;
borderFg: #e0e0e0;
borderFgActive: #62c0f7;
borderFgError: #e48383;
border: 1px;
borderActive: 2px;
borderError: 2px;
font: boxTextFont;
height: 32px;
}
defaultCheckboxIcon: icon {{ "default_checkbox_check", windowActiveFg, point(4px, 7px) }};
defaultCheckbox: Checkbox {
textFg: windowTextFg;
textBg: windowBg;
checkBg: #ffffff;
checkFg: #b3b3b3;
checkFgOver: #b3b3b3;
checkFgActive: windowActiveBg;
width: -44px;
height: 22px;
textPosition: point(32px, 2px);
diameter: 22px;
thickness: 2px;
checkIcon: defaultCheckboxIcon;
font: normalFont;
duration: 120;
}
defaultRadiobutton: Radiobutton {
textFg: windowTextFg;
textBg: windowBg;
checkBg: #ffffff;
checkFg: #b3b3b3;
checkFgOver: #bfbfbf;
checkFgActive: #4eb3ee;
width: -46px;
height: 22px;
textPosition: point(34px, 0px);
diameter: 22px;
thickness: 2px;
checkSkip: 65px; // * 0.1
font: boxTextFont;
duration: 120;
}
defaultIconButton: IconButton {
iconPosition: point(-1px, -1px);
iconPositionDown: point(-1px, -1px);

View File

@ -58,6 +58,7 @@ void MainWindow::init() {
}
initSize();
updateUnreadCounter();
}
HitTestResult MainWindow::hitTest(const QPoint &p) const {

View File

@ -26,8 +26,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "mainwindow.h"
#include "lang.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
#include "dialogs/dialogs_layout.h"
#include "styles/style_dialogs.h"
#include "styles/style_boxes.h"
#include "styles/style_window.h"
namespace Window {
@ -225,7 +227,7 @@ void Manager::moveWidgets() {
}
if (count > 1 || !_queuedNotifications.isEmpty()) {
auto deltaY = st::notifyHideAll.height + st::notifyDeltaY;
auto deltaY = st::notifyHideAllHeight + st::notifyDeltaY;
if (!_hideAll) {
_hideAll = new HideAllButton(notificationStartPosition(), lastShiftCurrent, notificationShiftDirection());
}
@ -735,17 +737,17 @@ void Notification::showReplyField() {
}
stopHiding();
_background = new Background(this);
_background.create(this);
_background->setGeometry(0, st::notifyMinHeight, width(), st::notifySendReply.height + st::notifyBorderWidth);
_background->show();
_replyArea = new InputArea(this, st::notifyReplyArea, lang(lng_message_ph), QString());
_replyArea.create(this, st::notifyReplyArea, lang(lng_message_ph), QString());
_replyArea->resize(width() - st::notifySendReply.width - 2 * st::notifyBorderWidth, st::notifySendReply.height);
_replyArea->moveToLeft(st::notifyBorderWidth, st::notifyMinHeight);
_replyArea->show();
_replyArea->setFocus();
_replyArea->setMaxLength(MaxMessageSize);
_replyArea->setCtrlEnterSubmit(CtrlEnterSubmitBoth);
_replyArea->setCtrlEnterSubmit(Ui::CtrlEnterSubmitBoth);
// Catch mouse press event to activate the window.
Sandbox::installEventFilter(this);
@ -860,8 +862,8 @@ Notification::~Notification() {
HideAllButton::HideAllButton(QPoint startPosition, int shift, Direction shiftDirection) : Widget(startPosition, shift, shiftDirection) {
setCursor(style::cur_pointer);
auto position = computePosition(st::notifyHideAll.height);
updateGeometry(position.x(), position.y(), st::notifyWidth, st::notifyHideAll.height);
auto position = computePosition(st::notifyHideAllHeight);
updateGeometry(position.x(), position.y(), st::notifyWidth, st::notifyHideAllHeight);
hide();
createWinId();
@ -913,7 +915,7 @@ void HideAllButton::paintEvent(QPaintEvent *e) {
Painter p(this);
p.setClipRect(e->rect());
p.fillRect(rect(), _mouseOver ? st::notifyHideAll.textBgOver : st::notifyHideAll.textBg);
p.fillRect(rect(), _mouseOver ? st::lightButtonBgOver : st::lightButtonBg);
p.fillRect(0, 0, width(), st::notifyBorderWidth, st::notifyBorder);
p.fillRect(0, height() - st::notifyBorderWidth, width(), st::notifyBorderWidth, st::notifyBorder);
p.fillRect(0, st::notifyBorderWidth, st::notifyBorderWidth, height() - 2 * st::notifyBorderWidth, st::notifyBorder);

View File

@ -26,6 +26,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
namespace Ui {
class IconButton;
class RoundButton;
class InputArea;
} // namespace Ui
namespace Window {
@ -248,7 +249,7 @@ private:
ChildWidget<Ui::IconButton> _close;
ChildWidget<Ui::RoundButton> _reply;
ChildWidget<Background> _background = { nullptr };
ChildWidget<InputArea> _replyArea = { nullptr };
ChildWidget<Ui::InputArea> _replyArea = { nullptr };
ChildWidget<Ui::IconButton> _replySend = { nullptr };
bool _waitingForInput = true;

View File

@ -21,6 +21,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "stdafx.h"
#include "window/slide_animation.h"
#include "styles/style_window.h"
namespace Window {
void SlideAnimation::paintContents(Painter &p, const QRect &update) const {

View File

@ -21,7 +21,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "stdafx.h"
#include "window/top_bar_widget.h"
#include "styles/style_history.h"
#include "styles/style_window.h"
#include "boxes/addcontactbox.h"
#include "boxes/confirmbox.h"
@ -41,7 +40,7 @@ TopBarWidget::TopBarWidget(MainWidget *w) : TWidget(w)
, _clearSelection(this, lang(lng_selected_clear), st::topBarClearButton)
, _forward(this, lang(lng_selected_forward), st::defaultActiveButton)
, _delete(this, lang(lng_selected_delete), st::defaultActiveButton)
, _info(this, nullptr, st::infoButton)
, _info(this, nullptr, st::topBarInfoButton)
, _mediaType(this, lang(lng_media_type), st::topBarButton)
, _search(this, st::topBarSearch)
, _menuToggle(this, st::topBarMenuToggle) {
@ -93,15 +92,23 @@ void TopBarWidget::onSearch() {
void TopBarWidget::showMenu() {
if (auto main = App::main()) {
if (auto peer = main->peer()) {
_menu.create(App::main());
App::main()->fillPeerMenu(peer, [this](const QString &text, base::lambda_unique<void()> callback) {
return _menu->addAction(text, std_::move(callback));
});
_menu->setHiddenCallback([this] {
_menu.destroyDelayed();
});
_menu->moveToRight(0, 0);
_menu->showAnimated(Ui::PanelAnimation::Origin::TopRight);
if (auto menu = _menu.ptr()) {
_menu = nullptr;
_menuToggle->removeEventFilter(menu);
menu->setHiddenCallback([menu] { menu->deleteLater(); });
menu->hideAnimated(Ui::DropdownMenu::HideOption::IgnoreShow);
} else {
_menu.create(App::main());
_menuToggle->installEventFilter(_menu);
App::main()->fillPeerMenu(peer, [this](const QString &text, base::lambda_unique<void()> callback) {
return _menu->addAction(text, std_::move(callback));
});
_menu->setHiddenCallback([this] {
_menu.destroyDelayed();
});
_menu->moveToRight(st::topBarMenuPosition.x(), st::topBarMenuPosition.y());
_menu->showAnimated(Ui::PanelAnimation::Origin::TopRight);
}
}
}
}

View File

@ -60,8 +60,7 @@ notifyDeltaX: 6px;
notifyDeltaY: 7px;
notifyActionsDuration: 200;
notifyHideAll: RoundButton(defaultBoxButton) {
}
notifyHideAllHeight: 36px;
notifyReplyArea: InputArea(defaultInputArea) {
font: normalFont;
@ -156,6 +155,78 @@ titleButtonClose: IconButton(titleButtonMinimize) {
};
}
// Legacy top bar.
topBarHeight: 54px;
topBarMenuPosition: point(-2px, 37px);
topBarDuration: 200;
topBarBackward: icon {{ "title_back", #a3a3a3 }};
topBarForwardAlpha: 0.6;
topBarBack: icon {{ "title_back", #259fd8 }};
topBarBackAlpha: 0.8;
topBarBackColor: #005faf;
topBarBackFont: font(16px);
topBarArrowPadding: margins(39px, 8px, 17px, 8px);
topBarMinPadding: 5px;
topBarButton: RoundButton {
textFg: btnYesColor;
textFgOver: btnYesColor;
secondaryTextFg: btnYesColor;
secondaryTextFgOver: btnYesColor;
textBg: windowBg;
textBgOver: #edf4f7;
width: -22px;
height: 28px;
padding: margins(0px, 14px, 12px, 12px);
textTop: 6px;
downTextTop: 6px;
font: font(fsize);
ripple: RippleAnimation(defaultRippleAnimation) {
color: lightButtonBgRipple;
}
}
topBarClearButton: RoundButton(defaultLightButton) {
width: -18px;
}
topBarSearch: IconButton {
width: 44px;
height: topBarHeight;
icon: icon {{ "title_search", menuIconFg }};
iconOver: icon {{ "title_search", menuIconFgOver }};
iconPosition: point(15px, 18px);
iconPositionDown: point(15px, 18px);
rippleAreaPosition: point(8px, 11px);
rippleAreaSize: 32px;
ripple: defaultRippleAnimation;
}
topBarMenuToggle: IconButton(topBarSearch) {
icon: icon {{ "title_menu_dots", menuIconFg }};
iconOver: icon {{ "title_menu_dots", menuIconFgOver }};
iconPosition: point(15px, 17px);
iconPositionDown: point(15px, 17px);
rippleAreaPosition: point(3px, 11px);
rippleAreaSize: 32px;
ripple: defaultRippleAnimation;
}
topBarActionSkip: 10px;
PeerAvatarButton {
size: pixels;
photoSize: pixels;
}
topBarInfoButton: PeerAvatarButton {
size: topBarHeight;
photoSize: 42px;
}
// Mac specific
macAccessoryWidth: 450.;

View File

@ -3,4 +3,4 @@ AppVersionStrMajor 0.10
AppVersionStrSmall 0.10.20
AppVersionStr 0.10.20
AlphaChannel 0
BetaVersion 10019006
BetaVersion 10019007

View File

@ -462,6 +462,8 @@
'<(src_loc)/ui/effects/radial_animation.h',
'<(src_loc)/ui/effects/rect_shadow.cpp',
'<(src_loc)/ui/effects/rect_shadow.h',
'<(src_loc)/ui/effects/ripple_animation.cpp',
'<(src_loc)/ui/effects/ripple_animation.h',
'<(src_loc)/ui/effects/round_image_checkbox.cpp',
'<(src_loc)/ui/effects/round_image_checkbox.h',
'<(src_loc)/ui/effects/widget_fade_wrap.cpp',
@ -504,6 +506,8 @@
'<(src_loc)/ui/widgets/filled_slider.h',
'<(src_loc)/ui/widgets/inner_dropdown.cpp',
'<(src_loc)/ui/widgets/inner_dropdown.h',
'<(src_loc)/ui/widgets/input_fields.cpp',
'<(src_loc)/ui/widgets/input_fields.h',
'<(src_loc)/ui/widgets/label_simple.cpp',
'<(src_loc)/ui/widgets/label_simple.h',
'<(src_loc)/ui/widgets/media_slider.cpp',
@ -528,12 +532,8 @@
'<(src_loc)/ui/emoji_config.h',
'<(src_loc)/ui/filedialog.cpp',
'<(src_loc)/ui/filedialog.h',
'<(src_loc)/ui/flatinput.cpp',
'<(src_loc)/ui/flatinput.h',
'<(src_loc)/ui/flatlabel.cpp',
'<(src_loc)/ui/flatlabel.h',
'<(src_loc)/ui/flattextarea.cpp',
'<(src_loc)/ui/flattextarea.h',
'<(src_loc)/ui/images.cpp',
'<(src_loc)/ui/images.h',
'<(src_loc)/ui/scrollarea.cpp',