185 lines
4.8 KiB
C++
185 lines
4.8 KiB
C++
// This file is part of Desktop App Toolkit,
|
|
// a set of libraries for developing nice desktop applications.
|
|
//
|
|
// For license and copyright information please follow this link:
|
|
// https://github.com/desktop-app/legal/blob/master/LEGAL
|
|
//
|
|
#include "ui/widgets/side_bar_button.h"
|
|
|
|
#include "ui/effects/ripple_animation.h"
|
|
|
|
#include <QtGui/QtEvents>
|
|
|
|
namespace Ui {
|
|
namespace {
|
|
|
|
constexpr auto kMaxLabelLines = 3;
|
|
|
|
} // namespace
|
|
|
|
SideBarButton::SideBarButton(
|
|
not_null<QWidget*> parent,
|
|
const QString &title,
|
|
const style::SideBarButton &st)
|
|
: RippleButton(parent, st.ripple)
|
|
, _st(st)
|
|
, _text(_st.minTextWidth) {
|
|
_text.setText(_st.style, title);
|
|
setAttribute(Qt::WA_OpaquePaintEvent);
|
|
|
|
style::PaletteChanged(
|
|
) | rpl::start_with_next([=] {
|
|
_iconCache = _iconCacheActive = QImage();
|
|
update();
|
|
}, lifetime());
|
|
}
|
|
|
|
void SideBarButton::setActive(bool active) {
|
|
if (_active == active) {
|
|
return;
|
|
}
|
|
_active = active;
|
|
update();
|
|
}
|
|
|
|
void SideBarButton::setBadge(const QString &badge, bool muted) {
|
|
if (_badge.toString() == badge && _badgeMuted == muted) {
|
|
return;
|
|
}
|
|
_badge.setText(_st.badgeStyle, badge);
|
|
_badgeMuted = muted;
|
|
const auto width = badge.isEmpty()
|
|
? 0
|
|
: std::max(_st.badgeHeight, _badge.maxWidth() + 2 * _st.badgeSkip);
|
|
if (_iconCacheBadgeWidth != width) {
|
|
_iconCacheBadgeWidth = width;
|
|
_iconCache = _iconCacheActive = QImage();
|
|
}
|
|
update();
|
|
}
|
|
|
|
void SideBarButton::setIconOverride(
|
|
const style::icon *iconOverride,
|
|
const style::icon *iconOverrideActive) {
|
|
_iconOverride = iconOverride;
|
|
_iconOverrideActive = iconOverrideActive;
|
|
update();
|
|
}
|
|
|
|
int SideBarButton::resizeGetHeight(int newWidth) {
|
|
auto result = _st.minHeight;
|
|
const auto text = std::min(
|
|
_text.countHeight(newWidth - _st.textSkip * 2),
|
|
_st.style.font->height * kMaxLabelLines);
|
|
const auto add = text - _st.style.font->height;
|
|
return result + std::max(add, 0);
|
|
}
|
|
|
|
void SideBarButton::paintEvent(QPaintEvent *e) {
|
|
auto p = Painter(this);
|
|
const auto clip = e->rect();
|
|
|
|
p.fillRect(clip, _active ? _st.textBgActive : _st.textBg);
|
|
|
|
RippleButton::paintRipple(p, 0, 0);
|
|
|
|
const auto &icon = computeIcon();
|
|
const auto x = (_st.iconPosition.x() < 0)
|
|
? (width() - icon.width()) / 2
|
|
: _st.iconPosition.x();
|
|
const auto y = (_st.iconPosition.y() < 0)
|
|
? (height() - icon.height()) / 2
|
|
: _st.iconPosition.y();
|
|
if (_iconCacheBadgeWidth) {
|
|
validateIconCache();
|
|
p.drawImage(x, y, _active ? _iconCacheActive : _iconCache);
|
|
} else {
|
|
icon.paint(p, x, y, width());
|
|
}
|
|
p.setPen(_active ? _st.textFgActive : _st.textFg);
|
|
_text.drawElided(
|
|
p,
|
|
_st.textSkip,
|
|
_st.textTop,
|
|
(width() - 2 * _st.textSkip),
|
|
kMaxLabelLines,
|
|
style::al_top);
|
|
|
|
if (_iconCacheBadgeWidth) {
|
|
const auto desiredLeft = width() / 2 + _st.badgePosition.x();
|
|
const auto x = std::min(
|
|
desiredLeft,
|
|
width() - _iconCacheBadgeWidth - st::defaultScrollArea.width);
|
|
const auto y = _st.badgePosition.y();
|
|
|
|
auto hq = PainterHighQualityEnabler(p);
|
|
p.setPen(Qt::NoPen);
|
|
p.setBrush((_badgeMuted && !_active)
|
|
? _st.badgeBgMuted
|
|
: _st.badgeBg);
|
|
const auto r = _st.badgeHeight / 2;
|
|
p.drawRoundedRect(x, y, _iconCacheBadgeWidth, _st.badgeHeight, r, r);
|
|
|
|
p.setPen(_st.badgeFg);
|
|
_badge.draw(
|
|
p,
|
|
x + (_iconCacheBadgeWidth - _badge.maxWidth()) / 2,
|
|
y + (_st.badgeHeight - _st.badgeStyle.font->height) / 2,
|
|
width());
|
|
}
|
|
}
|
|
|
|
const style::icon &SideBarButton::computeIcon() const {
|
|
return _active
|
|
? (_iconOverrideActive
|
|
? *_iconOverrideActive
|
|
: !_st.iconActive.empty()
|
|
? _st.iconActive
|
|
: _iconOverride
|
|
? *_iconOverride
|
|
: _st.icon)
|
|
: _iconOverride
|
|
? *_iconOverride
|
|
: _st.icon;
|
|
}
|
|
|
|
void SideBarButton::validateIconCache() {
|
|
Expects(_st.iconPosition.x() < 0);
|
|
|
|
if (!(_active ? _iconCacheActive : _iconCache).isNull()) {
|
|
return;
|
|
}
|
|
const auto &icon = computeIcon();
|
|
auto image = QImage(
|
|
icon.size() * style::DevicePixelRatio(),
|
|
QImage::Format_ARGB32_Premultiplied);
|
|
image.setDevicePixelRatio(style::DevicePixelRatio());
|
|
image.fill(Qt::transparent);
|
|
{
|
|
auto p = QPainter(&image);
|
|
icon.paint(p, 0, 0, icon.width());
|
|
p.setCompositionMode(QPainter::CompositionMode_Source);
|
|
p.setBrush(Qt::transparent);
|
|
auto pen = QPen(Qt::transparent);
|
|
pen.setWidth(2 * _st.badgeStroke);
|
|
p.setPen(pen);
|
|
auto hq = PainterHighQualityEnabler(p);
|
|
const auto desiredLeft = (icon.width() / 2) + _st.badgePosition.x();
|
|
const auto x = std::min(
|
|
desiredLeft,
|
|
(width()
|
|
- _iconCacheBadgeWidth
|
|
- st::defaultScrollArea.width
|
|
- (width() / 2)
|
|
+ (icon.width() / 2)));
|
|
const auto top = (_st.iconPosition.y() >= 0)
|
|
? _st.iconPosition.y()
|
|
: (height() - icon.height()) / 2;
|
|
const auto y = _st.badgePosition.y() - top;
|
|
const auto r = _st.badgeHeight / 2.;
|
|
p.drawRoundedRect(x, y, _iconCacheBadgeWidth, _st.badgeHeight, r, r);
|
|
}
|
|
(_active ? _iconCacheActive : _iconCache) = std::move(image);
|
|
}
|
|
|
|
} // namespace Ui
|