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

animations refactored

This commit is contained in:
John Preston
2015-12-08 15:33:37 +03:00
parent f25fde09b7
commit 0b96dd5362
71 changed files with 1370 additions and 1584 deletions

View File

@@ -26,7 +26,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
#include "window.h"
namespace {
AnimationManager *manager = 0;
AnimationManager *_manager = 0;
};
namespace anim {
@@ -78,34 +78,34 @@ namespace anim {
return delta * (t2 * t2 * t + 1);
}
void start(Animated *obj) {
if (!manager) return;
manager->start(obj);
}
void step(Animated *obj) {
if (!manager) return;
manager->step(obj);
}
void stop(Animated *obj) {
if (!manager) return;
manager->stop(obj);
}
void startManager() {
delete manager;
manager = new AnimationManager();
delete _manager;
_manager = new AnimationManager();
}
void stopManager() {
delete manager;
manager = 0;
delete _manager;
_manager = 0;
}
}
bool AnimatedGif::animStep(float64 ms) {
void Animation::start() {
if (!_manager) return;
_cb->start();
_manager->start(this);
_animating = true;
}
void Animation::stop() {
if (!_manager) return;
_animating = false;
_manager->stop(this);
}
void AnimatedGif::step_frame(float64 ms, bool timer) {
int32 f = frame;
while (f < images.size() && ms > delays[f]) {
++f;
@@ -152,13 +152,14 @@ bool AnimatedGif::animStep(float64 ms) {
}
if (frame != f) {
frame = f;
if (msg && App::main()) {
App::main()->msgUpdated(msg);
} else {
emit updated();
if (timer) {
if (msg && App::main()) {
App::main()->msgUpdated(msg);
} else {
emit updated();
}
}
}
return true;
}
void AnimatedGif::start(HistoryItem *row, const FileLocation &f) {
@@ -205,7 +206,7 @@ void AnimatedGif::start(HistoryItem *row, const FileLocation &f) {
msg = row;
anim::start(this);
_a_frames.start();
if (msg) {
msg->initDimensions();
if (App::main()) App::main()->itemResized(msg, true);
@@ -233,7 +234,7 @@ void AnimatedGif::stop(bool onItemRemoved) {
delays.clear();
w = h = frame = framesCount = duration = 0;
anim::stop(this);
_a_frames.stop();
if (row && !onItemRemoved) {
row->initDimensions();
if (App::main()) App::main()->itemResized(row, true);

View File

@@ -24,8 +24,6 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
#include <QtCore/QTimer>
#include <QtGui/QColor>
class Animated;
namespace anim {
typedef float64 (*transition)(const float64 &delta, const float64 &dt);
@@ -187,216 +185,203 @@ namespace anim {
float64 _from_r, _from_g, _from_b, _from_a, _delta_r, _delta_g, _delta_b, _delta_a;
};
void start(Animated *obj);
void step(Animated *obj);
void stop(Animated *obj);
void startManager();
void stopManager();
};
class Animated {
class Animation;
class AnimationCallbacks {
public:
virtual void start() {
}
virtual void step(Animation *a, uint64 ms, bool timer) = 0;
virtual ~AnimationCallbacks() {
}
};
class Animation {
public:
Animated() : animStarted(0), animInProcess(false) {
Animation(AnimationCallbacks *cb) : _cb(cb), _animating(false) {
}
virtual bool animStep(float64 ms) = 0;
void start();
void stop();
void animReset() {
animStarted = float64(getms());
void step(uint64 ms, bool timer = false) {
_cb->step(this, ms, timer);
}
virtual ~Animated() {
if (animating()) {
anim::stop(this);
}
void step() {
step(getms(), false);
}
bool animating() const {
return animInProcess;
}
private:
float64 animStarted;
bool animInProcess;
friend class AnimationManager;
};
class AnimationFunc {
public:
virtual bool animStep(float64 ms) = 0;
virtual ~AnimationFunc() {
}
};
template <typename Type>
class AnimationFuncOwned : public AnimationFunc {
public:
typedef bool (Type::*Method)(float64);
AnimationFuncOwned(Type *obj, Method method) : _obj(obj), _method(method) {
}
bool animStep(float64 ms) {
return (_obj->*_method)(ms);
}
private:
Type *_obj;
Method _method;
};
template <typename Type>
AnimationFunc *animFunc(Type *obj, typename AnimationFuncOwned<Type>::Method method) {
return new AnimationFuncOwned<Type>(obj, method);
}
class Animation : public Animated {
public:
Animation(AnimationFunc *func) : _func(func) {
}
void start() {
anim::start(this);
}
void stop() {
anim::stop(this);
}
//Animation
bool animStep(float64 ms) {
return _func->animStep(ms);
return _animating;
}
~Animation() {
delete _func;
if (_animating) stop();
delete _cb;
}
private:
AnimationFunc *_func;
AnimationCallbacks *_cb;
bool _animating;
};
template <typename Type>
class AnimationCallbacksRelative : public AnimationCallbacks {
public:
typedef void (Type::*Method)(float64, bool);
AnimationCallbacksRelative(Type *obj, Method method) : _started(0), _obj(obj), _method(method) {
}
void start() {
_started = float64(getms());
}
void step(Animation *a, uint64 ms, bool timer) {
(_obj->*_method)(ms - _started, timer);
}
private:
float64 _started;
Type *_obj;
Method _method;
};
template <typename Type>
AnimationCallbacks *animation(Type *obj, typename AnimationCallbacksRelative<Type>::Method method) {
return new AnimationCallbacksRelative<Type>(obj, method);
}
template <typename Type>
class AnimationCallbacksAbsolute : public AnimationCallbacks {
public:
typedef void (Type::*Method)(uint64, bool);
AnimationCallbacksAbsolute(Type *obj, Method method) : _obj(obj), _method(method) {
}
void step(Animation *a, uint64 ms, bool timer) {
(_obj->*_method)(ms, timer);
}
private:
Type *_obj;
Method _method;
};
template <typename Type>
AnimationCallbacks *animation(Type *obj, typename AnimationCallbacksAbsolute<Type>::Method method) {
return new AnimationCallbacksAbsolute<Type>(obj, method);
}
class AnimationManager : public QObject {
Q_OBJECT
public:
AnimationManager() : timer(this), iterating(false) {
timer.setSingleShot(false);
connect(&timer, SIGNAL(timeout()), this, SLOT(timeout()));
AnimationManager() : _timer(this), _iterating(false) {
_timer.setSingleShot(false);
connect(&_timer, SIGNAL(timeout()), this, SLOT(timeout()));
}
void start(Animated *obj) {
obj->animReset();
if (iterating) {
toStart.insert(obj);
if (!toStop.isEmpty()) {
toStop.remove(obj);
void start(Animation *obj) {
if (_iterating) {
_starting.insert(obj, NullType());
if (!_stopping.isEmpty()) {
_stopping.remove(obj);
}
} else {
if (!objs.size()) {
timer.start(AnimationTimerDelta);
}
objs.insert(obj);
}
obj->animInProcess = true;
}
void step(Animated *obj) {
if (iterating) return;
float64 ms = float64(getms());
AnimObjs::iterator i = objs.find(obj);
if (i != objs.cend()) {
Animated *obj = *i;
if (!obj->animStep(ms - obj->animStarted)) {
objs.erase(i);
if (!objs.size()) {
timer.stop();
}
obj->animInProcess = false;
if (_objects.isEmpty()) {
_timer.start(AnimationTimerDelta);
}
_objects.insert(obj, NullType());
}
}
void stop(Animated *obj) {
if (iterating) {
toStop.insert(obj);
if (!toStart.isEmpty()) {
toStart.insert(obj);
void stop(Animation *obj) {
if (_iterating) {
_stopping.insert(obj, NullType());
if (!_starting.isEmpty()) {
_starting.insert(obj, NullType());
}
} else {
AnimObjs::iterator i = objs.find(obj);
if (i != objs.cend()) {
objs.erase(i);
if (!objs.size()) {
timer.stop();
AnimatingObjects::iterator i = _objects.find(obj);
if (i != _objects.cend()) {
_objects.erase(i);
if (_objects.isEmpty()) {
_timer.stop();
}
}
}
obj->animInProcess = false;
}
public slots:
void timeout() {
iterating = true;
float64 ms = float64(getms());
for (AnimObjs::iterator i = objs.begin(), e = objs.end(); i != e; ) {
Animated *obj = *i;
if (!obj->animStep(ms - obj->animStarted)) {
i = objs.erase(i);
obj->animInProcess = false;
} else {
++i;
}
_iterating = true;
uint64 ms = getms();
for (AnimatingObjects::const_iterator i = _objects.begin(), e = _objects.end(); i != e; ++i) {
i.key()->step(ms, true);
}
iterating = false;
if (!toStart.isEmpty()) {
for (AnimObjs::iterator i = toStart.begin(), e = toStart.end(); i != e; ++i) {
objs.insert(*i);
_iterating = false;
if (!_starting.isEmpty()) {
for (AnimatingObjects::iterator i = _starting.begin(), e = _starting.end(); i != e; ++i) {
_objects.insert(i.key(), NullType());
}
toStart.clear();
_starting.clear();
}
if (!toStop.isEmpty()) {
for (AnimObjs::iterator i = toStop.begin(), e = toStop.end(); i != e; ++i) {
objs.remove(*i);
if (!_stopping.isEmpty()) {
for (AnimatingObjects::iterator i = _stopping.begin(), e = _stopping.end(); i != e; ++i) {
_objects.remove(i.key());
}
toStop.clear();
_stopping.clear();
}
if (!objs.size()) {
timer.stop();
if (!_objects.size()) {
_timer.stop();
}
}
private:
typedef QSet<Animated*> AnimObjs;
AnimObjs objs;
AnimObjs toStart;
AnimObjs toStop;
QTimer timer;
bool iterating;
typedef QMap<Animation*, NullType> AnimatingObjects;
AnimatingObjects _objects, _starting, _stopping;
QTimer _timer;
bool _iterating;
};
class HistoryItem;
class FileLocation;
class AnimatedGif : public QObject, public Animated {
class AnimatedGif : public QObject {
Q_OBJECT
public:
AnimatedGif() : msg(0), file(0), access(false), reader(0), w(0), h(0), frame(0), framesCount(0), duration(0) {
AnimatedGif() : QObject()
, msg(0)
, file(0)
, access(false)
, reader(0)
, w(0)
, h(0)
, frame(0)
, framesCount(0)
, duration(0)
, _a_frames(animation(this, &AnimatedGif::step_frame)) {
}
bool animStep(float64 ms);
void step_frame(float64 ms, bool timer);
void start(HistoryItem *row, const FileLocation &file);
void stop(bool onItemRemoved = false);
@@ -430,4 +415,7 @@ private:
QVector<QImage> images;
QVector<int64> delays;
int32 framesCount, duration;
Animation _a_frames;
};

View File

@@ -21,10 +21,14 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
#include "stdafx.h"
#include "gui/flatbutton.h"
FlatButton::FlatButton(QWidget *parent, const QString &text, const style::flatButton &st) : Button(parent),
_text(text),
_st(st), _autoFontPadding(0),
a_bg(st.bgColor->c), a_text(st.color->c), _opacity(1) {
FlatButton::FlatButton(QWidget *parent, const QString &text, const style::flatButton &st) : Button(parent)
, _text(text)
, _st(st)
, _autoFontPadding(0)
, a_bg(st.bgColor->c)
, a_text(st.color->c)
, _a_appearance(animation(this, &FlatButton::step_appearance))
, _opacity(1) {
if (_st.width < 0) {
_st.width = textWidth() - _st.width;
} else if (!_st.width) {
@@ -88,19 +92,17 @@ void FlatButton::resizeEvent(QResizeEvent *e) {
return Button::resizeEvent(e);
}
bool FlatButton::animStep(float64 ms) {
void FlatButton::step_appearance(float64 ms, bool timer) {
float64 dt = ms / _st.duration;
bool res = true;
if (dt >= 1) {
_a_appearance.stop();
a_bg.finish();
a_text.finish();
res = false;
} else {
a_bg.update(dt, anim::linear);
a_text.update(dt, anim::linear);
}
update();
return res;
if (timer) update();
}
void FlatButton::onStateChange(int oldState, ButtonStateChangeSource source) {
@@ -110,12 +112,12 @@ void FlatButton::onStateChange(int oldState, ButtonStateChangeSource source) {
a_bg.start(bgColorTo->c);
a_text.start(colorTo->c);
if (source == ButtonByUser || source == ButtonByPress) {
anim::stop(this);
_a_appearance.stop();
a_bg.finish();
a_text.finish();
update();
} else {
anim::start(this);
_a_appearance.start();
}
}
@@ -164,8 +166,14 @@ void LinkButton::onStateChange(int oldState, ButtonStateChangeSource source) {
LinkButton::~LinkButton() {
}
IconedButton::IconedButton(QWidget *parent, const style::iconedButton &st, const QString &text) : Button(parent),
_text(text), _st(st), _width(_st.width), a_opacity(_st.opacity), a_bg(_st.bgColor->c), _opacity(1) {
IconedButton::IconedButton(QWidget *parent, const style::iconedButton &st, const QString &text) : Button(parent)
, _text(text)
, _st(st)
, _width(_st.width)
, a_opacity(_st.opacity)
, a_bg(_st.bgColor->c)
, _a_appearance(animation(this, &IconedButton::step_appearance))
, _opacity(1) {
if (_width < 0) {
_width = _st.font->width(text) - _width;
@@ -199,25 +207,23 @@ QString IconedButton::getText() const {
return _text;
}
bool IconedButton::animStep(float64 ms) {
bool res = true;
void IconedButton::step_appearance(float64 ms, bool timer) {
if (_st.duration <= 1) {
_a_appearance.stop();
a_opacity.finish();
a_bg.finish();
res = false;
} else {
float64 dt = ms / _st.duration;
if (dt >= 1) {
_a_appearance.stop();
a_opacity.finish();
a_bg.finish();
res = false;
} else {
a_opacity.update(dt, anim::linear);
a_bg.update(dt, anim::linear);
}
}
update();
return res;
if (timer) update();
}
void IconedButton::onStateChange(int oldState, ButtonStateChangeSource source) {
@@ -225,12 +231,12 @@ void IconedButton::onStateChange(int oldState, ButtonStateChangeSource source) {
a_bg.start(((_state & (StateOver | StateDown)) ? _st.overBgColor : _st.bgColor)->c);
if (source == ButtonByUser || source == ButtonByPress) {
anim::stop(this);
_a_appearance.stop();
a_opacity.finish();
a_bg.finish();
update();
} else {
anim::start(this);
_a_appearance.start();
}
}
@@ -283,10 +289,14 @@ void MaskedButton::paintEvent(QPaintEvent *e) {
}
}
BoxButton::BoxButton(QWidget *parent, const QString &text, const style::BoxButton &st) : Button(parent),
_text(text.toUpper()), _fullText(text.toUpper()), _textWidth(st.font->width(_text)),
_st(st),
a_textBgOverOpacity(0), a_textFg(st.textFg->c), _a_over(animFunc(this, &BoxButton::animStep_over)) {
BoxButton::BoxButton(QWidget *parent, const QString &text, const style::BoxButton &st) : Button(parent)
, _text(text.toUpper())
, _fullText(text.toUpper())
, _textWidth(st.font->width(_text))
, _st(st)
, a_textBgOverOpacity(0)
, a_textFg(st.textFg->c)
, _a_over(animation(this, &BoxButton::step_over)) {
if (_st.width <= 0) {
resize(_textWidth - _st.width, _st.height);
} else {
@@ -322,19 +332,17 @@ void BoxButton::paintEvent(QPaintEvent *e) {
p.drawText((width() - _textWidth) / 2, _st.textTop + _st.font->ascent, _text);
}
bool BoxButton::animStep_over(float64 ms) {
void BoxButton::step_over(float64 ms, bool timer) {
float64 dt = ms / _st.duration;
bool res = true;
if (dt >= 1) {
_a_over.stop();
a_textFg.finish();
a_textBgOverOpacity.finish();
res = false;
} else {
a_textFg.update(dt, anim::linear);
a_textBgOverOpacity.update(dt, anim::linear);
}
update();
return res;
if (timer) update();
}
void BoxButton::onStateChange(int oldState, ButtonStateChangeSource source) {

View File

@@ -25,7 +25,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
#include "gui/animation.h"
#include "style.h"
class FlatButton : public Button, public Animated {
class FlatButton : public Button {
Q_OBJECT
public:
@@ -34,7 +34,7 @@ public:
void resizeEvent(QResizeEvent *e);
bool animStep(float64 ms);
void step_appearance(float64 ms, bool timer);
void paintEvent(QPaintEvent *e);
void setOpacity(float64 o);
float64 opacity() const;
@@ -63,7 +63,10 @@ private:
style::font _autoFont;
anim::cvalue a_bg, a_text;
Animation _a_appearance;
float64 _opacity;
};
class LinkButton : public Button {
@@ -89,14 +92,14 @@ private:
style::linkButton _st;
};
class IconedButton : public Button, public Animated {
class IconedButton : public Button {
Q_OBJECT
public:
IconedButton(QWidget *parent, const style::iconedButton &st, const QString &text = QString());
bool animStep(float64 ms);
void step_appearance(float64 ms, bool timer);
void paintEvent(QPaintEvent *e);
void setOpacity(float64 o);
@@ -117,6 +120,7 @@ protected:
anim::fvalue a_opacity;
anim::cvalue a_bg;
Animation _a_appearance;
float64 _opacity;
};
@@ -141,7 +145,7 @@ public:
void paintEvent(QPaintEvent *e);
bool animStep_over(float64 ms);
void step_over(float64 ms, bool timer);
public slots:

View File

@@ -24,8 +24,13 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
#include "flatcheckbox.h"
FlatCheckbox::FlatCheckbox(QWidget *parent, const QString &text, bool checked, const style::flatCheckbox &st) : Button(parent),
_st(st), a_over(0, 0), _text(text), _opacity(1), _checked(checked) {
FlatCheckbox::FlatCheckbox(QWidget *parent, const QString &text, bool checked, const style::flatCheckbox &st) : Button(parent)
, _st(st)
, a_over(0, 0)
, _a_appearance(animation(this, &FlatCheckbox::step_appearance))
, _text(text)
, _opacity(1)
, _checked(checked) {
connect(this, SIGNAL(clicked()), this, SLOT(onClicked()));
connect(this, SIGNAL(stateChanged(int, ButtonStateChangeSource)), this, SLOT(onStateChange(int, ButtonStateChangeSource)));
setCursor(_st.cursor);
@@ -60,17 +65,17 @@ void FlatCheckbox::onClicked() {
void FlatCheckbox::onStateChange(int oldState, ButtonStateChangeSource source) {
if ((_state & StateOver) && !(oldState & StateOver)) {
a_over.start(1);
anim::start(this);
_a_appearance.start();
} else if (!(_state & StateOver) && (oldState & StateOver)) {
a_over.start(0);
anim::start(this);
_a_appearance.start();
}
if ((_state & StateDisabled) && !(oldState & StateDisabled)) {
setCursor(_st.disabledCursor);
anim::start(this);
_a_appearance.start();
} else if (!(_state & StateDisabled) && (oldState & StateDisabled)) {
setCursor(_st.cursor);
anim::start(this);
_a_appearance.start();
}
}
@@ -114,17 +119,15 @@ void FlatCheckbox::paintEvent(QPaintEvent *e) {
}
}
bool FlatCheckbox::animStep(float64 ms) {
void FlatCheckbox::step_appearance(float64 ms, bool timer) {
float64 dt = ms / _st.duration;
bool res = true;
if (dt >= 1) {
_a_appearance.stop();
a_over.finish();
res = false;
} else {
a_over.update(dt, _st.bgFunc);
}
update();
return res;
if (timer) update();
}
template <typename Type>
@@ -135,7 +138,8 @@ public:
TemplateRadiobuttonsGroup(const QString &name) : _name(name), _val(0) {
}
void remove(Type * const &radio);
void remove(Type * const &radio) {
}
int32 val() const {
return _val;
}
@@ -232,12 +236,16 @@ FlatRadiobutton::~FlatRadiobutton() {
reinterpret_cast<FlatRadiobuttonGroup*>(_group)->remove(this);
}
Checkbox::Checkbox(QWidget *parent, const QString &text, bool checked, const style::Checkbox &st) : Button(parent),
_st(st),
a_over(0), a_checked(checked ? 1 : 0),
_a_over(animFunc(this, &Checkbox::animStep_over)), _a_checked(animFunc(this, &Checkbox::animStep_checked)),
_text(text), _fullText(text), _textWidth(st.font->width(text)),
_checked(checked) {
Checkbox::Checkbox(QWidget *parent, const QString &text, bool checked, const style::Checkbox &st) : Button(parent)
, _st(st)
, a_over(0)
, a_checked(checked ? 1 : 0)
, _a_over(animation(this, &Checkbox::step_over))
, _a_checked(animation(this, &Checkbox::step_checked))
, _text(text)
, _fullText(text)
, _textWidth(st.font->width(text))
, _checked(checked) {
if (_st.width <= 0) {
resize(_textWidth - _st.width, _st.height);
} else {
@@ -275,30 +283,26 @@ void Checkbox::setChecked(bool checked) {
}
}
bool Checkbox::animStep_over(float64 ms) {
void Checkbox::step_over(float64 ms, bool timer) {
float64 dt = ms / _st.duration;
bool res = true;
if (dt >= 1) {
_a_over.stop();
a_over.finish();
res = false;
} else {
a_over.update(dt, anim::linear);
}
update(_checkRect);
return res;
if (timer) update(_checkRect);
}
bool Checkbox::animStep_checked(float64 ms) {
void Checkbox::step_checked(float64 ms, bool timer) {
float64 dt = ms / _st.duration;
bool res = true;
if (dt >= 1) {
a_checked.finish();
res = false;
_a_checked.stop();
} else {
a_checked.update(dt, anim::linear);
}
update(_checkRect);
return res;
if (timer) update(_checkRect);
}
void Checkbox::paintEvent(QPaintEvent *e) {
@@ -372,12 +376,18 @@ void Checkbox::onStateChange(int oldState, ButtonStateChangeSource source) {
}
}
Radiobutton::Radiobutton(QWidget *parent, const QString &group, int32 value, const QString &text, bool checked, const style::Radiobutton &st) : Button(parent),
_st(st),
a_over(0), a_checked(checked ? 1 : 0),
_a_over(animFunc(this, &Radiobutton::animStep_over)), _a_checked(animFunc(this, &Radiobutton::animStep_checked)),
_text(text), _fullText(text), _textWidth(st.font->width(text)),
_checked(checked), _group(radiobuttons.reg(group)), _value(value) {
Radiobutton::Radiobutton(QWidget *parent, const QString &group, int32 value, const QString &text, bool checked, const style::Radiobutton &st) : Button(parent)
, _st(st)
, a_over(0)
, a_checked(checked ? 1 : 0)
, _a_over(animation(this, &Radiobutton::step_over))
, _a_checked(animation(this, &Radiobutton::step_checked))
, _text(text)
, _fullText(text)
, _textWidth(st.font->width(text))
, _checked(checked)
, _group(radiobuttons.reg(group))
, _value(value) {
if (_st.width <= 0) {
resize(_textWidth - _st.width, _st.height);
} else {
@@ -419,30 +429,26 @@ void Radiobutton::setChecked(bool checked) {
}
}
bool Radiobutton::animStep_over(float64 ms) {
void Radiobutton::step_over(float64 ms, bool timer) {
float64 dt = ms / _st.duration;
bool res = true;
if (dt >= 1) {
_a_over.stop();
a_over.finish();
res = false;
} else {
a_over.update(dt, anim::linear);
}
update(_checkRect);
return res;
if (timer) update(_checkRect);
}
bool Radiobutton::animStep_checked(float64 ms) {
void Radiobutton::step_checked(float64 ms, bool timer) {
float64 dt = ms / _st.duration;
bool res = true;
if (dt >= 1) {
a_checked.finish();
res = false;
_a_checked.stop();
} else {
a_checked.update(dt, anim::linear);
}
update(_checkRect);
return res;
if (timer) update(_checkRect);
}
void Radiobutton::paintEvent(QPaintEvent *e) {

View File

@@ -22,7 +22,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
#include "gui/button.h"
class FlatCheckbox : public Button, public Animated {
class FlatCheckbox : public Button {
Q_OBJECT
public:
@@ -32,7 +32,7 @@ public:
bool checked() const;
void setChecked(bool checked);
bool animStep(float64 ms);
void step_appearance(float64 ms, bool timer);
void paintEvent(QPaintEvent *e);
void setOpacity(float64 o);
@@ -50,6 +50,8 @@ private:
style::flatCheckbox _st;
anim::fvalue a_over;
Animation _a_appearance;
QString _text;
style::font _font;
@@ -91,8 +93,8 @@ public:
bool checked() const;
void setChecked(bool checked);
bool animStep_over(float64 ms);
bool animStep_checked(float64 ms);
void step_over(float64 ms, bool timer);
void step_checked(float64 ms, bool timer);
void paintEvent(QPaintEvent *e);
@@ -133,8 +135,8 @@ public:
return _value;
}
bool animStep_over(float64 ms);
bool animStep_checked(float64 ms);
void step_over(float64 ms, bool timer);
void step_checked(float64 ms, bool timer);
void paintEvent(QPaintEvent *e);

View File

@@ -51,10 +51,20 @@ namespace {
InputStyle<MaskedInputField> _inputFieldStyle;
}
FlatInput::FlatInput(QWidget *parent, const style::flatInput &st, const QString &pholder, const QString &v) : QLineEdit(v, parent),
_oldtext(v), _fullph(pholder), _fastph(false), _customUpDown(false), _phVisible(!v.length()),
a_phLeft(_phVisible ? 0 : st.phShift), a_phAlpha(_phVisible ? 1 : 0), a_phColor(st.phColor->c),
a_borderColor(st.borderColor->c), a_bgColor(st.bgColor->c), _notingBene(0), _st(st) {
FlatInput::FlatInput(QWidget *parent, const style::flatInput &st, const QString &pholder, const QString &v) : QLineEdit(v, parent)
, _oldtext(v)
, _fullph(pholder)
, _fastph(false)
, _customUpDown(false)
, _phVisible(!v.length())
, a_phLeft(_phVisible ? 0 : st.phShift)
, a_phAlpha(_phVisible ? 1 : 0)
, a_phColor(st.phColor->c)
, a_borderColor(st.borderColor->c)
, a_bgColor(st.bgColor->c)
, _a_appearance(animation(this, &FlatInput::step_appearance))
, _notingBene(0)
, _st(st) {
resize(_st.width, _st.height);
setFont(_st.font->f);
@@ -158,7 +168,7 @@ void FlatInput::paintEvent(QPaintEvent *e) {
}
bool phDraw = _phVisible;
if (animating()) {
if (_a_appearance.animating()) {
p.setOpacity(a_phAlpha.current());
phDraw = true;
}
@@ -180,7 +190,7 @@ void FlatInput::focusInEvent(QFocusEvent *e) {
a_borderColor.start(_st.borderActive->c);
}
a_bgColor.start(_st.bgActive->c);
anim::start(this);
_a_appearance.start();
QLineEdit::focusInEvent(e);
emit focused();
}
@@ -191,7 +201,7 @@ void FlatInput::focusOutEvent(QFocusEvent *e) {
a_borderColor.start(_st.borderColor->c);
}
a_bgColor.start(_st.bgColor->c);
anim::start(this);
_a_appearance.start();
QLineEdit::focusOutEvent(e);
emit blurred();
}
@@ -224,11 +234,10 @@ QSize FlatInput::minimumSizeHint() const {
return geometry().size();
}
bool FlatInput::animStep(float64 ms) {
void FlatInput::step_appearance(float64 ms, bool timer) {
float dt = ms / _st.phDuration;
bool res = true;
if (dt >= 1) {
res = false;
_a_appearance.stop();
a_phLeft.finish();
a_phAlpha.finish();
a_phColor.finish();
@@ -236,8 +245,8 @@ bool FlatInput::animStep(float64 ms) {
if (_notingBene > 0) {
_notingBene = -1;
a_borderColor.start((hasFocus() ? _st.borderActive : _st.borderColor)->c);
anim::start(this);
return true;
_a_appearance.start();
return;
} else if (_notingBene) {
_notingBene = 0;
}
@@ -249,8 +258,7 @@ bool FlatInput::animStep(float64 ms) {
a_bgColor.update(dt, _st.phColorFunc);
a_borderColor.update(dt, _st.phColorFunc);
}
update();
return res;
if (timer) update();
}
void FlatInput::setPlaceholder(const QString &ph) {
@@ -279,7 +287,7 @@ void FlatInput::updatePlaceholder() {
} else {
a_phLeft.start(vis ? 0 : _st.phShift);
a_phAlpha.start(vis ? 1 : 0);
anim::start(this);
_a_appearance.start();
}
_phVisible = vis;
}
@@ -345,11 +353,11 @@ void FlatInput::notaBene() {
_notingBene = 1;
setFocus();
a_borderColor.start(_st.borderError->c);
anim::start(this);
_a_appearance.start();
}
CountryCodeInput::CountryCodeInput(QWidget *parent, const style::flatInput &st) : FlatInput(parent, st), _nosignal(false) {
CountryCodeInput::CountryCodeInput(QWidget *parent, const style::flatInput &st) : FlatInput(parent, st)
, _nosignal(false) {
}
void CountryCodeInput::startErasing(QKeyEvent *e) {
@@ -541,38 +549,39 @@ void PhonePartInput::onChooseCode(const QString &code) {
updatePlaceholder();
}
InputArea::InputArea(QWidget *parent, const style::InputArea &st, const QString &ph, const QString &val) : TWidget(parent),
_maxLength(-1),
_inner(this),
_oldtext(val),
InputArea::InputArea(QWidget *parent, const style::InputArea &st, const QString &ph, const QString &val) : TWidget(parent)
, _maxLength(-1)
, _inner(this)
, _oldtext(val)
_ctrlEnterSubmit(CtrlEnterSubmitCtrlEnter),
_undoAvailable(false),
_redoAvailable(false),
_inHeightCheck(false),
, _ctrlEnterSubmit(CtrlEnterSubmitCtrlEnter)
, _undoAvailable(false)
, _redoAvailable(false)
, _inHeightCheck(false)
_customUpDown(false),
, _customUpDown(false)
_placeholderFull(ph),
_placeholderVisible(val.isEmpty()),
a_placeholderLeft(_placeholderVisible ? 0 : st.placeholderShift),
a_placeholderOpacity(_placeholderVisible ? 1 : 0),
a_placeholderFg(st.placeholderFg->c),
_a_placeholderFg(animFunc(this, &InputArea::animStep_placeholderFg)),
_a_placeholderShift(animFunc(this, &InputArea::animStep_placeholderShift)),
, _placeholderFull(ph)
, _placeholderVisible(val.isEmpty())
, a_placeholderLeft(_placeholderVisible ? 0 : st.placeholderShift)
, a_placeholderOpacity(_placeholderVisible ? 1 : 0)
, a_placeholderFg(st.placeholderFg->c)
, _a_placeholderFg(animation(this, &InputArea::step_placeholderFg))
, _a_placeholderShift(animation(this, &InputArea::step_placeholderShift))
a_borderOpacityActive(0),
a_borderFg(st.borderFg->c),
_a_border(animFunc(this, &InputArea::animStep_border)),
, a_borderOpacityActive(0)
, a_borderFg(st.borderFg->c)
, _a_border(animation(this, &InputArea::step_border))
_focused(false), _error(false),
, _focused(false)
, _error(false)
_st(st),
, _st(st)
_touchPress(false),
_touchRightButton(false),
_touchMove(false),
_correcting(false) {
, _touchPress(false)
, _touchRightButton(false)
, _touchMove(false)
, _correcting(false) {
_inner.setAcceptRichText(false);
resize(_st.width, _st.heightMin);
@@ -1106,47 +1115,42 @@ void InputArea::onRedoAvailable(bool avail) {
if (App::wnd()) App::wnd()->updateGlobalMenu();
}
bool InputArea::animStep_placeholderFg(float64 ms) {
float dt = ms / _st.duration;
bool res = true;
void InputArea::step_placeholderFg(float64 ms, bool timer) {
float64 dt = ms / _st.duration;
if (dt >= 1) {
res = false;
_a_placeholderFg.stop();
a_placeholderFg.finish();
} else {
a_placeholderFg.update(dt, anim::linear);
}
update();
return res;
if (timer) update();
}
bool InputArea::animStep_placeholderShift(float64 ms) {
float dt = ms / _st.duration;
bool res = true;
void InputArea::step_placeholderShift(float64 ms, bool timer) {
float64 dt = ms / _st.duration;
if (dt >= 1) {
res = false;
_a_placeholderShift.stop();
a_placeholderLeft.finish();
a_placeholderOpacity.finish();
} else {
a_placeholderLeft.update(dt, anim::linear);
a_placeholderOpacity.update(dt, anim::linear);
}
update();
return res;
if (timer) update();
}
bool InputArea::animStep_border(float64 ms) {
float dt = ms / _st.duration;
void InputArea::step_border(float64 ms, bool timer) {
float64 dt = ms / _st.duration;
bool res = true;
if (dt >= 1) {
res = false;
_a_border.stop();
a_borderFg.finish();
a_borderOpacityActive.finish();
} else {
a_borderFg.update(dt, anim::linear);
a_borderOpacityActive.update(dt, anim::linear);
}
update();
return res;
if (timer) update();
}
void InputArea::updatePlaceholder() {
@@ -1261,36 +1265,37 @@ void InputArea::showError() {
}
}
InputField::InputField(QWidget *parent, const style::InputField &st, const QString &ph, const QString &val) : TWidget(parent),
_maxLength(-1),
_inner(this),
_oldtext(val),
InputField::InputField(QWidget *parent, const style::InputField &st, const QString &ph, const QString &val) : TWidget(parent)
, _maxLength(-1)
, _inner(this)
, _oldtext(val)
_undoAvailable(false),
_redoAvailable(false),
, _undoAvailable(false)
, _redoAvailable(false)
_customUpDown(true),
, _customUpDown(true)
_placeholderFull(ph),
_placeholderVisible(val.isEmpty()),
a_placeholderLeft(_placeholderVisible ? 0 : st.placeholderShift),
a_placeholderOpacity(_placeholderVisible ? 1 : 0),
a_placeholderFg(st.placeholderFg->c),
_a_placeholderFg(animFunc(this, &InputField::animStep_placeholderFg)),
_a_placeholderShift(animFunc(this, &InputField::animStep_placeholderShift)),
, _placeholderFull(ph)
, _placeholderVisible(val.isEmpty())
, a_placeholderLeft(_placeholderVisible ? 0 : st.placeholderShift)
, a_placeholderOpacity(_placeholderVisible ? 1 : 0)
, a_placeholderFg(st.placeholderFg->c)
, _a_placeholderFg(animation(this, &InputField::step_placeholderFg))
, _a_placeholderShift(animation(this, &InputField::step_placeholderShift))
a_borderOpacityActive(0),
a_borderFg(st.borderFg->c),
_a_border(animFunc(this, &InputField::animStep_border)),
, a_borderOpacityActive(0)
, a_borderFg(st.borderFg->c)
, _a_border(animation(this, &InputField::step_border))
_focused(false), _error(false),
, _focused(false)
, _error(false)
_st(st),
, _st(st)
_touchPress(false),
_touchRightButton(false),
_touchMove(false),
_correcting(false) {
, _touchPress(false)
, _touchRightButton(false)
, _touchMove(false)
, _correcting(false) {
_inner.setAcceptRichText(false);
resize(_st.width, _st.height);
@@ -1834,47 +1839,41 @@ void InputField::selectAll() {
_inner.setTextCursor(c);
}
bool InputField::animStep_placeholderFg(float64 ms) {
float dt = ms / _st.duration;
bool res = true;
void InputField::step_placeholderFg(float64 ms, bool timer) {
float64 dt = ms / _st.duration;
if (dt >= 1) {
res = false;
_a_placeholderFg.stop();
a_placeholderFg.finish();
} else {
a_placeholderFg.update(dt, anim::linear);
}
update();
return res;
if (timer) update();
}
bool InputField::animStep_placeholderShift(float64 ms) {
float dt = ms / _st.duration;
bool res = true;
void InputField::step_placeholderShift(float64 ms, bool timer) {
float64 dt = ms / _st.duration;
if (dt >= 1) {
res = false;
_a_placeholderShift.stop();
a_placeholderLeft.finish();
a_placeholderOpacity.finish();
} else {
a_placeholderLeft.update(dt, anim::linear);
a_placeholderOpacity.update(dt, anim::linear);
}
update();
return res;
if (timer) update();
}
bool InputField::animStep_border(float64 ms) {
float dt = ms / _st.duration;
bool res = true;
void InputField::step_border(float64 ms, bool timer) {
float64 dt = ms / _st.duration;
if (dt >= 1) {
res = false;
_a_border.stop();
a_borderFg.finish();
a_borderOpacityActive.finish();
} else {
a_borderFg.update(dt, anim::linear);
a_borderOpacityActive.update(dt, anim::linear);
}
update();
return res;
if (timer) update();
}
void InputField::updatePlaceholder() {
@@ -1981,34 +1980,35 @@ void InputField::showError() {
}
}
MaskedInputField::MaskedInputField(QWidget *parent, const style::InputField &st, const QString &placeholder, const QString &val) : QLineEdit(val, parent),
_st(st),
_maxLength(-1),
_oldtext(val),
MaskedInputField::MaskedInputField(QWidget *parent, const style::InputField &st, const QString &placeholder, const QString &val) : QLineEdit(val, parent)
, _st(st)
, _maxLength(-1)
, _oldtext(val)
_undoAvailable(false),
_redoAvailable(false),
, _undoAvailable(false)
, _redoAvailable(false)
_customUpDown(false),
, _customUpDown(false)
_placeholderFull(placeholder),
_placeholderVisible(val.isEmpty()),
_placeholderFast(false),
a_placeholderLeft(_placeholderVisible ? 0 : st.placeholderShift),
a_placeholderOpacity(_placeholderVisible ? 1 : 0),
a_placeholderFg(st.placeholderFg->c),
_a_placeholderFg(animFunc(this, &MaskedInputField::animStep_placeholderFg)),
_a_placeholderShift(animFunc(this, &MaskedInputField::animStep_placeholderShift)),
, _placeholderFull(placeholder)
, _placeholderVisible(val.isEmpty())
, _placeholderFast(false)
, a_placeholderLeft(_placeholderVisible ? 0 : st.placeholderShift)
, a_placeholderOpacity(_placeholderVisible ? 1 : 0)
, a_placeholderFg(st.placeholderFg->c)
, _a_placeholderFg(animation(this, &MaskedInputField::step_placeholderFg))
, _a_placeholderShift(animation(this, &MaskedInputField::step_placeholderShift))
a_borderOpacityActive(0),
a_borderFg(st.borderFg->c),
_a_border(animFunc(this, &MaskedInputField::animStep_border)),
, a_borderOpacityActive(0)
, a_borderFg(st.borderFg->c)
, _a_border(animation(this, &MaskedInputField::step_border))
_focused(false), _error(false),
, _focused(false)
, _error(false)
_touchPress(false),
_touchRightButton(false),
_touchMove(false) {
, _touchPress(false)
, _touchRightButton(false)
, _touchMove(false) {
resize(_st.width, _st.height);
setFont(_st.font->f);
@@ -2188,47 +2188,41 @@ QSize MaskedInputField::minimumSizeHint() const {
return geometry().size();
}
bool MaskedInputField::animStep_placeholderFg(float64 ms) {
float dt = ms / _st.duration;
bool res = true;
void MaskedInputField::step_placeholderFg(float64 ms, bool timer) {
float64 dt = ms / _st.duration;
if (dt >= 1) {
res = false;
_a_placeholderFg.stop();
a_placeholderFg.finish();
} else {
a_placeholderFg.update(dt, anim::linear);
}
update();
return res;
if (timer) update();
}
bool MaskedInputField::animStep_placeholderShift(float64 ms) {
float dt = ms / _st.duration;
bool res = true;
void MaskedInputField::step_placeholderShift(float64 ms, bool timer) {
float64 dt = ms / _st.duration;
if (dt >= 1) {
res = false;
_a_placeholderShift.stop();
a_placeholderLeft.finish();
a_placeholderOpacity.finish();
} else {
a_placeholderLeft.update(dt, anim::linear);
a_placeholderOpacity.update(dt, anim::linear);
}
update();
return res;
if (timer) update();
}
bool MaskedInputField::animStep_border(float64 ms) {
float dt = ms / _st.duration;
bool res = true;
void MaskedInputField::step_border(float64 ms, bool timer) {
float64 dt = ms / _st.duration;
if (dt >= 1) {
res = false;
_a_border.stop();
a_borderFg.finish();
a_borderOpacityActive.finish();
} else {
a_borderFg.update(dt, anim::linear);
a_borderOpacityActive.update(dt, anim::linear);
}
update();
return res;
if (timer) update();
}
bool MaskedInputField::setPlaceholder(const QString &placeholder) {

View File

@@ -23,7 +23,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
#include "style.h"
#include "animation.h"
class FlatInput : public QLineEdit, public Animated {
class FlatInput : public QLineEdit {
Q_OBJECT
T_WIDGET
@@ -50,7 +50,7 @@ public:
QRect getTextRect() const;
bool animStep(float64 ms);
void step_appearance(float64 ms, bool timer);
QSize sizeHint() const;
QSize minimumSizeHint() const;
@@ -98,6 +98,7 @@ private:
anim::ivalue a_phLeft;
anim::fvalue a_phAlpha;
anim::cvalue a_phColor, a_borderColor, a_bgColor;
Animation _a_appearance;
int _notingBene;
style::flatInput _st;
@@ -196,9 +197,9 @@ public:
}
void updatePlaceholder();
bool animStep_placeholderFg(float64 ms);
bool animStep_placeholderShift(float64 ms);
bool animStep_border(float64 ms);
void step_placeholderFg(float64 ms, bool timer);
void step_placeholderShift(float64 ms, bool timer);
void step_border(float64 ms, bool timer);
QSize sizeHint() const;
QSize minimumSizeHint() const;
@@ -354,9 +355,9 @@ public:
}
void updatePlaceholder();
bool animStep_placeholderFg(float64 ms);
bool animStep_placeholderShift(float64 ms);
bool animStep_border(float64 ms);
void step_placeholderFg(float64 ms, bool timer);
void step_placeholderShift(float64 ms, bool timer);
void step_border(float64 ms, bool timer);
QSize sizeHint() const;
QSize minimumSizeHint() const;
@@ -523,9 +524,9 @@ public:
QRect getTextRect() const;
bool animStep_placeholderFg(float64 ms);
bool animStep_placeholderShift(float64 ms);
bool animStep_border(float64 ms);
void step_placeholderFg(float64 ms, bool timer);
void step_placeholderShift(float64 ms, bool timer);
void step_border(float64 ms, bool timer);
QSize sizeHint() const;
QSize minimumSizeHint() const;

View File

@@ -24,12 +24,27 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
#include "flattextarea.h"
#include "window.h"
FlatTextarea::FlatTextarea(QWidget *parent, const style::flatTextarea &st, const QString &pholder, const QString &v) : QTextEdit(parent),
_minHeight(-1), _maxHeight(-1), _maxLength(-1), _ctrlEnterSubmit(true),
_oldtext(v), _phVisible(!v.length()),
a_phLeft(_phVisible ? 0 : st.phShift), a_phAlpha(_phVisible ? 1 : 0), a_phColor(st.phColor->c),
_st(st), _undoAvailable(false), _redoAvailable(false), _inDrop(false), _inHeightCheck(false), _fakeMargin(0),
_touchPress(false), _touchRightButton(false), _touchMove(false), _correcting(false) {
FlatTextarea::FlatTextarea(QWidget *parent, const style::flatTextarea &st, const QString &pholder, const QString &v) : QTextEdit(parent)
, _minHeight(-1)
, _maxHeight(-1)
, _maxLength(-1)
, _ctrlEnterSubmit(true)
, _oldtext(v)
, _phVisible(!v.length())
, a_phLeft(_phVisible ? 0 : st.phShift)
, a_phAlpha(_phVisible ? 1 : 0)
, a_phColor(st.phColor->c)
, _a_appearance(animation(this, &FlatTextarea::step_appearance))
, _st(st)
, _undoAvailable(false)
, _redoAvailable(false)
, _inDrop(false)
, _inHeightCheck(false)
, _fakeMargin(0)
, _touchPress(false)
, _touchRightButton(false)
, _touchMove(false)
, _correcting(false) {
setAcceptRichText(false);
resize(_st.width, _st.font->height);
@@ -74,10 +89,10 @@ _touchPress(false), _touchRightButton(false), _touchMove(false), _correcting(fal
void FlatTextarea::setTextFast(const QString &text) {
setPlainText(text);
if (animating()) {
if (_a_appearance.animating()) {
a_phLeft.finish();
a_phAlpha.finish();
anim::stop(this);
_a_appearance.stop();
update();
}
}
@@ -184,7 +199,7 @@ void FlatTextarea::paintEvent(QPaintEvent *e) {
QRect r(rect().intersected(e->rect()));
p.fillRect(r, _st.bgColor->b);
bool phDraw = _phVisible;
if (animating()) {
if (_a_appearance.animating()) {
p.setOpacity(a_phAlpha.current());
phDraw = true;
}
@@ -203,13 +218,13 @@ void FlatTextarea::paintEvent(QPaintEvent *e) {
void FlatTextarea::focusInEvent(QFocusEvent *e) {
a_phColor.start(_st.phFocusColor->c);
anim::start(this);
_a_appearance.start();
QTextEdit::focusInEvent(e);
}
void FlatTextarea::focusOutEvent(QFocusEvent *e) {
a_phColor.start(_st.phColor->c);
anim::start(this);
_a_appearance.start();
QTextEdit::focusOutEvent(e);
}
@@ -807,11 +822,10 @@ void FlatTextarea::onRedoAvailable(bool avail) {
if (App::wnd()) App::wnd()->updateGlobalMenu();
}
bool FlatTextarea::animStep(float64 ms) {
void FlatTextarea::step_appearance(float64 ms, bool timer) {
float dt = ms / _st.phDuration;
bool res = true;
if (dt >= 1) {
res = false;
_a_appearance.stop();
a_phLeft.finish();
a_phAlpha.finish();
a_phColor.finish();
@@ -823,8 +837,7 @@ bool FlatTextarea::animStep(float64 ms) {
a_phAlpha.update(dt, _st.phAlphaFunc);
a_phColor.update(dt, _st.phColorFunc);
}
update();
return res;
if (timer) update();
}
void FlatTextarea::setPlaceholder(const QString &ph) {
@@ -839,7 +852,7 @@ void FlatTextarea::updatePlaceholder() {
a_phLeft.start(vis ? 0 : _st.phShift);
a_phAlpha.start(vis ? 1 : 0);
anim::start(this);
_a_appearance.start();
_phVisible = vis;
}

View File

@@ -24,7 +24,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
#include "style.h"
#include "animation.h"
class FlatTextarea : public QTextEdit, public Animated {
class FlatTextarea : public QTextEdit {
Q_OBJECT
T_WIDGET
@@ -56,7 +56,7 @@ public:
QRect getTextRect() const;
int32 fakeMargin() const;
bool animStep(float64 ms);
void step_appearance(float64 ms, bool timer);
QSize sizeHint() const;
QSize minimumSizeHint() const;
@@ -127,6 +127,8 @@ private:
anim::ivalue a_phLeft;
anim::fvalue a_phAlpha;
anim::cvalue a_phColor;
Animation _a_appearance;
style::flatTextarea _st;
bool _undoAvailable, _redoAvailable, _inDrop, _inHeightCheck;

View File

@@ -36,7 +36,7 @@ PopupMenu::PopupMenu(const style::PopupMenu &st) : TWidget(0)
, _selected(-1)
, _childMenuIndex(-1)
, a_opacity(1)
, _a_hide(animFunc(this, &PopupMenu::animStep_hide))
, _a_hide(animation(this, &PopupMenu::step_hide))
, _deleteOnHide(true)
, _triggering(false)
, _deleteLater(false) {
@@ -54,7 +54,7 @@ PopupMenu::PopupMenu(QMenu *menu, const style::PopupMenu &st) : TWidget(0)
, _selected(-1)
, _childMenuIndex(-1)
, a_opacity(1)
, _a_hide(animFunc(this, &PopupMenu::animStep_hide))
, _a_hide(animation(this, &PopupMenu::step_hide))
, _deleteOnHide(true)
, _triggering(false)
, _deleteLater(false) {
@@ -440,18 +440,16 @@ void PopupMenu::hideFinish() {
hide();
}
bool PopupMenu::animStep_hide(float64 ms) {
void PopupMenu::step_hide(float64 ms, bool timer) {
float64 dt = ms / _st.duration;
bool res = true;
if (dt >= 1) {
_a_hide.stop();
a_opacity.finish();
hideFinish();
res = false;
} else {
a_opacity.update(dt, anim::linear);
}
update();
return res;
if (timer) update();
}
void PopupMenu::deleteOnHide(bool del) {

View File

@@ -59,7 +59,7 @@ private:
void childHiding(PopupMenu *child);
bool animStep_hide(float64 ms);
void step_hide(float64 ms, bool timer);
void init();
void hideFinish();

View File

@@ -38,12 +38,20 @@ void ScrollShadow::changeVisibility(bool shown) {
setVisible(shown);
}
ScrollBar::ScrollBar(ScrollArea *parent, bool vert, const style::flatScroll *st) : QWidget(parent), _st(st), _vertical(vert),
_over(false), _overbar(false), _moving(false), _topSh(false), _bottomSh(false),
_connected(vert ? parent->verticalScrollBar() : parent->horizontalScrollBar()),
_scrollMax(_connected->maximum()), _hideIn(-1),
a_bg((_st->hiding ? st::transparent : _st->bgColor)->c),
a_bar((_st->hiding ? st::transparent : _st->barColor)->c) {
ScrollBar::ScrollBar(ScrollArea *parent, bool vert, const style::flatScroll *st) : QWidget(parent)
, _st(st)
, _vertical(vert)
, _over(false)
, _overbar(false)
, _moving(false)
, _topSh(false)
, _bottomSh(false)
, _connected(vert ? parent->verticalScrollBar() : parent->horizontalScrollBar())
, _scrollMax(_connected->maximum())
, _hideIn(-1)
, a_bg((_st->hiding ? st::transparent : _st->bgColor)->c)
, a_bar((_st->hiding ? st::transparent : _st->barColor)->c)
, _a_appearance(animation(this, &ScrollBar::step_appearance)) {
recountSize();
_hideTimer.setSingleShot(true);
@@ -115,7 +123,7 @@ void ScrollBar::onHideTimer() {
_hideIn = -1;
a_bg.start(QColor(a_bg.current().red(), a_bg.current().green(), a_bg.current().blue(), 0));
a_bar.start(QColor(a_bar.current().red(), a_bar.current().green(), a_bar.current().blue(), 0));
anim::start(this);
_a_appearance.start();
}
ScrollArea *ScrollBar::area() {
@@ -144,26 +152,24 @@ void ScrollBar::paintEvent(QPaintEvent *e) {
}
}
bool ScrollBar::animStep(float64 ms) {
void ScrollBar::step_appearance(float64 ms, bool timer) {
float64 dt = ms / _st->duration;
bool res = true;
if (dt >= 1) {
_a_appearance.stop();
a_bg.finish();
a_bar.finish();
res = false;
} else {
a_bg.update(dt, anim::linear);
a_bar.update(dt, anim::linear);
}
update();
return res;
if (timer) update();
}
void ScrollBar::hideTimeout(int64 dt) {
if (_hideIn < 0) {
a_bg.start((_over ? _st->bgOverColor : _st->bgColor)->c);
a_bar.start((_overbar ? _st->barOverColor : _st->barColor)->c);
anim::start(this);
_a_appearance.start();
}
_hideIn = dt;
if (!_moving && _hideIn >= 0) {
@@ -177,7 +183,7 @@ void ScrollBar::enterEvent(QEvent *e) {
_over = true;
a_bg.start(_st->bgOverColor->c);
a_bar.start(_st->barColor->c);
anim::start(this);
_a_appearance.start();
}
void ScrollBar::leaveEvent(QEvent *e) {
@@ -185,7 +191,7 @@ void ScrollBar::leaveEvent(QEvent *e) {
setMouseTracking(false);
a_bg.start(_st->bgColor->c);
a_bar.start(_st->barColor->c);
anim::start(this);
_a_appearance.start();
if (_hideIn >= 0) {
_hideTimer.start(_hideIn);
} else if (_st->hiding) {
@@ -202,7 +208,7 @@ void ScrollBar::mouseMoveEvent(QMouseEvent *e) {
if (!_moving) {
a_bar.start((newOverBar ? _st->barOverColor : _st->barColor)->c);
a_bg.start(_st->bgOverColor->c);
anim::start(this);
_a_appearance.start();
}
}
if (_moving) {
@@ -232,7 +238,7 @@ void ScrollBar::mousePressEvent(QMouseEvent *e) {
_overbar = true;
a_bar.start(_st->barOverColor->c);
a_bg.start(_st->bgOverColor->c);
anim::start(this);
_a_appearance.start();
}
}
emit area()->scrollStarted();
@@ -257,7 +263,7 @@ void ScrollBar::mouseReleaseEvent(QMouseEvent *e) {
_hideTimer.start(_hideIn);
}
}
if (a) anim::start(this);
if (a) _a_appearance.start();
emit area()->scrollFinished();
}
if (!_over) {

View File

@@ -50,7 +50,7 @@ private:
};
class ScrollBar : public QWidget, public Animated {
class ScrollBar : public QWidget {
Q_OBJECT
public:
@@ -67,7 +67,7 @@ public:
void mouseReleaseEvent(QMouseEvent *e);
void resizeEvent(QResizeEvent *e);
bool animStep(float64 ms);
void step_appearance(float64 ms, bool timer);
void hideTimeout(int64 dt);
@@ -100,6 +100,8 @@ private:
QTimer _hideTimer;
anim::cvalue a_bg, a_bar;
Animation _a_appearance;
QRect _bar;
};

View File

@@ -1,160 +0,0 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
*/
#include "stdafx.h"
#include "switcher.h"
Switcher::Switcher(QWidget *parent, const style::switcher &st) : TWidget(parent)
, _selected(0)
, _over(-1)
, _wasOver(-1)
, _pressed(-1)
, _st(st)
, a_bgOver(_st.bgColor->c)
, a_bgWasOver(_st.bgHovered->c) {
resize(width(), _st.height);
}
void Switcher::leaveEvent(QEvent *e) {
setOver(-1);
if (_pressed >= 0) return;
setMouseTracking(false);
return TWidget::leaveEvent(e);
}
void Switcher::enterEvent(QEvent *e) {
setMouseTracking(true);
return TWidget::enterEvent(e);
}
void Switcher::mousePressEvent(QMouseEvent *e) {
if (e->buttons() & Qt::LeftButton) {
mouseMoveEvent(e);
if (_over != _pressed) {
_pressed = _over;
e->accept();
}
}
}
void Switcher::mouseMoveEvent(QMouseEvent *e) {
if (rect().contains(e->pos())) {
if (width()) {
setOver((e->pos().x() * _buttons.size()) / width());
}
} else {
setOver(-1);
}
}
void Switcher::mouseReleaseEvent(QMouseEvent *e) {
if (_pressed >= 0) {
if (_pressed == _over && _pressed != _selected) {
setSelected(_pressed);
} else {
setSelected(_selected);
}
} else {
leaveEvent(e);
}
}
void Switcher::addButton(const QString &btn) {
_buttons.push_back(btn);
update();
}
bool Switcher::animStep(float64 ms) {
float64 dt = ms / _st.duration;
bool res = true;
if (dt >= 1) {
res = false;
a_bgOver.finish();
a_bgWasOver.finish();
} else {
a_bgOver.update(dt, anim::linear);
a_bgWasOver.update(dt, anim::linear);
}
update();
return res;
}
void Switcher::paintEvent(QPaintEvent *e) {
QPainter p(this);
p.fillRect(rect(), _st.bgColor->b);
if (!_buttons.isEmpty()) {
p.setFont(_st.font->f);
float64 btnWidth = float64(width()) / _buttons.size();
for (int i = 0; i < _buttons.size(); ++i) {
QRect btnRect(qRound(i * btnWidth), 0, qRound((i + 1) * btnWidth) - qRound(i * btnWidth), height());
if (i == _selected) {
p.fillRect(btnRect, _st.bgActive->b);
} else if (i == _over) {
p.fillRect(btnRect, a_bgOver.current());
} else if (i == _wasOver) {
p.fillRect(btnRect, a_bgWasOver.current());
}
p.setPen((i == _selected ? _st.activeColor : _st.textColor)->p);
p.drawText(btnRect, _buttons[i], style::al_center);
}
}
if (_st.border) {
p.fillRect(0, 0, width() - _st.border, _st.border, _st.borderColor->b);
p.fillRect(width() - _st.border, 0, _st.border, height() - _st.border, _st.borderColor->b);
p.fillRect(_st.border, height() - _st.border, width() - _st.border, _st.border, _st.borderColor->b);
p.fillRect(0, _st.border, _st.border, height() - _st.border, _st.borderColor->b);
}
}
int Switcher::selected() const {
return _selected;
}
void Switcher::setSelected(int selected) {
if (selected != _selected) {
_selected = selected;
emit changed();
}
_pressed = _over = _wasOver = -1;
anim::stop(this);
setCursor(style::cur_default);
update();
}
void Switcher::setOver(int over) {
if (over != _over) {
QColor c(a_bgOver.current());
if (_wasOver == over) {
a_bgOver = anim::cvalue(a_bgWasOver.current(), _st.bgHovered->c);
} else {
a_bgOver = anim::cvalue(_st.bgColor->c, _st.bgHovered->c);
}
a_bgWasOver = anim::cvalue(c, _st.bgColor->c);
_wasOver = _over;
_over = over;
anim::start(this);
setCursor((_over >= 0 && _over != _selected) ? style::cur_pointer : style::cur_default);
}
}

View File

@@ -1,65 +0,0 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
*/
#pragma once
#include <QtWidgets/QWidget>
#include "gui/twidget.h"
class Switcher : public TWidget, public Animated {
Q_OBJECT
public:
Switcher(QWidget *parent, const style::switcher &st);
void mousePressEvent(QMouseEvent *e);
void mouseMoveEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
void paintEvent(QPaintEvent *e);
void enterEvent(QEvent *e);
void leaveEvent(QEvent *e);
void addButton(const QString &btn);
bool animStep(float64 ms);
int selected() const;
void setSelected(int selected);
signals:
void changed();
private:
void setOver(int over);
int _selected;
int _over, _wasOver, _pressed;
typedef QVector<QString> Buttons;
Buttons _buttons;
style::switcher _st;
anim::cvalue a_bgOver, a_bgWasOver;
};