File indexing completed on 2024-05-12 17:08:53
0001 /* 0002 SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "abstractlayoutmanager.h" 0008 #include "itemcontainer.h" 0009 0010 #include <cmath> 0011 0012 AbstractLayoutManager::AbstractLayoutManager(AppletsLayout *layout) 0013 : QObject(layout) 0014 , m_layout(layout) 0015 { 0016 } 0017 0018 AbstractLayoutManager::~AbstractLayoutManager() 0019 { 0020 } 0021 0022 AppletsLayout *AbstractLayoutManager::layout() const 0023 { 0024 return m_layout; 0025 } 0026 0027 QSizeF AbstractLayoutManager::cellSize() const 0028 { 0029 return m_cellSize; 0030 } 0031 0032 QSizeF AbstractLayoutManager::cellAlignedContainingSize(const QSizeF &size) const 0033 { 0034 return QSizeF(m_cellSize.width() * ceil(size.width() / m_cellSize.width()), m_cellSize.height() * ceil(size.height() / m_cellSize.height())); 0035 } 0036 0037 void AbstractLayoutManager::setCellSize(const QSizeF &size) 0038 { 0039 m_cellSize = size; 0040 } 0041 0042 QRectF AbstractLayoutManager::candidateGeometry(ItemContainer *item) const 0043 { 0044 const QRectF originalItemRect = QRectF(item->x(), item->y(), item->width(), item->height()); 0045 0046 // TODO: a default minimum size 0047 QSizeF minimumSize = QSize(m_layout->minimumItemWidth(), m_layout->minimumItemHeight()); 0048 if (item->layoutAttached()) { 0049 minimumSize = QSizeF(qMax(minimumSize.width(), item->layoutAttached()->property("minimumWidth").toReal()), 0050 qMax(minimumSize.height(), item->layoutAttached()->property("minimumHeight").toReal())); 0051 } 0052 0053 const QRectF ltrRect = nextAvailableSpace(item, minimumSize, AppletsLayout::LeftToRight); 0054 const QRectF rtlRect = nextAvailableSpace(item, minimumSize, AppletsLayout::RightToLeft); 0055 const QRectF ttbRect = nextAvailableSpace(item, minimumSize, AppletsLayout::TopToBottom); 0056 const QRectF bttRect = nextAvailableSpace(item, minimumSize, AppletsLayout::BottomToTop); 0057 0058 // Take the closest rect, unless the item prefers a particular positioning strategy 0059 QMap<int, QRectF> distances; 0060 if (!ltrRect.isEmpty()) { 0061 const int dist = 0062 item->preferredLayoutDirection() == AppletsLayout::LeftToRight ? 0 : QPointF(originalItemRect.center() - ltrRect.center()).manhattanLength(); 0063 distances[dist] = ltrRect; 0064 } 0065 if (!rtlRect.isEmpty()) { 0066 const int dist = 0067 item->preferredLayoutDirection() == AppletsLayout::RightToLeft ? 0 : QPointF(originalItemRect.center() - rtlRect.center()).manhattanLength(); 0068 distances[dist] = rtlRect; 0069 } 0070 if (!ttbRect.isEmpty()) { 0071 const int dist = 0072 item->preferredLayoutDirection() == AppletsLayout::TopToBottom ? 0 : QPointF(originalItemRect.center() - ttbRect.center()).manhattanLength(); 0073 distances[dist] = ttbRect; 0074 } 0075 if (!bttRect.isEmpty()) { 0076 const int dist = 0077 item->preferredLayoutDirection() == AppletsLayout::BottomToTop ? 0 : QPointF(originalItemRect.center() - bttRect.center()).manhattanLength(); 0078 distances[dist] = bttRect; 0079 } 0080 0081 if (distances.isEmpty()) { 0082 // Failure to layout, completely full 0083 return originalItemRect; 0084 } else { 0085 return distances.first(); 0086 } 0087 } 0088 0089 void AbstractLayoutManager::positionItem(ItemContainer *item) 0090 { 0091 // Give it a sane size if uninitialized: this may change size hints 0092 if (item->width() <= 0 || item->height() <= 0) { 0093 item->setSize(QSizeF(qMax(m_layout->minimumItemWidth(), m_layout->defaultItemWidth()), // 0094 qMax(m_layout->minimumItemHeight(), m_layout->defaultItemHeight()))); 0095 } 0096 0097 QRectF candidate = candidateGeometry(item); 0098 // Use setProperty to allow Behavior on to take effect 0099 item->setProperty("x", candidate.topLeft().x()); 0100 item->setProperty("y", candidate.topLeft().y()); 0101 item->setSize(candidate.size()); 0102 } 0103 0104 void AbstractLayoutManager::positionItemAndAssign(ItemContainer *item) 0105 { 0106 releaseSpace(item); 0107 positionItem(item); 0108 assignSpace(item); 0109 } 0110 0111 bool AbstractLayoutManager::assignSpace(ItemContainer *item) 0112 { 0113 if (assignSpaceImpl(item)) { 0114 Q_EMIT layoutNeedsSaving(); 0115 return true; 0116 } else { 0117 return false; 0118 } 0119 } 0120 0121 void AbstractLayoutManager::releaseSpace(ItemContainer *item) 0122 { 0123 releaseSpaceImpl(item); 0124 Q_EMIT layoutNeedsSaving(); 0125 } 0126 0127 void AbstractLayoutManager::layoutGeometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) 0128 { 0129 Q_UNUSED(newGeometry); 0130 Q_UNUSED(oldGeometry); 0131 // NOTE: Empty base implementation, don't put anything here 0132 } 0133 0134 #include "moc_abstractlayoutmanager.cpp"