Last active
June 7, 2023 00:09
-
-
Save HookedBehemoth/f77eb4826af96ad66ddf82c076d465eb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "qquick_masonry.h" | |
MasonryLayout::MasonryLayout() : QQuickItem() { | |
connect(this, &QQuickItem::widthChanged, this, &MasonryLayout::handleWidthChanged); | |
} | |
void MasonryLayout::setSpacing(int32_t spacing) { | |
if (m_spacing == spacing) { | |
return; | |
} | |
m_spacing = spacing; | |
doPositioningAll(); | |
} | |
void MasonryLayout::setElements(uint elements) { | |
if (m_elements == elements) { | |
return; | |
} | |
m_elements = elements; | |
doPositioningAll(); | |
} | |
void MasonryLayout::itemChange(QQuickItem::ItemChange change, QQuickItem::ItemChangeData const& value) { | |
if (change == QQuickItem::ItemChange::ItemChildAddedChange) { | |
doPositioningSingle(value.item); | |
} | |
QQuickItem::itemChange(change, value); | |
} | |
void MasonryLayout::handleWidthChanged() { | |
doPositioningAll(); | |
} | |
void MasonryLayout::doPositioningAll() { | |
/* We're not done layouting. */ | |
/* TODO: find better way. */ | |
if (width() == 0.0) { | |
return; | |
} | |
/* Calculate element width */ | |
m_width = width() / m_elements - 2 * m_spacing; | |
/* Reset masonry row progress */ | |
m_progress.resize(m_elements); | |
std::fill( | |
m_progress.begin(), | |
m_progress.end(), | |
m_spacing | |
); | |
setHeight(0.0); | |
for (auto item : childItems()) { | |
doPositioningSingle(item); | |
} | |
} | |
void MasonryLayout::doPositioningSingle(QQuickItem *item) { | |
if (m_progress.empty()) return; | |
auto it = std::min_element(m_progress.begin(), m_progress.end()); | |
auto idx = it - m_progress.begin(); | |
auto aspect_ratio = item->height() / item->width(); | |
item->setWidth(m_width); | |
item->setHeight(aspect_ratio * m_width); | |
/** | |
* || ||| ||| || | |
* ^ ^ ^ | |
* Spacing | Start | |
* Double Spacing | |
*/ | |
item->setX(m_spacing + (m_width + 2 * m_spacing) * idx); | |
item->setY(*it); | |
*it += item->height() + 2 * m_spacing; | |
if (*it > height()) { | |
setHeight(*it); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <QQuickItem> | |
class MasonryLayout : public QQuickItem { | |
Q_OBJECT | |
Q_PROPERTY(int32_t spacing READ spacing WRITE setSpacing) | |
Q_PROPERTY(uint elements READ elements WRITE setElements) | |
QML_ELEMENT | |
public: | |
MasonryLayout(); | |
int32_t spacing() const { return m_spacing; } | |
void setSpacing(int32_t spacing); | |
uint elements() const { return m_elements; } | |
void setElements(uint elements); | |
private: | |
void itemChange(QQuickItem::ItemChange change, QQuickItem::ItemChangeData const& value); | |
void handleWidthChanged(); | |
void doPositioningAll(); | |
void doPositioningSingle(QQuickItem *item); | |
int32_t m_spacing = 0; | |
uint m_elements = 1; | |
qreal m_width; | |
std::vector<qreal> m_progress; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment