Added support of locked state to side bar button.
This commit is contained in:
parent
e2304a3c76
commit
676d8697c6
3 changed files with 133 additions and 1 deletions
|
|
@ -7,6 +7,7 @@
|
||||||
#include "ui/widgets/side_bar_button.h"
|
#include "ui/widgets/side_bar_button.h"
|
||||||
|
|
||||||
#include "ui/effects/ripple_animation.h"
|
#include "ui/effects/ripple_animation.h"
|
||||||
|
#include "styles/style_widgets.h"
|
||||||
|
|
||||||
#include <QtGui/QtEvents>
|
#include <QtGui/QtEvents>
|
||||||
|
|
||||||
|
|
@ -14,6 +15,7 @@ namespace Ui {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr auto kMaxLabelLines = 3;
|
constexpr auto kMaxLabelLines = 3;
|
||||||
|
constexpr auto kPremiumLockedOpacity = 0.6;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
@ -23,6 +25,14 @@ SideBarButton::SideBarButton(
|
||||||
const style::SideBarButton &st)
|
const style::SideBarButton &st)
|
||||||
: RippleButton(parent, st.ripple)
|
: RippleButton(parent, st.ripple)
|
||||||
, _st(st)
|
, _st(st)
|
||||||
|
, _arcPen(
|
||||||
|
_st.textFg,
|
||||||
|
// Use a divider to get 1.5.
|
||||||
|
st::sideBarButtonLockPenWidth
|
||||||
|
/ float64(st::sideBarButtonLockPenWidthDivider),
|
||||||
|
Qt::SolidLine,
|
||||||
|
Qt::SquareCap,
|
||||||
|
Qt::RoundJoin)
|
||||||
, _text(_st.minTextWidth) {
|
, _text(_st.minTextWidth) {
|
||||||
_text.setText(_st.style, title);
|
_text.setText(_st.style, title);
|
||||||
setAttribute(Qt::WA_OpaquePaintEvent);
|
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||||
|
|
@ -30,6 +40,7 @@ SideBarButton::SideBarButton(
|
||||||
style::PaletteChanged(
|
style::PaletteChanged(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
_iconCache = _iconCacheActive = QImage();
|
_iconCache = _iconCacheActive = QImage();
|
||||||
|
_lock.iconCache = _lock.iconCacheActive = QImage();
|
||||||
update();
|
update();
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
}
|
}
|
||||||
|
|
@ -66,6 +77,26 @@ void SideBarButton::setIconOverride(
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SideBarButton::setLocked(bool locked) {
|
||||||
|
if (_lock.locked == locked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_lock.locked = locked;
|
||||||
|
const auto charFiller = QChar('l');
|
||||||
|
const auto count = std::ceil(st::sideBarButtonLockSize.width()
|
||||||
|
/ float(_st.style.font->width(charFiller)));
|
||||||
|
const auto filler = QString().fill(charFiller, count);
|
||||||
|
const auto result = _lock.locked
|
||||||
|
? (filler + _text.toString())
|
||||||
|
: _text.toString().mid(count);
|
||||||
|
_text.setText(_st.style, result);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SideBarButton::locked() const {
|
||||||
|
return _lock.locked;
|
||||||
|
}
|
||||||
|
|
||||||
int SideBarButton::resizeGetHeight(int newWidth) {
|
int SideBarButton::resizeGetHeight(int newWidth) {
|
||||||
auto result = _st.minHeight;
|
auto result = _st.minHeight;
|
||||||
const auto text = std::min(
|
const auto text = std::min(
|
||||||
|
|
@ -79,10 +110,15 @@ void SideBarButton::paintEvent(QPaintEvent *e) {
|
||||||
auto p = Painter(this);
|
auto p = Painter(this);
|
||||||
const auto clip = e->rect();
|
const auto clip = e->rect();
|
||||||
|
|
||||||
p.fillRect(clip, _active ? _st.textBgActive : _st.textBg);
|
const auto &bg = _active ? _st.textBgActive : _st.textBg;
|
||||||
|
p.fillRect(clip, bg);
|
||||||
|
|
||||||
RippleButton::paintRipple(p, 0, 0);
|
RippleButton::paintRipple(p, 0, 0);
|
||||||
|
|
||||||
|
if (_lock.locked) {
|
||||||
|
p.setOpacity(kPremiumLockedOpacity);
|
||||||
|
}
|
||||||
|
|
||||||
const auto &icon = computeIcon();
|
const auto &icon = computeIcon();
|
||||||
const auto x = (_st.iconPosition.x() < 0)
|
const auto x = (_st.iconPosition.x() < 0)
|
||||||
? (width() - icon.width()) / 2
|
? (width() - icon.width()) / 2
|
||||||
|
|
@ -127,6 +163,28 @@ void SideBarButton::paintEvent(QPaintEvent *e) {
|
||||||
y + (_st.badgeHeight - _st.badgeStyle.font->height) / 2,
|
y + (_st.badgeHeight - _st.badgeStyle.font->height) / 2,
|
||||||
width());
|
width());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_lock.locked) {
|
||||||
|
auto lineWidths = QVector<int>();
|
||||||
|
lineWidths.reserve(kMaxLabelLines);
|
||||||
|
_text.countLineWidths(width() - 2 * _st.textSkip, &lineWidths);
|
||||||
|
if (lineWidths.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
validateLockIconCache();
|
||||||
|
|
||||||
|
const auto &icon = _active ? _lock.iconCacheActive : _lock.iconCache;
|
||||||
|
const auto size = icon.size() / style::DevicePixelRatio();
|
||||||
|
p.translate(
|
||||||
|
(width() - lineWidths.front()) / 2.,
|
||||||
|
_st.textTop + (_st.style.font->height - size.height()) / 2.);
|
||||||
|
p.setOpacity(1.);
|
||||||
|
p.fillRect(QRect(QPoint(), size), bg);
|
||||||
|
p.setOpacity(kPremiumLockedOpacity);
|
||||||
|
p.translate(-_st.style.font->spacew / 2., 0);
|
||||||
|
|
||||||
|
p.drawImage(0, 0, icon);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const style::icon &SideBarButton::computeIcon() const {
|
const style::icon &SideBarButton::computeIcon() const {
|
||||||
|
|
@ -182,4 +240,59 @@ void SideBarButton::validateIconCache() {
|
||||||
(_active ? _iconCacheActive : _iconCache) = std::move(image);
|
(_active ? _iconCacheActive : _iconCache) = std::move(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SideBarButton::validateLockIconCache() {
|
||||||
|
if (!(_active ? _lock.iconCacheActive : _lock.iconCache).isNull()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto &size = st::sideBarButtonLockSize;
|
||||||
|
auto image = QImage(
|
||||||
|
size * style::DevicePixelRatio(),
|
||||||
|
QImage::Format_ARGB32_Premultiplied);
|
||||||
|
image.setDevicePixelRatio(style::DevicePixelRatio());
|
||||||
|
image.fill(Qt::transparent);
|
||||||
|
{
|
||||||
|
auto p = QPainter(&image);
|
||||||
|
auto hq = PainterHighQualityEnabler(p);
|
||||||
|
|
||||||
|
const auto &arcOffset = st::sideBarButtonLockArcOffset;
|
||||||
|
const auto arcWidth = size.width() - arcOffset * 2;
|
||||||
|
const auto &arcHeight = st::sideBarButtonLockArcHeight;
|
||||||
|
|
||||||
|
const auto blockRectWidth = size.width();
|
||||||
|
const auto blockRectHeight = st::sideBarButtonLockBlockHeight;
|
||||||
|
const auto blockRectTop = size.height() - blockRectHeight;
|
||||||
|
|
||||||
|
const auto blockRect = QRectF(
|
||||||
|
(size.width() - blockRectWidth) / 2,
|
||||||
|
blockRectTop,
|
||||||
|
blockRectWidth,
|
||||||
|
blockRectHeight);
|
||||||
|
const auto lineHeight = -(blockRect.y() - arcHeight)
|
||||||
|
+ _arcPen.width() / 2.;
|
||||||
|
|
||||||
|
p.setPen(Qt::NoPen);
|
||||||
|
p.setBrush(_st.textFg);
|
||||||
|
{
|
||||||
|
p.drawRoundedRect(blockRect, 2, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
p.translate(size.width() - arcOffset, blockRect.y());
|
||||||
|
|
||||||
|
p.setPen(_arcPen);
|
||||||
|
const auto rLine = QLineF(0, 0, 0, lineHeight);
|
||||||
|
const auto lLine = rLine.translated(-arcWidth, 0);
|
||||||
|
p.drawLine(rLine);
|
||||||
|
p.drawLine(lLine);
|
||||||
|
|
||||||
|
p.drawArc(
|
||||||
|
-arcWidth,
|
||||||
|
-arcHeight - _arcPen.width() / 2.,
|
||||||
|
arcWidth,
|
||||||
|
arcHeight * 2,
|
||||||
|
0,
|
||||||
|
180 * 16);
|
||||||
|
}
|
||||||
|
(_active ? _lock.iconCacheActive : _lock.iconCache) = std::move(image);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
|
||||||
|
|
@ -29,18 +29,23 @@ public:
|
||||||
void setIconOverride(
|
void setIconOverride(
|
||||||
const style::icon *iconOverride,
|
const style::icon *iconOverride,
|
||||||
const style::icon *iconOverrideActive = nullptr);
|
const style::icon *iconOverrideActive = nullptr);
|
||||||
|
void setLocked(bool locked);
|
||||||
|
|
||||||
int resizeGetHeight(int newWidth) override;
|
int resizeGetHeight(int newWidth) override;
|
||||||
|
|
||||||
|
[[nodiscard]] bool locked() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
|
||||||
[[nodiscard]] const style::icon &computeIcon() const;
|
[[nodiscard]] const style::icon &computeIcon() const;
|
||||||
void validateIconCache();
|
void validateIconCache();
|
||||||
|
void validateLockIconCache();
|
||||||
|
|
||||||
const style::SideBarButton &_st;
|
const style::SideBarButton &_st;
|
||||||
const style::icon *_iconOverride = nullptr;
|
const style::icon *_iconOverride = nullptr;
|
||||||
const style::icon *_iconOverrideActive = nullptr;
|
const style::icon *_iconOverrideActive = nullptr;
|
||||||
|
const QPen _arcPen;
|
||||||
Ui::Text::String _text;
|
Ui::Text::String _text;
|
||||||
Ui::Text::String _badge;
|
Ui::Text::String _badge;
|
||||||
QImage _iconCache;
|
QImage _iconCache;
|
||||||
|
|
@ -49,6 +54,12 @@ private:
|
||||||
bool _active = false;
|
bool _active = false;
|
||||||
bool _badgeMuted = false;
|
bool _badgeMuted = false;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
bool locked = false;
|
||||||
|
QImage iconCache;
|
||||||
|
QImage iconCacheActive;
|
||||||
|
} _lock;
|
||||||
|
|
||||||
};
|
};
|
||||||
//
|
//
|
||||||
//class SideBarMenu final {
|
//class SideBarMenu final {
|
||||||
|
|
|
||||||
|
|
@ -1559,3 +1559,11 @@ callShadow: Shadow {
|
||||||
extend: margins(9px, 8px, 9px, 10px);
|
extend: margins(9px, 8px, 9px, 10px);
|
||||||
fallback: windowShadowFgFallback;
|
fallback: windowShadowFgFallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sideBarButtonLockArcOffset: 2px;
|
||||||
|
sideBarButtonLockSize: size(9px, 10px);
|
||||||
|
sideBarButtonLockArcHeight: 3px;
|
||||||
|
sideBarButtonLockBlockHeight: 5px;
|
||||||
|
sideBarButtonLockLineHeight: 1px;
|
||||||
|
sideBarButtonLockPenWidth: 3px;
|
||||||
|
sideBarButtonLockPenWidthDivider: 2;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue