mirror-chatterino2/src/widgets/helper/Button.cpp

300 lines
6.9 KiB
C++
Raw Normal View History

2018-08-08 15:35:54 +02:00
#include "Button.hpp"
2017-04-12 17:46:44 +02:00
#include <QApplication>
2017-04-12 17:46:44 +02:00
#include <QDebug>
#include <QDesktopWidget>
2017-04-12 17:46:44 +02:00
#include <QPainter>
2018-06-28 20:03:04 +02:00
#include "singletons/Theme.hpp"
#include "util/FunctionEventFilter.hpp"
2017-04-14 17:52:22 +02:00
namespace chatterino {
2017-04-12 17:46:44 +02:00
2018-08-08 15:35:54 +02:00
Button::Button(BaseWidget *parent)
: BaseWidget(parent)
2017-04-12 17:46:44 +02:00
{
2018-08-06 21:17:03 +02:00
connect(&effectTimer_, &QTimer::timeout, this,
2018-08-08 15:35:54 +02:00
&Button::onMouseEffectTimeout);
2017-04-12 17:46:44 +02:00
2018-06-06 10:46:23 +02:00
this->effectTimer_.setInterval(20);
this->effectTimer_.start();
2018-06-06 13:35:06 +02:00
this->setMouseTracking(true);
2017-04-12 17:46:44 +02:00
}
2018-08-08 15:35:54 +02:00
void Button::setMouseEffectColor(boost::optional<QColor> color)
2017-04-12 17:46:44 +02:00
{
2018-06-06 10:46:23 +02:00
this->mouseEffectColor_ = color;
2017-04-12 17:46:44 +02:00
}
2018-08-08 15:35:54 +02:00
void Button::setPixmap(const QPixmap &_pixmap)
2018-01-17 16:52:51 +01:00
{
2018-06-06 10:46:23 +02:00
this->pixmap_ = _pixmap;
2018-01-17 16:52:51 +01:00
this->update();
}
2018-08-08 15:35:54 +02:00
const QPixmap &Button::getPixmap() const
2018-01-17 16:52:51 +01:00
{
2018-06-06 10:46:23 +02:00
return this->pixmap_;
}
2018-08-08 15:35:54 +02:00
void Button::setDim(bool value)
2018-07-04 13:05:54 +02:00
{
this->dimPixmap_ = value;
this->update();
}
2018-08-08 15:35:54 +02:00
bool Button::getDim() const
2018-07-04 13:05:54 +02:00
{
return this->dimPixmap_;
}
2018-08-08 15:35:54 +02:00
void Button::setEnable(bool value)
{
this->enabled_ = value;
this->update();
}
2018-08-08 15:35:54 +02:00
bool Button::getEnable() const
{
return this->enabled_;
}
2018-08-08 15:35:54 +02:00
qreal Button::getCurrentDimAmount() const
{
return this->dimPixmap_ && !this->mouseOver_ ? 0.7 : 1;
}
2018-08-08 15:35:54 +02:00
void Button::setBorderColor(const QColor &color)
2018-06-06 10:46:23 +02:00
{
this->borderColor_ = color;
this->update();
2018-06-06 10:46:23 +02:00
}
2018-08-08 15:35:54 +02:00
const QColor &Button::getBorderColor() const
2018-06-06 10:46:23 +02:00
{
return this->borderColor_;
2018-01-17 16:52:51 +01:00
}
2018-08-08 15:35:54 +02:00
void Button::setMenu(std::unique_ptr<QMenu> menu)
{
this->menu_ = std::move(menu);
this->menu_->installEventFilter(
new FunctionEventFilter(this, [this](QObject *, QEvent *event) {
if (event->type() == QEvent::Hide) {
QTimer::singleShot(20, this,
[this] { this->menuVisible_ = false; });
}
return false;
}));
}
2018-08-08 15:35:54 +02:00
void Button::paintEvent(QPaintEvent *)
2017-04-12 17:46:44 +02:00
{
QPainter painter(this);
2017-04-12 17:46:44 +02:00
2018-01-17 16:52:51 +01:00
painter.setRenderHint(QPainter::SmoothPixmapTransform);
2018-06-06 10:46:23 +02:00
if (!this->pixmap_.isNull()) {
if (!this->mouseOver_ && this->dimPixmap_ && this->enabled_) {
painter.setOpacity(this->getCurrentDimAmount());
2018-07-04 13:05:54 +02:00
}
2018-01-17 16:52:51 +01:00
QRect rect = this->rect();
2018-06-06 10:46:23 +02:00
int s = int(6 * this->getScale());
2018-01-17 16:52:51 +01:00
2018-06-06 10:46:23 +02:00
rect.moveLeft(s);
rect.setRight(rect.right() - s - s);
rect.moveTop(s);
rect.setBottom(rect.bottom() - s - s);
painter.drawPixmap(rect, this->pixmap_);
2018-07-04 13:05:54 +02:00
painter.setOpacity(1);
2018-06-06 10:46:23 +02:00
}
2018-01-17 16:52:51 +01:00
this->fancyPaint(painter);
2018-06-06 10:46:23 +02:00
if (this->borderColor_.isValid()) {
painter.setRenderHint(QPainter::Antialiasing, false);
painter.setPen(this->borderColor_);
painter.drawRect(0, 0, this->width() - 1, this->height() - 1);
2018-01-17 16:52:51 +01:00
}
2017-04-12 17:46:44 +02:00
}
2018-08-08 15:35:54 +02:00
void Button::fancyPaint(QPainter &painter)
2017-04-12 17:46:44 +02:00
{
if (!this->enabled_) {
return;
}
2018-01-24 15:08:22 +01:00
painter.setRenderHint(QPainter::HighQualityAntialiasing);
painter.setRenderHint(QPainter::Antialiasing);
QColor c;
2018-06-06 10:46:23 +02:00
if (this->mouseEffectColor_) {
c = this->mouseEffectColor_.get();
} else {
2018-08-06 21:17:03 +02:00
c = this->theme->isLightTheme() ? QColor(0, 0, 0)
: QColor(255, 255, 255);
}
2017-04-12 17:46:44 +02:00
2018-06-06 10:46:23 +02:00
if (this->hoverMultiplier_ > 0) {
2018-06-06 13:35:06 +02:00
QRadialGradient gradient(QPointF(mousePos_), this->width() / 2);
2017-04-12 17:46:44 +02:00
2018-08-06 21:17:03 +02:00
gradient.setColorAt(0, QColor(c.red(), c.green(), c.blue(),
int(50 * this->hoverMultiplier_)));
gradient.setColorAt(1, QColor(c.red(), c.green(), c.blue(),
int(40 * this->hoverMultiplier_)));
2017-04-12 17:46:44 +02:00
painter.fillRect(this->rect(), gradient);
}
2018-06-06 10:46:23 +02:00
for (auto effect : this->clickEffects_) {
2017-04-12 17:46:44 +02:00
QRadialGradient gradient(effect.position.x(), effect.position.y(),
2018-08-06 21:17:03 +02:00
effect.progress * qreal(width()) * 2,
effect.position.x(), effect.position.y());
2017-04-12 17:46:44 +02:00
2018-08-06 21:17:03 +02:00
gradient.setColorAt(0, QColor(c.red(), c.green(), c.blue(),
int((1 - effect.progress) * 95)));
gradient.setColorAt(0.9999, QColor(c.red(), c.green(), c.blue(),
int((1 - effect.progress) * 95)));
2018-06-06 10:46:23 +02:00
gradient.setColorAt(1, QColor(c.red(), c.green(), c.blue(), int(0)));
2017-04-12 17:46:44 +02:00
painter.fillRect(this->rect(), gradient);
}
}
2018-08-08 15:35:54 +02:00
void Button::enterEvent(QEvent *)
2017-04-12 17:46:44 +02:00
{
2018-06-06 10:46:23 +02:00
this->mouseOver_ = true;
2017-04-12 17:46:44 +02:00
}
2018-08-08 15:35:54 +02:00
void Button::leaveEvent(QEvent *)
2017-04-12 17:46:44 +02:00
{
2018-06-06 10:46:23 +02:00
this->mouseOver_ = false;
2017-04-12 17:46:44 +02:00
}
2018-08-08 15:35:54 +02:00
void Button::mousePressEvent(QMouseEvent *event)
2017-04-12 17:46:44 +02:00
{
if (!this->enabled_) {
return;
}
2017-04-12 17:46:44 +02:00
if (event->button() != Qt::LeftButton) {
return;
}
2018-06-06 10:46:23 +02:00
this->clickEffects_.push_back(ClickEffect(event->pos()));
2017-04-12 17:46:44 +02:00
2018-06-06 10:46:23 +02:00
this->mouseDown_ = true;
emit this->leftMousePress();
if (this->menu_ && !this->menuVisible_) {
QTimer::singleShot(80, this, [this] { this->showMenu(); });
2018-08-09 16:44:04 +02:00
this->mouseDown_ = false;
this->mouseOver_ = false;
}
2017-04-12 17:46:44 +02:00
}
2018-08-08 15:35:54 +02:00
void Button::mouseReleaseEvent(QMouseEvent *event)
2017-04-12 17:46:44 +02:00
{
if (!this->enabled_) {
return;
}
2017-04-12 17:46:44 +02:00
if (event->button() != Qt::LeftButton) {
return;
}
2018-06-06 10:46:23 +02:00
this->mouseDown_ = false;
2017-09-15 17:23:49 +02:00
if (this->rect().contains(event->pos())) {
emit clicked();
}
2017-04-12 17:46:44 +02:00
}
2018-08-08 15:35:54 +02:00
void Button::mouseMoveEvent(QMouseEvent *event)
2017-04-12 17:46:44 +02:00
{
if (!this->enabled_) {
return;
}
2018-06-06 10:46:23 +02:00
this->mousePos_ = event->pos();
2018-06-06 13:35:06 +02:00
this->update();
2017-04-12 17:46:44 +02:00
}
2018-08-08 15:35:54 +02:00
void Button::onMouseEffectTimeout()
2017-04-12 17:46:44 +02:00
{
bool performUpdate = false;
2018-06-06 10:46:23 +02:00
if (selected_) {
if (this->hoverMultiplier_ != 0) {
2018-08-06 21:17:03 +02:00
this->hoverMultiplier_ =
std::max(0.0, this->hoverMultiplier_ - 0.1);
2017-04-12 17:46:44 +02:00
performUpdate = true;
}
2018-06-06 10:46:23 +02:00
} else if (mouseOver_) {
if (this->hoverMultiplier_ != 1) {
2018-08-06 21:17:03 +02:00
this->hoverMultiplier_ =
std::min(1.0, this->hoverMultiplier_ + 0.5);
2017-04-12 17:46:44 +02:00
performUpdate = true;
}
} else {
2018-06-06 10:46:23 +02:00
if (this->hoverMultiplier_ != 0) {
2018-08-06 21:17:03 +02:00
this->hoverMultiplier_ =
std::max(0.0, this->hoverMultiplier_ - 0.3);
2017-04-12 17:46:44 +02:00
performUpdate = true;
}
}
2018-06-06 10:46:23 +02:00
if (this->clickEffects_.size() != 0) {
2017-04-12 17:46:44 +02:00
performUpdate = true;
2018-08-06 21:17:03 +02:00
for (auto it = this->clickEffects_.begin();
it != this->clickEffects_.end();) {
2018-06-06 13:35:06 +02:00
it->progress += mouseDown_ ? 0.02 : 0.07;
2017-04-12 17:46:44 +02:00
2018-06-06 13:35:06 +02:00
if (it->progress >= 1.0) {
2018-06-06 10:46:23 +02:00
it = this->clickEffects_.erase(it);
2017-04-12 17:46:44 +02:00
} else {
it++;
}
}
}
if (performUpdate) {
update();
}
}
2018-08-08 15:35:54 +02:00
void Button::showMenu()
{
if (!this->menu_) return;
auto point = [this] {
auto bounds = QApplication::desktop()->availableGeometry(this);
auto point = this->mapToGlobal(
QPoint(this->width() - this->menu_->width(), this->height()));
if (point.y() + this->menu_->height() > bounds.bottom()) {
point.setY(point.y() - this->menu_->height() - this->height());
}
return point;
};
this->menu_->popup(point());
this->menu_->move(point());
this->menuVisible_ = true;
}
} // namespace chatterino