moved countrycodeinput to flatinput, started InputField with bottom border
This commit is contained in:
		
							parent
							
								
									ea4186eb0c
								
							
						
					
					
						commit
						a5c81cfd3b
					
				
					 9 changed files with 528 additions and 183 deletions
				
			
		|  | @ -19,6 +19,7 @@ defaultFontFamily: 'Open Sans'; | |||
| semibold: 'Open Sans Semibold'; | ||||
| 
 | ||||
| fsize: 13px; | ||||
| normalFont: font(fsize); | ||||
| 
 | ||||
| spriteFile: ':/gui/art/sprite.png' / 2:':/gui/art/sprite_125x.png' / 3:':/gui/art/sprite_150x.png' / 4:':/gui/art/sprite_200x.png'; | ||||
| emojiImgSize: 18px; // exceptional value for retina | ||||
|  | @ -32,9 +33,9 @@ counterMacInvColor: #ffffff01; | |||
| 
 | ||||
| lineWidth: 1px; | ||||
| 
 | ||||
| transparent: rgba(255, 255, 255, 0); | ||||
| white: rgba(255, 255, 255, 255); | ||||
| black: rgba(0, 0, 0, 255); | ||||
| transparent: #fff0; | ||||
| white: #fff; | ||||
| black: #000; | ||||
| 
 | ||||
| color1: #c03d33; // red | ||||
| color2: #4fad2d; // green | ||||
|  | @ -50,12 +51,37 @@ wideModeWidth: 640px; | |||
| wndMinHeight: 480px; | ||||
| wndDefWidth: 800px; | ||||
| wndDefHeight: 600px; | ||||
| wndBG: #FFF; | ||||
| wndBG: white; | ||||
| wndShadow: sprite(209px, 46px, 19px, 19px); | ||||
| wndShadowShift: 1px; | ||||
| 
 | ||||
| layerAlpha: 0.5; | ||||
| layerBG: #000; | ||||
| layerBG: black; | ||||
| 
 | ||||
| defaultInputField: InputField { | ||||
| 	textFg: black; | ||||
| 	textMargins: margins(5px, 5px, 5px, 5px); | ||||
| 	textAlign: align(left); | ||||
| 
 | ||||
| 	placeholderFg: #999; | ||||
| 	placeholderFgActive: #aaa; | ||||
| 	placeholderMargins: margins(2px, 0px, 2px, 0px); | ||||
| 	placeholderAlign: align(left); | ||||
| 	placeholderShift: 50px; | ||||
| 	duration: 200; | ||||
| 
 | ||||
| 	borderFg: #e0e0e0; | ||||
| 	borderFgActive: #62c0f7; | ||||
| 	borderFgError: #e48383; | ||||
| 
 | ||||
| 	border: 1px; | ||||
| 	borderActive: 2px; | ||||
| 	borderError: 2px; | ||||
| 
 | ||||
| 	font: normalFont; | ||||
| 
 | ||||
| 	height: 32px; | ||||
| } | ||||
| 
 | ||||
| titleBG: #6389a8; | ||||
| titleColor: #0f8dcc;//rgb(20, 136, 210); | ||||
|  | @ -200,7 +226,7 @@ btnDefBack: flatButton(btnDefFlat) { | |||
| } | ||||
| 
 | ||||
| linkCropLimit: 360px; | ||||
| linkFont: font(fsize); | ||||
| linkFont: normalFont; | ||||
| linkOverFont: font(fsize underline); | ||||
| btnDefLink: linkButton { | ||||
| 	color: btnYesColor; | ||||
|  |  | |||
|  | @ -267,3 +267,33 @@ botKeyboardButton { | |||
| 	textTop: number; | ||||
| 	downTextTop: number; | ||||
| } | ||||
| 
 | ||||
| InputField { | ||||
| 	textFg: color; | ||||
| 	textMargins: margins; | ||||
| 	textAlign: align; | ||||
| 
 | ||||
| 	placeholderFg: color; | ||||
| 	placeholderFgActive: color; | ||||
| 	placeholderMargins: margins; | ||||
| 	placeholderAlign: align; | ||||
| 	placeholderShift: number; | ||||
| 
 | ||||
| 	duration: number; | ||||
| 
 | ||||
| 	borderFg: color; | ||||
| 	borderFgActive: color; | ||||
| 	borderFgError: color; | ||||
| 
 | ||||
| 	border: number; | ||||
| 	borderActive: number; | ||||
| 	borderError: number; | ||||
| 
 | ||||
| 	font: font; | ||||
| 
 | ||||
| 	width: number; | ||||
| 	height: number; | ||||
| 
 | ||||
| 	iconSprite: sprite; | ||||
| 	iconPosition: point; | ||||
| } | ||||
|  |  | |||
|  | @ -1,83 +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. | ||||
| 
 | ||||
| Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
 | ||||
| Copyright (c) 2014 John Preston, https://desktop.telegram.org
 | ||||
| */ | ||||
| #include "stdafx.h" | ||||
| #include "style.h" | ||||
| 
 | ||||
| #include "gui/countrycodeinput.h" | ||||
| #include "gui/countryinput.h" | ||||
| 
 | ||||
| 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 old(text()); | ||||
| 	setText('+' + code); | ||||
| 	_nosignal = true; | ||||
| 	correctValue(0, old); | ||||
| 	_nosignal = false; | ||||
| 	emit changed(); | ||||
| } | ||||
| 
 | ||||
| void CountryCodeInput::correctValue(QKeyEvent *e, const QString &was) { | ||||
| 	QString oldText(text()), newText, addToNumber; | ||||
| 	int oldPos(cursorPosition()), newPos(-1), oldLen(oldText.length()), start = 0, digits = 5; | ||||
| 	newText.reserve(oldLen + 1); | ||||
| 	newText += '+'; | ||||
| 	if (oldLen && oldText[0] == '+') { | ||||
| 		++start; | ||||
| 	} | ||||
| 	for (int i = start; i < oldLen; ++i) { | ||||
| 		QChar ch(oldText[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 != oldText) { | ||||
| 		setText(newText); | ||||
| 		if (newPos != oldPos) { | ||||
| 			setCursorPosition(newPos); | ||||
| 		} | ||||
| 	} | ||||
| 	if (!_nosignal && was != newText) { | ||||
| 		emit codeChanged(newText.mid(1)); | ||||
| 	} | ||||
| 	if (!addToNumber.isEmpty()) { | ||||
| 		emit addedToNumber(addToNumber); | ||||
| 	} | ||||
| } | ||||
|  | @ -1,47 +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. | ||||
| 
 | ||||
| Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
 | ||||
| Copyright (c) 2014 John Preston, https://desktop.telegram.org
 | ||||
| */ | ||||
| #pragma once | ||||
| 
 | ||||
| #include "gui/flatinput.h" | ||||
| 
 | ||||
| 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(QKeyEvent *e, const QString &was); | ||||
| 
 | ||||
| private: | ||||
| 
 | ||||
| 	bool _nosignal; | ||||
| 
 | ||||
| }; | ||||
|  | @ -20,11 +20,13 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org | |||
| 
 | ||||
| #include "flatinput.h" | ||||
| #include "window.h" | ||||
| #include "countryinput.h" | ||||
| 
 | ||||
| namespace { | ||||
| 	class FlatInputStyle : public QCommonStyle { | ||||
| 	template <typename InputClass> | ||||
| 	class InputStyle : public QCommonStyle { | ||||
| 	public: | ||||
| 		FlatInputStyle() { | ||||
| 		InputStyle() { | ||||
| 		} | ||||
| 
 | ||||
| 		void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = 0) const { | ||||
|  | @ -32,14 +34,15 @@ namespace { | |||
| 		QRect subElementRect(SubElement r, const QStyleOption *opt, const QWidget *widget = 0) const { | ||||
| 			switch (r) { | ||||
| 				case SE_LineEditContents: | ||||
| 					const FlatInput *w = widget ? qobject_cast<const FlatInput*>(widget) : 0; | ||||
| 					const InputClass *w = widget ? qobject_cast<const InputClass*>(widget) : 0; | ||||
| 					return w ? w->getTextRect() : QCommonStyle::subElementRect(r, opt, widget); | ||||
| 				break; | ||||
| 			} | ||||
| 			return QCommonStyle::subElementRect(r, opt, widget); | ||||
| 		} | ||||
| 	}; | ||||
| 	FlatInputStyle _flatInputStyle; | ||||
| 	InputStyle<FlatInput> _flatInputStyle; | ||||
| 	InputStyle<InputField> _inputFieldStyle; | ||||
| } | ||||
| 
 | ||||
| FlatInput::FlatInput(QWidget *parent, const style::flatInput &st, const QString &pholder, const QString &v) : QLineEdit(v, parent), _fullph(pholder), _oldtext(v), _kev(0), _customUpDown(false), _phVisible(!v.length()), | ||||
|  | @ -285,3 +288,359 @@ void FlatInput::notaBene() { | |||
| 	a_borderColor.start(_st.borderError->c); | ||||
| 	anim::start(this); | ||||
| } | ||||
| 
 | ||||
| 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 old(text()); | ||||
| 	setText('+' + code); | ||||
| 	_nosignal = true; | ||||
| 	correctValue(0, old); | ||||
| 	_nosignal = false; | ||||
| 	emit changed(); | ||||
| } | ||||
| 
 | ||||
| void CountryCodeInput::correctValue(QKeyEvent *e, const QString &was) { | ||||
| 	QString oldText(text()), newText, addToNumber; | ||||
| 	int oldPos(cursorPosition()), newPos(-1), oldLen(oldText.length()), start = 0, digits = 5; | ||||
| 	newText.reserve(oldLen + 1); | ||||
| 	newText += '+'; | ||||
| 	if (oldLen && oldText[0] == '+') { | ||||
| 		++start; | ||||
| 	} | ||||
| 	for (int i = start; i < oldLen; ++i) { | ||||
| 		QChar ch(oldText[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 != oldText) { | ||||
| 		setText(newText); | ||||
| 		if (newPos != oldPos) { | ||||
| 			setCursorPosition(newPos); | ||||
| 		} | ||||
| 	} | ||||
| 	if (!_nosignal && was != newText) { | ||||
| 		emit codeChanged(newText.mid(1)); | ||||
| 	} | ||||
| 	if (!addToNumber.isEmpty()) { | ||||
| 		emit addedToNumber(addToNumber); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| InputField::InputField(QWidget *parent, const style::InputField &st, const QString &pholder, const QString &v) : QLineEdit(v, parent), | ||||
| _lastText(v), | ||||
| _keyEvent(0), | ||||
| _customUpDown(false), | ||||
| 
 | ||||
| _placeholderFull(pholder), | ||||
| _placeholderVisible(!v.length()), | ||||
| a_placeholderLeft(_placeholderVisible ? 0 : st.placeholderShift), | ||||
| a_placeholderOpacity(_placeholderVisible ? 1 : 0), | ||||
| a_placeholderFg(st.placeholderFg->c), | ||||
| _placeholderFgAnim(animFunc(this, &InputField::placeholderFgStep)), | ||||
| _placeholderShiftAnim(animFunc(this, &InputField::placeholderShiftStep)), | ||||
| 
 | ||||
| a_borderFg(st.borderFg->c), | ||||
| a_borderOpacityActive(0), | ||||
| _borderAnim(animFunc(this, &InputField::borderStep)), | ||||
| 
 | ||||
| _focused(false), _error(false), _st(&st) { | ||||
| 	resize(_st->width, _st->height); | ||||
| 
 | ||||
| 	setFont(_st->font->f); | ||||
| 	setAlignment(_st->textAlign); | ||||
| 	setLayoutDirection(cLangDir()); | ||||
| 
 | ||||
| 	QPalette p(palette()); | ||||
| 	p.setColor(QPalette::Text, _st->textFg->c); | ||||
| 	setPalette(p); | ||||
| 
 | ||||
| 	connect(this, SIGNAL(textChanged(const QString &)), this, SLOT(onTextChange(const QString &))); | ||||
| 	connect(this, SIGNAL(textEdited(const QString &)), this, SLOT(onTextEdited())); | ||||
| 	if (App::wnd()) connect(this, SIGNAL(selectionChanged()), App::wnd(), SLOT(updateGlobalMenu())); | ||||
| 
 | ||||
| 	setStyle(&_inputFieldStyle); | ||||
| 	setTextMargins(0, 0, 0, 0); | ||||
| 	setContentsMargins(0, 0, 0, 0); | ||||
| 
 | ||||
| 	setAttribute(Qt::WA_AcceptTouchEvents); | ||||
| 	_touchTimer.setSingleShot(true); | ||||
| 	connect(&_touchTimer, SIGNAL(timeout()), this, SLOT(onTouchTimer())); | ||||
| } | ||||
| 
 | ||||
| void InputField::setCustomUpDown(bool customUpDown) { | ||||
| 	_customUpDown = customUpDown; | ||||
| } | ||||
| 
 | ||||
| void InputField::onTouchTimer() { | ||||
| 	_touchRightButton = true; | ||||
| } | ||||
| 
 | ||||
| bool InputField::event(QEvent *e) { | ||||
| 	if (e->type() == QEvent::TouchBegin || e->type() == QEvent::TouchUpdate || e->type() == QEvent::TouchEnd || e->type() == QEvent::TouchCancel) { | ||||
| 		QTouchEvent *ev = static_cast<QTouchEvent*>(e); | ||||
| 		if (ev->device()->type() == QTouchDevice::TouchScreen) { | ||||
| 			touchEvent(ev); | ||||
| 			return QLineEdit::event(e); | ||||
| 		} | ||||
| 	} | ||||
| 	return QLineEdit::event(e); | ||||
| } | ||||
| 
 | ||||
| void InputField::touchEvent(QTouchEvent *e) { | ||||
| 	switch (e->type()) { | ||||
| 	case QEvent::TouchBegin: | ||||
| 		if (_touchPress || e->touchPoints().isEmpty()) return; | ||||
| 		_touchTimer.start(QApplication::startDragTime()); | ||||
| 		_touchPress = true; | ||||
| 		_touchMove = _touchRightButton = false; | ||||
| 		_touchStart = e->touchPoints().cbegin()->screenPos().toPoint(); | ||||
| 		break; | ||||
| 
 | ||||
| 	case QEvent::TouchUpdate: | ||||
| 		if (!_touchPress || e->touchPoints().isEmpty()) return; | ||||
| 		if (!_touchMove && (e->touchPoints().cbegin()->screenPos().toPoint() - _touchStart).manhattanLength() >= QApplication::startDragDistance()) { | ||||
| 			_touchMove = true; | ||||
| 		} | ||||
| 		break; | ||||
| 
 | ||||
| 	case QEvent::TouchEnd: | ||||
| 		if (!_touchPress) return; | ||||
| 		if (!_touchMove && window()) { | ||||
| 			Qt::MouseButton btn(_touchRightButton ? Qt::RightButton : Qt::LeftButton); | ||||
| 			QPoint mapped(mapFromGlobal(_touchStart)), winMapped(window()->mapFromGlobal(_touchStart)); | ||||
| 
 | ||||
| 			if (_touchRightButton) { | ||||
| 				QContextMenuEvent contextEvent(QContextMenuEvent::Mouse, mapped, _touchStart); | ||||
| 				contextMenuEvent(&contextEvent); | ||||
| 			} | ||||
| 		} | ||||
| 		_touchTimer.stop(); | ||||
| 		_touchPress = _touchMove = _touchRightButton = false; | ||||
| 		break; | ||||
| 
 | ||||
| 	case QEvent::TouchCancel: | ||||
| 		_touchPress = false; | ||||
| 		_touchTimer.stop(); | ||||
| 		break; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| QRect InputField::getTextRect() const { | ||||
| 	QMargins m = _st->textMargins + QMargins(-2, -1, -2, -1); | ||||
| 	if (rtl()) { | ||||
| 		int l = m.left(); | ||||
| 		m.setLeft(m.right()); | ||||
| 		m.setRight(l); | ||||
| 	} | ||||
| 	return rect().marginsRemoved(m); | ||||
| } | ||||
| 
 | ||||
| void InputField::paintEvent(QPaintEvent *e) { | ||||
| 	Painter p(this); | ||||
| 
 | ||||
| 	if (_st->border) { | ||||
| 		p.fillRect(0, height() - _st->border, width(), _st->border, _st->borderFg->b); | ||||
| 	} | ||||
| 	if (_st->borderActive && a_borderOpacityActive.current() > 0) { | ||||
| 		p.setOpacity(a_borderOpacityActive.current()); | ||||
| 		p.fillRect(0, height() - _st->borderActive, width(), _st->borderActive, a_borderFg.current()); | ||||
| 		p.setOpacity(1); | ||||
| 	} | ||||
| 	if (_st->iconSprite.pxWidth()) { | ||||
| 		p.drawSpriteLeft(_st->iconPosition, width(), _st->iconSprite); | ||||
| 	} | ||||
| 
 | ||||
| 	bool drawPlaceholder = _placeholderVisible; | ||||
| 	if (_placeholderShiftAnim.animating()) { | ||||
| 		p.setOpacity(a_placeholderOpacity.current()); | ||||
| 		drawPlaceholder = true; | ||||
| 	} | ||||
| 	if (drawPlaceholder) { | ||||
| 		p.save(); | ||||
| 		p.setClipRect(rect()); | ||||
| 
 | ||||
| 		QRect r(rect().marginsRemoved(_st->textMargins + _st->placeholderMargins)); | ||||
| 		r.moveLeft(r.left() + a_placeholderLeft.current()); | ||||
| 		if (rtl()) r.moveLeft(width() - r.left() - r.width()); | ||||
| 
 | ||||
| 		p.setFont(_st->font->f); | ||||
| 		p.setPen(a_placeholderFg.current()); | ||||
| 		p.drawText(r, _placeholder, _st->placeholderAlign); | ||||
| 
 | ||||
| 		p.restore(); | ||||
| 	} | ||||
| 	QLineEdit::paintEvent(e); | ||||
| } | ||||
| 
 | ||||
| void InputField::focusInEvent(QFocusEvent *e) { | ||||
| 	if (!_focused) { | ||||
| 		_focused = true; | ||||
| 
 | ||||
| 		a_placeholderFg.start(_st->placeholderFgActive->c); | ||||
| 		_placeholderFgAnim.start(); | ||||
| 
 | ||||
| 		a_borderFg.start((_error ? _st->borderFgError : _st->borderFgActive)->c); | ||||
| 		a_borderOpacityActive.start(1); | ||||
| 		_borderAnim.start(); | ||||
| 	} | ||||
| 	QLineEdit::focusInEvent(e); | ||||
| 	emit focused(); | ||||
| } | ||||
| 
 | ||||
| void InputField::focusOutEvent(QFocusEvent *e) { | ||||
| 	if (_focused) { | ||||
| 		_focused = false; | ||||
| 
 | ||||
| 		a_placeholderFg.start(_st->placeholderFg->c); | ||||
| 		_placeholderFgAnim.start(); | ||||
| 
 | ||||
| 		a_borderFg.start((_error ? _st->borderFgError : _st->borderFg)->c); | ||||
| 		a_borderOpacityActive.start(_error ? 1 : 0); | ||||
| 		_borderAnim.start(); | ||||
| 	} | ||||
| 	QLineEdit::focusOutEvent(e); | ||||
| 	emit blurred(); | ||||
| } | ||||
| 
 | ||||
| void InputField::resizeEvent(QResizeEvent *e) { | ||||
| 	int32 availw = width() - _st->textMargins.left() - _st->textMargins.right() - _st->placeholderMargins.left() - _st->placeholderMargins.right() - 2; | ||||
| 	_placeholder = (_st->font->m.width(_placeholderFull) > availw) ? _st->font->m.elidedText(_placeholderFull, Qt::ElideRight, availw) : _placeholderFull; | ||||
| 	update(); | ||||
| } | ||||
| 
 | ||||
| QSize InputField::sizeHint() const { | ||||
| 	return geometry().size(); | ||||
| } | ||||
| 
 | ||||
| QSize InputField::minimumSizeHint() const { | ||||
| 	return geometry().size(); | ||||
| } | ||||
| 
 | ||||
| bool InputField::placeholderFgStep(float64 ms) { | ||||
| 	float dt = ms / _st->duration; | ||||
| 	bool res = true; | ||||
| 	if (dt >= 1) { | ||||
| 		res = false; | ||||
| 		a_placeholderFg.finish(); | ||||
| 	} else { | ||||
| 		a_placeholderFg.update(dt, anim::linear); | ||||
| 	} | ||||
| 	update(); | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| bool InputField::placeholderShiftStep(float64 ms) { | ||||
| 	float dt = ms / _st->duration; | ||||
| 	bool res = true; | ||||
| 	if (dt >= 1) { | ||||
| 		res = false; | ||||
| 		a_placeholderLeft.finish(); | ||||
| 		a_placeholderOpacity.finish(); | ||||
| 	} else { | ||||
| 		a_placeholderLeft.update(dt, anim::linear); | ||||
| 		a_placeholderOpacity.update(dt, anim::linear); | ||||
| 	} | ||||
| 	update(); | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| bool InputField::borderStep(float64 ms) { | ||||
| 	float dt = ms / _st->duration; | ||||
| 	bool res = true; | ||||
| 	if (dt >= 1) { | ||||
| 		res = false; | ||||
| 		a_borderFg.finish(); | ||||
| 		a_borderOpacityActive.finish(); | ||||
| 	} else { | ||||
| 		a_borderFg.update(dt, anim::linear); | ||||
| 		a_borderOpacityActive.update(dt, anim::linear); | ||||
| 	} | ||||
| 	update(); | ||||
| 	return res; | ||||
| } | ||||
| 
 | ||||
| void InputField::updatePlaceholder() { | ||||
| 	bool placeholderVisible = !_lastText.isEmpty(); | ||||
| 	if (placeholderVisible != _placeholderVisible) { | ||||
| 		_placeholderVisible = placeholderVisible; | ||||
| 
 | ||||
| 		a_placeholderLeft.start(_placeholderVisible ? 0 : _st->placeholderShift); | ||||
| 		a_placeholderOpacity.start(_placeholderVisible ? 1 : 0); | ||||
| 		_placeholderShiftAnim.start(); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void InputField::correctValue(QKeyEvent *e, const QString &was) { | ||||
| } | ||||
| 
 | ||||
| void InputField::keyPressEvent(QKeyEvent *e) { | ||||
| 	QString was(_lastText); | ||||
| 
 | ||||
| 	_keyEvent = e; | ||||
| 	if (_customUpDown && (e->key() == Qt::Key_Up || e->key() == Qt::Key_Down)) { | ||||
| 		e->ignore(); | ||||
| 	} else { | ||||
| 		QLineEdit::keyPressEvent(e); | ||||
| 	} | ||||
| 
 | ||||
| 	if (was == _lastText) { // call correct manually
 | ||||
| 		correctValue(_keyEvent, was); | ||||
| 		_lastText = text(); | ||||
| 		if (was != _lastText) emit changed(); | ||||
| 		updatePlaceholder(); | ||||
| 	} | ||||
| 	if (e->key() == Qt::Key_Escape) { | ||||
| 		emit cancelled(); | ||||
| 	} else if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) { | ||||
| 		emit accepted(); | ||||
| 	} | ||||
| 	_keyEvent = 0; | ||||
| } | ||||
| 
 | ||||
| void InputField::onTextEdited() { | ||||
| 	QString was(_lastText); | ||||
| 	correctValue(_keyEvent, was); | ||||
| 	_lastText = text(); | ||||
| 	if (was != _lastText) emit changed(); | ||||
| 	updatePlaceholder(); | ||||
| 	if (App::wnd()) App::wnd()->updateGlobalMenu(); | ||||
| } | ||||
| 
 | ||||
| void InputField::onTextChange(const QString &text) { | ||||
| 	_lastText = text; | ||||
| 	if (App::wnd()) App::wnd()->updateGlobalMenu(); | ||||
| } | ||||
| 
 | ||||
| void InputField::setError(bool error) { | ||||
| 	if (error != _error) { | ||||
| 		_error = error; | ||||
| 
 | ||||
| 		a_borderFg.start((_error ? _st->borderFgError : (_focused ? _st->borderFgActive : _st->borderFg))->c); | ||||
| 		a_borderOpacityActive.start((_error || _focused) ? 1 : 0); | ||||
| 		_borderAnim.start(); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -89,3 +89,106 @@ private: | |||
| 	bool _touchPress, _touchRightButton, _touchMove; | ||||
| 	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(QKeyEvent *e, const QString &was); | ||||
| 
 | ||||
| private: | ||||
| 
 | ||||
| 	bool _nosignal; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| class InputField : public QLineEdit { | ||||
| 	Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
| 	InputField(QWidget *parent, const style::InputField &st, const QString &ph = QString(), const QString &val = QString()); | ||||
| 
 | ||||
| 	bool event(QEvent *e); | ||||
| 	void touchEvent(QTouchEvent *e); | ||||
| 	void paintEvent(QPaintEvent *e); | ||||
| 	void focusInEvent(QFocusEvent *e); | ||||
| 	void focusOutEvent(QFocusEvent *e); | ||||
| 	void keyPressEvent(QKeyEvent *e); | ||||
| 	void resizeEvent(QResizeEvent *e); | ||||
| 
 | ||||
| 	void setError(bool error); | ||||
| 
 | ||||
| 	void updatePlaceholder(); | ||||
| 
 | ||||
| 	QRect getTextRect() const; | ||||
| 
 | ||||
| 	bool placeholderFgStep(float64 ms); | ||||
| 	bool placeholderShiftStep(float64 ms); | ||||
| 	bool borderStep(float64 ms); | ||||
| 
 | ||||
| 	QSize sizeHint() const; | ||||
| 	QSize minimumSizeHint() const; | ||||
| 
 | ||||
| 	void setCustomUpDown(bool customUpDown); | ||||
| 
 | ||||
| public slots: | ||||
| 
 | ||||
| 	void onTextChange(const QString &text); | ||||
| 	void onTextEdited(); | ||||
| 
 | ||||
| 	void onTouchTimer(); | ||||
| 
 | ||||
| signals: | ||||
| 
 | ||||
| 	void changed(); | ||||
| 	void cancelled(); | ||||
| 	void accepted(); | ||||
| 	void focused(); | ||||
| 	void blurred(); | ||||
| 
 | ||||
| protected: | ||||
| 
 | ||||
| 	virtual void correctValue(QKeyEvent *e, const QString &was); | ||||
| 
 | ||||
| private: | ||||
| 
 | ||||
| 	QString _lastText; | ||||
| 	QKeyEvent *_keyEvent; | ||||
| 
 | ||||
| 	bool _customUpDown; | ||||
| 
 | ||||
| 	QString _placeholder, _placeholderFull; | ||||
| 	bool _placeholderVisible; | ||||
| 	anim::ivalue a_placeholderLeft; | ||||
| 	anim::fvalue a_placeholderOpacity; | ||||
| 	anim::cvalue a_placeholderFg; | ||||
| 	Animation _placeholderFgAnim, _placeholderShiftAnim; | ||||
| 
 | ||||
| 	anim::fvalue a_borderOpacityActive; | ||||
| 	anim::cvalue a_borderFg; | ||||
| 	Animation _borderAnim; | ||||
| 
 | ||||
| 	bool _focused, _error; | ||||
| 
 | ||||
| 	const style::InputField *_st; | ||||
| 
 | ||||
| 	QTimer _touchTimer; | ||||
| 	bool _touchPress, _touchRightButton, _touchMove; | ||||
| 	QPoint _touchStart; | ||||
| }; | ||||
|  |  | |||
|  | @ -20,7 +20,6 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org | |||
| #include <QtWidgets/QWidget> | ||||
| #include "gui/flatbutton.h" | ||||
| #include "gui/phoneinput.h" | ||||
| #include "gui/countrycodeinput.h" | ||||
| #include "gui/countryinput.h" | ||||
| #include "intro.h" | ||||
| 
 | ||||
|  |  | |||
|  | @ -208,10 +208,6 @@ | |||
|       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild> | ||||
|       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="GeneratedFiles\Debug\moc_countrycodeinput.cpp"> | ||||
|       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild> | ||||
|       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="GeneratedFiles\Debug\moc_countryinput.cpp"> | ||||
|       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild> | ||||
|       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> | ||||
|  | @ -474,10 +470,6 @@ | |||
|       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | ||||
|       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="GeneratedFiles\Deploy\moc_countrycodeinput.cpp"> | ||||
|       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | ||||
|       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="GeneratedFiles\Deploy\moc_countryinput.cpp"> | ||||
|       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | ||||
|       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild> | ||||
|  | @ -765,10 +757,6 @@ | |||
|       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild> | ||||
|       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="GeneratedFiles\Release\moc_countrycodeinput.cpp"> | ||||
|       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild> | ||||
|       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="GeneratedFiles\Release\moc_countryinput.cpp"> | ||||
|       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">true</ExcludedFromBuild> | ||||
|       <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | ||||
|  | @ -1001,7 +989,6 @@ | |||
|     <ClCompile Include="SourceFiles\gui\boxshadow.cpp" /> | ||||
|     <ClCompile Include="SourceFiles\gui\button.cpp" /> | ||||
|     <ClCompile Include="SourceFiles\gui\contextmenu.cpp" /> | ||||
|     <ClCompile Include="SourceFiles\gui\countrycodeinput.cpp" /> | ||||
|     <ClCompile Include="SourceFiles\gui\countryinput.cpp" /> | ||||
|     <ClCompile Include="SourceFiles\gui\emoji_config.cpp" /> | ||||
|     <ClCompile Include="SourceFiles\gui\filedialog.cpp" /> | ||||
|  | @ -1467,20 +1454,6 @@ | |||
|       <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs> | ||||
|       <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs> | ||||
|     </CustomBuild> | ||||
|     <CustomBuild Include="SourceFiles\gui\countrycodeinput.h"> | ||||
|       <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Moc%27ing countrycodeinput.h...</Message> | ||||
|       <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs> | ||||
|       <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\moc.exe"  "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp"  -DAL_LIBTYPE_STATIC -DUNICODE -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI  "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\ffmpeg-2.6.3" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui" "-fstdafx.h" "-f../../SourceFiles/gui/countrycodeinput.h"</Command> | ||||
|       <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Moc%27ing countrycodeinput.h...</Message> | ||||
|       <Message Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">Moc%27ing countrycodeinput.h...</Message> | ||||
|       <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs> | ||||
|       <Outputs Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs> | ||||
|       <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(QTDIR)\bin\moc.exe"  "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp"  -DAL_LIBTYPE_STATIC -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG  "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\libogg-1.3.2\include" "-I.\..\..\Libraries\opus\include" "-I.\..\..\Libraries\opusfile\include" "-I.\..\..\Libraries\mpg123-1.22.1\ports\MSVC++" "-I.\..\..\Libraries\mpg123-1.22.1\src\libmpg123" "-I.\..\..\Libraries\faad2-2.7\include" "-I.\..\..\Libraries\faad2-2.7\common\mp4ff" "-I.\..\..\Libraries\ffmpeg-2.6.3" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui" "-fstdafx.h" "-f../../SourceFiles/gui/countrycodeinput.h"</Command> | ||||
|       <Command Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">"$(QTDIR)\bin\moc.exe"  "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp"  -DAL_LIBTYPE_STATIC -DCUSTOM_API_ID -DUNICODE -D_WITH_DEBUG -DWIN32 -DWIN64 -DHAVE_STDINT_H -DZLIB_WINAPI -DQT_NO_DEBUG -DNDEBUG  "-I.\..\..\Libraries\lzma\C" "-I.\..\..\Libraries\libexif-0.6.20" "-I.\..\..\Libraries\zlib-1.2.8" "-I.\..\..\Libraries\OpenSSL-Win32\include" "-I.\..\..\Libraries\ffmpeg-2.6.3" "-I.\..\..\Libraries\openal-soft\include" "-I.\SourceFiles" "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\..\Libraries\QtStatic\qtbase\include\QtCore\5.4.0\QtCore" "-I.\..\..\Libraries\QtStatic\qtbase\include\QtGui\5.4.0\QtGui" "-fstdafx.h" "-f../../SourceFiles/gui/countrycodeinput.h"</Command> | ||||
|       <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs> | ||||
|       <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs> | ||||
|       <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs> | ||||
|     </CustomBuild> | ||||
|     <CustomBuild Include="SourceFiles\gui\phoneinput.h"> | ||||
|       <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Moc%27ing phoneinput.h...</Message> | ||||
|       <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs> | ||||
|  |  | |||
|  | @ -87,9 +87,6 @@ | |||
|     <ClCompile Include="SourceFiles\gui\phoneinput.cpp"> | ||||
|       <Filter>gui</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="SourceFiles\gui\countrycodeinput.cpp"> | ||||
|       <Filter>gui</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="SourceFiles\gui\countryinput.cpp"> | ||||
|       <Filter>gui</Filter> | ||||
|     </ClCompile> | ||||
|  | @ -546,15 +543,6 @@ | |||
|     <ClCompile Include="GeneratedFiles\Release\moc_countryinput.cpp"> | ||||
|       <Filter>Generated Files\Release</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="GeneratedFiles\Deploy\moc_countrycodeinput.cpp"> | ||||
|       <Filter>Generated Files\Deploy</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="GeneratedFiles\Debug\moc_countrycodeinput.cpp"> | ||||
|       <Filter>Generated Files\Debug</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="GeneratedFiles\Release\moc_countrycodeinput.cpp"> | ||||
|       <Filter>Generated Files\Release</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="GeneratedFiles\Deploy\moc_contactsbox.cpp"> | ||||
|       <Filter>Generated Files\Deploy</Filter> | ||||
|     </ClCompile> | ||||
|  | @ -1020,9 +1008,6 @@ | |||
|     <CustomBuild Include="SourceFiles\gui\phoneinput.h"> | ||||
|       <Filter>gui</Filter> | ||||
|     </CustomBuild> | ||||
|     <CustomBuild Include="SourceFiles\gui\countrycodeinput.h"> | ||||
|       <Filter>gui</Filter> | ||||
|     </CustomBuild> | ||||
|     <CustomBuild Include="SourceFiles\gui\countryinput.h"> | ||||
|       <Filter>gui</Filter> | ||||
|     </CustomBuild> | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 John Preston
						John Preston