-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathstretchtitlelabel.cpp
More file actions
117 lines (99 loc) · 3 KB
/
Copy pathstretchtitlelabel.cpp
File metadata and controls
117 lines (99 loc) · 3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/**
* @file stretchtitlelabel.cpp
* @brief Implements leading-letter stretch animation for the app title.
*/
#include "stretchtitlelabel.h"
#include <QAbstractAnimation>
#include <QColor>
#include <QEasingCurve>
#include <QFontMetrics>
#include <QPainter>
#include <QPaintEvent>
#include <QTimer>
#include <QVariantAnimation>
StretchTitleLabel::StretchTitleLabel(QWidget *parent)
: QLabel(parent)
{
m_anim = new QVariantAnimation(this);
m_anim->setDuration(900);
m_anim->setStartValue(1.0);
m_anim->setKeyValueAt(0.45, 1.85);
m_anim->setEndValue(1.0);
m_anim->setEasingCurve(QEasingCurve::InOutCubic);
connect(m_anim, &QVariantAnimation::valueChanged, this, [this](const QVariant &v) {
setStretch(v.toReal());
});
m_idleTimer = new QTimer(this);
m_idleTimer->setInterval(3500);
connect(m_idleTimer, &QTimer::timeout, this, &StretchTitleLabel::startStretchPulse);
m_idleTimer->start();
// First pulse shortly after the window appears.
QTimer::singleShot(900, this, &StretchTitleLabel::startStretchPulse);
}
void StretchTitleLabel::setPulseEnabled(bool enabled)
{
if (enabled) {
if (!m_idleTimer->isActive()) {
m_idleTimer->start();
}
return;
}
m_idleTimer->stop();
m_anim->stop();
setStretch(1.0);
}
qreal StretchTitleLabel::stretch() const
{
return m_stretch;
}
void StretchTitleLabel::setStretch(qreal value)
{
m_stretch = qMax(1.0, value);
update();
}
void StretchTitleLabel::startStretchPulse()
{
if (m_anim->state() == QAbstractAnimation::Running) {
return;
}
m_anim->stop();
m_anim->setCurrentTime(0);
m_anim->start();
}
void StretchTitleLabel::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
const QString full = text();
if (full.isEmpty()) {
return;
}
QPainter p(this);
p.setRenderHint(QPainter::TextAntialiasing, true);
p.setRenderHint(QPainter::Antialiasing, true);
p.setFont(font());
p.setPen(palette().color(QPalette::WindowText));
// Prefer stylesheet/color from QLabel when available.
const QColor ink = QColor(QStringLiteral("#111111"));
p.setPen(ink);
const QFontMetrics fm(font());
const QString first = full.left(1);
const QString rest = full.mid(1);
const int firstW = fm.horizontalAdvance(first);
const int restW = fm.horizontalAdvance(rest);
const int stretchedFirstW = qRound(firstW * m_stretch);
const int totalW = stretchedFirstW + restW;
const int baseY = (height() + fm.ascent() - fm.descent()) / 2;
const int startX = 0; // left-aligned like the original title block
auto drawAt = [&](int y, const QColor &color) {
p.setPen(color);
p.save();
p.translate(startX, y);
p.scale(m_stretch, 1.0);
p.drawText(0, baseY, first);
p.restore();
p.drawText(startX + stretchedFirstW, baseY + y, rest);
};
drawAt(2, QColor(0, 0, 0, 90));
drawAt(0, QColor(QStringLiteral("#111111")));
Q_UNUSED(totalW);
}