6#include "QskLinearLayoutEngine.h"
7#include "QskLayoutMetrics.h"
8#include "QskLayoutChain.h"
9#include "QskLayoutElement.h"
10#include "QskSizePolicy.h"
18 QQuickItem* item, Qt::Orientation orientation, qreal constraint )
21 return layoutItem.metrics( orientation, constraint );
27 Element( QQuickItem* item );
28 Element( qreal spacing );
29 Element(
const Element& );
31 Element& operator=(
const Element& );
33 qreal spacing()
const;
34 QQuickItem* item()
const;
37 void setStretch(
int );
39 bool isIgnored()
const;
42 Qt::Orientation,
bool isLayoutOrientation )
const;
56 class ElementsVector :
public std::vector< Element >
60 inline int count()
const {
return static_cast< int >( size() ); }
64Element::Element( QQuickItem* item )
70Element::Element( qreal spacing )
71 : m_spacing( spacing )
76Element::Element(
const Element& other )
77 : m_stretch( other.m_stretch )
78 , m_isSpacer( other.m_isSpacer )
80 if ( other.m_isSpacer )
81 m_spacing = other.m_spacing;
83 m_item = other.m_item;
86Element& Element::operator=(
const Element& other )
88 m_isSpacer = other.m_isSpacer;
90 if ( other.m_isSpacer )
91 m_spacing = other.m_spacing;
93 m_item = other.m_item;
95 m_stretch = other.m_stretch;
100inline qreal Element::spacing()
const
102 return m_isSpacer ? m_spacing : -1.0;
105inline QQuickItem* Element::item()
const
107 return m_isSpacer ? nullptr : m_item;
110inline int Element::stretch()
const
115inline void Element::setStretch(
int stretch )
120bool Element::isIgnored()
const
122 return !( m_isSpacer || qskIsVisibleToLayout( m_item ) );
126 Qt::Orientation orientation,
bool isLayoutOrientation )
const
134 const auto policy = qskSizePolicy( m_item ).policy( orientation );
136 if ( isLayoutOrientation )
139 cell.stretch = ( policy & QskSizePolicy::ExpandFlag ) ? 1 : 0;
141 cell.stretch = m_stretch;
144 cell.canGrow = policy & QskSizePolicy::GrowFlag;
148 if ( isLayoutOrientation )
150 cell.metrics.setMinimum( m_spacing );
151 cell.metrics.setPreferred( m_spacing );
153 if ( m_stretch <= 0 )
154 cell.metrics.setMaximum( m_spacing );
156 cell.stretch = qMax( m_stretch, 0 );
163class QskLinearLayoutEngine::PrivateData
167 PrivateData( Qt::Orientation orientation, uint dimension )
168 : dimension( dimension )
170 , orientation( orientation )
174 inline Element* elementAt(
int index )
const
176 if ( ( index < 0 ) || ( index >= this->elements.count() ) )
179 return const_cast< Element*
>( &this->elements[index] );
182 ElementsVector elements;
186 mutable int sumIgnored : 30;
187 unsigned int orientation : 2;
190QskLinearLayoutEngine::QskLinearLayoutEngine(
191 Qt::Orientation orientation, uint dimension )
192 : m_data( new PrivateData( orientation, dimension ) )
196QskLinearLayoutEngine::~QskLinearLayoutEngine()
200bool QskLinearLayoutEngine::setOrientation( Qt::Orientation orientation )
202 if ( m_data->orientation != orientation )
204 m_data->orientation = orientation;
205 invalidate( LayoutCache );
213Qt::Orientation QskLinearLayoutEngine::orientation()
const
215 return static_cast< Qt::Orientation
>( m_data->orientation );
218bool QskLinearLayoutEngine::setDimension( uint dimension )
223 if ( m_data->dimension != dimension )
225 m_data->dimension = dimension;
226 invalidate( LayoutCache );
234uint QskLinearLayoutEngine::dimension()
const
236 return m_data->dimension;
239int QskLinearLayoutEngine::count()
const
241 return m_data->elements.count();
244bool QskLinearLayoutEngine::setStretchFactorAt(
int index,
int stretchFactor )
246 if (
auto element = m_data->elementAt( index ) )
248 if ( stretchFactor < 0 )
251 if ( element->stretch() != stretchFactor )
253 element->setStretch( stretchFactor );
254 invalidate( LayoutCache );
263int QskLinearLayoutEngine::stretchFactorAt(
int index )
const
265 if (
const auto element = m_data->elementAt( index ) )
266 return element->stretch();
271int QskLinearLayoutEngine::insertItem( QQuickItem* item,
int index )
273 auto& elements = m_data->elements;
275 if ( index < 0 || index > count() )
277 index = elements.count();
278 elements.emplace_back( item );
282 elements.emplace( elements.begin() + index, item );
289int QskLinearLayoutEngine::insertSpacerAt(
int index, qreal spacing )
291 spacing = qMax( spacing,
static_cast< qreal
>( 0.0 ) );
293 auto& elements = m_data->elements;
295 if ( index < 0 || index > count() )
297 index = elements.count();
298 elements.emplace_back( spacing );
302 elements.emplace( elements.begin() + index, spacing );
305 invalidate( LayoutCache );
309bool QskLinearLayoutEngine::removeAt(
int index )
311 auto element = m_data->elementAt( index );
312 if ( element ==
nullptr )
315 if ( element->isIgnored() )
316 m_data->sumIgnored--;
318 const auto itemType = qskSizePolicy( element->item() ).constraintType();
320 int invalidationMode = LayoutCache;
322 if ( itemType > QskSizePolicy::Unconstrained )
323 invalidationMode |= ElementCache;
325 m_data->elements.erase( m_data->elements.begin() + index );
326 invalidate( invalidationMode );
331bool QskLinearLayoutEngine::clear()
336 m_data->elements.clear();
342QskSizePolicy QskLinearLayoutEngine::sizePolicyAt(
int index )
const
344 return qskSizePolicy( itemAt( index ) );
347int QskLinearLayoutEngine::indexOf(
const QQuickItem* item )
const
356 for (
int i = count() - 1; i >= 0; --i )
358 if ( itemAt( i ) == item )
366QQuickItem* QskLinearLayoutEngine::itemAt(
int index )
const
368 if (
const auto element = m_data->elementAt( index ) )
369 return element->item();
374qreal QskLinearLayoutEngine::spacerAt(
int index )
const
376 if (
const auto element = m_data->elementAt( index ) )
377 return element->spacing();
382void QskLinearLayoutEngine::layoutItems()
387 for (
const auto& element : m_data->elements )
389 if ( element.isIgnored() )
392 if (
auto item = element.item() )
394 if ( qskIsAdjustableByLayout( item ) )
396 const QRect grid( col, row, 1, 1 );
400 const auto rect = geometryAt( &layoutElement, grid );
401 if ( rect.size().isValid() )
402 qskSetItemGeometry( item, rect );
406 if ( m_data->orientation == Qt::Horizontal )
408 if ( ++col == m_data->dimension )
416 if ( ++row == m_data->dimension )
425int QskLinearLayoutEngine::effectiveCount( Qt::Orientation orientation )
const
427 const uint cellCount = effectiveCount();
429 if ( orientation == m_data->orientation )
431 return qMin( cellCount, m_data->dimension );
435 int count = cellCount / m_data->dimension;
436 if ( cellCount % m_data->dimension )
443int QskLinearLayoutEngine::effectiveCount()
const
445 if ( m_data->sumIgnored < 0 )
447 m_data->sumIgnored = 0;
449 for (
const auto& element : m_data->elements )
451 if ( element.isIgnored() )
452 m_data->sumIgnored++;
456 return m_data->elements.count() - m_data->sumIgnored;
459void QskLinearLayoutEngine::invalidateElementCache()
461 m_data->sumIgnored = -1;
464void QskLinearLayoutEngine::setupChain( Qt::Orientation orientation,
465 const QskLayoutChain::Segments& constraints,
QskLayoutChain& chain )
const
470 const bool isLayoutOrientation = ( orientation == m_data->orientation );
472 qreal constraint = -1.0;
474 for (
const auto& element : m_data->elements )
476 if ( element.isIgnored() )
479 if ( !constraints.isEmpty() )
480 constraint = constraints[index1].length;
482 auto cell = element.cell( orientation, isLayoutOrientation );
484 if ( element.item() )
485 cell.metrics = qskItemMetrics( element.item(), orientation, constraint );
487 chain.expandCell( index2, cell );
489 if ( isLayoutOrientation )
491 if ( ++index2 == m_data->dimension )
499 if ( ++index1 == m_data->dimension )