feat: add ButtonRow component
SHAPE MORPHHHHHHHHHHHHH
This commit is contained in:
parent
17281a66a5
commit
deb28b44ab
4 changed files with 176 additions and 2 deletions
|
|
@ -21,6 +21,7 @@ StyledRect {
|
||||||
|
|
||||||
property bool radiusMorph
|
property bool radiusMorph
|
||||||
property alias shapeMorph: stateLayer.shapeMorph
|
property alias shapeMorph: stateLayer.shapeMorph
|
||||||
|
property bool fillWidth // For ButtonRow
|
||||||
|
|
||||||
property font font
|
property font font
|
||||||
property int type: ButtonBase.Filled
|
property int type: ButtonBase.Filled
|
||||||
|
|
@ -42,6 +43,7 @@ StyledRect {
|
||||||
property color disabledOnColour: Qt.alpha(Colours.palette.m3onSurface, 0.38)
|
property color disabledOnColour: Qt.alpha(Colours.palette.m3onSurface, 0.38)
|
||||||
|
|
||||||
property bool internalChecked
|
property bool internalChecked
|
||||||
|
property real shapeMorphExpansion: pressed ? 1.16 : 1
|
||||||
readonly property color onColour: disabled ? disabledOnColour : internalChecked ? activeOnColour : inactiveOnColour
|
readonly property color onColour: disabled ? disabledOnColour : internalChecked ? activeOnColour : inactiveOnColour
|
||||||
|
|
||||||
signal clicked
|
signal clicked
|
||||||
|
|
@ -82,4 +84,10 @@ StyledRect {
|
||||||
type: Anim.DefaultEffects
|
type: Anim.DefaultEffects
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Behavior on shapeMorphExpansion {
|
||||||
|
Anim {
|
||||||
|
type: Anim.FastSpatial
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
qml_module(caelestia-components
|
qml_module(caelestia-components
|
||||||
URI Caelestia.Components
|
URI Caelestia.Components
|
||||||
SOURCES
|
SOURCES
|
||||||
lazylistview.hpp lazylistview.cpp
|
lazylistview.cpp
|
||||||
wavyline.hpp wavyline.cpp
|
wavyline.cpp
|
||||||
|
buttonrow.cpp
|
||||||
LIBRARIES
|
LIBRARIES
|
||||||
Qt::Quick
|
Qt::Quick
|
||||||
)
|
)
|
||||||
|
|
|
||||||
127
plugin/src/Caelestia/Components/buttonrow.cpp
Normal file
127
plugin/src/Caelestia/Components/buttonrow.cpp
Normal file
|
|
@ -0,0 +1,127 @@
|
||||||
|
#include "buttonrow.hpp"
|
||||||
|
|
||||||
|
namespace caelestia::components {
|
||||||
|
|
||||||
|
ButtonRow::ButtonRow(QQuickItem* parent)
|
||||||
|
: QQuickItem(parent)
|
||||||
|
, m_dirty(false)
|
||||||
|
, m_spacing(0.0) {
|
||||||
|
setFlag(QQuickItem::ItemHasContents, true);
|
||||||
|
QObject::connect(this, &ButtonRow::widthChanged, this, &ButtonRow::invalidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal ButtonRow::spacing() const {
|
||||||
|
return m_spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ButtonRow::setSpacing(qreal spacing) {
|
||||||
|
if (qFuzzyCompare(m_spacing + 1.0, spacing + 1.0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_spacing = spacing;
|
||||||
|
emit spacingChanged();
|
||||||
|
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ButtonRow::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData& data) {
|
||||||
|
if (change == QQuickItem::ItemChildAddedChange) {
|
||||||
|
auto* const child = data.item;
|
||||||
|
QObject::connect(child, &QQuickItem::implicitWidthChanged, this, &ButtonRow::invalidate);
|
||||||
|
QObject::connect(child, &QQuickItem::implicitHeightChanged, this, &ButtonRow::invalidate);
|
||||||
|
QObject::connect(child, &QQuickItem::visibleChanged, this, &ButtonRow::invalidate);
|
||||||
|
|
||||||
|
const auto* childMeta = child->metaObject();
|
||||||
|
const auto morphSignalIdx = childMeta->indexOfSignal("shapeMorphExpansionChanged()");
|
||||||
|
if (morphSignalIdx != -1)
|
||||||
|
QObject::connect(child, childMeta->method(morphSignalIdx), this,
|
||||||
|
metaObject()->method(metaObject()->indexOfSlot("invalidate()")));
|
||||||
|
|
||||||
|
invalidate();
|
||||||
|
} else if (change == QQuickItem::ItemChildRemovedChange) {
|
||||||
|
QObject::disconnect(data.item, nullptr, this, nullptr);
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
QQuickItem::itemChange(change, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ButtonRow::updatePolish() {
|
||||||
|
if (m_dirty) {
|
||||||
|
relayout();
|
||||||
|
m_dirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ButtonRow::invalidate() {
|
||||||
|
m_dirty = true;
|
||||||
|
polish();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ButtonRow::relayout() {
|
||||||
|
const auto children = childItems();
|
||||||
|
const auto nChildren = children.size();
|
||||||
|
const auto totalSpacing = static_cast<qreal>(nChildren - 1) * m_spacing;
|
||||||
|
|
||||||
|
qreal reservedWidth = 0;
|
||||||
|
int fillWidthCount = 0;
|
||||||
|
qreal maxHeight = 0;
|
||||||
|
for (auto* const child : children) {
|
||||||
|
if (!child->isVisible())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
maxHeight = qMax(maxHeight, child->implicitHeight());
|
||||||
|
|
||||||
|
const auto prop = child->property("fillWidth");
|
||||||
|
if (!prop.isValid())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (prop.toBool())
|
||||||
|
fillWidthCount++;
|
||||||
|
else
|
||||||
|
reservedWidth += child->implicitWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fillWidthCount == 0)
|
||||||
|
fillWidthCount = 1; // Avoid divide by 0
|
||||||
|
|
||||||
|
qreal accX = 0;
|
||||||
|
const auto widthPerItem = (width() - totalSpacing - reservedWidth) / static_cast<qreal>(fillWidthCount);
|
||||||
|
for (int i = 0; i < nChildren; ++i) {
|
||||||
|
auto* const child = children[i];
|
||||||
|
if (!child->isVisible())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto prevExtraWidth = i > 0 ? getMorphExpansion(children[i - 1]) : 0.0;
|
||||||
|
auto nextExtraWidth = i < nChildren - 1 ? getMorphExpansion(children[i + 1]) : 0.0;
|
||||||
|
|
||||||
|
// Items at edges push by full amount, items in middle push by half
|
||||||
|
if (i > 1)
|
||||||
|
prevExtraWidth /= 2;
|
||||||
|
if (i < nChildren - 2)
|
||||||
|
nextExtraWidth /= 2;
|
||||||
|
|
||||||
|
const auto childWidth = child->property("fillWidth").toBool() ? widthPerItem : child->implicitWidth();
|
||||||
|
|
||||||
|
child->setWidth(childWidth + getMorphExpansion(child, childWidth) - prevExtraWidth - nextExtraWidth);
|
||||||
|
child->setHeight(maxHeight);
|
||||||
|
|
||||||
|
child->setX(accX);
|
||||||
|
child->setY(0);
|
||||||
|
accX += child->width() + m_spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
setImplicitWidth(reservedWidth + totalSpacing);
|
||||||
|
setImplicitHeight(maxHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal ButtonRow::getMorphExpansion(const QQuickItem* item) {
|
||||||
|
return getMorphExpansion(item, item->implicitWidth());
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal ButtonRow::getMorphExpansion(const QQuickItem* item, qreal width) {
|
||||||
|
const auto prop = item->property("shapeMorphExpansion");
|
||||||
|
return width * (prop.isValid() ? prop.toReal() - 1 : 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace caelestia::components
|
||||||
38
plugin/src/Caelestia/Components/buttonrow.hpp
Normal file
38
plugin/src/Caelestia/Components/buttonrow.hpp
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <qquickitem.h>
|
||||||
|
|
||||||
|
namespace caelestia::components {
|
||||||
|
|
||||||
|
class ButtonRow : public QQuickItem {
|
||||||
|
Q_OBJECT
|
||||||
|
QML_ELEMENT
|
||||||
|
|
||||||
|
Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ButtonRow(QQuickItem* parent = nullptr);
|
||||||
|
|
||||||
|
qreal spacing() const;
|
||||||
|
void setSpacing(qreal spacing);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void spacingChanged();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData& data) override;
|
||||||
|
void updatePolish() override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void invalidate();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void relayout();
|
||||||
|
static qreal getMorphExpansion(const QQuickItem* item);
|
||||||
|
static qreal getMorphExpansion(const QQuickItem* item, qreal width);
|
||||||
|
|
||||||
|
bool m_dirty;
|
||||||
|
qreal m_spacing;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace caelestia::components
|
||||||
Loading…
Add table
Reference in a new issue