2
0
mirror of https://github.com/kotatogram/kotatogram-desktop synced 2025-08-31 06:35:14 +00:00

Closed beta 10019014: New input fields design and animations.

This commit is contained in:
John Preston
2016-12-09 21:56:01 +03:00
parent 2d48cde27a
commit 90234cb7a0
51 changed files with 1068 additions and 940 deletions

View File

@@ -95,7 +95,16 @@ CountryInput::CountryInput(QWidget *parent, const style::InputField &st) : TWidg
, _st(st)
, _text(lang(lng_country_code)) {
initCountries();
resize(_st.width, _st.height);
resize(_st.width, _st.heightMin);
auto availableWidth = width() - _st.textMargins.left() - _st.textMargins.right() - _st.placeholderMargins.left() - _st.placeholderMargins.right() - 1;
auto placeholderFont = _st.placeholderFont->f;
placeholderFont.setStyleStrategy(QFont::PreferMatch);
auto metrics = QFontMetrics(placeholderFont);
auto placeholder = QString();// metrics.elidedText(lang(lng_country_fake_ph), Qt::ElideRight, availableWidth);
if (!placeholder.isNull()) {
_placeholderPath.addText(0, QFontMetrics(placeholderFont).ascent(), placeholderFont, placeholder);
}
}
void CountryInput::paintEvent(QPaintEvent *e) {
@@ -106,7 +115,7 @@ void CountryInput::paintEvent(QPaintEvent *e) {
p.fillRect(r, _st.textBg);
}
if (_st.border) {
p.fillRect(0, height() - _st.border, width(), _st.border, _st.borderFg->b);
p.fillRect(0, height() - _st.border, width(), _st.border, _st.borderFg);
}
st::introCountryIcon.paint(p, width() - st::introCountryIcon.width() - st::introCountryIconPosition.x(), st::introCountryIconPosition.y(), width());
@@ -114,6 +123,30 @@ void CountryInput::paintEvent(QPaintEvent *e) {
p.setFont(_st.font);
p.setPen(_st.textFg);
p.drawText(rect().marginsRemoved(_st.textMargins), _text, _st.textAlign);
if (!_placeholderPath.isEmpty()) {
auto placeholderShiftDegree = 1.;
p.save();
p.setClipRect(r);
auto placeholderTop = anim::interpolate(0, _st.placeholderShift, placeholderShiftDegree);
QRect r(rect().marginsRemoved(_st.textMargins + _st.placeholderMargins));
r.moveTop(r.top() + placeholderTop);
if (rtl()) r.moveLeft(width() - r.left() - r.width());
auto placeholderScale = 1. - (1. - _st.placeholderScale) * placeholderShiftDegree;
auto placeholderFg = anim::color(_st.placeholderFg, _st.placeholderFgActive, 0.);
placeholderFg = anim::color(placeholderFg, _st.placeholderFgError, 0.);
PainterHighQualityEnabler hq(p);
p.setPen(Qt::NoPen);
p.setBrush(placeholderFg);
p.translate(r.topLeft());
p.scale(placeholderScale, placeholderScale);
p.drawPath(_placeholderPath);
p.restore();
}
}
void CountryInput::mouseMoveEvent(QMouseEvent *e) {

View File

@@ -56,6 +56,7 @@ private:
const style::InputField &_st;
bool _active = false;
QString _text;
QPainterPath _placeholderPath;
};

View File

@@ -29,7 +29,8 @@ FadeAnimation::FadeAnimation(TWidget *widget) : _widget(widget) {
bool FadeAnimation::paint(Painter &p) {
if (_cache.isNull()) return false;
p.setOpacity(_animation.current(getms(), _visible ? 1. : 0.));
auto opacity = _animation.current(getms(), _visible ? 1. : 0.);
p.setOpacity(opacity);
p.drawPixmap(0, 0, _cache);
return true;
}
@@ -64,7 +65,9 @@ void FadeAnimation::stopAnimation() {
if (!_cache.isNull()) {
_cache = QPixmap();
updateCallback();
_widget->showChildren();
if (_visible) {
_widget->showChildren();
}
if (_finishedCallback) {
_finishedCallback();
}

File diff suppressed because it is too large Load Diff

View File

@@ -247,8 +247,6 @@ class FlatInput : public QLineEdit {
public:
FlatInput(QWidget *parent, const style::FlatInput &st, const QString &ph = QString(), const QString &val = QString());
void setPlaceholder(const QString &ph);
void setPlaceholderFast(bool fast);
void updatePlaceholder();
const QString &placeholder() const;
QRect placeholderRect() const;
@@ -309,7 +307,6 @@ private:
void updatePlaceholderText();
QString _oldtext, _ph, _fullph;
bool _fastph = false;
bool _customUpDown = false;
@@ -324,17 +321,17 @@ private:
QPoint _touchStart;
};
enum CtrlEnterSubmit {
CtrlEnterSubmitEnter,
CtrlEnterSubmitCtrlEnter,
CtrlEnterSubmitBoth,
enum class CtrlEnterSubmit {
Enter,
CtrlEnter,
Both,
};
class InputArea : public TWidget {
Q_OBJECT
public:
InputArea(QWidget *parent, const style::InputArea &st, const QString &ph = QString(), const QString &val = QString());
InputArea(QWidget *parent, const style::InputField &st, const QString &ph = QString(), const QString &val = QString());
void showError();
@@ -345,9 +342,7 @@ public:
const QString &getLastText() const {
return _oldtext;
}
void updatePlaceholder();
void step_border(float64 ms, bool timer);
void finishAnimations();
QSize sizeHint() const override;
QSize minimumSizeHint() const override;
@@ -362,30 +357,30 @@ public:
void setCtrlEnterSubmit(CtrlEnterSubmit ctrlEnterSubmit);
void setTextCursor(const QTextCursor &cursor) {
return _inner.setTextCursor(cursor);
return _inner->setTextCursor(cursor);
}
QTextCursor textCursor() const {
return _inner.textCursor();
return _inner->textCursor();
}
void setText(const QString &text) {
_inner.setText(text);
updatePlaceholder();
_inner->setText(text);
startPlaceholderAnimation();
}
void clear() {
_inner.clear();
updatePlaceholder();
_inner->clear();
startPlaceholderAnimation();
}
bool hasFocus() const {
return _inner.hasFocus();
return _inner->hasFocus();
}
void setFocus() {
_inner.setFocus();
_inner->setFocus();
}
void clearFocus() {
_inner.clearFocus();
_inner->clearFocus();
}
public slots:
private slots:
void onTouchTimer();
void onDocumentContentsChange(int position, int charsRemoved, int charsAdded);
@@ -394,6 +389,8 @@ public slots:
void onUndoAvailable(bool avail);
void onRedoAvailable(bool avail);
void onFocusInner();
signals:
void changed();
void submitted(bool ctrlShiftEnter);
@@ -405,6 +402,9 @@ signals:
void resized();
protected:
void startPlaceholderAnimation();
void startBorderAnimation();
void insertEmoji(EmojiPtr emoji, QTextCursor c);
TWidget *tparent() {
return qobject_cast<TWidget*>(parentWidget());
@@ -421,10 +421,6 @@ protected:
void resizeEvent(QResizeEvent *e) override;
private:
int32 _maxLength;
bool heightAutoupdated();
void checkContentHeight();
class Inner : public QTextEdit {
public:
Inner(InputArea *parent);
@@ -436,7 +432,6 @@ private:
void focusInEvent(QFocusEvent *e) override;
void focusOutEvent(QFocusEvent *e) override;
void keyPressEvent(QKeyEvent *e) override;
void paintEvent(QPaintEvent *e) override;
void contextMenuEvent(QContextMenuEvent *e) override;
QMimeData *createMimeDataFromSelection() const override;
@@ -450,41 +445,55 @@ private:
};
friend class Inner;
void focusInInner();
bool heightAutoupdated();
void checkContentHeight();
void createPlaceholderPath();
void setErrorShown(bool error);
void focusInInner(bool focusByMouse);
void focusOutInner();
void processDocumentContentsChange(int position, int charsAdded);
void startBorderAnimation();
const style::InputField &_st;
Inner _inner;
int _maxLength = -1;
ChildWidget<Inner> _inner;
QString _oldtext;
CtrlEnterSubmit _ctrlEnterSubmit;
bool _undoAvailable, _redoAvailable, _inHeightCheck;
CtrlEnterSubmit _ctrlEnterSubmit = CtrlEnterSubmit::CtrlEnter;
bool _undoAvailable = false;
bool _redoAvailable = false;
bool _inHeightCheck = false;
bool _customUpDown;
bool _customUpDown = false;
QString _placeholder, _placeholderFull;
bool _placeholderVisible;
Animation _a_placeholderFocused;
Animation _a_placeholderVisible;
QString _placeholder;
QString _placeholderFull;
Animation _a_placeholderShifted;
bool _placeholderShifted = false;
QPainterPath _placeholderPath;
anim::value a_borderOpacityActive;
anim::value a_borderFgActive;
anim::value a_borderFgError;
BasicAnimation _a_border;
Animation _a_borderShown;
int _borderAnimationStart = 0;
Animation _a_borderOpacity;
bool _borderVisible = false;
bool _focused, _error;
Animation _a_focused;
Animation _a_error;
const style::InputArea &_st;
bool _focused = false;
bool _error = false;
QTimer _touchTimer;
bool _touchPress, _touchRightButton, _touchMove;
bool _touchPress = false;
bool _touchRightButton = false;
bool _touchMove = false;
QPoint _touchStart;
bool _correcting;
bool _correcting = false;
};
@@ -503,11 +512,8 @@ public:
const QString &getLastText() const {
return _oldtext;
}
void updatePlaceholder();
void setPlaceholderHidden(bool forcePlaceholderHidden);
void finishPlaceholderAnimation();
void step_border(float64 ms, bool timer);
void finishAnimations();
QSize sizeHint() const override;
QSize minimumSizeHint() const override;
@@ -521,38 +527,41 @@ public:
void customUpDown(bool isCustom);
void setTextCursor(const QTextCursor &cursor) {
return _inner.setTextCursor(cursor);
return _inner->setTextCursor(cursor);
}
QTextCursor textCursor() const {
return _inner.textCursor();
return _inner->textCursor();
}
void setText(const QString &text) {
_inner.setText(text);
updatePlaceholder();
_inner->setText(text);
startPlaceholderAnimation();
}
void clear() {
_inner.clear();
updatePlaceholder();
_inner->clear();
startPlaceholderAnimation();
}
bool hasFocus() const {
return _inner.hasFocus();
return _inner->hasFocus();
}
void setFocus() {
_inner.setFocus();
QTextCursor c(_inner.textCursor());
c.movePosition(QTextCursor::End);
_inner.setTextCursor(c);
_inner->setFocus();
auto cursor = _inner->textCursor();
cursor.movePosition(QTextCursor::End);
_inner->setTextCursor(cursor);
}
void clearFocus() {
_inner.clearFocus();
_inner->clearFocus();
}
void setCursorPosition(int pos) {
QTextCursor c(_inner.textCursor());
c.setPosition(pos);
_inner.setTextCursor(c);
auto cursor = _inner->textCursor();
cursor.setPosition(pos);
_inner->setTextCursor(cursor);
}
public slots:
void selectAll();
private slots:
void onTouchTimer();
void onDocumentContentsChange(int position, int charsRemoved, int charsAdded);
@@ -561,7 +570,7 @@ public slots:
void onUndoAvailable(bool avail);
void onRedoAvailable(bool avail);
void selectAll();
void onFocusInner();
signals:
void changed();
@@ -573,6 +582,9 @@ signals:
void blurred();
protected:
void startPlaceholderAnimation();
void startBorderAnimation();
void insertEmoji(EmojiPtr emoji, QTextCursor c);
TWidget *tparent() {
return qobject_cast<TWidget*>(parentWidget());
@@ -589,9 +601,6 @@ protected:
void resizeEvent(QResizeEvent *e) override;
private:
int32 _maxLength;
bool _forcePlaceholderHidden = false;
class Inner : public QTextEdit {
public:
Inner(InputField *parent);
@@ -603,7 +612,6 @@ private:
void focusInEvent(QFocusEvent *e) override;
void focusOutEvent(QFocusEvent *e) override;
void keyPressEvent(QKeyEvent *e) override;
void paintEvent(QPaintEvent *e) override;
void contextMenuEvent(QContextMenuEvent *e) override;
QMimeData *createMimeDataFromSelection() const override;
@@ -617,40 +625,52 @@ private:
};
friend class Inner;
void focusInInner();
void createPlaceholderPath();
void setErrorShown(bool error);
void focusInInner(bool focusByMouse);
void focusOutInner();
void processDocumentContentsChange(int position, int charsAdded);
void startBorderAnimation();
const style::InputField &_st;
Inner _inner;
int _maxLength = -1;
bool _forcePlaceholderHidden = false;
ChildWidget<Inner> _inner;
QString _oldtext;
bool _undoAvailable, _redoAvailable;
bool _undoAvailable = false;
bool _redoAvailable = false;
bool _customUpDown;
bool _customUpDown = true;
QString _placeholder, _placeholderFull;
bool _placeholderVisible;
Animation _a_placeholderFocused;
Animation _a_placeholderVisible;
QString _placeholder;
QString _placeholderFull;
Animation _a_placeholderShifted;
bool _placeholderShifted = false;
QPainterPath _placeholderPath;
anim::value a_borderOpacityActive;
anim::value a_borderFgActive;
anim::value a_borderFgError;
BasicAnimation _a_border;
Animation _a_borderShown;
int _borderAnimationStart = 0;
Animation _a_borderOpacity;
bool _borderVisible = false;
bool _focused, _error;
Animation _a_focused;
Animation _a_error;
const style::InputField &_st;
bool _focused = false;
bool _error = false;
QTimer _touchTimer;
bool _touchPress, _touchRightButton, _touchMove;
bool _touchPress = false;
bool _touchRightButton = false;
bool _touchMove = false;
QPoint _touchStart;
bool _correcting;
bool _correcting = false;
};
class MaskedInputField : public QLineEdit {
@@ -662,14 +682,8 @@ public:
void showError();
bool setPlaceholder(const QString &ph);
void setPlaceholderFast(bool fast);
void updatePlaceholder();
QRect getTextRect() const;
void step_border(float64 ms, bool timer);
QSize sizeHint() const override;
QSize minimumSizeHint() const override;
@@ -677,13 +691,16 @@ public:
const QString &getLastText() const {
return _oldtext;
}
void setPlaceholderHidden(bool forcePlaceholderHidden);
void finishAnimations();
void setText(const QString &text) {
QLineEdit::setText(text);
updatePlaceholder();
startPlaceholderAnimation();
}
void clear() {
QLineEdit::clear();
updatePlaceholder();
startPlaceholderAnimation();
}
QMargins getMargins() const {
@@ -706,6 +723,9 @@ signals:
void blurred();
protected:
void startBorderAnimation();
void startPlaceholderAnimation();
bool event(QEvent *e) override;
void touchEvent(QTouchEvent *e);
void paintEvent(QPaintEvent *e) override;
@@ -726,13 +746,14 @@ protected:
}
void setCorrectedText(QString &now, int &nowCursor, const QString &newText, int newPos);
virtual void paintPlaceholder(Painter &p, TimeMs ms);
virtual void paintAdditionalPlaceholder(Painter &p, TimeMs ms) {
}
style::font phFont() {
return _st.font;
}
void placeholderPreparePaint(Painter &p, TimeMs ms);
void placeholderAdditionalPrepare(Painter &p, TimeMs ms);
const QString &placeholder() const;
QRect placeholderRect() const;
@@ -740,34 +761,43 @@ protected:
const style::InputField &_st;
private:
void startBorderAnimation();
void updatePlaceholderText();
void createPlaceholderPath();
void setErrorShown(bool error);
int32 _maxLength;
int _maxLength = -1;
bool _forcePlaceholderHidden = false;
QString _oldtext;
int32 _oldcursor;
int _oldcursor = 0;
bool _undoAvailable, _redoAvailable;
bool _undoAvailable = false;
bool _redoAvailable = false;
bool _customUpDown;
bool _customUpDown = false;
QString _placeholder, _placeholderFull;
bool _placeholderVisible, _placeholderFast;
Animation _a_placeholderFocused;
Animation _a_placeholderVisible;
QString _placeholder;
QString _placeholderFull;
Animation _a_placeholderShifted;
bool _placeholderShifted = false;
QPainterPath _placeholderPath;
anim::value a_borderOpacityActive;
anim::value a_borderFgActive;
anim::value a_borderFgError;
BasicAnimation _a_border;
Animation _a_borderShown;
int _borderAnimationStart = 0;
Animation _a_borderOpacity;
bool _borderVisible = false;
bool _focused, _error;
Animation _a_focused;
Animation _a_error;
bool _focused = false;
bool _error = false;
style::margins _textMargins;
QTimer _touchTimer;
bool _touchPress, _touchRightButton, _touchMove;
bool _touchPress = false;
bool _touchRightButton = false;
bool _touchMove = false;
QPoint _touchStart;
};
@@ -810,10 +840,11 @@ protected:
void keyPressEvent(QKeyEvent *e) override;
void correctValue(const QString &was, int32 wasCursor, QString &now, int32 &nowCursor) override;
void paintPlaceholder(Painter &p, TimeMs ms) override;
void paintAdditionalPlaceholder(Painter &p, TimeMs ms) override;
private:
QVector<int> _pattern;
QString _additionalPlaceholder;
};
@@ -838,7 +869,7 @@ public:
protected:
void correctValue(const QString &was, int32 wasCursor, QString &now, int32 &nowCursor) override;
void paintPlaceholder(Painter &p, TimeMs ms) override;
void paintAdditionalPlaceholder(Painter &p, TimeMs ms) override;
private:
QString _linkPlaceholder;
@@ -855,11 +886,11 @@ protected:
void focusInEvent(QFocusEvent *e) override;
void correctValue(const QString &was, int32 wasCursor, QString &now, int32 &nowCursor) override;
void paintPlaceholder(Painter &p, TimeMs ms) override;
void paintAdditionalPlaceholder(Painter &p, TimeMs ms) override;
private:
QString _defaultPlaceholder;
QVector<int> _pattern;
QString _additionalPlaceholder;
};

View File

@@ -700,7 +700,7 @@ void MultiSelect::Inner::addItem(std_::unique_ptr<Item> item, AddItemWay way) {
if (way != AddItemWay::SkipAnimation) {
_items.back()->showAnimated();
} else {
_field->finishPlaceholderAnimation();
_field->finishAnimations();
finishHeightAnimation();
}
}

View File

@@ -181,16 +181,20 @@ FlatInput {
phDuration: int;
}
InputArea {
InputField {
textBg: color;
textFg: color;
textMargins: margins;
textAlign: align;
placeholderFg: color;
placeholderFgActive: color;
placeholderFgError: color;
placeholderMargins: margins;
placeholderAlign: align;
placeholderScale: double;
placeholderShift: pixels;
placeholderFont: font;
duration: int;
@@ -209,34 +213,6 @@ InputArea {
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;
@@ -602,44 +578,21 @@ attentionLeftOutlineButton: OutlineButton(defaultLeftOutlineButton) {
}
}
defaultInputArea: InputArea {
textBg: windowBg;
textFg: windowFg;
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: activeLineFg;
borderFgError: #e48383;
border: 1px;
borderActive: 2px;
borderError: 2px;
font: boxTextFont;
heightMin: 32px;
heightMax: 128px;
}
defaultInputField: InputField {
textBg: windowBg;
textFg: windowFg;
textMargins: margins(0px, 6px, 0px, 4px);
textMargins: margins(0px, 26px, 0px, 4px);
textAlign: align(topleft);
placeholderFg: #999999;
placeholderFgActive: #aaaaaa;
placeholderMargins: margins(2px, 0px, 2px, 0px);
placeholderFg: windowSubTextFg;
placeholderFgActive: windowActiveTextFg;
placeholderFgError: attentionButtonFg;
placeholderMargins: margins(0px, 0px, 0px, 0px);
placeholderAlign: align(topleft);
placeholderShift: 50px;
duration: 120;
placeholderScale: 0.9;
placeholderShift: -20px;
placeholderFont: font(semibold 14px);
duration: 150;
borderFg: #e0e0e0;
borderFgActive: activeLineFg;
@@ -651,7 +604,8 @@ defaultInputField: InputField {
font: boxTextFont;
height: 32px;
heightMin: 52px;
heightMax: 148px;
}
defaultCheckboxIcon: icon {{ "default_checkbox_check", windowFgActive, point(4px, 7px) }};
@@ -909,3 +863,10 @@ MediaPlayerButton {
rippleAreaSize: pixels;
ripple: RippleAnimation;
}
ProfilePeerListItem {
button: OutlineButton;
statusFg: color;
statusFgOver: color;
statusFgActive: color;
}