code moved to QskLayoutChain

This commit is contained in:
Uwe Rathmann 2019-07-01 14:45:25 +02:00
parent a7fa7e3769
commit 9593226e0c
5 changed files with 482 additions and 436 deletions

View File

@ -0,0 +1,321 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#include "QskLayoutChain.h"
#include <qvarlengtharray.h>
#include <qvector.h>
#ifdef QSK_LAYOUT_COMPAT
#include <cmath>
#endif
QskLayoutChain::QskLayoutChain()
{
}
QskLayoutChain::~QskLayoutChain()
{
}
void QskLayoutChain::invalidate()
{
m_cells.clear();
m_constraint = -2;
}
void QskLayoutChain::reset( int count, qreal constraint )
{
m_cells.assign( count, Cell() );
m_constraint = constraint;
}
void QskLayoutChain::addCell( int index, const Cell& cell )
{
auto& combinedCell = m_cells[ index ];
combinedCell.canGrow |= cell.canGrow;
combinedCell.stretch = qMax( combinedCell.stretch, cell.stretch );
m_sumStretches += cell.stretch;
combinedCell.hint.intersect( cell.hint );
}
void QskLayoutChain::finish()
{
qreal minimum = 0.0;
qreal preferred = 0.0;
qreal maximum = 0.0;
if ( !m_cells.empty() )
{
for ( auto& cellData : m_cells )
{
minimum += cellData.hint.minimum();
preferred += cellData.hint.preferred();
if ( cellData.stretch == 0 && !cellData.canGrow )
maximum += cellData.hint.preferred();
else
maximum += cellData.hint.maximum(); // overflow ???
}
const qreal spacing = ( m_cells.size() - 1 ) * m_spacing;
minimum += spacing;
preferred += spacing;
maximum += spacing;
}
m_boundingHint.setMinimum( minimum );
m_boundingHint.setPreferred( preferred );
m_boundingHint.setMaximum( maximum );
}
bool QskLayoutChain::setSpacing( qreal spacing )
{
if ( m_spacing != spacing )
{
m_spacing = spacing;
return true;
}
return false;
}
QVector< QskLayoutChain::Range > QskLayoutChain::geometries( qreal size ) const
{
QVector< Range > ranges;
if ( size <= m_boundingHint.minimum() )
{
ranges = distributed( Qt::MinimumSize, 0.0, 0.0 );
}
else if ( size < m_boundingHint.preferred() )
{
ranges = minimumExpanded( size );
}
else if ( size <= m_boundingHint.maximum() )
{
ranges = preferredStretched( size );
}
else
{
const qreal padding = size - m_boundingHint.maximum();
qreal offset = 0.0;
qreal extra = 0.0;;
if ( m_extraSpacingAt == Qt::LeftEdge )
{
offset = padding;
}
else if ( m_extraSpacingAt == Qt::RightEdge )
{
offset = 0.0;
}
else if ( m_extraSpacingAt == ( Qt::LeftEdge | Qt::RightEdge ) )
{
offset = 0.5 * padding;
}
else
{
extra = padding / m_cells.size();
}
ranges = distributed( Qt::MaximumSize, offset, extra );
}
return ranges;
}
QVector< QskLayoutChain::Range > QskLayoutChain::distributed(
int which, qreal offset, const qreal extra ) const
{
qreal fillSpacing = 0.0;
QVector< Range > ranges( m_cells.size() );
for ( int i = 0; i < ranges.count(); i++ )
{
auto& range = ranges[i];
offset += fillSpacing;
fillSpacing = m_spacing;
range.start = offset;
range.length = m_cells[i].hint.size( which ) + extra;
offset += range.length;
}
return ranges;
}
QVector< QskLayoutChain::Range > QskLayoutChain::minimumExpanded( qreal size ) const
{
QVector< Range > ranges( m_cells.size() );
qreal fillSpacing = 0.0;
qreal offset = 0.0;
/*
We have different options how to distribute the availabe space
- according to the preferred sizes
- items with a larger preferred size are stretchier: this is
what QSK_LAYOUT_COMPAT does ( compatible with QGridLayoutEngine )
- somehow using the stretch factors
*/
#ifdef QSK_LAYOUT_COMPAT
/*
Code does not make much sense, but this is what QGridLayoutEngine does.
The implementation is intended to help during the migration, but is supposed
to be removed then TODO ...
*/
qreal sumFactors = 0.0;
QVarLengthArray< qreal > factors( m_cells.size() );
const qreal desired = m_boundingHint.preferred() - m_boundingHint.minimum();
const qreal available = size - m_boundingHint.minimum();
for ( uint i = 0; i < m_cells.size(); i++ )
{
const auto& hint = m_cells[i].hint;
const qreal l = hint.preferred() - hint.minimum();
factors[i] = l * std::pow( available / desired, l / desired );
sumFactors += factors[i];
}
for ( uint i = 0; i < m_cells.size(); i++ )
{
const auto& hint = m_cells[i].hint;
auto& range = ranges[i];
offset += fillSpacing;
fillSpacing = m_spacing;
range.start = offset;
range.length = hint.minimum() + available * ( factors[i] / sumFactors );
offset += range.length;
}
#else
const qreal factor = ( size - m_boundingHint.minimum() ) /
( m_boundingHint.preferred() - m_boundingHint.minimum() );
for ( uint i = 0; i < m_cells.size(); i++ )
{
const auto& hint = m_cells[i].hint;
auto& range = ranges[i];
offset += fillSpacing;
fillSpacing = m_spacing;
range.start = offset;
range.length = hint.minimum() + factor * ( hint.preferred() - hint.minimum() );
offset += range.length;
}
#endif
return ranges;
}
QVector< QskLayoutChain::Range > QskLayoutChain::preferredStretched( qreal size ) const
{
const int count = m_cells.size();
auto sumSizes = size - ( count - 1 ) * m_spacing;
qreal sumFactors = 0.0;
QVarLengthArray< qreal > factors( count );
for ( int i = 0; i < count; i++ )
{
const auto& hint = m_cells[i].hint;
if ( hint.preferred() >= hint.maximum() )
{
factors[i] = 0.0;
}
else
{
if ( m_sumStretches == 0 )
factors[i] = m_cells[i].canGrow ? 1.0 : 0.0;
else
factors[i] = m_cells[i].stretch;
}
sumFactors += factors[i];
}
QVector< Range > ranges( count );
Q_FOREVER
{
bool done = true;
for ( int i = 0; i < count; i++ )
{
if ( factors[i] < 0.0 )
continue;
const auto size = sumSizes * factors[i] / sumFactors;
const auto& hint = m_cells[i].hint;
const auto boundedSize =
qBound( hint.preferred(), size, hint.maximum() );
if ( boundedSize != size )
{
ranges[i].length = boundedSize;
sumSizes -= boundedSize;
sumFactors -= factors[i];
factors[i] = -1.0;
done = false;
}
}
if ( done )
break;
}
qreal offset = 0;
qreal fillSpacing = 0.0;
for ( int i = 0; i < count; i++ )
{
auto& range = ranges[i];
const auto& factor = factors[i];
offset += fillSpacing;
fillSpacing = m_spacing;
range.start = offset;
if ( factor >= 0.0 )
{
if ( factor > 0.0 )
range.length = sumSizes * factor / sumFactors;
else
range.length = m_cells[i].hint.preferred();
}
offset += range.length;
}
return ranges;
}

View File

@ -0,0 +1,70 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#ifndef QSK_LAYOUT_CHAIN_H
#define QSK_LAYOUT_CHAIN_H
#include <QskLayoutHint.h>
#include <qvector.h>
#include <vector>
class QskLayoutChain
{
public:
class Range
{
public:
inline qreal end() const { return start + length; }
qreal start = 0.0;
qreal length = 0.0;
};
class Cell
{
public:
QskLayoutHint hint;
int stretch = 0;
bool canGrow = false;
};
QskLayoutChain();
~QskLayoutChain();
void invalidate();
void reset( int count, qreal constraint );
void addCell( int index, const Cell& );
void finish();
bool setSpacing( qreal spacing );
qreal spacing() const { return m_spacing; }
void setExtraSpacingAt( Qt::Edges edges ) { m_extraSpacingAt = edges; }
QVector< Range > geometries( qreal size ) const;
QskLayoutHint boundingHint() const { return m_boundingHint; }
inline qreal constraint() const { return m_constraint; }
inline int count() const { return m_cells.size(); }
private:
Q_DISABLE_COPY( QskLayoutChain )
QVector< Range > distributed( int which, qreal offset, qreal extra ) const;
QVector< Range > minimumExpanded( qreal size ) const;
QVector< Range > preferredStretched( qreal size ) const;
QskLayoutHint m_boundingHint;
qreal m_constraint = -2;
qreal m_spacing = 0;
Qt::Edges m_extraSpacingAt;
int m_sumStretches = 0;
std::vector< Cell > m_cells;
};
#endif

View File

@ -1,3 +1,8 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#ifndef QSK_LAYOUT_HINT_H #ifndef QSK_LAYOUT_HINT_H
#define QSK_LAYOUT_HINT_H #define QSK_LAYOUT_HINT_H

View File

@ -1,17 +1,17 @@
/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#include "QskLinearLayoutEngine.h" #include "QskLinearLayoutEngine.h"
#include "QskLayoutHint.h" #include "QskLayoutHint.h"
#include "QskLayoutConstraint.h" #include "QskLayoutConstraint.h"
#include "QskLayoutChain.h"
#include "QskSizePolicy.h" #include "QskSizePolicy.h"
#include "QskQuick.h" #include "QskQuick.h"
#include <qvector.h> #include <qvector.h>
#include <qvarlengtharray.h>
#include <vector>
#ifdef QSK_LAYOUT_COMPAT
#include <cmath>
#endif
static constexpr qreal qskDefaultSpacing() static constexpr qreal qskDefaultSpacing()
{ {
@ -21,58 +21,6 @@ static constexpr qreal qskDefaultSpacing()
namespace namespace
{ {
class Range
{
public:
inline qreal end() const { return start + length; }
qreal start = 0.0;
qreal length = 0.0;
};
class CellData
{
public:
QskLayoutHint hint;
int stretch = 0;
bool canGrow = false;
};
class CellTable
{
public:
void invalidate();
void reset( int count, qreal constraint );
void addCellData( int index, const CellData& );
void finish();
bool setSpacing( qreal spacing );
qreal spacing() const { return m_spacing; }
void setExtraSpacingAt( Qt::Edges edges ) { m_extraSpacingAt = edges; }
QVector< Range > cellRanges( qreal size ) const;
QskLayoutHint boundingHint() const { return m_boundingHint; }
inline qreal constraint() const { return m_constraint; }
inline int count() const { return m_cells.size(); }
private:
QVector< Range > distributed( int which, qreal offset, qreal extra ) const;
QVector< Range > minimumExpanded( qreal size ) const;
QVector< Range > preferredStretched( qreal size ) const;
QskLayoutHint m_boundingHint;
qreal m_constraint = -2;
qreal m_spacing = 0;
Qt::Edges m_extraSpacingAt;
int m_sumStretches = 0;
std::vector< CellData > m_cells;
};
class CellGeometries class CellGeometries
{ {
public: public:
@ -92,313 +40,10 @@ namespace
QSizeF boundingSize; QSizeF boundingSize;
QVector< Range > rows; QVector< QskLayoutChain::Range > rows;
QVector< Range > columns; QVector< QskLayoutChain::Range > columns;
}; };
}
void CellTable::invalidate()
{
m_cells.clear();
m_constraint = -2;
}
void CellTable::reset( int count, qreal constraint )
{
m_cells.assign( count, CellData() );
m_constraint = constraint;
}
void CellTable::addCellData( int index, const CellData& data )
{
auto& combinedData = m_cells[ index ];
combinedData.canGrow |= data.canGrow;
combinedData.stretch = qMax( combinedData.stretch, data.stretch );
m_sumStretches += data.stretch;
combinedData.hint.intersect( data.hint );
}
void CellTable::finish()
{
qreal minimum = 0.0;
qreal preferred = 0.0;
qreal maximum = 0.0;
if ( !m_cells.empty() )
{
for ( auto& cellData : m_cells )
{
minimum += cellData.hint.minimum();
preferred += cellData.hint.preferred();
if ( cellData.stretch == 0 && !cellData.canGrow )
maximum += cellData.hint.preferred();
else
maximum += cellData.hint.maximum(); // overflow ???
}
const qreal spacing = ( m_cells.size() - 1 ) * m_spacing;
minimum += spacing;
preferred += spacing;
maximum += spacing;
}
m_boundingHint.setMinimum( minimum );
m_boundingHint.setPreferred( preferred );
m_boundingHint.setMaximum( maximum );
}
bool CellTable::setSpacing( qreal spacing )
{
if ( m_spacing != spacing )
{
m_spacing = spacing;
return true;
}
return false;
}
QVector< Range > CellTable::cellRanges( qreal size ) const
{
QVector< Range > ranges;
if ( size <= m_boundingHint.minimum() )
{
ranges = distributed( Qt::MinimumSize, 0.0, 0.0 );
}
else if ( size < m_boundingHint.preferred() )
{
ranges = minimumExpanded( size );
}
else if ( size <= m_boundingHint.maximum() )
{
ranges = preferredStretched( size );
}
else
{
const qreal padding = size - m_boundingHint.maximum();
qreal offset = 0.0;
qreal extra = 0.0;;
if ( m_extraSpacingAt == Qt::LeftEdge )
{
offset = padding;
}
else if ( m_extraSpacingAt == Qt::RightEdge )
{
offset = 0.0;
}
else if ( m_extraSpacingAt == ( Qt::LeftEdge | Qt::RightEdge ) )
{
offset = 0.5 * padding;
}
else
{
extra = padding / m_cells.size();
}
ranges = distributed( Qt::MaximumSize, offset, extra );
}
return ranges;
}
QVector< Range > CellTable::distributed(
int which, qreal offset, const qreal extra ) const
{
qreal fillSpacing = 0.0;
QVector< Range > ranges( m_cells.size() );
for ( int i = 0; i < ranges.count(); i++ )
{
auto& range = ranges[i];
offset += fillSpacing;
fillSpacing = m_spacing;
range.start = offset;
range.length = m_cells[i].hint.size( which ) + extra;
offset += range.length;
}
return ranges;
}
QVector< Range > CellTable::minimumExpanded( qreal size ) const
{
QVector< Range > ranges( m_cells.size() );
qreal fillSpacing = 0.0;
qreal offset = 0.0;
/*
We have different options how to distribute the availabe space
- according to the preferred sizes
- items with a larger preferred size are stretchier: this is
what QSK_LAYOUT_COMPAT does ( compatible with QGridLayoutEngine )
- somehow using the stretch factors
*/
#ifdef QSK_LAYOUT_COMPAT
/*
Code does not make much sense, but this is what QGridLayoutEngine does.
The implementation is intended to help during the migration, but is supposed
to be removed then TODO ...
*/
qreal sumFactors = 0.0;
QVarLengthArray< qreal > factors( m_cells.size() );
const qreal desired = m_boundingHint.preferred() - m_boundingHint.minimum();
const qreal available = size - m_boundingHint.minimum();
for ( uint i = 0; i < m_cells.size(); i++ )
{
const auto& hint = m_cells[i].hint;
const qreal l = hint.preferred() - hint.minimum();
factors[i] = l * std::pow( available / desired, l / desired );
sumFactors += factors[i];
}
for ( uint i = 0; i < m_cells.size(); i++ )
{
const auto& hint = m_cells[i].hint;
auto& range = ranges[i];
offset += fillSpacing;
fillSpacing = m_spacing;
range.start = offset;
range.length = hint.minimum() + available * ( factors[i] / sumFactors );
offset += range.length;
}
#else
const qreal factor = ( size - m_boundingHint.minimum() ) /
( m_boundingHint.preferred() - m_boundingHint.minimum() );
for ( uint i = 0; i < m_cells.size(); i++ )
{
const auto& hint = m_cells[i].hint;
auto& range = ranges[i];
offset += fillSpacing;
fillSpacing = m_spacing;
range.start = offset;
range.length = hint.minimum() + factor * ( hint.preferred() - hint.minimum() );
offset += range.length;
}
#endif
return ranges;
}
QVector< Range > CellTable::preferredStretched( qreal size ) const
{
const int count = m_cells.size();
auto sumSizes = size - ( count - 1 ) * m_spacing;
qreal sumFactors = 0.0;
QVarLengthArray< qreal > factors( count );
for ( int i = 0; i < count; i++ )
{
const auto& hint = m_cells[i].hint;
if ( hint.preferred() >= hint.maximum() )
{
factors[i] = 0.0;
}
else
{
if ( m_sumStretches == 0 )
factors[i] = m_cells[i].canGrow ? 1.0 : 0.0;
else
factors[i] = m_cells[i].stretch;
}
sumFactors += factors[i];
}
QVector< Range > ranges( count );
Q_FOREVER
{
bool done = true;
for ( int i = 0; i < count; i++ )
{
if ( factors[i] < 0.0 )
continue;
const auto size = sumSizes * factors[i] / sumFactors;
const auto& hint = m_cells[i].hint;
const auto boundedSize =
qBound( hint.preferred(), size, hint.maximum() );
if ( boundedSize != size )
{
ranges[i].length = boundedSize;
sumSizes -= boundedSize;
sumFactors -= factors[i];
factors[i] = -1.0;
done = false;
}
}
if ( done )
break;
}
qreal offset = 0;
qreal fillSpacing = 0.0;
for ( int i = 0; i < count; i++ )
{
auto& range = ranges[i];
const auto& factor = factors[i];
offset += fillSpacing;
fillSpacing = m_spacing;
range.start = offset;
if ( factor >= 0.0 )
{
if ( factor > 0.0 )
range.length = sumSizes * factor / sumFactors;
else
range.length = m_cells[i].hint.preferred();
}
offset += range.length;
}
return ranges;
}
namespace
{
class EntryData class EntryData
{ {
public: public:
@ -478,15 +123,16 @@ namespace
int effectiveCount() const; int effectiveCount() const;
int effectiveCount( Qt::Orientation orientation ) const; int effectiveCount( Qt::Orientation orientation ) const;
void updateCellTable( Qt::Orientation, void resetChain( Qt::Orientation,
const QVector< Range >& constraints, CellTable& ) const; const QVector< QskLayoutChain::Range >& constraints,
QskLayoutChain& ) const;
QskLayoutConstraint::Type constraintType() const; QskLayoutConstraint::Type constraintType() const;
void invalidate(); void invalidate();
private: private:
CellData cellData( const EntryData&, QskLayoutChain::Cell cell( const EntryData&,
Qt::Orientation, qreal constraint ) const; Qt::Orientation, qreal constraint ) const;
inline EntryData* entryAt( int index ) const inline EntryData* entryAt( int index ) const
@ -504,7 +150,7 @@ namespace
uint m_dimension; uint m_dimension;
mutable int m_sumIgnored : 19; mutable int m_sumIgnored : 19;
mutable int m_constrainedType : 3; mutable int m_constraintType : 3;
unsigned int m_defaultAlignment : 8; unsigned int m_defaultAlignment : 8;
unsigned int m_orientation : 2; unsigned int m_orientation : 2;
@ -575,7 +221,7 @@ bool EntryData::isConstrained( Qt::Orientation orientation ) const
EntryTable::EntryTable( Qt::Orientation orientation, uint dimension ) EntryTable::EntryTable( Qt::Orientation orientation, uint dimension )
: m_dimension( dimension ) : m_dimension( dimension )
, m_sumIgnored( -1 ) , m_sumIgnored( -1 )
, m_constrainedType( -1 ) , m_constraintType( -1 )
, m_defaultAlignment( Qt::AlignLeft | Qt::AlignVCenter ) , m_defaultAlignment( Qt::AlignLeft | Qt::AlignVCenter )
, m_orientation( orientation ) , m_orientation( orientation )
{ {
@ -782,7 +428,7 @@ bool EntryTable::retainSizeWhenHiddenAt( int index ) const
void EntryTable::invalidate() void EntryTable::invalidate()
{ {
m_sumIgnored = -1; m_sumIgnored = -1;
m_constrainedType = -1; m_constraintType = -1;
} }
int EntryTable::effectiveCount() const int EntryTable::effectiveCount() const
@ -821,9 +467,9 @@ int EntryTable::effectiveCount( Qt::Orientation orientation ) const
QskLayoutConstraint::Type EntryTable::constraintType() const QskLayoutConstraint::Type EntryTable::constraintType() const
{ {
if ( m_constrainedType < 0 ) if ( m_constraintType < 0 )
{ {
m_constrainedType = QskLayoutConstraint::Unconstrained; m_constraintType = QskLayoutConstraint::Unconstrained;
for ( const auto& entry : m_entries ) for ( const auto& entry : m_entries )
{ {
@ -831,23 +477,23 @@ QskLayoutConstraint::Type EntryTable::constraintType() const
if ( itemType != QskLayoutConstraint::Unconstrained ) if ( itemType != QskLayoutConstraint::Unconstrained )
{ {
if ( m_constrainedType == QskLayoutConstraint::Unconstrained ) if ( m_constraintType == QskLayoutConstraint::Unconstrained )
{ {
m_constrainedType = itemType; m_constraintType = itemType;
} }
else if ( m_constrainedType != itemType ) else if ( m_constraintType != itemType )
{ {
qWarning( "QskLinearLayoutEngine: conflicting constraints"); qWarning( "QskLinearLayoutEngine: conflicting constraints");
m_constrainedType = QskLayoutConstraint::Unconstrained; m_constraintType = QskLayoutConstraint::Unconstrained;
} }
} }
} }
} }
return static_cast< QskLayoutConstraint::Type >( m_constrainedType ); return static_cast< QskLayoutConstraint::Type >( m_constraintType );
} }
CellData EntryTable::cellData( const EntryData& entry, QskLayoutChain::Cell EntryTable::cell( const EntryData& entry,
Qt::Orientation orientation, qreal constraint ) const Qt::Orientation orientation, qreal constraint ) const
{ {
int stretch = 0; int stretch = 0;
@ -934,28 +580,29 @@ CellData EntryTable::cellData( const EntryData& entry,
} }
} }
CellData cellData; QskLayoutChain::Cell cell;
cellData.hint = QskLayoutHint( minimum, preferred, maximum ); cell.hint = QskLayoutHint( minimum, preferred, maximum );
cellData.stretch = stretch; cell.stretch = stretch;
cellData.canGrow = canGrow; cell.canGrow = canGrow;
return cellData; return cell;
} }
void EntryTable::updateCellTable( Qt::Orientation orientation, void EntryTable::resetChain( Qt::Orientation orientation,
const QVector< Range >& constraints, CellTable& cellTable ) const const QVector< QskLayoutChain::Range >& constraints,
QskLayoutChain& chain ) const
{ {
const auto count = effectiveCount( orientation ); const auto count = effectiveCount( orientation );
const qreal constraint = const qreal constraint =
constraints.isEmpty() ? -1.0 : constraints.last().end(); constraints.isEmpty() ? -1.0 : constraints.last().end();
if ( ( cellTable.constraint() == constraint ) if ( ( chain.constraint() == constraint )
&& ( cellTable.count() == count ) ) && ( chain.count() == count ) )
{ {
return; // already up to date return; // already up to date
} }
cellTable.reset( count, constraint ); chain.reset( count, constraint );
uint index1 = 0; uint index1 = 0;
uint index2 = 0; uint index2 = 0;
@ -968,8 +615,8 @@ void EntryTable::updateCellTable( Qt::Orientation orientation,
const qreal cellConstraint = const qreal cellConstraint =
constraints.isEmpty() ? -1.0 : constraints[index1].length; constraints.isEmpty() ? -1.0 : constraints[index1].length;
const auto data = cellData( entry, orientation, cellConstraint ); const auto cell = this->cell( entry, orientation, cellConstraint );
cellTable.addCellData( index2, data ); chain.addCell( index2, cell );
if ( m_orientation != orientation ) if ( m_orientation != orientation )
{ {
@ -989,22 +636,23 @@ void EntryTable::updateCellTable( Qt::Orientation orientation,
} }
} }
cellTable.finish(); chain.finish();
} }
// --------- // ---------
static inline void qskUpdateCellTable( Qt::Orientation orientation, static inline void qskResetChain( Qt::Orientation orientation,
const QVector< Range >& constraints, const QVector< QskLayoutChain::Range >& constraints,
const EntryTable& entryTable, CellTable& cellTable ) const EntryTable& entryTable, QskLayoutChain& chain )
{ {
entryTable.updateCellTable( orientation, constraints, cellTable ); entryTable.resetChain( orientation, constraints, chain );
} }
static inline void qskUpdateCellTable( Qt::Orientation orientation, static inline void qskResetChain( Qt::Orientation orientation,
const EntryTable& entryTable, CellTable& cellTable ) const EntryTable& entryTable, QskLayoutChain& chain )
{ {
entryTable.updateCellTable( orientation, QVector< Range >(), cellTable ); const QVector< QskLayoutChain::Range > constraints;
entryTable.resetChain( orientation, constraints, chain );
} }
class QskLinearLayoutEngine::PrivateData class QskLinearLayoutEngine::PrivateData
@ -1015,8 +663,8 @@ class QskLinearLayoutEngine::PrivateData
: entryTable( orientation, dimension ) : entryTable( orientation, dimension )
, blockInvalidate( false ) , blockInvalidate( false )
{ {
rowTable.setSpacing( qskDefaultSpacing() ); rowChain.setSpacing( qskDefaultSpacing() );
colTable.setSpacing( qskDefaultSpacing() ); colChain.setSpacing( qskDefaultSpacing() );
} }
EntryTable entryTable; EntryTable entryTable;
@ -1024,8 +672,8 @@ class QskLinearLayoutEngine::PrivateData
Qt::LayoutDirection visualDirection = Qt::LeftToRight; Qt::LayoutDirection visualDirection = Qt::LeftToRight;
Qt::Edges extraSpacingAt; Qt::Edges extraSpacingAt;
CellTable colTable; QskLayoutChain colChain;
CellTable rowTable; QskLayoutChain rowChain;
CellGeometries geometries; CellGeometries geometries;
@ -1127,10 +775,10 @@ void QskLinearLayoutEngine::setSpacing( qreal spacing, Qt::Orientations orientat
bool doInvalidate = false; bool doInvalidate = false;
if ( orientations & Qt::Horizontal ) if ( orientations & Qt::Horizontal )
doInvalidate |= m_data->colTable.setSpacing( spacing ); doInvalidate |= m_data->colChain.setSpacing( spacing );
if ( orientations & Qt::Vertical ) if ( orientations & Qt::Vertical )
doInvalidate |= m_data->rowTable.setSpacing( spacing ); doInvalidate |= m_data->rowChain.setSpacing( spacing );
if ( doInvalidate ) if ( doInvalidate )
invalidate( CellCache | LayoutCache ); invalidate( CellCache | LayoutCache );
@ -1139,9 +787,9 @@ void QskLinearLayoutEngine::setSpacing( qreal spacing, Qt::Orientations orientat
qreal QskLinearLayoutEngine::spacing( Qt::Orientation orientation ) const qreal QskLinearLayoutEngine::spacing( Qt::Orientation orientation ) const
{ {
if ( orientation == Qt::Horizontal ) if ( orientation == Qt::Horizontal )
return m_data->colTable.spacing(); return m_data->colChain.spacing();
else else
return m_data->rowTable.spacing(); return m_data->rowChain.spacing();
} }
void QskLinearLayoutEngine::setExtraSpacingAt( Qt::Edges edges ) void QskLinearLayoutEngine::setExtraSpacingAt( Qt::Edges edges )
@ -1152,7 +800,7 @@ void QskLinearLayoutEngine::setExtraSpacingAt( Qt::Edges edges )
m_data->extraSpacingAt = edges; m_data->extraSpacingAt = edges;
Qt::Edges colEdges = edges & ~( Qt::TopEdge | Qt::BottomEdge ); Qt::Edges colEdges = edges & ~( Qt::TopEdge | Qt::BottomEdge );
m_data->colTable.setExtraSpacingAt( colEdges ); m_data->colChain.setExtraSpacingAt( colEdges );
/* /*
FlowLayoutInfo does not have an orientation, so we always FlowLayoutInfo does not have an orientation, so we always
@ -1167,7 +815,7 @@ void QskLinearLayoutEngine::setExtraSpacingAt( Qt::Edges edges )
if ( edges & Qt::BottomEdge ) if ( edges & Qt::BottomEdge )
rowEdges |= Qt::RightEdge; rowEdges |= Qt::RightEdge;
m_data->rowTable.setExtraSpacingAt( rowEdges ); m_data->rowChain.setExtraSpacingAt( rowEdges );
invalidate( LayoutCache ); invalidate( LayoutCache );
} }
@ -1235,8 +883,8 @@ void QskLinearLayoutEngine::invalidate( int what )
if ( what & CellCache ) if ( what & CellCache )
{ {
m_data->rowTable.invalidate(); m_data->rowChain.invalidate();
m_data->colTable.invalidate(); m_data->colChain.invalidate();
} }
if ( what & LayoutCache ) if ( what & LayoutCache )
@ -1315,37 +963,37 @@ QSizeF QskLinearLayoutEngine::sizeHint( Qt::SizeHint which, const QSizeF& constr
const auto constraintType = m_data->entryTable.constraintType(); const auto constraintType = m_data->entryTable.constraintType();
auto& colTable = m_data->colTable; auto& colChain = m_data->colChain;
auto& rowTable = m_data->rowTable; auto& rowChain = m_data->rowChain;
m_data->blockInvalidate = true; m_data->blockInvalidate = true;
if ( ( constraint.width() >= 0 ) && if ( ( constraint.width() >= 0 ) &&
( constraintType == QskLayoutConstraint::HeightForWidth ) ) ( constraintType == QskLayoutConstraint::HeightForWidth ) )
{ {
qskUpdateCellTable( Qt::Horizontal, entryTable, colTable ); qskResetChain( Qt::Horizontal, entryTable, colChain );
const auto cellConstraints = colTable.cellRanges( constraint.width() ); const auto cellConstraints = colChain.geometries( constraint.width() );
qskUpdateCellTable( Qt::Vertical, cellConstraints, entryTable, rowTable ); qskResetChain( Qt::Vertical, cellConstraints, entryTable, rowChain );
} }
else if ( ( constraint.height() >= 0 ) && else if ( ( constraint.height() >= 0 ) &&
( constraintType == QskLayoutConstraint::WidthForHeight ) ) ( constraintType == QskLayoutConstraint::WidthForHeight ) )
{ {
qskUpdateCellTable( Qt::Vertical, entryTable, rowTable ); qskResetChain( Qt::Vertical, entryTable, rowChain );
const auto cellConstraints = rowTable.cellRanges( constraint.height() ); const auto cellConstraints = rowChain.geometries( constraint.height() );
qskUpdateCellTable( Qt::Horizontal, cellConstraints, entryTable, colTable ); qskResetChain( Qt::Horizontal, cellConstraints, entryTable, colChain );
} }
else else
{ {
qskUpdateCellTable( Qt::Horizontal, entryTable, colTable ); qskResetChain( Qt::Horizontal, entryTable, colChain );
qskUpdateCellTable( Qt::Vertical, entryTable, rowTable ); qskResetChain( Qt::Vertical, entryTable, rowChain );
} }
m_data->blockInvalidate = false; m_data->blockInvalidate = false;
const qreal width = colTable.boundingHint().size( which ); const qreal width = colChain.boundingHint().size( which );
const qreal height = rowTable.boundingHint().size( which ); const qreal height = rowChain.boundingHint().size( which );
return QSizeF( width, height ); return QSizeF( width, height );
} }
@ -1377,41 +1025,41 @@ void QskLinearLayoutEngine::updateCellGeometries( const QSizeF& size )
auto& geometries = m_data->geometries; auto& geometries = m_data->geometries;
geometries.boundingSize = size; geometries.boundingSize = size;
auto& colTable = m_data->colTable; auto& colChain = m_data->colChain;
auto& rowTable = m_data->rowTable; auto& rowChain = m_data->rowChain;
auto& entryTable = m_data->entryTable; auto& entryTable = m_data->entryTable;
const QVector< Range > noConstraints; const QVector< QskLayoutChain::Range > noConstraints;
switch( entryTable.constraintType() ) switch( entryTable.constraintType() )
{ {
case QskLayoutConstraint::WidthForHeight: case QskLayoutConstraint::WidthForHeight:
{ {
qskUpdateCellTable( Qt::Vertical, entryTable, rowTable ); qskResetChain( Qt::Vertical, entryTable, rowChain );
geometries.rows = rowTable.cellRanges( size.height() ); geometries.rows = rowChain.geometries( size.height() );
qskUpdateCellTable( Qt::Horizontal, geometries.rows, entryTable, colTable ); qskResetChain( Qt::Horizontal, geometries.rows, entryTable, colChain );
geometries.columns = colTable.cellRanges( size.width() ); geometries.columns = colChain.geometries( size.width() );
break; break;
} }
case QskLayoutConstraint::HeightForWidth: case QskLayoutConstraint::HeightForWidth:
{ {
qskUpdateCellTable( Qt::Horizontal, entryTable, colTable ); qskResetChain( Qt::Horizontal, entryTable, colChain );
geometries.columns = colTable.cellRanges( size.width() ); geometries.columns = colChain.geometries( size.width() );
qskUpdateCellTable( Qt::Vertical, geometries.columns, entryTable, rowTable ); qskResetChain( Qt::Vertical, geometries.columns, entryTable, rowChain );
geometries.rows = rowTable.cellRanges( size.height() ); geometries.rows = rowChain.geometries( size.height() );
break; break;
} }
default: default:
{ {
qskUpdateCellTable( Qt::Horizontal, entryTable, colTable ); qskResetChain( Qt::Horizontal, entryTable, colChain );
geometries.columns = colTable.cellRanges( size.width() ); geometries.columns = colChain.geometries( size.width() );
qskUpdateCellTable( Qt::Vertical, entryTable, rowTable ); qskResetChain( Qt::Vertical, entryTable, rowChain );
geometries.rows = rowTable.cellRanges( size.height() ); geometries.rows = rowChain.geometries( size.height() );
} }
} }
} }

View File

@ -237,6 +237,7 @@ HEADERS += \
layouts/QskIndexedLayoutBox.h \ layouts/QskIndexedLayoutBox.h \
layouts/QskLayoutConstraint.h \ layouts/QskLayoutConstraint.h \
layouts/QskLayoutHint.h \ layouts/QskLayoutHint.h \
layouts/QskLayoutChain.h \
layouts/QskLinearBox.h \ layouts/QskLinearBox.h \
layouts/QskLinearLayoutEngine.h \ layouts/QskLinearLayoutEngine.h \
layouts/QskStackBoxAnimator.h \ layouts/QskStackBoxAnimator.h \
@ -248,6 +249,7 @@ SOURCES += \
layouts/QskIndexedLayoutBox.cpp \ layouts/QskIndexedLayoutBox.cpp \
layouts/QskLayoutConstraint.cpp \ layouts/QskLayoutConstraint.cpp \
layouts/QskLayoutHint.cpp \ layouts/QskLayoutHint.cpp \
layouts/QskLayoutChain.cpp \
layouts/QskLinearBox.cpp \ layouts/QskLinearBox.cpp \
layouts/QskLinearLayoutEngine.cpp \ layouts/QskLinearLayoutEngine.cpp \
layouts/QskStackBoxAnimator.cpp \ layouts/QskStackBoxAnimator.cpp \