ArchitectureColoredPainting/qt-material-widgets/components/qtmaterialfab.cpp

322 lines
7.2 KiB
C++
Raw Normal View History

2023-03-06 12:38:25 +08:00
#include "qtmaterialfab.h"
#include "qtmaterialfab_p.h"
#include <QtWidgets/QGraphicsDropShadowEffect>
#include <QState>
#include <QEvent>
#include <QPainter>
#include "lib/qtmaterialrippleoverlay.h"
/*!
* \class QtMaterialFloatingActionButtonPrivate
* \internal
*/
/*!
* \internal
*/
QtMaterialFloatingActionButtonPrivate::QtMaterialFloatingActionButtonPrivate(QtMaterialFloatingActionButton *q)
: QtMaterialRaisedButtonPrivate(q)
{
}
/*!
* \internal
*/
QtMaterialFloatingActionButtonPrivate::~QtMaterialFloatingActionButtonPrivate()
{
}
/*!
* \internal
*/
void QtMaterialFloatingActionButtonPrivate::init()
{
Q_Q(QtMaterialFloatingActionButton);
corner = Qt::BottomRightCorner;
mini = false;
offsX = 34;
offsY = 36;
q->setRole(Material::Primary);
q->setFixedSize(DefaultDiameter, DefaultDiameter);
q->setGeometry(fabGeometry());
setupProperties();
if (q->parentWidget()) {
q->parentWidget()->installEventFilter(q);
}
q->setFixedRippleRadius(50);
}
/*!
* \internal
*/
QRect QtMaterialFloatingActionButtonPrivate::fabGeometry() const
{
Q_Q(const QtMaterialFloatingActionButton);
QWidget *parent = q->parentWidget();
if (!parent) {
return QRect();
}
const int s = mini ? MiniDiameter : DefaultDiameter;
switch (corner)
{
case Qt::TopLeftCorner:
return QRect(offsX, offsY, s, s);
case Qt::TopRightCorner:
return QRect(parent->width()-(offsX+s), offsY, s, s);
case Qt::BottomLeftCorner:
return QRect(offsX, parent->height()-(offsY+s), s, s);
case Qt::BottomRightCorner:
default:
break;
}
return QRect(parent->width()-(offsX+s), parent->height()-(offsY+s), s, s);
}
/*!
* \internal
*/
void QtMaterialFloatingActionButtonPrivate::setupProperties()
{
if (mini) {
effect->setColor(QColor(0, 0, 0, 80));
normalState->assignProperty(effect, "offset", QPointF(0, 3));
normalState->assignProperty(effect, "blurRadius", 13);
pressedState->assignProperty(effect, "offset", QPointF(0, 7));
pressedState->assignProperty(effect, "blurRadius", 20);
} else {
effect->setColor(QColor(0, 0, 0, 105));
normalState->assignProperty(effect, "offset", QPointF(0, 6));
normalState->assignProperty(effect, "blurRadius", 16);
pressedState->assignProperty(effect, "offset", QPointF(0, 11));
pressedState->assignProperty(effect, "blurRadius", 28);
}
}
/*!
* \class QtMaterialFloatingActionButton
*/
QtMaterialFloatingActionButton::QtMaterialFloatingActionButton(const QIcon &icon, QWidget *parent)
: QtMaterialRaisedButton(*new QtMaterialFloatingActionButtonPrivate(this), parent)
{
d_func()->init();
setIcon(icon);
}
QtMaterialFloatingActionButton::~QtMaterialFloatingActionButton()
{
}
/*!
* \reimp
*/
QSize QtMaterialFloatingActionButton::sizeHint() const
{
Q_D(const QtMaterialFloatingActionButton);
if (d->mini) {
return QSize(QtMaterialFloatingActionButtonPrivate::MiniDiameter,
QtMaterialFloatingActionButtonPrivate::MiniDiameter);
} else {
return QSize(QtMaterialFloatingActionButtonPrivate::DefaultDiameter,
QtMaterialFloatingActionButtonPrivate::DefaultDiameter);
}
}
void QtMaterialFloatingActionButton::setMini(bool state)
{
Q_D(QtMaterialFloatingActionButton);
if (d->mini == state) {
return;
}
d->mini = state;
setFixedSize(d->diameter(), d->diameter());
setFixedRippleRadius(state ? 30 : 50);
d->setupProperties();
updateClipPath();
setGeometry(d->fabGeometry());
update();
}
bool QtMaterialFloatingActionButton::isMini() const
{
Q_D(const QtMaterialFloatingActionButton);
return d->mini;
}
void QtMaterialFloatingActionButton::setCorner(Qt::Corner corner)
{
Q_D(QtMaterialFloatingActionButton);
if (d->corner == corner) {
return;
}
d->corner = corner;
setGeometry(d->fabGeometry());
update();
}
Qt::Corner QtMaterialFloatingActionButton::corner() const
{
Q_D(const QtMaterialFloatingActionButton);
return d->corner;
}
void QtMaterialFloatingActionButton::setOffset(int x, int y)
{
Q_D(QtMaterialFloatingActionButton);
d->offsX = x;
d->offsY = y;
setGeometry(d->fabGeometry());
update();
}
QSize QtMaterialFloatingActionButton::offset() const
{
Q_D(const QtMaterialFloatingActionButton);
return QSize(d->offsX, d->offsY);
}
void QtMaterialFloatingActionButton::setXOffset(int x)
{
Q_D(QtMaterialFloatingActionButton);
d->offsX = x;
setGeometry(d->fabGeometry());
update();
}
int QtMaterialFloatingActionButton::xOffset() const
{
Q_D(const QtMaterialFloatingActionButton);
return d->offsX;
}
void QtMaterialFloatingActionButton::setYOffset(int y)
{
Q_D(QtMaterialFloatingActionButton);
d->offsY = y;
setGeometry(d->fabGeometry());
update();
}
int QtMaterialFloatingActionButton::yOffset() const
{
Q_D(const QtMaterialFloatingActionButton);
return d->offsY;
}
/*!
* \reimp
*/
bool QtMaterialFloatingActionButton::event(QEvent *event)
{
Q_D(QtMaterialFloatingActionButton);
if (!parent()) {
return QtMaterialRaisedButton::event(event);
}
switch (event->type())
{
case QEvent::ParentChange:
{
parent()->installEventFilter(this);
setGeometry(d->fabGeometry());
break;
}
case QEvent::ParentAboutToChange:
{
parent()->removeEventFilter(this);
break;
}
default:
break;
}
return QtMaterialRaisedButton::event(event);
}
/*!
* \reimp
*/
bool QtMaterialFloatingActionButton::eventFilter(QObject *obj, QEvent *event)
{
const QEvent::Type type = event->type();
if (QEvent::Move == type || QEvent::Resize == type)
{
Q_D(QtMaterialFloatingActionButton);
setGeometry(d->fabGeometry());
}
return QtMaterialRaisedButton::eventFilter(obj, event);
}
/*!
* \reimp
*/
void QtMaterialFloatingActionButton::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
Q_D(QtMaterialFloatingActionButton);
QRect square = QRect(0, 0, d->diameter(), d->diameter());
square.moveCenter(rect().center());
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing);
QBrush brush;
brush.setStyle(Qt::SolidPattern);
if (isEnabled()) {
brush.setColor(backgroundColor());
} else {
brush.setColor(disabledBackgroundColor());
}
painter.setBrush(brush);
painter.setPen(Qt::NoPen);
painter.drawEllipse(square);
QRect iconGeometry(0, 0, d->iconSize(), d->iconSize());
iconGeometry.moveCenter(square.center());
QPixmap pixmap = icon().pixmap(QSize(d->iconSize(), d->iconSize()));
QPainter icon(&pixmap);
icon.setCompositionMode(QPainter::CompositionMode_SourceIn);
icon.fillRect(pixmap.rect(), isEnabled() ? foregroundColor()
: disabledForegroundColor());
painter.drawPixmap(iconGeometry, pixmap);
}
void QtMaterialFloatingActionButton::updateClipPath()
{
Q_D(QtMaterialFloatingActionButton);
QPainterPath path;
path.addEllipse(0, 0, d->diameter(), d->diameter());
d->rippleOverlay->setClipPath(path);
}