mirror of
https://github.com/kotatogram/kotatogram-desktop
synced 2025-08-31 22:55:11 +00:00
Intro redesign done.
This commit is contained in:
@@ -255,6 +255,7 @@ void RoundButton::updateText() {
|
||||
_secondaryTextWidth = _secondaryText.isEmpty() ? 0 : _st.font->width(_secondaryText);
|
||||
|
||||
resizeToText();
|
||||
update();
|
||||
}
|
||||
|
||||
void RoundButton::resizeToText() {
|
||||
|
@@ -1798,199 +1798,6 @@ void FlatInput::notaBene() {
|
||||
_a_appearance.start();
|
||||
}
|
||||
|
||||
CountryCodeInput::CountryCodeInput(QWidget *parent, const style::FlatInput &st) : FlatInput(parent, st)
|
||||
, _nosignal(false) {
|
||||
}
|
||||
|
||||
void CountryCodeInput::startErasing(QKeyEvent *e) {
|
||||
setFocus();
|
||||
keyPressEvent(e);
|
||||
}
|
||||
|
||||
void CountryCodeInput::codeSelected(const QString &code) {
|
||||
QString wasText(getLastText()), newText = '+' + code;
|
||||
setText(newText);
|
||||
_nosignal = true;
|
||||
correctValue(wasText, newText);
|
||||
_nosignal = false;
|
||||
emit changed();
|
||||
}
|
||||
|
||||
void CountryCodeInput::correctValue(const QString &was, QString &now) {
|
||||
QString newText, addToNumber;
|
||||
int oldPos(cursorPosition()), newPos(-1), oldLen(now.length()), start = 0, digits = 5;
|
||||
newText.reserve(oldLen + 1);
|
||||
newText += '+';
|
||||
if (oldLen && now[0] == '+') {
|
||||
++start;
|
||||
}
|
||||
for (int i = start; i < oldLen; ++i) {
|
||||
QChar ch(now[i]);
|
||||
if (ch.isDigit()) {
|
||||
if (!digits || !--digits) {
|
||||
addToNumber += ch;
|
||||
} else {
|
||||
newText += ch;
|
||||
}
|
||||
}
|
||||
if (i == oldPos) {
|
||||
newPos = newText.length();
|
||||
}
|
||||
}
|
||||
if (!addToNumber.isEmpty()) {
|
||||
QString validCode = findValidCode(newText.mid(1));
|
||||
addToNumber = newText.mid(1 + validCode.length()) + addToNumber;
|
||||
newText = '+' + validCode;
|
||||
}
|
||||
if (newPos < 0 || newPos > newText.length()) {
|
||||
newPos = newText.length();
|
||||
}
|
||||
if (newText != now) {
|
||||
now = newText;
|
||||
setText(newText);
|
||||
updatePlaceholder();
|
||||
if (newPos != oldPos) {
|
||||
setCursorPosition(newPos);
|
||||
}
|
||||
}
|
||||
if (!_nosignal && was != newText) {
|
||||
emit codeChanged(newText.mid(1));
|
||||
}
|
||||
if (!addToNumber.isEmpty()) {
|
||||
emit addedToNumber(addToNumber);
|
||||
}
|
||||
}
|
||||
|
||||
PhonePartInput::PhonePartInput(QWidget *parent, const style::FlatInput &st) : FlatInput(parent, st, lang(lng_phone_ph)) {
|
||||
}
|
||||
|
||||
void PhonePartInput::paintEvent(QPaintEvent *e) {
|
||||
FlatInput::paintEvent(e);
|
||||
|
||||
Painter p(this);
|
||||
auto t = text();
|
||||
if (!_pattern.isEmpty() && !t.isEmpty()) {
|
||||
auto ph = placeholder().mid(t.size());
|
||||
if (!ph.isEmpty()) {
|
||||
p.setClipRect(rect());
|
||||
auto phRect = placeholderRect();
|
||||
int tw = phFont()->width(t);
|
||||
if (tw < phRect.width()) {
|
||||
phRect.setLeft(phRect.left() + tw);
|
||||
phPrepare(p);
|
||||
p.drawText(phRect, ph, style::al_left);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PhonePartInput::keyPressEvent(QKeyEvent *e) {
|
||||
if (e->key() == Qt::Key_Backspace && text().isEmpty()) {
|
||||
emit voidBackspace(e);
|
||||
} else {
|
||||
FlatInput::keyPressEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
void PhonePartInput::correctValue(const QString &was, QString &now) {
|
||||
QString newText;
|
||||
int oldPos(cursorPosition()), newPos(-1), oldLen(now.length()), digitCount = 0;
|
||||
for (int i = 0; i < oldLen; ++i) {
|
||||
if (now[i].isDigit()) {
|
||||
++digitCount;
|
||||
}
|
||||
}
|
||||
if (digitCount > MaxPhoneTailLength) digitCount = MaxPhoneTailLength;
|
||||
|
||||
bool inPart = !_pattern.isEmpty();
|
||||
int curPart = -1, leftInPart = 0;
|
||||
newText.reserve(oldLen);
|
||||
for (int i = 0; i < oldLen; ++i) {
|
||||
if (i == oldPos && newPos < 0) {
|
||||
newPos = newText.length();
|
||||
}
|
||||
|
||||
QChar ch(now[i]);
|
||||
if (ch.isDigit()) {
|
||||
if (!digitCount--) {
|
||||
break;
|
||||
}
|
||||
if (inPart) {
|
||||
if (leftInPart) {
|
||||
--leftInPart;
|
||||
} else {
|
||||
newText += ' ';
|
||||
++curPart;
|
||||
inPart = curPart < _pattern.size();
|
||||
leftInPart = inPart ? (_pattern.at(curPart) - 1) : 0;
|
||||
|
||||
++oldPos;
|
||||
}
|
||||
}
|
||||
newText += ch;
|
||||
} else if (ch == ' ' || ch == '-' || ch == '(' || ch == ')') {
|
||||
if (inPart) {
|
||||
if (leftInPart) {
|
||||
} else {
|
||||
newText += ch;
|
||||
++curPart;
|
||||
inPart = curPart < _pattern.size();
|
||||
leftInPart = inPart ? _pattern.at(curPart) : 0;
|
||||
}
|
||||
} else {
|
||||
newText += ch;
|
||||
}
|
||||
}
|
||||
}
|
||||
int32 newlen = newText.size();
|
||||
while (newlen > 0 && newText.at(newlen - 1).isSpace()) {
|
||||
--newlen;
|
||||
}
|
||||
if (newlen < newText.size()) newText = newText.mid(0, newlen);
|
||||
if (newPos < 0) {
|
||||
newPos = newText.length();
|
||||
}
|
||||
if (newText != now) {
|
||||
now = newText;
|
||||
setText(now);
|
||||
updatePlaceholder();
|
||||
setCursorPosition(newPos);
|
||||
}
|
||||
}
|
||||
|
||||
void PhonePartInput::addedToNumber(const QString &added) {
|
||||
setFocus();
|
||||
QString wasText(getLastText()), newText = added + wasText;
|
||||
setText(newText);
|
||||
setCursorPosition(added.length());
|
||||
correctValue(wasText, newText);
|
||||
updatePlaceholder();
|
||||
}
|
||||
|
||||
void PhonePartInput::onChooseCode(const QString &code) {
|
||||
_pattern = phoneNumberParse(code);
|
||||
if (!_pattern.isEmpty() && _pattern.at(0) == code.size()) {
|
||||
_pattern.pop_front();
|
||||
} else {
|
||||
_pattern.clear();
|
||||
}
|
||||
if (_pattern.isEmpty()) {
|
||||
setPlaceholder(lang(lng_phone_ph));
|
||||
} else {
|
||||
QString ph;
|
||||
ph.reserve(20);
|
||||
for (int i = 0, l = _pattern.size(); i < l; ++i) {
|
||||
ph.append(' ');
|
||||
ph.append(QString(_pattern.at(i), QChar(0x2212)));
|
||||
}
|
||||
setPlaceholder(ph);
|
||||
}
|
||||
auto newText = getLastText();
|
||||
correctValue(newText, newText);
|
||||
setPlaceholderFast(!_pattern.isEmpty());
|
||||
updatePlaceholder();
|
||||
}
|
||||
|
||||
InputArea::InputArea(QWidget *parent, const style::InputArea &st, const QString &ph, const QString &val) : TWidget(parent)
|
||||
, _maxLength(-1)
|
||||
, _inner(this)
|
||||
@@ -3533,6 +3340,23 @@ MaskedInputField::MaskedInputField(QWidget *parent, const style::InputField &st,
|
||||
updatePlaceholder();
|
||||
}
|
||||
|
||||
void MaskedInputField::setCorrectedText(QString &now, int &nowCursor, const QString &newText, int newPos) {
|
||||
if (newPos < 0 || newPos > newText.size()) {
|
||||
newPos = newText.size();
|
||||
}
|
||||
auto updateText = (newText != now);
|
||||
if (updateText) {
|
||||
now = newText;
|
||||
setText(now);
|
||||
updatePlaceholder();
|
||||
}
|
||||
auto updateCursorPosition = (newPos != nowCursor) || updateText;
|
||||
if (updateCursorPosition) {
|
||||
nowCursor = newPos;
|
||||
setCursorPosition(nowCursor);
|
||||
}
|
||||
}
|
||||
|
||||
void MaskedInputField::customUpDown(bool custom) {
|
||||
_customUpDown = custom;
|
||||
}
|
||||
@@ -3770,9 +3594,6 @@ QRect MaskedInputField::placeholderRect() const {
|
||||
return rect().marginsRemoved(_st.textMargins + _st.placeholderMargins);
|
||||
}
|
||||
|
||||
void MaskedInputField::correctValue(const QString &was, int32 wasCursor, QString &now, int32 &nowCursor) {
|
||||
}
|
||||
|
||||
void MaskedInputField::paintPlaceholder(Painter &p) {
|
||||
bool drawPlaceholder = _placeholderVisible;
|
||||
if (_a_placeholderShift.animating()) {
|
||||
@@ -3860,6 +3681,195 @@ void MaskedInputField::onCursorPositionChanged(int oldPosition, int position) {
|
||||
_oldcursor = position;
|
||||
}
|
||||
|
||||
CountryCodeInput::CountryCodeInput(QWidget *parent, const style::InputField &st) : MaskedInputField(parent, st)
|
||||
, _nosignal(false) {
|
||||
}
|
||||
|
||||
void CountryCodeInput::startErasing(QKeyEvent *e) {
|
||||
setFocus();
|
||||
keyPressEvent(e);
|
||||
}
|
||||
|
||||
void CountryCodeInput::codeSelected(const QString &code) {
|
||||
auto wasText = getLastText();
|
||||
auto wasCursor = cursorPosition();
|
||||
auto newText = '+' + code;
|
||||
auto newCursor = newText.size();
|
||||
setText(newText);
|
||||
_nosignal = true;
|
||||
correctValue(wasText, wasCursor, newText, newCursor);
|
||||
_nosignal = false;
|
||||
emit changed();
|
||||
}
|
||||
|
||||
void CountryCodeInput::correctValue(const QString &was, int32 wasCursor, QString &now, int32 &nowCursor) {
|
||||
QString newText, addToNumber;
|
||||
int oldPos(nowCursor), newPos(-1), oldLen(now.length()), start = 0, digits = 5;
|
||||
newText.reserve(oldLen + 1);
|
||||
if (oldLen && now[0] == '+') {
|
||||
if (start == oldPos) {
|
||||
newPos = newText.length();
|
||||
}
|
||||
++start;
|
||||
}
|
||||
newText += '+';
|
||||
for (int i = start; i < oldLen; ++i) {
|
||||
if (i == oldPos) {
|
||||
newPos = newText.length();
|
||||
}
|
||||
auto ch = now[i];
|
||||
if (ch.isDigit()) {
|
||||
if (!digits || !--digits) {
|
||||
addToNumber += ch;
|
||||
} else {
|
||||
newText += ch;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!addToNumber.isEmpty()) {
|
||||
auto validCode = findValidCode(newText.mid(1));
|
||||
addToNumber = newText.mid(1 + validCode.length()) + addToNumber;
|
||||
newText = '+' + validCode;
|
||||
}
|
||||
setCorrectedText(now, nowCursor, newText, newPos);
|
||||
|
||||
if (!_nosignal && was != newText) {
|
||||
emit codeChanged(newText.mid(1));
|
||||
}
|
||||
if (!addToNumber.isEmpty()) {
|
||||
emit addedToNumber(addToNumber);
|
||||
}
|
||||
}
|
||||
|
||||
PhonePartInput::PhonePartInput(QWidget *parent, const style::InputField &st) : MaskedInputField(parent, st, lang(lng_phone_ph)) {
|
||||
}
|
||||
|
||||
void PhonePartInput::paintPlaceholder(Painter &p) {
|
||||
auto t = getLastText();
|
||||
if (!_pattern.isEmpty() && !t.isEmpty()) {
|
||||
auto ph = placeholder().mid(t.size());
|
||||
if (!ph.isEmpty()) {
|
||||
p.setClipRect(rect());
|
||||
auto phRect = placeholderRect();
|
||||
int tw = phFont()->width(t);
|
||||
if (tw < phRect.width()) {
|
||||
phRect.setLeft(phRect.left() + tw);
|
||||
placeholderPreparePaint(p);
|
||||
p.drawText(phRect, ph, style::al_topleft);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
MaskedInputField::paintPlaceholder(p);
|
||||
}
|
||||
}
|
||||
|
||||
void PhonePartInput::keyPressEvent(QKeyEvent *e) {
|
||||
if (e->key() == Qt::Key_Backspace && getLastText().isEmpty()) {
|
||||
emit voidBackspace(e);
|
||||
} else {
|
||||
MaskedInputField::keyPressEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
void PhonePartInput::correctValue(const QString &was, int32 wasCursor, QString &now, int32 &nowCursor) {
|
||||
QString newText;
|
||||
int oldPos(nowCursor), newPos(-1), oldLen(now.length()), digitCount = 0;
|
||||
for (int i = 0; i < oldLen; ++i) {
|
||||
if (now[i].isDigit()) {
|
||||
++digitCount;
|
||||
}
|
||||
}
|
||||
if (digitCount > MaxPhoneTailLength) digitCount = MaxPhoneTailLength;
|
||||
|
||||
bool inPart = !_pattern.isEmpty();
|
||||
int curPart = -1, leftInPart = 0;
|
||||
newText.reserve(oldLen);
|
||||
for (int i = 0; i < oldLen; ++i) {
|
||||
if (i == oldPos && newPos < 0) {
|
||||
newPos = newText.length();
|
||||
}
|
||||
|
||||
auto ch = now[i];
|
||||
if (ch.isDigit()) {
|
||||
if (!digitCount--) {
|
||||
break;
|
||||
}
|
||||
if (inPart) {
|
||||
if (leftInPart) {
|
||||
--leftInPart;
|
||||
} else {
|
||||
newText += ' ';
|
||||
++curPart;
|
||||
inPart = curPart < _pattern.size();
|
||||
leftInPart = inPart ? (_pattern.at(curPart) - 1) : 0;
|
||||
|
||||
++oldPos;
|
||||
}
|
||||
}
|
||||
newText += ch;
|
||||
} else if (ch == ' ' || ch == '-' || ch == '(' || ch == ')') {
|
||||
if (inPart) {
|
||||
if (leftInPart) {
|
||||
} else {
|
||||
newText += ch;
|
||||
++curPart;
|
||||
inPart = curPart < _pattern.size();
|
||||
leftInPart = inPart ? _pattern.at(curPart) : 0;
|
||||
}
|
||||
} else {
|
||||
newText += ch;
|
||||
}
|
||||
}
|
||||
}
|
||||
auto newlen = newText.size();
|
||||
while (newlen > 0 && newText.at(newlen - 1).isSpace()) {
|
||||
--newlen;
|
||||
}
|
||||
if (newlen < newText.size()) {
|
||||
newText = newText.mid(0, newlen);
|
||||
}
|
||||
setCorrectedText(now, nowCursor, newText, newPos);
|
||||
}
|
||||
|
||||
void PhonePartInput::addedToNumber(const QString &added) {
|
||||
setFocus();
|
||||
auto wasText = getLastText();
|
||||
auto wasCursor = cursorPosition();
|
||||
auto newText = added + wasText;
|
||||
auto newCursor = newText.size();
|
||||
setText(newText);
|
||||
setCursorPosition(added.length());
|
||||
correctValue(wasText, wasCursor, newText, newCursor);
|
||||
updatePlaceholder();
|
||||
}
|
||||
|
||||
void PhonePartInput::onChooseCode(const QString &code) {
|
||||
_pattern = phoneNumberParse(code);
|
||||
if (!_pattern.isEmpty() && _pattern.at(0) == code.size()) {
|
||||
_pattern.pop_front();
|
||||
} else {
|
||||
_pattern.clear();
|
||||
}
|
||||
if (_pattern.isEmpty()) {
|
||||
setPlaceholder(lang(lng_phone_ph));
|
||||
} else {
|
||||
QString ph;
|
||||
ph.reserve(20);
|
||||
for (int i = 0, l = _pattern.size(); i < l; ++i) {
|
||||
ph.append(' ');
|
||||
ph.append(QString(_pattern.at(i), QChar(0x2212)));
|
||||
}
|
||||
setPlaceholder(ph);
|
||||
}
|
||||
auto wasText = getLastText();
|
||||
auto wasCursor = cursorPosition();
|
||||
auto newText = getLastText();
|
||||
auto newCursor = newText.size();
|
||||
correctValue(wasText, wasCursor, newText, newCursor);
|
||||
setPlaceholderFast(!_pattern.isEmpty());
|
||||
updatePlaceholder();
|
||||
}
|
||||
|
||||
PasswordInput::PasswordInput(QWidget *parent, const style::InputField &st, const QString &ph, const QString &val) : MaskedInputField(parent, st, ph, val) {
|
||||
setEchoMode(QLineEdit::Password);
|
||||
}
|
||||
@@ -3873,29 +3883,22 @@ PortInput::PortInput(QWidget *parent, const style::InputField &st, const QString
|
||||
void PortInput::correctValue(const QString &was, int32 wasCursor, QString &now, int32 &nowCursor) {
|
||||
QString newText;
|
||||
newText.reserve(now.size());
|
||||
int32 newCursor = nowCursor;
|
||||
for (int32 i = 0, l = now.size(); i < l; ++i) {
|
||||
auto newPos = nowCursor;
|
||||
for (auto i = 0, l = now.size(); i < l; ++i) {
|
||||
if (now.at(i).isDigit()) {
|
||||
newText.append(now.at(i));
|
||||
} else if (i < nowCursor) {
|
||||
--newCursor;
|
||||
--newPos;
|
||||
}
|
||||
}
|
||||
if (!newText.toInt()) {
|
||||
newText = QString();
|
||||
newCursor = 0;
|
||||
newPos = 0;
|
||||
} else if (newText.toInt() > 65535) {
|
||||
newText = was;
|
||||
newCursor = wasCursor;
|
||||
}
|
||||
if (newText != now) {
|
||||
now = newText;
|
||||
setText(newText);
|
||||
}
|
||||
if (newCursor != nowCursor) {
|
||||
nowCursor = newCursor;
|
||||
setCursorPosition(newCursor);
|
||||
newPos = wasCursor;
|
||||
}
|
||||
setCorrectedText(now, nowCursor, newText, newPos);
|
||||
}
|
||||
|
||||
UsernameInput::UsernameInput(QWidget *parent, const style::InputField &st, const QString &ph, const QString &val, bool isLink) : MaskedInputField(parent, st, ph, val),
|
||||
@@ -3916,13 +3919,13 @@ void UsernameInput::paintPlaceholder(Painter &p) {
|
||||
}
|
||||
|
||||
void UsernameInput::correctValue(const QString &was, int32 wasCursor, QString &now, int32 &nowCursor) {
|
||||
QString newText;
|
||||
int32 newCursor = nowCursor, from, len = now.size();
|
||||
for (from = 0; from < len; ++from) {
|
||||
auto newPos = nowCursor;
|
||||
auto from = 0, len = now.size();
|
||||
for (; from < len; ++from) {
|
||||
if (!now.at(from).isSpace()) {
|
||||
break;
|
||||
}
|
||||
if (newCursor > 0) --newCursor;
|
||||
if (newPos > 0) --newPos;
|
||||
}
|
||||
len -= from;
|
||||
if (len > MaxUsernameLength) len = MaxUsernameLength + (now.at(from) == '@' ? 1 : 0);
|
||||
@@ -3933,18 +3936,7 @@ void UsernameInput::correctValue(const QString &was, int32 wasCursor, QString &n
|
||||
}
|
||||
--len;
|
||||
}
|
||||
newText = now.mid(from, len);
|
||||
if (newCursor > len) {
|
||||
newCursor = len;
|
||||
}
|
||||
if (newText != now) {
|
||||
now = newText;
|
||||
setText(newText);
|
||||
}
|
||||
if (newCursor != nowCursor) {
|
||||
nowCursor = newCursor;
|
||||
setCursorPosition(newCursor);
|
||||
}
|
||||
setCorrectedText(now, nowCursor, now.mid(from, len), newPos);
|
||||
}
|
||||
|
||||
PhoneInput::PhoneInput(QWidget *parent, const style::InputField &st, const QString &ph, const QString &val) : MaskedInputField(parent, st, ph, val)
|
||||
@@ -3996,7 +3988,7 @@ void PhoneInput::paintPlaceholder(Painter &p) {
|
||||
}
|
||||
|
||||
void PhoneInput::correctValue(const QString &was, int32 wasCursor, QString &now, int32 &nowCursor) {
|
||||
QString digits(now);
|
||||
auto digits = now;
|
||||
digits.replace(QRegularExpression(qsl("[^\\d]")), QString());
|
||||
_pattern = phoneNumberParse(digits);
|
||||
|
||||
@@ -4075,16 +4067,10 @@ void PhoneInput::correctValue(const QString &was, int32 wasCursor, QString &now,
|
||||
while (newlen > 0 && newText.at(newlen - 1).isSpace()) {
|
||||
--newlen;
|
||||
}
|
||||
if (newlen < newText.size()) newText = newText.mid(0, newlen);
|
||||
if (newPos < 0) {
|
||||
newPos = newText.length();
|
||||
}
|
||||
if (newText != now) {
|
||||
now = newText;
|
||||
setText(newText);
|
||||
updatePlaceholder();
|
||||
setCursorPosition(newPos);
|
||||
if (newlen < newText.size()) {
|
||||
newText = newText.mid(0, newlen);
|
||||
}
|
||||
setCorrectedText(now, nowCursor, newText, newPos);
|
||||
}
|
||||
|
||||
} // namespace Ui
|
||||
|
@@ -114,7 +114,7 @@ public:
|
||||
};
|
||||
void setTagMimeProcessor(std_::unique_ptr<TagMimeProcessor> &&processor);
|
||||
|
||||
public slots:
|
||||
public slots:
|
||||
void onTouchTimer();
|
||||
|
||||
void onDocumentContentsChange(int position, int charsRemoved, int charsAdded);
|
||||
@@ -267,7 +267,7 @@ public:
|
||||
return _oldtext;
|
||||
}
|
||||
|
||||
public slots:
|
||||
public slots:
|
||||
void onTextChange(const QString &text);
|
||||
void onTextEdited();
|
||||
|
||||
@@ -330,52 +330,6 @@ private:
|
||||
QPoint _touchStart;
|
||||
};
|
||||
|
||||
class CountryCodeInput : public FlatInput {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CountryCodeInput(QWidget *parent, const style::FlatInput &st);
|
||||
|
||||
public slots:
|
||||
void startErasing(QKeyEvent *e);
|
||||
void codeSelected(const QString &code);
|
||||
|
||||
signals:
|
||||
void codeChanged(const QString &code);
|
||||
void addedToNumber(const QString &added);
|
||||
|
||||
protected:
|
||||
void correctValue(const QString &was, QString &now) override;
|
||||
|
||||
private:
|
||||
bool _nosignal;
|
||||
|
||||
};
|
||||
|
||||
class PhonePartInput : public FlatInput {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PhonePartInput(QWidget *parent, const style::FlatInput &st);
|
||||
|
||||
public slots:
|
||||
void addedToNumber(const QString &added);
|
||||
void onChooseCode(const QString &code);
|
||||
|
||||
signals:
|
||||
void voidBackspace(QKeyEvent *e);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
|
||||
void correctValue(const QString &was, QString &now) override;
|
||||
|
||||
private:
|
||||
QVector<int> _pattern;
|
||||
|
||||
};
|
||||
|
||||
enum CtrlEnterSubmit {
|
||||
CtrlEnterSubmitEnter,
|
||||
CtrlEnterSubmitCtrlEnter,
|
||||
@@ -439,7 +393,7 @@ public:
|
||||
_inner.clearFocus();
|
||||
}
|
||||
|
||||
public slots:
|
||||
public slots:
|
||||
void onTouchTimer();
|
||||
|
||||
void onDocumentContentsChange(int position, int charsRemoved, int charsAdded);
|
||||
@@ -610,7 +564,7 @@ public:
|
||||
_inner.setTextCursor(c);
|
||||
}
|
||||
|
||||
public slots:
|
||||
public slots:
|
||||
void onTouchTimer();
|
||||
|
||||
void onDocumentContentsChange(int position, int charsRemoved, int charsAdded);
|
||||
@@ -715,20 +669,11 @@ private:
|
||||
|
||||
class MaskedInputField : public QLineEdit {
|
||||
Q_OBJECT
|
||||
T_WIDGET
|
||||
T_WIDGET
|
||||
|
||||
public:
|
||||
MaskedInputField(QWidget *parent, const style::InputField &st, const QString &placeholder = QString(), const QString &val = QString());
|
||||
|
||||
bool event(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 contextMenuEvent(QContextMenuEvent *e) override;
|
||||
|
||||
void showError();
|
||||
|
||||
bool setPlaceholder(const QString &ph);
|
||||
@@ -757,7 +702,7 @@ public:
|
||||
updatePlaceholder();
|
||||
}
|
||||
|
||||
public slots:
|
||||
public slots:
|
||||
void onTextChange(const QString &text);
|
||||
void onCursorPositionChanged(int oldPosition, int position);
|
||||
|
||||
@@ -773,6 +718,15 @@ signals:
|
||||
void blurred();
|
||||
|
||||
protected:
|
||||
bool event(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 contextMenuEvent(QContextMenuEvent *e) override;
|
||||
|
||||
void enterEventHook(QEvent *e) {
|
||||
return QLineEdit::enterEvent(e);
|
||||
}
|
||||
@@ -780,7 +734,10 @@ protected:
|
||||
return QLineEdit::leaveEvent(e);
|
||||
}
|
||||
|
||||
virtual void correctValue(const QString &was, int32 wasCursor, QString &now, int32 &nowCursor);
|
||||
virtual void correctValue(const QString &was, int32 wasCursor, QString &now, int32 &nowCursor) {
|
||||
}
|
||||
void setCorrectedText(QString &now, int &nowCursor, const QString &newText, int newPos);
|
||||
|
||||
virtual void paintPlaceholder(Painter &p);
|
||||
|
||||
style::font phFont() {
|
||||
@@ -828,6 +785,52 @@ private:
|
||||
QPoint _touchStart;
|
||||
};
|
||||
|
||||
class CountryCodeInput : public MaskedInputField {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CountryCodeInput(QWidget *parent, const style::InputField &st);
|
||||
|
||||
public slots:
|
||||
void startErasing(QKeyEvent *e);
|
||||
void codeSelected(const QString &code);
|
||||
|
||||
signals:
|
||||
void codeChanged(const QString &code);
|
||||
void addedToNumber(const QString &added);
|
||||
|
||||
protected:
|
||||
void correctValue(const QString &was, int32 wasCursor, QString &now, int32 &nowCursor) override;
|
||||
|
||||
private:
|
||||
bool _nosignal;
|
||||
|
||||
};
|
||||
|
||||
class PhonePartInput : public MaskedInputField {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PhonePartInput(QWidget *parent, const style::InputField &st);
|
||||
|
||||
public slots:
|
||||
void addedToNumber(const QString &added);
|
||||
void onChooseCode(const QString &code);
|
||||
|
||||
signals:
|
||||
void voidBackspace(QKeyEvent *e);
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
|
||||
void correctValue(const QString &was, int32 wasCursor, QString &now, int32 &nowCursor) override;
|
||||
void paintPlaceholder(Painter &p) override;
|
||||
|
||||
private:
|
||||
QVector<int> _pattern;
|
||||
|
||||
};
|
||||
|
||||
class PasswordInput : public MaskedInputField {
|
||||
public:
|
||||
PasswordInput(QWidget *parent, const style::InputField &st, const QString &ph = QString(), const QString &val = QString());
|
||||
|
@@ -43,6 +43,57 @@ TextParseOptions _labelMarkedOptions = {
|
||||
|
||||
} // namespace
|
||||
|
||||
CrossFadeAnimation::CrossFadeAnimation(const style::color &bg) : _bg(bg) {
|
||||
}
|
||||
|
||||
void CrossFadeAnimation::addLine(Part was, Part now) {
|
||||
_lines.push_back(Line(std_::move(was), std_::move(now)));
|
||||
}
|
||||
|
||||
void CrossFadeAnimation::paintFrame(Painter &p, float64 positionReady, float64 alphaWas, float64 alphaNow) {
|
||||
if (_lines.isEmpty()) return;
|
||||
|
||||
for_const (auto &line, _lines) {
|
||||
paintLine(p, line, positionReady, alphaWas, alphaNow);
|
||||
}
|
||||
}
|
||||
|
||||
void CrossFadeAnimation::paintLine(Painter &p, const Line &line, float64 positionReady, float64 alphaWas, float64 alphaNow) {
|
||||
auto &snapshotWas = line.was.snapshot;
|
||||
auto &snapshotNow = line.now.snapshot;
|
||||
t_assert(!snapshotWas.isNull() || !snapshotNow.isNull());
|
||||
|
||||
auto positionWas = line.was.position;
|
||||
auto positionNow = line.now.position;
|
||||
auto left = anim::interpolate(positionWas.x(), positionNow.x(), positionReady);
|
||||
auto topDelta = (snapshotNow.height() / cIntRetinaFactor()) - (snapshotWas.height() / cIntRetinaFactor());
|
||||
auto widthDelta = (snapshotNow.width() / cIntRetinaFactor()) - (snapshotWas.width() / cIntRetinaFactor());
|
||||
auto topWas = anim::interpolate(positionWas.y(), positionNow.y() + topDelta, positionReady);
|
||||
auto topNow = topWas - topDelta;
|
||||
|
||||
p.setOpacity(alphaWas);
|
||||
if (!snapshotWas.isNull()) {
|
||||
p.drawPixmap(left, topWas, snapshotWas);
|
||||
if (topDelta > 0) {
|
||||
p.fillRect(left, topWas - topDelta, snapshotWas.width() / cIntRetinaFactor(), topDelta, _bg);
|
||||
}
|
||||
}
|
||||
if (widthDelta > 0) {
|
||||
p.fillRect(left + (snapshotWas.width() / cIntRetinaFactor()), topNow, widthDelta, snapshotNow.height() / cIntRetinaFactor(), _bg);
|
||||
}
|
||||
|
||||
p.setOpacity(alphaNow);
|
||||
if (!snapshotNow.isNull()) {
|
||||
p.drawPixmap(left, topNow, snapshotNow);
|
||||
if (topDelta < 0) {
|
||||
p.fillRect(left, topNow + topDelta, snapshotNow.width() / cIntRetinaFactor(), -topDelta, _bg);
|
||||
}
|
||||
}
|
||||
if (widthDelta < 0) {
|
||||
p.fillRect(left + (snapshotNow.width() / cIntRetinaFactor()), topWas, -widthDelta, snapshotWas.height() / cIntRetinaFactor(), _bg);
|
||||
}
|
||||
}
|
||||
|
||||
LabelSimple::LabelSimple(QWidget *parent, const style::LabelSimple &st, const QString &value) : TWidget(parent)
|
||||
, _st(st) {
|
||||
setText(value);
|
||||
@@ -548,6 +599,72 @@ void FlatLabel::clickHandlerPressedChanged(const ClickHandlerPtr &action, bool a
|
||||
update();
|
||||
}
|
||||
|
||||
std_::unique_ptr<CrossFadeAnimation> FlatLabel::CrossFade(FlatLabel *from, FlatLabel *to, const style::color &bg, QPoint fromPosition, QPoint toPosition) {
|
||||
auto result = std_::make_unique<CrossFadeAnimation>(bg);
|
||||
|
||||
struct Data {
|
||||
QImage full;
|
||||
QVector<int> lineWidths;
|
||||
int lineHeight = 0;
|
||||
int lineAddTop = 0;
|
||||
};
|
||||
auto prepareData = [&bg](FlatLabel *label) {
|
||||
auto result = Data();
|
||||
result.full = QImage(label->size() * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
|
||||
result.full.setDevicePixelRatio(cRetinaFactor());
|
||||
result.full.fill(bg->c);
|
||||
Painter(&result.full).drawImage(0, 0, myGrabImage(label));
|
||||
auto textWidth = label->width() - label->_st.margin.left() - label->_st.margin.right();
|
||||
label->_text.countLineWidths(textWidth, &result.lineWidths);
|
||||
result.lineHeight = label->_st.font->height;
|
||||
auto addedHeight = (label->_tst.lineHeight - result.lineHeight);
|
||||
if (addedHeight > 0) {
|
||||
result.lineAddTop = addedHeight / 2;
|
||||
result.lineHeight += addedHeight;
|
||||
}
|
||||
return std_::move(result);
|
||||
};
|
||||
auto was = prepareData(from);
|
||||
auto now = prepareData(to);
|
||||
|
||||
auto maxLines = qMax(was.lineWidths.size(), now.lineWidths.size());
|
||||
auto fillDataTill = [maxLines](Data &data) {
|
||||
for (auto i = data.lineWidths.size(); i != maxLines; ++i) {
|
||||
data.lineWidths.push_back(-1);
|
||||
}
|
||||
};
|
||||
fillDataTill(was);
|
||||
fillDataTill(now);
|
||||
auto preparePart = [](FlatLabel *label, QPoint position, Data &data, int index, Data &other) {
|
||||
auto result = CrossFadeAnimation::Part();
|
||||
auto lineWidth = data.lineWidths[index];
|
||||
if (lineWidth < 0) {
|
||||
lineWidth = other.lineWidths[index];
|
||||
}
|
||||
auto fullWidth = data.full.width() / cIntRetinaFactor();
|
||||
auto top = index * data.lineHeight + data.lineAddTop;
|
||||
auto left = 0;
|
||||
if (label->_st.align & Qt::AlignHCenter) {
|
||||
left += (fullWidth - lineWidth) / 2;
|
||||
} else if (label->_st.align & Qt::AlignRight) {
|
||||
left += (fullWidth - lineWidth);
|
||||
}
|
||||
auto snapshotRect = data.full.rect().intersected(QRect(left * cIntRetinaFactor(), top * cIntRetinaFactor(), lineWidth * cIntRetinaFactor(), label->_st.font->height * cIntRetinaFactor()));
|
||||
if (!snapshotRect.isEmpty()) {
|
||||
result.snapshot = App::pixmapFromImageInPlace(data.full.copy(snapshotRect));
|
||||
result.snapshot.setDevicePixelRatio(cRetinaFactor());
|
||||
}
|
||||
auto positionBase = position + label->pos();
|
||||
result.position = positionBase + QPoint(label->_st.margin.left() + left, label->_st.margin.top() + top);
|
||||
return std_::move(result);
|
||||
};
|
||||
for (int i = 0; i != maxLines; ++i) {
|
||||
result->addLine(preparePart(from, fromPosition, was, i, now), preparePart(to, toPosition, now, i, was));
|
||||
}
|
||||
|
||||
return std_::move(result);
|
||||
}
|
||||
|
||||
Text::StateResult FlatLabel::dragActionUpdate() {
|
||||
auto m = mapFromGlobal(_lastMousePos);
|
||||
auto state = getTextState(m);
|
||||
|
@@ -26,6 +26,37 @@ namespace Ui {
|
||||
|
||||
class PopupMenu;
|
||||
|
||||
class CrossFadeAnimation {
|
||||
public:
|
||||
CrossFadeAnimation(const style::color &bg);
|
||||
|
||||
struct Part {
|
||||
QPixmap snapshot;
|
||||
QPoint position;
|
||||
};
|
||||
void addLine(Part was, Part now);
|
||||
|
||||
void paintFrame(Painter &p, float64 dt) {
|
||||
auto progress = anim::linear(1., dt);
|
||||
paintFrame(p, progress, 1. - progress, progress);
|
||||
}
|
||||
|
||||
void paintFrame(Painter &p, float64 positionReady, float64 alphaWas, float64 alphaNow);
|
||||
|
||||
private:
|
||||
struct Line {
|
||||
Line(Part was, Part now) : was(std_::move(was)), now(std_::move(now)) {
|
||||
}
|
||||
Part was;
|
||||
Part now;
|
||||
};
|
||||
void paintLine(Painter &p, const Line &line, float64 positionReady, float64 alphaWas, float64 alphaNow);
|
||||
|
||||
const style::color &_bg;
|
||||
QList<Line> _lines;
|
||||
|
||||
};
|
||||
|
||||
class LabelSimple : public TWidget {
|
||||
public:
|
||||
LabelSimple(QWidget *parent, const style::LabelSimple &st = st::defaultLabelSimple, const QString &value = QString());
|
||||
@@ -81,6 +112,8 @@ public:
|
||||
void clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) override;
|
||||
void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) override;
|
||||
|
||||
static std_::unique_ptr<CrossFadeAnimation> CrossFade(FlatLabel *from, FlatLabel *to, const style::color &bg, QPoint fromPosition = QPoint(), QPoint toPosition = QPoint());
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void mouseMoveEvent(QMouseEvent *e) override;
|
||||
|
@@ -160,7 +160,7 @@ private:
|
||||
class SplittedWidgetOther;
|
||||
class ScrollArea : public QScrollArea {
|
||||
Q_OBJECT
|
||||
T_WIDGET
|
||||
T_WIDGET
|
||||
|
||||
public:
|
||||
ScrollArea(QWidget *parent, const style::FlatScroll &st = st::defaultFlatScroll, bool handleTouch = true);
|
||||
|
Reference in New Issue
Block a user