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; boxTitleHeight: 54px;
boxButtonFont: font(boxFontSize semibold); 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); boxButtonPadding: margins(12px, 16px, 22px, 16px);
boxLabel: flatLabel(labelDefFlat) { boxLabel: flatLabel(labelDefFlat) {
font: font(boxFontSize); font: font(boxFontSize);
align: align(topleft); 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 { solidScroll: flatScroll {
barColor: #3f729734; barColor: #3f729734;
bgColor: #214f751a; bgColor: #214f751a;
@ -279,40 +135,6 @@ linkCropLimit: 360px;
linkFont: normalFont; linkFont: normalFont;
linkOverFont: font(fsize underline); 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 { scrollDef: flatScroll {
barColor: #00000053; barColor: #00000053;
bgColor: #0000001a; bgColor: #0000001a;
@ -375,63 +197,6 @@ noContactsHeight: 100px;
noContactsFont: font(fsize); noContactsFont: font(fsize);
noContactsColor: #777777; 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; activeFadeInDuration: 500;
activeFadeOutDuration: 3000; activeFadeOutDuration: 3000;
@ -704,13 +469,6 @@ boxPhotoTextFg: #808080;
cropPointSize: 10px; cropPointSize: 10px;
cropSkip: 13px; cropSkip: 13px;
cropMinSize: 20px; cropMinSize: 20px;
confirmCaptionArea: InputArea(defaultInputArea) {
textMargins: margins(1px, 6px, 1px, 4px);
heightMax: 56px;
}
confirmBg: #f2f2f2;
confirmMaxHeight: 245px;
confirmCompressedSkip: 10px;
profileMaxWidth: 410px; profileMaxWidth: 410px;
profilePadding: margins(28px, 30px, 28px, 0px); profilePadding: margins(28px, 30px, 28px, 0px);
@ -725,20 +483,6 @@ forwardFont: font(16px);
forwardBg: #0000004c; forwardBg: #0000004c;
forwardFg: #ffffff; 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); emojiTextFont: font(15px);
emojiReplaceWidth: 52px; emojiReplaceWidth: 52px;
emojiReplaceHeight: 56px; emojiReplaceHeight: 56px;
@ -784,12 +528,6 @@ botKbScroll: flatScroll(solidScroll) {
deltax: 3px; deltax: 3px;
width: 10px; width: 10px;
} }
switchPmButton: RoundButton(defaultBoxButton) {
width: 320px;
height: 34px;
textTop: 7px;
downTextTop: 8px;
}
minPhotoSize: 100px; minPhotoSize: 100px;
maxMediaSize: 420px; maxMediaSize: 420px;
@ -867,23 +605,6 @@ videoIcon: icon {
}; };
locationSize: size(320px, 240px); 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; mentionHeight: 40px;
mentionScroll: flatScroll(scrollDef) { mentionScroll: flatScroll(scrollDef) {
topsh: 0px; topsh: 0px;
@ -934,11 +655,6 @@ inlineRowFileDescriptionTop: 23px;
inlineResultsMinWidth: 64px; inlineResultsMinWidth: 64px;
inlineDurationMargin: 3px; inlineDurationMargin: 3px;
editTextArea: InputArea(defaultInputArea) {
textMargins: margins(1px, 6px, 1px, 4px);
heightMax: 256px;
}
toastFont: normalFont; toastFont: normalFont;
toastMaxWidth: 480px; toastMaxWidth: 480px;
toastMinMargin: 13px; toastMinMargin: 13px;
@ -948,11 +664,6 @@ toastPadding: margins(19px, 13px, 19px, 12px);
toastFadeInDuration: 200; toastFadeInDuration: 200;
toastFadeOutDuration: 1000; toastFadeOutDuration: 1000;
infoButton: PeerAvatarButton {
size: topBarHeight;
photoSize: 42px;
}
// forward declaration for single "title_back" usage. // forward declaration for single "title_back" usage.
profileTopBarBackIconFg: #0290d7; profileTopBarBackIconFg: #0290d7;
profileTopBarBackIcon: icon {{ "title_back", profileTopBarBackIconFg }}; profileTopBarBackIcon: icon {{ "title_back", profileTopBarBackIconFg }};

View file

@ -30,49 +30,6 @@ textStyle {
lineHeight: pixels; 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 { flatScroll {
barColor: color; barColor: color;
bgColor: color; bgColor: color;
@ -125,143 +82,3 @@ botKeyboardButton {
textTop: pixels; textTop: pixels;
downTextTop: 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 // widgets
activeButtonBg: windowActiveBg; activeButtonBg: windowActiveBg;
activeButtonBgOver: #46b4eb; activeButtonBgOver: #46b4eb;
activeButtonBgRipple: #177eb2;
activeButtonFg: windowActiveFg; activeButtonFg: windowActiveFg;
activeButtonFgOver: activeButtonFg; activeButtonFgOver: activeButtonFg;
activeButtonSecondaryFg: #cceeff; activeButtonSecondaryFg: #cceeff;
@ -44,6 +45,7 @@ activeButtonSecondaryFgOver: activeButtonSecondaryFg;
lightButtonBg: windowBg; lightButtonBg: windowBg;
lightButtonBgOver: #edf7ff; lightButtonBgOver: #edf7ff;
lightButtonBgRipple: #c7e1f6;
lightButtonFg: #2b99d5; lightButtonFg: #2b99d5;
lightButtonFgOver: lightButtonFg; lightButtonFgOver: lightButtonFg;
@ -92,6 +94,11 @@ boxBlockTitleAdditionalFg: #808080;
boxBlockTitleCloseFg: cancelIconFg; boxBlockTitleCloseFg: cancelIconFg;
boxBlockTitleCloseFgOver: cancelIconFgOver; boxBlockTitleCloseFgOver: cancelIconFgOver;
attentionBoxButtonFg: #ea4b2f;
attentionBoxButtonFgOver: #ea4b2f;
attentionBoxButtonBgOver: #fff0ed;
attentionBoxButtonBgRipple: #efbcb2;
membersAboutLimitFg: windowSubTextFg; membersAboutLimitFg: windowSubTextFg;
contactsBg: windowBg; contactsBg: windowBg;
@ -188,6 +195,7 @@ historyReplyCancelFgOver: cancelIconFgOver;
historyComposeButtonBg: historyComposeAreaBg; historyComposeButtonBg: historyComposeAreaBg;
historyComposeButtonBgOver: #f5f5f5; historyComposeButtonBgOver: #f5f5f5;
historyComposeButtonBgRipple: #e7e7e7;
historyTextInFg: windowTextFg; historyTextInFg: windowTextFg;
historyTextOutFg: windowTextFg; historyTextOutFg: windowTextFg;

View file

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

View file

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

View file

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

View file

@ -1037,15 +1037,15 @@ void AppClass::uploadProfilePhoto(const QImage &tosend, const PeerId &peerId) {
PreparedPhotoThumbs photoThumbs; PreparedPhotoThumbs photoThumbs;
QVector<MTPPhotoSize> photoSizes; 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); 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))); 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); 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))); 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); 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))); 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/filedialog.h"
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "apiwrap.h" #include "apiwrap.h"

View file

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

View file

@ -28,6 +28,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "mainwindow.h" #include "mainwindow.h"
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "styles/style_boxes.h"
AutoLockBox::AutoLockBox() : AutoLockBox::AutoLockBox() :
_close(this, lang(lng_box_ok), st::defaultBoxButton) { _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 "mainwindow.h"
#include "window/window_theme.h" #include "window/window_theme.h"
#include "styles/style_overview.h" #include "styles/style_overview.h"
#include "styles/style_boxes.h"
BackgroundBox::BackgroundBox() : ItemListBox(st::backgroundScroll) BackgroundBox::BackgroundBox() : ItemListBox(st::backgroundScroll)
, _inner(this) { , _inner(this) {

View file

@ -23,6 +23,48 @@ using "basic.style";
using "ui/widgets/widgets.style"; using "ui/widgets/widgets.style";
using "intro/intro.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; boxBlockTitleHeight: 48px;
boxBlockTitlePosition: point(18px, 14px); boxBlockTitlePosition: point(18px, 14px);
boxBlockTitleFont: font(boxFontSize semibold); boxBlockTitleFont: font(boxFontSize semibold);
@ -46,6 +88,8 @@ boxLinkButton: LinkButton {
overFont: font(boxFontSize underline); overFont: font(boxFontSize underline);
} }
boxOptionListPadding: margins(2px, 20px, 2px, 2px);
confirmInviteTitle: flatLabel(labelDefFlat) { confirmInviteTitle: flatLabel(labelDefFlat) {
font: font(16px semibold); font: font(16px semibold);
align: align(center); align: align(center);
@ -281,7 +325,7 @@ sessionTerminateAllButton: LinkButton(boxLinkButton) {
passcodeHeaderFont: font(19px); passcodeHeaderFont: font(19px);
passcodeHeaderHeight: 80px; passcodeHeaderHeight: 80px;
passcodeInput: flatInput(inpIntroPhone) { passcodeInput: FlatInput(introPhone) {
} }
passcodeSubmit: RoundButton(introNextButton) { passcodeSubmit: RoundButton(introNextButton) {
width: 225px; width: 225px;
@ -340,3 +384,45 @@ aboutLabel: flatLabel(labelDefFlat) {
aboutTextStyle: textStyle(defaultTextStyle) { aboutTextStyle: textStyle(defaultTextStyle) {
lineHeight: 22px; 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; class RoundButton;
} // namespace Ui } // namespace Ui
namespace st {
extern const style::RoundButton &defaultBoxButton;
extern const style::RoundButton &cancelBoxButton;
} // namespace style
class InformBox; class InformBox;
class ConfirmBox : public AbstractBox, public ClickHandlerHost { class ConfirmBox : public AbstractBox, public ClickHandlerHost {
Q_OBJECT Q_OBJECT

View file

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

View file

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

View file

@ -27,7 +27,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "mainwindow.h" #include "mainwindow.h"
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
#include "history/history_location_manager.h" #include "history/history_location_manager.h"
#include "styles/style_boxes.h"
ConnectionBox::ConnectionBox() : AbstractBox(st::boxWidth) ConnectionBox::ConnectionBox() : AbstractBox(st::boxWidth)
, _hostInput(this, st::connectionHostInputField, lang(lng_connection_host_ph), Global::ConnectionProxy().host) , _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" #include "abstractbox.h"
namespace Ui { namespace Ui {
class InputField;
class PortInput;
class PasswordInput;
class Checkbox; class Checkbox;
class Radiobutton; class Radiobutton;
class RoundButton; class RoundButton;
@ -47,10 +50,10 @@ protected:
void doSetInnerFocus() override; void doSetInnerFocus() override;
private: private:
ChildWidget<InputField> _hostInput; ChildWidget<Ui::InputField> _hostInput;
ChildWidget<PortInput> _portInput; ChildWidget<Ui::PortInput> _portInput;
ChildWidget<InputField> _userInput; ChildWidget<Ui::InputField> _userInput;
ChildWidget<PasswordField> _passwordInput; ChildWidget<Ui::PasswordInput> _passwordInput;
ChildWidget<Ui::Radiobutton> _autoRadio; ChildWidget<Ui::Radiobutton> _autoRadio;
ChildWidget<Ui::Radiobutton> _httpProxyRadio; ChildWidget<Ui::Radiobutton> _httpProxyRadio;
ChildWidget<Ui::Radiobutton> _tcpProxyRadio; ChildWidget<Ui::Radiobutton> _tcpProxyRadio;

View file

@ -29,6 +29,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "mainwidget.h" #include "mainwidget.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "langloaderplain.h" #include "langloaderplain.h"
#include "styles/style_boxes.h"
LanguageBox::LanguageBox() : LanguageBox::LanguageBox() :
_close(this, lang(lng_box_ok), st::defaultBoxButton) { _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 "localstorage.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
PasscodeBox::PasscodeBox(bool turningOff) : AbstractBox(st::boxWidth) PasscodeBox::PasscodeBox(bool turningOff) : AbstractBox(st::boxWidth)
, _replacedBy(0) , _replacedBy(0)

View file

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

View file

@ -27,6 +27,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "photocropbox.h" #include "photocropbox.h"
#include "fileuploader.h" #include "fileuploader.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "styles/style_boxes.h"
PhotoCropBox::PhotoCropBox(const QImage &img, const PeerId &peer) : AbstractBox() PhotoCropBox::PhotoCropBox(const QImage &img, const PeerId &peer) : AbstractBox()
, _downState(0) , _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 "history/history_media_types.h"
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
#include "styles/style_history.h" #include "styles/style_history.h"
#include "styles/style_boxes.h"
PhotoSendBox::PhotoSendBox(const FileLoadResultPtr &file) : AbstractBox(st::boxWideWidth) PhotoSendBox::PhotoSendBox(const FileLoadResultPtr &file) : AbstractBox(st::boxWideWidth)
, _file(file) , _file(file)
@ -141,7 +143,7 @@ PhotoSendBox::PhotoSendBox(const FileLoadResultPtr &file) : AbstractBox(st::boxW
updateBoxSize(); updateBoxSize();
_caption->setMaxLength(MaxPhotoCaption); _caption->setMaxLength(MaxPhotoCaption);
_caption->setCtrlEnterSubmit(CtrlEnterSubmitBoth); _caption->setCtrlEnterSubmit(Ui::CtrlEnterSubmitBoth);
connect(_compressed, SIGNAL(changed()), this, SLOT(onCompressedChange())); connect(_compressed, SIGNAL(changed()), this, SLOT(onCompressedChange()));
connect(_caption, SIGNAL(resized()), this, SLOT(onCaptionResized())); connect(_caption, SIGNAL(resized()), this, SLOT(onCaptionResized()));
connect(_caption, SIGNAL(submitted(bool)), this, SLOT(onSend(bool))); connect(_caption, SIGNAL(submitted(bool)), this, SLOT(onSend(bool)));
@ -493,13 +495,13 @@ EditCaptionBox::EditCaptionBox(HistoryItem *msg) : AbstractBox(st::boxWideWidth)
if (_animated || _photo || _doc) { if (_animated || _photo || _doc) {
_field.create(this, st::confirmCaptionArea, lang(lng_photo_caption), caption); _field.create(this, st::confirmCaptionArea, lang(lng_photo_caption), caption);
_field->setMaxLength(MaxPhotoCaption); _field->setMaxLength(MaxPhotoCaption);
_field->setCtrlEnterSubmit(CtrlEnterSubmitBoth); _field->setCtrlEnterSubmit(Ui::CtrlEnterSubmitBoth);
} else { } else {
auto original = msg->originalText(); auto original = msg->originalText();
QString text = textApplyEntities(original.text, original.entities); QString text = textApplyEntities(original.text, original.entities);
_field.create(this, st::editTextArea, lang(lng_photo_caption), text); _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->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(); updateBoxSize();
connect(_field, SIGNAL(submitted(bool)), this, SLOT(onSave(bool))); 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 { namespace Ui {
class Checkbox; class Checkbox;
class RoundButton; class RoundButton;
class InputArea;
} // namespace Ui } // namespace Ui
class PhotoSendBox : public AbstractBox { class PhotoSendBox : public AbstractBox {
@ -57,7 +58,7 @@ private:
QPixmap _thumb; QPixmap _thumb;
ChildWidget<InputArea> _caption; ChildWidget<Ui::InputArea> _caption;
bool _compressedFromSettings; bool _compressedFromSettings;
ChildWidget<Ui::Checkbox> _compressed; ChildWidget<Ui::Checkbox> _compressed;
@ -108,7 +109,7 @@ private:
QPixmap _thumb; QPixmap _thumb;
ChildWidget<InputArea> _field = { nullptr }; ChildWidget<Ui::InputArea> _field = { nullptr };
ChildWidget<Ui::RoundButton> _save; ChildWidget<Ui::RoundButton> _save;
ChildWidget<Ui::RoundButton> _cancel; 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 "boxes/confirmbox.h"
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
#include "mainwindow.h" #include "mainwindow.h"
ReportBox::ReportBox(ChannelData *channel) : AbstractBox(st::boxWidth) ReportBox::ReportBox(ChannelData *channel) : AbstractBox(st::boxWidth)
@ -75,9 +76,9 @@ void ReportBox::resizeEvent(QResizeEvent *e) {
void ReportBox::onChange() { void ReportBox::onChange() {
if (_reasonOther->checked()) { if (_reasonOther->checked()) {
if (!_reasonOtherText) { 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->show();
_reasonOtherText->setCtrlEnterSubmit(CtrlEnterSubmitBoth); _reasonOtherText->setCtrlEnterSubmit(Ui::CtrlEnterSubmitBoth);
_reasonOtherText->setMaxLength(MaxPhotoCaption); _reasonOtherText->setMaxLength(MaxPhotoCaption);
_reasonOtherText->resize(width() - (st::boxPadding.left() + st::boxOptionListPadding.left() + st::boxPadding.right()), _reasonOtherText->height()); _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 { namespace Ui {
class Radiobutton; class Radiobutton;
class RoundButton; class RoundButton;
class InputArea;
} // namespace Ui } // namespace Ui
class ReportBox : public AbstractBox, public RPCSender { class ReportBox : public AbstractBox, public RPCSender {
@ -59,7 +60,7 @@ private:
ChildWidget<Ui::Radiobutton> _reasonViolence; ChildWidget<Ui::Radiobutton> _reasonViolence;
ChildWidget<Ui::Radiobutton> _reasonPornography; ChildWidget<Ui::Radiobutton> _reasonPornography;
ChildWidget<Ui::Radiobutton> _reasonOther; ChildWidget<Ui::Radiobutton> _reasonOther;
ChildWidget<InputArea> _reasonOtherText = { nullptr }; ChildWidget<Ui::InputArea> _reasonOtherText = { nullptr };
ChildWidget<Ui::RoundButton> _report, _cancel; 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 "mainwidget.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
UsernameBox::UsernameBox() : AbstractBox(st::boxWidth), UsernameBox::UsernameBox() : AbstractBox(st::boxWidth),

View file

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

View file

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

View file

@ -22,7 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "core/utils.h" #include "core/utils.h"
#define BETA_VERSION_MACRO (10019006ULL) #define BETA_VERSION_MACRO (10019007ULL)
constexpr int AppVersion = 10020; constexpr int AppVersion = 10020;
constexpr str_const AppVersionStr = "0.10.20"; 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 "stdafx.h"
#include "data/data_drafts.h" #include "data/data_drafts.h"
#include "ui/widgets/input_fields.h"
#include "historywidget.h" #include "historywidget.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "localstorage.h" #include "localstorage.h"
@ -30,6 +31,13 @@ namespace {
} // 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) { void applyPeerCloudDraft(PeerId peerId, const MTPDdraftMessage &draft) {
auto history = App::history(peerId); auto history = App::history(peerId);
auto text = qs(draft.vmessage); auto text = qs(draft.vmessage);

View file

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

View file

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

View file

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

View file

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

View file

@ -152,7 +152,30 @@ struct SendAction {
int32 progress; 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 { namespace Data {
struct Draft; struct Draft;

View file

@ -136,7 +136,7 @@ historyPeer8UserpicBg: #f7b37c;
historyPeer8UserpicFg: #de8d62; historyPeer8UserpicFg: #de8d62;
historyPeer8UserpicPerson: icon {{ size(120px, 120px), historyPeer8UserpicBg }, { "userpic_person", historyPeer8UserpicFg }}; historyPeer8UserpicPerson: icon {{ size(120px, 120px), historyPeer8UserpicBg }, { "userpic_person", historyPeer8UserpicFg }};
historyComposeField: flatTextarea { historyComposeField: FlatTextarea {
textColor: #000000; textColor: #000000;
bgColor: historyComposeAreaBg; bgColor: historyComposeAreaBg;
align: align(left); align: align(left);
@ -170,12 +170,16 @@ historyComposeButton: FlatButton {
width: -32px; width: -32px;
height: 46px; height: 46px;
textTop: 12px; textTop: 14px;
overTextTop: 12px; overTextTop: 14px;
downTextTop: 13px; downTextTop: 14px;
font: semiboldFont; font: semiboldFont;
overFont: semiboldFont; overFont: semiboldFont;
ripple: RippleAnimation(defaultRippleAnimation) {
color: historyComposeButtonBgRipple;
}
} }
historyUnblock: FlatButton(historyComposeButton) { historyUnblock: FlatButton(historyComposeButton) {
color: #d15948; color: #d15948;
@ -290,23 +294,6 @@ historyInlineBotCancel: IconButton(historyReplyCancel) {
height: 46px; 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 { reportSpamHide: FlatButton {
duration: 200; duration: 200;
cursor: cursor(pointer); cursor: cursor(pointer);
@ -327,17 +314,6 @@ reportSpamHide: FlatButton {
font: font(fsize); font: font(fsize);
overFont: font(fsize underline); overFont: font(fsize underline);
} }
reportSpamButton: FlatButton(reportSpamHide) {
textTop: 6px;
overTextTop: 6px;
downTextTop: 7px;
width: -50px;
height: 30px;
bgColor: #888888;
overBgColor: #7b7b7b;
}
reportSpamSeparator: 30px; reportSpamSeparator: 30px;
reportSpamBg: #fffffff0; reportSpamBg: #fffffff0;
reportSpamFg: #000000; 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_history.h"
#include "styles/style_dialogs.h" #include "styles/style_dialogs.h"
#include "styles/style_window.h"
#include "styles/style_boxes.h"
#include "boxes/confirmbox.h" #include "boxes/confirmbox.h"
#include "boxes/photosendbox.h" #include "boxes/photosendbox.h"
#include "boxes/sharebox.h" #include "boxes/sharebox.h"
@ -77,13 +79,13 @@ QMimeData *mimeDataFromTextWithEntities(const TextWithEntities &forClipboard) {
for (auto &tag : tags) { for (auto &tag : tags) {
tag.id = mimeTagFromTag(tag.id); tag.id = mimeTagFromTag(tag.id);
} }
result->setData(FlatTextarea::tagsMimeType(), FlatTextarea::serializeTagsList(tags)); result->setData(Ui::FlatTextarea::tagsMimeType(), Ui::FlatTextarea::serializeTagsList(tags));
} }
return result; return result;
} }
// For mention tags save and validate userId, ignore tags for different userId. // For mention tags save and validate userId, ignore tags for different userId.
class FieldTagMimeProcessor : public FlatTextarea::TagMimeProcessor { class FieldTagMimeProcessor : public Ui::FlatTextarea::TagMimeProcessor {
public: public:
QString mimeTagFromTag(const QString &tagId) override { QString mimeTagFromTag(const QString &tagId) override {
return ::mimeTagFromTag(tagId); 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); setMinHeight(st::historySend.height - 2 * st::historySendPadding);
setMaxHeight(st::historyComposeFieldMaxHeight); setMaxHeight(st::historyComposeFieldMaxHeight);
} }
@ -2976,7 +2978,7 @@ QPoint SilentToggle::tooltipPos() const {
return QCursor::pos(); return QCursor::pos();
} }
EntitiesInText entitiesFromTextTags(const FlatTextarea::TagList &tags) { EntitiesInText entitiesFromTextTags(const TextWithTags::Tags &tags) {
EntitiesInText result; EntitiesInText result;
if (tags.isEmpty()) { if (tags.isEmpty()) {
return result; return result;
@ -3229,14 +3231,14 @@ void HistoryWidget::updateInlineBotQuery() {
MTP::cancel(_inlineBotResolveRequestId); MTP::cancel(_inlineBotResolveRequestId);
_inlineBotResolveRequestId = 0; _inlineBotResolveRequestId = 0;
} }
if (bot == LookingUpInlineBot) { if (bot == Ui::LookingUpInlineBot) {
_inlineBot = LookingUpInlineBot; _inlineBot = Ui::LookingUpInlineBot;
// Notify::inlineBotRequesting(true); // Notify::inlineBotRequesting(true);
_inlineBotResolveRequestId = MTP::send(MTPcontacts_ResolveUsername(MTP_string(_inlineBotUsername)), rpcDone(&HistoryWidget::inlineBotResolveDone), rpcFail(&HistoryWidget::inlineBotResolveFail, _inlineBotUsername)); _inlineBotResolveRequestId = MTP::send(MTPcontacts_ResolveUsername(MTP_string(_inlineBotUsername)), rpcDone(&HistoryWidget::inlineBotResolveDone), rpcFail(&HistoryWidget::inlineBotResolveFail, _inlineBotUsername));
return; return;
} }
} else if (bot == LookingUpInlineBot) { } else if (bot == Ui::LookingUpInlineBot) {
if (_inlineBot == LookingUpInlineBot) { if (_inlineBot == Ui::LookingUpInlineBot) {
return; return;
} }
bot = _inlineBot; bot = _inlineBot;
@ -4389,11 +4391,11 @@ void HistoryWidget::updateAfterDrag() {
} }
void HistoryWidget::updateFieldSubmitSettings() { void HistoryWidget::updateFieldSubmitSettings() {
FlatTextarea::SubmitSettings settings = FlatTextarea::SubmitSettings::Enter; auto settings = Ui::FlatTextarea::SubmitSettings::Enter;
if (_inlineBotCancel) { if (_inlineBotCancel) {
settings = FlatTextarea::SubmitSettings::None; settings = Ui::FlatTextarea::SubmitSettings::None;
} else if (cCtrlEnter()) { } else if (cCtrlEnter()) {
settings = FlatTextarea::SubmitSettings::CtrlEnter; settings = Ui::FlatTextarea::SubmitSettings::CtrlEnter;
} }
_field->setSubmitSettings(settings); _field->setSubmitSettings(settings);
} }
@ -5156,9 +5158,9 @@ void HistoryWidget::preloadHistoryIfNeeded() {
void HistoryWidget::onInlineBotCancel() { void HistoryWidget::onInlineBotCancel() {
auto &textWithTags = _field->getTextWithTags(); auto &textWithTags = _field->getTextWithTags();
if (textWithTags.text.size() > _inlineBotUsername.size() + 2) { 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 { } 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(); auto &textWithTags = _field->getTextWithTags();
if (specialGif) { if (specialGif) {
if (textWithTags.text.trimmed() == '@' + cInlineGifBotUsername() && textWithTags.text.at(0) == '@') { if (textWithTags.text.trimmed() == '@' + cInlineGifBotUsername() && textWithTags.text.at(0) == '@') {
clearFieldText(TextUpdateEvent::SaveDraft, FlatTextarea::AddToUndoHistory); clearFieldText(TextUpdateEvent::SaveDraft, Ui::FlatTextarea::AddToUndoHistory);
} }
} else { } else {
TextWithTags textWithTagsToSet; TextWithTags textWithTagsToSet;
@ -5905,7 +5907,7 @@ bool HistoryWidget::insertBotCommand(const QString &cmd, bool specialGif) {
} }
} else { } else {
if (!specialGif || _field->isEmpty()) { if (!specialGif || _field->isEmpty()) {
setFieldText({ toInsert, TextWithTags::Tags() }, TextUpdateEvent::SaveDraft, FlatTextarea::AddToUndoHistory); setFieldText({ toInsert, TextWithTags::Tags() }, TextUpdateEvent::SaveDraft, Ui::FlatTextarea::AddToUndoHistory);
_field->setFocus(); _field->setFocus();
return true; return true;
} }
@ -6027,7 +6029,7 @@ void HistoryWidget::inlineBotResolveDone(const MTPcontacts_ResolvedPeer &result)
QString inlineBotUsername; QString inlineBotUsername;
auto query = _field->getInlineBotQuery(&bot, &inlineBotUsername); auto query = _field->getInlineBotQuery(&bot, &inlineBotUsername);
if (inlineBotUsername == _inlineBotUsername) { if (inlineBotUsername == _inlineBotUsername) {
if (bot == LookingUpInlineBot) { if (bot == Ui::LookingUpInlineBot) {
bot = resolvedBot; bot = resolvedBot;
} }
} else { } else {
@ -6223,7 +6225,7 @@ void HistoryWidget::onKbToggle(bool manual) {
} }
void HistoryWidget::onCmdStart() { void HistoryWidget::onCmdStart() {
setFieldText({ qsl("/"), TextWithTags::Tags() }, 0, FlatTextarea::AddToUndoHistory); setFieldText({ qsl("/"), TextWithTags::Tags() }, 0, Ui::FlatTextarea::AddToUndoHistory);
} }
void HistoryWidget::contextMenuEvent(QContextMenuEvent *e) { void HistoryWidget::contextMenuEvent(QContextMenuEvent *e) {
@ -6502,7 +6504,7 @@ void HistoryWidget::clearInlineBot() {
} }
void HistoryWidget::inlineBotChanged() { void HistoryWidget::inlineBotChanged() {
bool isInlineBot = _inlineBot && (_inlineBot != LookingUpInlineBot); bool isInlineBot = _inlineBot && (_inlineBot != Ui::LookingUpInlineBot);
if (isInlineBot && !_inlineBotCancel) { if (isInlineBot && !_inlineBotCancel) {
_inlineBotCancel = std_::make_unique<Ui::IconButton>(this, st::historyInlineBotCancel); _inlineBotCancel = std_::make_unique<Ui::IconButton>(this, st::historyInlineBotCancel);
connect(_inlineBotCancel.get(), SIGNAL(clicked()), this, SLOT(onInlineBotCancel())); connect(_inlineBotCancel.get(), SIGNAL(clicked()), this, SLOT(onInlineBotCancel()));
@ -6532,7 +6534,7 @@ void HistoryWidget::onCheckFieldAutocomplete() {
if (!_history || _a_show.animating()) return; if (!_history || _a_show.animating()) return;
bool start = false; bool start = false;
bool isInlineBot = _inlineBot && (_inlineBot != LookingUpInlineBot); bool isInlineBot = _inlineBot && (_inlineBot != Ui::LookingUpInlineBot);
QString query = isInlineBot ? QString() : _field->getMentionHashtagBotCommandPart(start); QString query = isInlineBot ? QString() : _field->getMentionHashtagBotCommandPart(start);
if (!query.isEmpty()) { if (!query.isEmpty()) {
if (query.at(0) == '#' && cRecentWriteHashtags().isEmpty() && cRecentSearchHashtags().isEmpty()) Local::readRecentHashtagsAndBots(); if (query.at(0) == '#' && cRecentWriteHashtags().isEmpty() && cRecentSearchHashtags().isEmpty()) Local::readRecentHashtagsAndBots();
@ -6547,7 +6549,7 @@ void HistoryWidget::updateFieldPlaceholder() {
_field->setPlaceholder(lang(lng_edit_message_text)); _field->setPlaceholder(lang(lng_edit_message_text));
_send->setIcon(&st::historyEditSaveIcon, &st::historyEditSaveIconOver); _send->setIcon(&st::historyEditSaveIcon, &st::historyEditSaveIconOver);
} else { } else {
if (_inlineBot && _inlineBot != LookingUpInlineBot) { if (_inlineBot && _inlineBot != Ui::LookingUpInlineBot) {
_field->setPlaceholder(_inlineBot->botInfo->inlinePlaceholder.mid(1), _inlineBot->username.size() + 2); _field->setPlaceholder(_inlineBot->botInfo->inlinePlaceholder.mid(1), _inlineBot->username.size() + 2);
} else { } else {
_field->setPlaceholder(lang((_history && _history->isChannel() && !_history->isMegagroup()) ? (_silent->checked() ? lng_broadcast_silent_ph : lng_broadcast_ph) : lng_message_ph)); _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(); _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; _textUpdateEvents = events;
_field->setTextWithTags(textWithTags, undoHistoryAction); _field->setTextWithTags(textWithTags, undoHistoryAction);
_field->moveCursor(QTextCursor::End); _field->moveCursor(QTextCursor::End);

View file

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

View file

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

View file

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

View file

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

View file

@ -49,8 +49,8 @@ IntroPhone::IntroPhone(IntroWidget *parent) : IntroStep(parent)
, _a_error(animation(this, &IntroPhone::step_error)) , _a_error(animation(this, &IntroPhone::step_error))
, _next(this, lang(lng_intro_next), st::introNextButton) , _next(this, lang(lng_intro_next), st::introNextButton)
, _country(this, st::introCountry) , _country(this, st::introCountry)
, _phone(this, st::inpIntroPhone) , _phone(this, st::introPhone)
, _code(this, st::inpIntroCountryCode) , _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) , _signup(this, lng_phone_notreg(lt_signup_start, textcmdStartLink(1), lt_signup_end, textcmdStopLink()), FlatLabel::InitType::Rich, st::introErrorLabel, st::introErrorLabelTextStyle)
, _checkRequest(this) { , _checkRequest(this) {
setVisible(false); setVisible(false);
@ -110,7 +110,7 @@ void IntroPhone::resizeEvent(QResizeEvent *e) {
_next->move((width() - _next->width()) / 2, st::introBtnTop); _next->move((width() - _next->width()) / 2, st::introBtnTop);
_country->move((width() - _country->width()) / 2, st::introTextTop + st::introTextSize.height() + st::introCountry.top); _country->move((width() - _country->width()) / 2, st::introTextTop + st::introTextSize.height() + st::introCountry.top);
int phoneTop = _country->y() + _country->height() + st::introPhoneTop; 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); _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)); _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" #include "intro/introwidget.h"
namespace Ui { namespace Ui {
class PhonePartInput;
class CountryCodeInput;
class RoundButton; class RoundButton;
} // namespace Ui } // namespace Ui
@ -76,8 +78,8 @@ private:
QRect _textRect; QRect _textRect;
ChildWidget<CountryInput> _country; ChildWidget<CountryInput> _country;
ChildWidget<PhonePartInput> _phone; ChildWidget<Ui::PhonePartInput> _phone;
ChildWidget<CountryCodeInput> _code; ChildWidget<Ui::CountryCodeInput> _code;
ChildWidget<FlatLabel> _signup; ChildWidget<FlatLabel> _signup;
QPixmap _signupCache; QPixmap _signupCache;

View file

@ -22,12 +22,14 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "intro/intropwdcheck.h" #include "intro/intropwdcheck.h"
#include "styles/style_intro.h" #include "styles/style_intro.h"
#include "styles/style_boxes.h"
#include "ui/filedialog.h" #include "ui/filedialog.h"
#include "boxes/confirmbox.h" #include "boxes/confirmbox.h"
#include "lang.h" #include "lang.h"
#include "application.h" #include "application.h"
#include "intro/introsignup.h" #include "intro/introsignup.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
IntroPwdCheck::IntroPwdCheck(IntroWidget *parent) : IntroStep(parent) IntroPwdCheck::IntroPwdCheck(IntroWidget *parent) : IntroStep(parent)
, a_errorAlpha(0) , a_errorAlpha(0)
@ -36,8 +38,8 @@ IntroPwdCheck::IntroPwdCheck(IntroWidget *parent) : IntroStep(parent)
, _salt(parent->getPwdSalt()) , _salt(parent->getPwdSalt())
, _hasRecovery(parent->getHasRecovery()) , _hasRecovery(parent->getHasRecovery())
, _hint(parent->getPwdHint()) , _hint(parent->getPwdHint())
, _pwdField(this, st::inpIntroPassword, lang(lng_signin_password)) , _pwdField(this, st::introPassword, lang(lng_signin_password))
, _codeField(this, st::inpIntroPassword, lang(lng_signin_code)) , _codeField(this, st::introPassword, lang(lng_signin_code))
, _toRecover(this, lang(lng_signin_recover)) , _toRecover(this, lang(lng_signin_recover))
, _toPassword(this, lang(lng_signin_try_password)) , _toPassword(this, lang(lng_signin_try_password))
, _reset(this, lang(lng_signin_reset_account), st::introResetLink) , _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" #include "intro/introwidget.h"
class FlatInput;
namespace Ui { namespace Ui {
class FlatInput;
class RoundButton; class RoundButton;
class LinkButton; class LinkButton;
} // namespace Ui } // namespace Ui
@ -80,8 +79,8 @@ private:
bool _hasRecovery; bool _hasRecovery;
QString _hint, _emailPattern; QString _hint, _emailPattern;
ChildWidget<FlatInput> _pwdField; ChildWidget<Ui::FlatInput> _pwdField;
ChildWidget<FlatInput> _codeField; ChildWidget<Ui::FlatInput> _codeField;
ChildWidget<Ui::LinkButton> _toRecover; ChildWidget<Ui::LinkButton> _toRecover;
ChildWidget<Ui::LinkButton> _toPassword; ChildWidget<Ui::LinkButton> _toPassword;
ChildWidget<Ui::LinkButton> _reset; ChildWidget<Ui::LinkButton> _reset;

View file

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

View file

@ -20,11 +20,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/ */
#pragma once #pragma once
#include "ui/flatinput.h"
#include "intro/introwidget.h" #include "intro/introwidget.h"
namespace Ui { namespace Ui {
class RoundButton; class RoundButton;
class FlatInput;
} // namespace Ui } // namespace Ui
class IntroSignup final : public IntroStep { class IntroSignup final : public IntroStep {
@ -72,8 +72,8 @@ private:
QPixmap _photoSmall; QPixmap _photoSmall;
int32 _phLeft, _phTop; int32 _phLeft, _phTop;
ChildWidget<FlatInput> _first; ChildWidget<Ui::FlatInput> _first;
ChildWidget<FlatInput> _last; ChildWidget<Ui::FlatInput> _last;
QString _firstName, _lastName; QString _firstName, _lastName;
mtpRequestId _sentRequest = 0; 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 "styles/style_intro.h"
#include "autoupdater.h" #include "autoupdater.h"
#include "window/slide_animation.h" #include "window/slide_animation.h"
#include "styles/style_boxes.h"
IntroWidget::IntroWidget(QWidget *parent) : TWidget(parent) IntroWidget::IntroWidget(QWidget *parent) : TWidget(parent)
, _a_stage(animation(this, &IntroWidget::step_stage)) , _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) { 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))); attributes.push_back(MTP_documentAttributeImageSize(MTP_int(w), MTP_int(h)));
if (w < 20 * h && h < 20 * w) { if (w < 20 * h && h < 20 * w) {
if (animated) { if (animated) {
attributes.push_back(MTP_documentAttributeAnimated()); attributes.push_back(MTP_documentAttributeAnimated());
} else if (_type != PrepareDocument) { } 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); 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))); 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); 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))); 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); 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))); 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 "mainwindow.h"
#include "lang.h" #include "lang.h"
#include "media/media_audio.h" #include "media/media_audio.h"
#include "ui/widgets/input_fields.h"
#include "application.h" #include "application.h"
#include "apiwrap.h" #include "apiwrap.h"
@ -2369,8 +2370,8 @@ void writeDrafts(const PeerId &peer, const MessageDraft &localDraft, const Messa
_writeMap(WriteMapFast); _writeMap(WriteMapFast);
} }
auto msgTags = FlatTextarea::serializeTagsList(localDraft.textWithTags.tags); auto msgTags = Ui::FlatTextarea::serializeTagsList(localDraft.textWithTags.tags);
auto editTags = FlatTextarea::serializeTagsList(editDraft.textWithTags.tags); auto editTags = Ui::FlatTextarea::serializeTagsList(editDraft.textWithTags.tags);
int size = sizeof(quint64); int size = sizeof(quint64);
size += Serialize::stringSize(localDraft.textWithTags.text) + Serialize::bytearraySize(msgTags) + 2 * sizeof(qint32); size += Serialize::stringSize(localDraft.textWithTags.text) + Serialize::bytearraySize(msgTags) + 2 * sizeof(qint32);
@ -2476,8 +2477,8 @@ void readDraftsWithCursors(History *h) {
return; return;
} }
msgData.tags = FlatTextarea::deserializeTagsList(msgTagsSerialized, msgData.text.size()); msgData.tags = Ui::FlatTextarea::deserializeTagsList(msgTagsSerialized, msgData.text.size());
editData.tags = FlatTextarea::deserializeTagsList(editTagsSerialized, editData.text.size()); editData.tags = Ui::FlatTextarea::deserializeTagsList(editTagsSerialized, editData.text.size());
MessageCursor msgCursor, editCursor; MessageCursor msgCursor, editCursor;
_readDraftCursors(peer, msgCursor, editCursor); _readDraftCursors(peer, msgCursor, editCursor);

View file

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

View file

@ -22,6 +22,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "mainwidget.h" #include "mainwidget.h"
#include "styles/style_dialogs.h" #include "styles/style_dialogs.h"
#include "styles/style_history.h"
#include "ui/buttons/peer_avatar_button.h" #include "ui/buttons/peer_avatar_button.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/shadow.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 "core/qthelp_url.h"
#include "window/window_theme.h" #include "window/window_theme.h"
#include "window/player_wrap_widget.h" #include "window/player_wrap_widget.h"
#include "styles/style_boxes.h"
StackItemSection::StackItemSection(std_::unique_ptr<Window::SectionMemento> &&memento) : StackItem(nullptr) StackItemSection::StackItemSection(std_::unique_ptr<Window::SectionMemento> &&memento) : StackItem(nullptr)
, _memento(std_::move(memento)) { , _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 "dialogs/dialogs_layout.h"
#include "styles/style_dialogs.h" #include "styles/style_dialogs.h"
#include "styles/style_window.h" #include "styles/style_window.h"
#include "styles/style_boxes.h"
#include "ui/widgets/popup_menu.h" #include "ui/widgets/popup_menu.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "core/zlib_help.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); 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 current(int framew, int frameh, int outerw, int outerh, uint64 ms);
QPixmap frameOriginal() const { QPixmap frameOriginal() const {
Frame *frame = frameToShow(); if (auto frame = frameToShow()) {
if (!frame) return QPixmap(); auto result = QPixmap::fromImage(frame->original);
QPixmap result(frame ? QPixmap::fromImage(frame->original) : QPixmap()); result.detach();
result.detach(); return result;
return result; }
return QPixmap();
} }
bool currentDisplayed() const { bool currentDisplayed() const {
Frame *frame = frameToShow(); Frame *frame = frameToShow();

View file

@ -118,7 +118,7 @@ overviewLinksChecked: icon {
{ "overview_links_check", #ffffff, point(4px, 5px) }, { "overview_links_check", #ffffff, point(4px, 5px) },
}; };
overviewFilter: flatInput(inpDefGray) { overviewFilter: FlatInput(defaultFlatInput) {
font: font(fsize); font: font(fsize);
bgColor: #f2f2f2; bgColor: #f2f2f2;
phColor: #949494; 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/popup_menu.h"
#include "ui/widgets/tooltip.h" #include "ui/widgets/tooltip.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
#include "window/top_bar_widget.h" #include "window/top_bar_widget.h"
#include "window/window_theme.h" #include "window/window_theme.h"
#include "lang.h" #include "lang.h"
@ -77,17 +78,17 @@ OverviewInner::OverviewInner(OverviewWidget *overview, ScrollArea *scroll, PeerD
setMouseTracking(true); setMouseTracking(true);
connect(_cancelSearch, SIGNAL(clicked()), this, SLOT(onCancelSearch())); connect(_cancelSearch, SIGNAL(clicked()), this, SLOT(onCancelSearch()));
connect(&_search, SIGNAL(cancelled()), this, SLOT(onCancel())); connect(_search, SIGNAL(cancelled()), this, SLOT(onCancel()));
connect(&_search, SIGNAL(changed()), this, SLOT(onSearchUpdate())); connect(_search, SIGNAL(changed()), this, SLOT(onSearchUpdate()));
_searchTimer.setSingleShot(true); _searchTimer.setSingleShot(true);
connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchMessages())); connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchMessages()));
_cancelSearch->hide(); _cancelSearch->hide();
if (_type == OverviewLinks || _type == OverviewFiles) { if (_type == OverviewLinks || _type == OverviewFiles) {
_search.show(); _search->show();
} else { } 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) { void OverviewInner::searchReceived(SearchRequestType type, const MTPmessages_Messages &result, mtpRequestId req) {
if (!_search.text().isEmpty()) { if (!_search->text().isEmpty()) {
if (type == SearchFromStart) { if (type == SearchFromStart) {
SearchQueries::iterator i = _searchQueries.find(req); SearchQueries::iterator i = _searchQueries.find(req);
if (i != _searchQueries.cend()) { if (i != _searchQueries.cend()) {
@ -683,7 +684,7 @@ QPoint OverviewInner::mapMouseToItem(QPoint p, MsgId itemId, int32 itemIndex) {
void OverviewInner::activate() { void OverviewInner::activate() {
if (_type == OverviewLinks || _type == OverviewFiles) { if (_type == OverviewLinks || _type == OverviewFiles) {
_search.setFocus(); _search->setFocus();
} else { } else {
setFocus(); setFocus();
} }
@ -1111,7 +1112,7 @@ void OverviewInner::mouseReleaseEvent(QMouseEvent *e) {
} }
void OverviewInner::keyPressEvent(QKeyEvent *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(); onCancel();
} else if (e->key() == Qt::Key_Back) { } else if (e->key() == Qt::Key_Back) {
App::main()->showBackFromStack(); App::main()->showBackFromStack();
@ -1282,8 +1283,8 @@ int32 OverviewInner::resizeToWidth(int32 nwidth, int32 scrollTop, int32 minHeigh
} }
_rowsLeft = (_width - _rowWidth) / 2; _rowsLeft = (_width - _rowWidth) / 2;
_search.setGeometry(_rowsLeft, st::linksSearchMargin.top(), _rowWidth, _search.height()); _search->setGeometry(_rowsLeft, st::linksSearchMargin.top(), _rowWidth, _search->height());
_cancelSearch->moveToLeft(_rowsLeft + _rowWidth - _cancelSearch->width(), _search.y()); _cancelSearch->moveToLeft(_rowsLeft + _rowWidth - _cancelSearch->width(), _search->y());
if (_type == OverviewPhotos || _type == OverviewVideos) { if (_type == OverviewPhotos || _type == OverviewVideos) {
for (int32 i = 0, l = _items.size(); i < l; ++i) { for (int32 i = 0, l = _items.size(); i < l; ++i) {
@ -1334,14 +1335,14 @@ void OverviewInner::switchType(MediaOverviewType type) {
_type = type; _type = type;
_reversed = (_type != OverviewLinks && _type != OverviewFiles); _reversed = (_type != OverviewLinks && _type != OverviewFiles);
if (_type == OverviewLinks || _type == OverviewFiles) { if (_type == OverviewLinks || _type == OverviewFiles) {
_search.show(); _search->show();
} else { } else {
_search.hide(); _search->hide();
} }
if (!_search.getLastText().isEmpty()) { if (!_search->getLastText().isEmpty()) {
_search.setText(QString()); _search->setText(QString());
_search.updatePlaceholder(); _search->updatePlaceholder();
onSearchUpdate(); onSearchUpdate();
} }
_cancelSearch->hide(); _cancelSearch->hide();
@ -1425,7 +1426,7 @@ void OverviewInner::saveContextFile() {
bool OverviewInner::onSearchMessages(bool searchCache) { bool OverviewInner::onSearchMessages(bool searchCache) {
_searchTimer.stop(); _searchTimer.stop();
QString q = _search.text().trimmed(); QString q = _search->text().trimmed();
if (q.isEmpty()) { if (q.isEmpty()) {
if (_searchRequest) { if (_searchRequest) {
_searchRequest = 0; _searchRequest = 0;
@ -1462,7 +1463,7 @@ void OverviewInner::onNeedSearchMessages() {
} }
void OverviewInner::onSearchUpdate() { 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); bool inSearch = !filterText.isEmpty(), changed = (inSearch != _inSearch);
_inSearch = inSearch; _inSearch = inSearch;
@ -1495,11 +1496,11 @@ void OverviewInner::onCancel() {
} }
bool OverviewInner::onCancelSearch() { bool OverviewInner::onCancelSearch() {
if (_search.isHidden()) return false; if (_search->isHidden()) return false;
bool clearing = !_search.text().isEmpty(); bool clearing = !_search->text().isEmpty();
_cancelSearch->hide(); _cancelSearch->hide();
_search.clear(); _search->clear();
_search.updatePlaceholder(); _search->updatePlaceholder();
onSearchUpdate(); onSearchUpdate();
return clearing; return clearing;
} }
@ -1796,7 +1797,7 @@ void OverviewInner::recountMargins() {
_marginTop = st::playlistPadding; _marginTop = st::playlistPadding;
_marginBottom = qMax(_minHeight - _height - _marginTop, int32(st::playlistPadding)); _marginBottom = qMax(_minHeight - _height - _marginTop, int32(st::playlistPadding));
} else if (_type == OverviewLinks || _type == OverviewFiles) { } 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)); _marginBottom = qMax(_minHeight - _height - _marginTop, int32(st::playlistPadding));
} else { } else {
_marginBottom = st::playlistPadding; _marginBottom = st::playlistPadding;

View file

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

View file

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

View file

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

View file

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

View file

@ -21,6 +21,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
using "basic.style"; using "basic.style";
using "basic_types.style"; using "basic_types.style";
using "window/window.style";
profileBg: windowBg; profileBg: windowBg;
profileTopBarHeight: topBarHeight; 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 "profile/profile_actions_widget.h"
#include "styles/style_profile.h" #include "styles/style_profile.h"
#include "styles/style_boxes.h"
#include "ui/buttons/left_outline_button.h" #include "ui/buttons/left_outline_button.h"
#include "boxes/confirmbox.h" #include "boxes/confirmbox.h"
#include "boxes/report_box.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" #include "profile/profile_block_widget.h"
namespace style {
struct OutlineButton;
} // namespace style
namespace st {
extern const style::OutlineButton &defaultLeftOutlineButton;
} // namespace st
namespace Ui { namespace Ui {
class LeftOutlineButton; class LeftOutlineButton;
} // namespace Ui } // 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 "profile/profile_block_widget.h"
#include "styles/style_profile.h" #include "styles/style_profile.h"
#include "styles/style_widgets.h"
namespace Profile { namespace Profile {

View file

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

View file

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

View file

@ -129,7 +129,7 @@ void SettingsWidget::refreshManageAdminsButton() {
}; };
_manageAdmins.destroy(); _manageAdmins.destroy();
if (hasManageAdmins()) { 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(); _manageAdmins->show();
connect(_manageAdmins, SIGNAL(clicked()), this, SLOT(onManageAdmins())); connect(_manageAdmins, SIGNAL(clicked()), this, SLOT(onManageAdmins()));
} }
@ -152,7 +152,7 @@ void SettingsWidget::refreshInviteLinkButton() {
if (inviteLinkText.isEmpty()) { if (inviteLinkText.isEmpty()) {
_inviteLink.destroy(); _inviteLink.destroy();
} else { } else {
_inviteLink = new Ui::LeftOutlineButton(this, inviteLinkText, st::defaultLeftOutlineButton); _inviteLink.create(this, inviteLinkText, st::defaultLeftOutlineButton);
_inviteLink->show(); _inviteLink->show();
connect(_inviteLink, SIGNAL(clicked()), this, SLOT(onInviteLink())); 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/animation.h"
#include "ui/twidget.h" #include "ui/twidget.h"
#include "ui/flatinput.h"
#include "ui/flattextarea.h"
#include "ui/scrollarea.h" #include "ui/scrollarea.h"
#include "ui/images.h" #include "ui/images.h"
#include "ui/text/text.h" #include "ui/text/text.h"

View file

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

View file

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

View file

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

View file

@ -111,7 +111,7 @@ CountryInput::CountryInput(QWidget *parent, const style::countryInput &st) : QWi
} }
_arrow = App::pixmapFromImageInPlace(std_::move(trImage)); _arrow = App::pixmapFromImageInPlace(std_::move(trImage));
_inner = QRect(0, 0, _st.width, _st.height); _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) { void CountryInput::paintEvent(QPaintEvent *e) {

View file

@ -20,7 +20,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/ */
#pragma once #pragma once
#include "ui/flatinput.h"
#include "ui/scrollarea.h" #include "ui/scrollarea.h"
#include "ui/effects/rect_shadow.h" #include "ui/effects/rect_shadow.h"
#include "boxes/abstractbox.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) { void PanelAnimation::setFinalImage(QImage &&finalImage, QRect inner) {
t_assert(!started()); 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()); t_assert(!_finalImage.isNull());
_finalWidth = _finalImage.width(); _finalWidth = _finalImage.width();
@ -317,7 +317,7 @@ void PanelAnimation::createFadeMask() {
} }
ints += intsPerLineAdded; ints += intsPerLineAdded;
} }
_fadeMask = QPixmap::fromImage(style::colorizeImage(result, _st.fadeBg), Qt::ColorOnly); _fadeMask = App::pixmapFromImageInPlace(style::colorizeImage(result, _st.fadeBg));
_fadeHeight = _fadeMask.height(); _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 "stdafx.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/effects/ripple_animation.h"
namespace Ui { namespace Ui {
FlatButton::FlatButton(QWidget *parent, const QString &text, const style::FlatButton &st) : AbstractButton(parent) 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 { } else {
_a_appearance.start(); _a_appearance.start();
} }
handleRipples(oldState & StateDown, (source == StateChangeSource::ByPress));
}
void FlatButton::handleRipples(bool wasDown, bool wasPress) {
auto down = static_cast<bool>(_state & StateDown);
if (!_st.ripple.showDuration || down == wasDown) {
return;
}
if (down && wasPress) {
// Start a ripple only from mouse press.
if (!_ripple) {
_ripple = std_::make_unique<Ui::RippleAnimation>(_st.ripple, prepareRippleMask(), [this] { update(); });
}
auto clickPosition = mapFromGlobal(QCursor::pos());
_ripple->add(clickPosition);
} else if (!down && _ripple) {
// Finish ripple anyway.
_ripple->stopLast();
}
} }
void FlatButton::paintEvent(QPaintEvent *e) { void FlatButton::paintEvent(QPaintEvent *e) {
@ -97,6 +120,14 @@ void FlatButton::paintEvent(QPaintEvent *e) {
p.setOpacity(_opacity); p.setOpacity(_opacity);
p.fillRect(r, anim::brush(_st.bgColor, _st.overBgColor, a_over.current())); p.fillRect(r, anim::brush(_st.bgColor, _st.overBgColor, a_over.current()));
auto ms = getms();
if (_ripple) {
_ripple->paint(p, 0, 0, width(), ms);
if (_ripple->empty()) {
_ripple.reset();
}
}
p.setFont((_state & StateOver) ? _st.overFont : _st.font); p.setFont((_state & StateOver) ? _st.overFont : _st.font);
p.setRenderHint(QPainter::TextAntialiasing); p.setRenderHint(QPainter::TextAntialiasing);
p.setPen(anim::pen(_st.color, _st.overColor, a_over.current())); p.setPen(anim::pen(_st.color, _st.overColor, a_over.current()));
@ -107,6 +138,15 @@ void FlatButton::paintEvent(QPaintEvent *e) {
p.drawText(r, _text, style::al_top); 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) LinkButton::LinkButton(QWidget *parent, const QString &text, const style::LinkButton &st) : AbstractButton(parent)
, _text(text) , _text(text)
, _textWidth(st.font->width(_text)) , _textWidth(st.font->width(_text))
@ -210,16 +250,25 @@ int RoundButton::contentWidth() const {
void RoundButton::paintEvent(QPaintEvent *e) { void RoundButton::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
int innerWidth = contentWidth(); auto innerWidth = contentWidth();
auto rounded = rtlrect(rect().marginsRemoved(_st.padding), width()); auto rounded = rect().marginsRemoved(_st.padding);
if (_fullWidthOverride < 0) { if (_fullWidthOverride < 0) {
rounded = QRect(0, rounded.top(), innerWidth - _fullWidthOverride, rounded.height()); 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 over = (_state & StateOver);
auto down = (_state & StateDown);
if (over) { 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); p.setFont(_st.font);
@ -230,12 +279,12 @@ void RoundButton::paintEvent(QPaintEvent *e) {
int textTopDelta = (_state & StateDown) ? (_st.downTextTop - _st.textTop) : 0; int textTopDelta = (_state & StateDown) ? (_st.downTextTop - _st.textTop) : 0;
int textTop = _st.padding.top() + _st.textTop + textTopDelta; int textTop = _st.padding.top() + _st.textTop + textTopDelta;
if (!_text.isEmpty()) { if (!_text.isEmpty()) {
p.setPen(over ? _st.textFgOver : _st.textFg); p.setPen((over || down) ? _st.textFgOver : _st.textFg);
p.drawTextLeft(textLeft, textTop, width(), _text); p.drawTextLeft(textLeft, textTop, width(), _text);
} }
if (!_secondaryText.isEmpty()) { if (!_secondaryText.isEmpty()) {
textLeft += _textWidth + (_textWidth ? _st.secondarySkip : 0); 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); p.drawTextLeft(textLeft, textTop, width(), _secondaryText);
} }
_st.icon.paint(p, QPoint(_st.padding.left(), _st.padding.right() + textTopDelta), width()); _st.icon.paint(p, QPoint(_st.padding.left(), _st.padding.right() + textTopDelta), width());
@ -243,8 +292,50 @@ void RoundButton::paintEvent(QPaintEvent *e) {
void RoundButton::onStateChanged(int oldState, StateChangeSource source) { void RoundButton::onStateChanged(int oldState, StateChangeSource source) {
update(); 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) IconButton::IconButton(QWidget *parent, const style::IconButton &st) : AbstractButton(parent)
, _st(st) { , _st(st) {
resize(_st.width, _st.height); 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) { void IconButton::paintEvent(QPaintEvent *e) {
Painter p(this); 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 over = _a_over.current(getms(), (_state & StateOver) ? 1. : 0.);
auto overIcon = [this] { auto overIcon = [this] {
if (_iconOverrideOver) { if (_iconOverrideOver) {
@ -306,6 +406,50 @@ void IconButton::onStateChanged(int oldState, StateChangeSource source) {
update(); 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 } // namespace Ui

View file

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

View file

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

View file

@ -20,14 +20,232 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
*/ */
#pragma once #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 { class FlatInput : public QLineEdit {
Q_OBJECT Q_OBJECT
T_WIDGET T_WIDGET
public: public:
FlatInput(QWidget *parent, const style::flatInput &st, const QString &ph = QString(), const QString &val = QString()); FlatInput(QWidget *parent, const style::FlatInput &st, const QString &ph = QString(), const QString &val = QString());
void notaBene(); void notaBene();
@ -49,7 +267,7 @@ public:
return _oldtext; return _oldtext;
} }
public slots: public slots:
void onTextChange(const QString &text); void onTextChange(const QString &text);
void onTextEdited(); void onTextEdited();
@ -105,7 +323,7 @@ private:
Animation _a_appearance; Animation _a_appearance;
int _notingBene; int _notingBene;
const style::flatInput &_st; const style::FlatInput &_st;
QTimer _touchTimer; QTimer _touchTimer;
bool _touchPress, _touchRightButton, _touchMove; bool _touchPress, _touchRightButton, _touchMove;
@ -116,9 +334,9 @@ class CountryCodeInput : public FlatInput {
Q_OBJECT Q_OBJECT
public: public:
CountryCodeInput(QWidget *parent, const style::flatInput &st); CountryCodeInput(QWidget *parent, const style::FlatInput &st);
public slots: public slots:
void startErasing(QKeyEvent *e); void startErasing(QKeyEvent *e);
void codeSelected(const QString &code); void codeSelected(const QString &code);
@ -138,9 +356,9 @@ class PhonePartInput : public FlatInput {
Q_OBJECT Q_OBJECT
public: 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 addedToNumber(const QString &added);
void onChooseCode(const QString &code); void onChooseCode(const QString &code);
@ -221,7 +439,7 @@ public:
_inner.clearFocus(); _inner.clearFocus();
} }
public slots: public slots:
void onTouchTimer(); void onTouchTimer();
void onDocumentContentsChange(int position, int charsRemoved, int charsAdded); void onDocumentContentsChange(int position, int charsRemoved, int charsAdded);
@ -392,7 +610,7 @@ public:
_inner.setTextCursor(c); _inner.setTextCursor(c);
} }
public slots: public slots:
void onTouchTimer(); void onTouchTimer();
void onDocumentContentsChange(int position, int charsRemoved, int charsAdded); void onDocumentContentsChange(int position, int charsRemoved, int charsAdded);
@ -497,7 +715,7 @@ private:
class MaskedInputField : public QLineEdit { class MaskedInputField : public QLineEdit {
Q_OBJECT Q_OBJECT
T_WIDGET T_WIDGET
public: public:
MaskedInputField(QWidget *parent, const style::InputField &st, const QString &placeholder = QString(), const QString &val = QString()); MaskedInputField(QWidget *parent, const style::InputField &st, const QString &placeholder = QString(), const QString &val = QString());
@ -539,7 +757,7 @@ public:
updatePlaceholder(); updatePlaceholder();
} }
public slots: public slots:
void onTextChange(const QString &text); void onTextChange(const QString &text);
void onCursorPositionChanged(int oldPosition, int position); void onCursorPositionChanged(int oldPosition, int position);
@ -610,9 +828,9 @@ private:
QPoint _touchStart; QPoint _touchStart;
}; };
class PasswordField : public MaskedInputField { class PasswordInput : public MaskedInputField {
public: 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; 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 "styles/style_widgets.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
#include "lang.h" #include "lang.h"
namespace Ui { namespace Ui {

View file

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

View file

@ -35,6 +35,12 @@ LinkButton {
overFont: font; overFont: font;
} }
RippleAnimation {
color: color;
showDuration: int;
hideDuration: int;
}
FlatButton { FlatButton {
color: color; color: color;
overColor: color; overColor: color;
@ -53,6 +59,188 @@ FlatButton {
overFont: font; overFont: font;
duration: int; duration: int;
cursor: cursor; 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 { IconButton {
@ -66,6 +254,10 @@ IconButton {
iconPositionDown: point; iconPositionDown: point;
duration: int; duration: int;
rippleAreaPosition: point;
rippleAreaSize: pixels;
ripple: RippleAnimation;
} }
Shadow { Shadow {
@ -232,6 +424,194 @@ defaultLinkButton: LinkButton {
overFont: linkOverFont; 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 { defaultIconButton: IconButton {
iconPosition: point(-1px, -1px); iconPosition: point(-1px, -1px);
iconPositionDown: point(-1px, -1px); iconPositionDown: point(-1px, -1px);

View file

@ -58,6 +58,7 @@ void MainWindow::init() {
} }
initSize(); initSize();
updateUnreadCounter();
} }
HitTestResult MainWindow::hitTest(const QPoint &p) const { 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 "mainwindow.h"
#include "lang.h" #include "lang.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
#include "dialogs/dialogs_layout.h" #include "dialogs/dialogs_layout.h"
#include "styles/style_dialogs.h" #include "styles/style_dialogs.h"
#include "styles/style_boxes.h"
#include "styles/style_window.h" #include "styles/style_window.h"
namespace Window { namespace Window {
@ -225,7 +227,7 @@ void Manager::moveWidgets() {
} }
if (count > 1 || !_queuedNotifications.isEmpty()) { if (count > 1 || !_queuedNotifications.isEmpty()) {
auto deltaY = st::notifyHideAll.height + st::notifyDeltaY; auto deltaY = st::notifyHideAllHeight + st::notifyDeltaY;
if (!_hideAll) { if (!_hideAll) {
_hideAll = new HideAllButton(notificationStartPosition(), lastShiftCurrent, notificationShiftDirection()); _hideAll = new HideAllButton(notificationStartPosition(), lastShiftCurrent, notificationShiftDirection());
} }
@ -735,17 +737,17 @@ void Notification::showReplyField() {
} }
stopHiding(); stopHiding();
_background = new Background(this); _background.create(this);
_background->setGeometry(0, st::notifyMinHeight, width(), st::notifySendReply.height + st::notifyBorderWidth); _background->setGeometry(0, st::notifyMinHeight, width(), st::notifySendReply.height + st::notifyBorderWidth);
_background->show(); _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->resize(width() - st::notifySendReply.width - 2 * st::notifyBorderWidth, st::notifySendReply.height);
_replyArea->moveToLeft(st::notifyBorderWidth, st::notifyMinHeight); _replyArea->moveToLeft(st::notifyBorderWidth, st::notifyMinHeight);
_replyArea->show(); _replyArea->show();
_replyArea->setFocus(); _replyArea->setFocus();
_replyArea->setMaxLength(MaxMessageSize); _replyArea->setMaxLength(MaxMessageSize);
_replyArea->setCtrlEnterSubmit(CtrlEnterSubmitBoth); _replyArea->setCtrlEnterSubmit(Ui::CtrlEnterSubmitBoth);
// Catch mouse press event to activate the window. // Catch mouse press event to activate the window.
Sandbox::installEventFilter(this); Sandbox::installEventFilter(this);
@ -860,8 +862,8 @@ Notification::~Notification() {
HideAllButton::HideAllButton(QPoint startPosition, int shift, Direction shiftDirection) : Widget(startPosition, shift, shiftDirection) { HideAllButton::HideAllButton(QPoint startPosition, int shift, Direction shiftDirection) : Widget(startPosition, shift, shiftDirection) {
setCursor(style::cur_pointer); setCursor(style::cur_pointer);
auto position = computePosition(st::notifyHideAll.height); auto position = computePosition(st::notifyHideAllHeight);
updateGeometry(position.x(), position.y(), st::notifyWidth, st::notifyHideAll.height); updateGeometry(position.x(), position.y(), st::notifyWidth, st::notifyHideAllHeight);
hide(); hide();
createWinId(); createWinId();
@ -913,7 +915,7 @@ void HideAllButton::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
p.setClipRect(e->rect()); 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, 0, width(), st::notifyBorderWidth, st::notifyBorder);
p.fillRect(0, height() - st::notifyBorderWidth, 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); 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 { namespace Ui {
class IconButton; class IconButton;
class RoundButton; class RoundButton;
class InputArea;
} // namespace Ui } // namespace Ui
namespace Window { namespace Window {
@ -248,7 +249,7 @@ private:
ChildWidget<Ui::IconButton> _close; ChildWidget<Ui::IconButton> _close;
ChildWidget<Ui::RoundButton> _reply; ChildWidget<Ui::RoundButton> _reply;
ChildWidget<Background> _background = { nullptr }; ChildWidget<Background> _background = { nullptr };
ChildWidget<InputArea> _replyArea = { nullptr }; ChildWidget<Ui::InputArea> _replyArea = { nullptr };
ChildWidget<Ui::IconButton> _replySend = { nullptr }; ChildWidget<Ui::IconButton> _replySend = { nullptr };
bool _waitingForInput = true; bool _waitingForInput = true;

View file

@ -21,6 +21,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "stdafx.h" #include "stdafx.h"
#include "window/slide_animation.h" #include "window/slide_animation.h"
#include "styles/style_window.h"
namespace Window { namespace Window {
void SlideAnimation::paintContents(Painter &p, const QRect &update) const { 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 "stdafx.h"
#include "window/top_bar_widget.h" #include "window/top_bar_widget.h"
#include "styles/style_history.h"
#include "styles/style_window.h" #include "styles/style_window.h"
#include "boxes/addcontactbox.h" #include "boxes/addcontactbox.h"
#include "boxes/confirmbox.h" #include "boxes/confirmbox.h"
@ -41,7 +40,7 @@ TopBarWidget::TopBarWidget(MainWidget *w) : TWidget(w)
, _clearSelection(this, lang(lng_selected_clear), st::topBarClearButton) , _clearSelection(this, lang(lng_selected_clear), st::topBarClearButton)
, _forward(this, lang(lng_selected_forward), st::defaultActiveButton) , _forward(this, lang(lng_selected_forward), st::defaultActiveButton)
, _delete(this, lang(lng_selected_delete), 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) , _mediaType(this, lang(lng_media_type), st::topBarButton)
, _search(this, st::topBarSearch) , _search(this, st::topBarSearch)
, _menuToggle(this, st::topBarMenuToggle) { , _menuToggle(this, st::topBarMenuToggle) {
@ -93,15 +92,23 @@ void TopBarWidget::onSearch() {
void TopBarWidget::showMenu() { void TopBarWidget::showMenu() {
if (auto main = App::main()) { if (auto main = App::main()) {
if (auto peer = main->peer()) { if (auto peer = main->peer()) {
_menu.create(App::main()); if (auto menu = _menu.ptr()) {
App::main()->fillPeerMenu(peer, [this](const QString &text, base::lambda_unique<void()> callback) { _menu = nullptr;
return _menu->addAction(text, std_::move(callback)); _menuToggle->removeEventFilter(menu);
}); menu->setHiddenCallback([menu] { menu->deleteLater(); });
_menu->setHiddenCallback([this] { menu->hideAnimated(Ui::DropdownMenu::HideOption::IgnoreShow);
_menu.destroyDelayed(); } else {
}); _menu.create(App::main());
_menu->moveToRight(0, 0); _menuToggle->installEventFilter(_menu);
_menu->showAnimated(Ui::PanelAnimation::Origin::TopRight); 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; notifyDeltaY: 7px;
notifyActionsDuration: 200; notifyActionsDuration: 200;
notifyHideAll: RoundButton(defaultBoxButton) { notifyHideAllHeight: 36px;
}
notifyReplyArea: InputArea(defaultInputArea) { notifyReplyArea: InputArea(defaultInputArea) {
font: normalFont; 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 // Mac specific
macAccessoryWidth: 450.; macAccessoryWidth: 450.;

View file

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

View file

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