Add SettingsButton widget.

This commit is contained in:
John Preston 2019-10-29 18:20:44 +03:00
parent 45c0be45b2
commit 7d9ae816d4
3 changed files with 209 additions and 3 deletions

View file

@ -6,12 +6,15 @@
//
#include "ui/widgets/buttons.h"
#include "ui/widgets/checkbox.h"
#include "ui/effects/ripple_animation.h"
#include "ui/effects/cross_animation.h"
#include "ui/effects/numbers_animation.h"
#include "ui/image/image_prepare.h"
#include "ui/painter.h"
#include <QtGui/QtEvents>
namespace Ui {
LinkButton::LinkButton(
@ -628,4 +631,142 @@ QImage CrossButton::prepareRippleMask() const {
return RippleAnimation::ellipseMask(QSize(_st.cross.size, _st.cross.size));
}
SettingsButton::SettingsButton(
QWidget *parent,
rpl::producer<QString> &&text)
: SettingsButton(parent, std::move(text), st::defaultSettingsButton) {
}
SettingsButton::SettingsButton(
QWidget *parent,
rpl::producer<QString> &&text,
const style::SettingsButton &st)
: RippleButton(parent, st.ripple)
, _st(st) {
std::move(
text
) | rpl::start_with_next([this](QString &&value) {
setText(std::move(value));
}, lifetime());
}
SettingsButton *SettingsButton::toggleOn(rpl::producer<bool> &&toggled) {
Expects(_toggle == nullptr);
_toggle = std::make_unique<Ui::ToggleView>(
isOver() ? _st.toggleOver : _st.toggle,
false,
[this] { rtlupdate(toggleRect()); });
addClickHandler([this] {
_toggle->setChecked(!_toggle->checked(), anim::type::normal);
});
std::move(
toggled
) | rpl::start_with_next([this](bool toggled) {
_toggle->setChecked(toggled, anim::type::normal);
}, lifetime());
_toggle->finishAnimating();
return this;
}
bool SettingsButton::toggled() const {
return _toggle ? _toggle->checked() : false;
}
rpl::producer<bool> SettingsButton::toggledChanges() const {
if (_toggle) {
return _toggle->checkedChanges();
}
return nullptr;
}
rpl::producer<bool> SettingsButton::toggledValue() const {
if (_toggle) {
return _toggle->checkedValue();
}
return nullptr;
}
void SettingsButton::setColorOverride(std::optional<QColor> textColorOverride) {
_textColorOverride = textColorOverride;
update();
}
void SettingsButton::paintEvent(QPaintEvent *e) {
Painter p(this);
auto paintOver = (isOver() || isDown()) && !isDisabled();
p.fillRect(e->rect(), paintOver ? _st.textBgOver : _st.textBg);
paintRipple(p, 0, 0);
auto outerw = width();
p.setFont(_st.font);
p.setPen(_textColorOverride
? QPen(*_textColorOverride)
: paintOver
? _st.textFgOver
: _st.textFg);
p.drawTextLeft(
_st.padding.left(),
_st.padding.top(),
outerw,
_text,
_textWidth);
if (_toggle) {
auto rect = toggleRect();
_toggle->paint(p, rect.left(), rect.top(), outerw);
}
}
QRect SettingsButton::toggleRect() const {
Expects(_toggle != nullptr);
auto size = _toggle->getSize();
auto left = width() - _st.toggleSkip - size.width();
auto top = (height() - size.height()) / 2;
return { QPoint(left, top), size };
}
int SettingsButton::resizeGetHeight(int newWidth) {
updateVisibleText(newWidth);
return _st.padding.top() + _st.height + _st.padding.bottom();
}
void SettingsButton::onStateChanged(
State was,
StateChangeSource source) {
if (!isDisabled() || !isDown()) {
RippleButton::onStateChanged(was, source);
}
if (_toggle) {
_toggle->setStyle(isOver() ? _st.toggleOver : _st.toggle);
}
setPointerCursor(!isDisabled());
}
void SettingsButton::setText(QString &&text) {
_original = std::move(text);
_originalWidth = _st.font->width(_original);
updateVisibleText(width());
}
void SettingsButton::updateVisibleText(int newWidth) {
auto availableWidth = newWidth
- _st.padding.left()
- _st.padding.right();
if (_toggle) {
availableWidth -= (width() - toggleRect().x());
}
accumulate_max(availableWidth, 0);
if (availableWidth < _originalWidth) {
_text = _st.font->elided(_original, availableWidth);
_textWidth = _st.font->width(_text);
} else {
_text = _original;
_textWidth = _originalWidth;
}
update();
}
} // namespace Ui

View file

@ -17,6 +17,7 @@ namespace Ui {
class RippleAnimation;
class NumbersAnimation;
class ToggleView;
class LinkButton : public AbstractButton {
public:
@ -230,4 +231,44 @@ private:
};
class SettingsButton : public Ui::RippleButton {
public:
SettingsButton(
QWidget *parent,
rpl::producer<QString> &&text);
SettingsButton(
QWidget *parent,
rpl::producer<QString> &&text,
const style::SettingsButton &st);
SettingsButton *toggleOn(rpl::producer<bool> &&toggled);
bool toggled() const;
rpl::producer<bool> toggledChanges() const;
rpl::producer<bool> toggledValue() const;
void setColorOverride(std::optional<QColor> textColorOverride);
protected:
int resizeGetHeight(int newWidth) override;
void onStateChanged(
State was,
StateChangeSource source) override;
void paintEvent(QPaintEvent *e) override;
private:
void setText(QString &&text);
QRect toggleRect() const;
void updateVisibleText(int newWidth);
const style::SettingsButton &_st;
QString _original;
QString _text;
int _originalWidth = 0;
int _textWidth = 0;
std::unique_ptr<Ui::ToggleView> _toggle;
std::optional<QColor> _textColorOverride;
};
} // namespace Ui

View file

@ -485,7 +485,7 @@ ImportantTooltip {
duration: int;
}
InfoProfileButton {
SettingsButton {
textFg: color;
textFgOver: color;
textBg: color;
@ -503,8 +503,8 @@ InfoProfileButton {
ripple: RippleAnimation;
}
InfoProfileCountButton {
button: InfoProfileButton;
SettingsCountButton {
button: SettingsButton;
icon: icon;
iconPosition: point;
label: FlatLabel;
@ -1183,6 +1183,30 @@ backButton: IconButton(defaultIconButton) {
}
}
defaultSettingsToggle: Toggle(defaultToggle) {
untoggledFg: menuIconFg;
}
defaultSettingsToggleOver: Toggle(defaultSettingsToggle) {
untoggledFg: menuIconFgOver;
}
defaultSettingsButton: SettingsButton {
textFg: windowBoldFg;
textFgOver: windowBoldFgOver;
textBg: windowBg;
textBgOver: windowBgOver;
font: boxTextFont;
height: 20px;
padding: margins(22px, 10px, 22px, 8px);
toggle: defaultSettingsToggle;
toggleOver: defaultSettingsToggleOver;
toggleSkip: 23px;
ripple: defaultRippleAnimation;
}
// Windows specific title
windowTitleButton: IconButton {