7#include "LegendLayout.h"
12#include "ItemBuilder.h"
13#include "datasource/ChartDataSource.h"
15qreal sizeWithSpacing(
int count, qreal size, qreal spacing)
17 return size * count + spacing * (count - 1);
20LegendLayoutAttached::LegendLayoutAttached(
QObject *parent)
25qreal LegendLayoutAttached::minimumWidth()
const
27 return m_minimumWidth.value_or(0.0);
30void LegendLayoutAttached::setMinimumWidth(qreal newMinimumWidth)
32 if (newMinimumWidth == m_minimumWidth) {
36 m_minimumWidth = newMinimumWidth;
37 Q_EMIT minimumWidthChanged();
40bool LegendLayoutAttached::isMinimumWidthValid()
const
42 return m_minimumWidth.has_value();
45qreal LegendLayoutAttached::preferredWidth()
const
47 return m_preferredWidth.value_or(0.0);
50void LegendLayoutAttached::setPreferredWidth(qreal newPreferredWidth)
52 if (newPreferredWidth == m_preferredWidth) {
56 m_preferredWidth = newPreferredWidth;
57 Q_EMIT preferredWidthChanged();
60bool LegendLayoutAttached::isPreferredWidthValid()
const
62 return m_preferredWidth.has_value();
65qreal LegendLayoutAttached::maximumWidth()
const
67 return m_maximumWidth.value_or(0.0);
70void LegendLayoutAttached::setMaximumWidth(qreal newMaximumWidth)
72 if (newMaximumWidth == m_maximumWidth) {
76 m_maximumWidth = newMaximumWidth;
77 Q_EMIT maximumWidthChanged();
80bool LegendLayoutAttached::isMaximumWidthValid()
const
82 return m_maximumWidth.has_value();
90qreal LegendLayout::horizontalSpacing()
const
92 return m_horizontalSpacing;
95void LegendLayout::setHorizontalSpacing(qreal newHorizontalSpacing)
97 if (newHorizontalSpacing == m_horizontalSpacing) {
101 m_horizontalSpacing = newHorizontalSpacing;
103 Q_EMIT horizontalSpacingChanged();
106qreal LegendLayout::verticalSpacing()
const
108 return m_verticalSpacing;
111void LegendLayout::setVerticalSpacing(qreal newVerticalSpacing)
113 if (newVerticalSpacing == m_verticalSpacing) {
117 m_verticalSpacing = newVerticalSpacing;
119 Q_EMIT verticalSpacingChanged();
122qreal LegendLayout::preferredWidth()
const
124 return m_preferredWidth;
127void LegendLayout::componentComplete()
135void LegendLayout::updatePolish()
143 qreal itemWidth = 0.0;
144 qreal itemHeight = 0.0;
146 qreal layoutWidth =
width();
148 std::tie(columns, rows, itemWidth, itemHeight) = determineColumns();
154 for (
auto item : items) {
155 if (!item->isVisible() || item->implicitWidth() <= 0 || item->implicitHeight() <= 0) {
159 auto attached =
static_cast<LegendLayoutAttached *
>(qmlAttachedPropertiesObject<LegendLayout>(item,
true));
161 auto x = (itemWidth + m_horizontalSpacing) * column;
162 auto y = (itemHeight + m_verticalSpacing) * row;
165 item->setWidth(std::clamp(itemWidth, attached->minimumWidth(), attached->maximumWidth()));
170 if (layoutWidth > 0 && item->width() > layoutWidth && columns == 1) {
171 item->setWidth(layoutWidth);
175 if (column >= columns) {
181 setImplicitSize(sizeWithSpacing(columns, itemWidth, m_horizontalSpacing), sizeWithSpacing(rows, itemHeight, m_verticalSpacing));
184void LegendLayout::geometryChange(
const QRectF &newGeometry,
const QRectF &oldGeometry)
186 if (newGeometry != oldGeometry) {
199 auto item = data.item;
205 auto attached =
static_cast<LegendLayoutAttached *
>(qmlAttachedPropertiesObject<LegendLayout>(item,
true));
214 auto item = data.item;
216 item->disconnect(
this);
217 auto attached =
static_cast<LegendLayoutAttached *
>(qmlAttachedPropertiesObject<LegendLayout>(item,
false));
219 attached->disconnect(
this);
230std::tuple<int, int, qreal, qreal> LegendLayout::determineColumns()
232 auto minWidth = -std::numeric_limits<qreal>::max();
233 auto preferredWidth = -std::numeric_limits<qreal>::max();
234 auto maxWidth = std::numeric_limits<qreal>::max();
235 auto maxHeight = -std::numeric_limits<qreal>::max();
249 for (
auto item : items) {
250 if (!item->isVisible() || item->implicitWidth() <= 0 || item->implicitHeight() <= 0) {
254 auto attached =
static_cast<LegendLayoutAttached *
>(qmlAttachedPropertiesObject<LegendLayout>(item,
true));
256 if (attached->isMinimumWidthValid()) {
257 minWidth = std::max(minWidth, attached->minimumWidth());
259 minWidth = std::max(minWidth, item->implicitWidth());
262 if (attached->isPreferredWidthValid()) {
263 preferredWidth = std::max(preferredWidth, attached->preferredWidth());
266 if (attached->isMaximumWidthValid()) {
267 maxWidth = std::min(maxWidth, attached->maximumWidth());
270 maxHeight = std::max(maxHeight, item->implicitHeight());
275 if (itemCount == 0) {
276 return std::make_tuple(0, 0, 0, 0);
279 auto availableWidth =
width();
286 if (availableWidth <= m_horizontalSpacing) {
287 if (maxWidth <= 0.0) {
288 availableWidth = sizeWithSpacing(itemCount, minWidth, m_horizontalSpacing);
290 availableWidth = sizeWithSpacing(itemCount, maxWidth, m_horizontalSpacing);
296 if (maxWidth <= 0.0 || maxWidth >= std::numeric_limits<qreal>::max()) {
297 maxWidth = availableWidth;
301 if (maxWidth < minWidth) {
305 if (preferredWidth != m_preferredWidth) {
306 m_preferredWidth = preferredWidth;
307 Q_EMIT preferredWidthChanged();
311 auto rows = itemCount;
317 auto minTotalWidth = sizeWithSpacing(columns, minWidth, m_horizontalSpacing);
318 auto maxTotalWidth = sizeWithSpacing(columns, maxWidth, m_horizontalSpacing);
323 if (minTotalWidth <= availableWidth && maxTotalWidth >= availableWidth) {
332 if (maxTotalWidth < availableWidth) {
335 columns = std::ceil(itemCount /
float(rows));
345 if (minTotalWidth > availableWidth) {
347 columns = std::ceil(itemCount /
float(rows));
355 auto itemWidth = fit ? (availableWidth - m_horizontalSpacing * (columns - 1)) / columns : maxWidth;
359 rows = std::ceil(itemCount /
float(columns));
361 return std::make_tuple(columns, rows, itemWidth, maxHeight);
364#include "moc_LegendLayout.cpp"
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QList< QQuickItem * > childItems() const const
virtual void componentComplete() override
virtual void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
void implicitHeightChanged()
void implicitWidthChanged()
virtual void itemChange(ItemChange change, const ItemChangeData &value)