2
0
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:
John Preston
2016-11-24 22:28:23 +03:00
parent 6e0394dd42
commit 3da0533339
71 changed files with 2150 additions and 1776 deletions

View File

@@ -255,6 +255,7 @@ void RoundButton::updateText() {
_secondaryTextWidth = _secondaryText.isEmpty() ? 0 : _st.font->width(_secondaryText);
resizeToText();
update();
}
void RoundButton::resizeToText() {

View File

@@ -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

View File

@@ -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());

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);