QskLayoutChain prepared to be usable for grid layouts

This commit is contained in:
Uwe Rathmann 2019-07-13 10:03:04 +02:00
parent 4f48a3ab92
commit e9ff7cca40
5 changed files with 133 additions and 54 deletions

View File

@ -32,15 +32,26 @@ void QskLayoutChain::reset( int count, qreal constraint )
m_cells.assign( count, Cell() );
m_constraint = constraint;
m_sumStretches = 0;
m_validCells = 0;
}
void QskLayoutChain::expandTo( int index, const Cell& newCell )
{
if ( !newCell.isValid )
return;
auto& cell = m_cells[ index ];
cell.canGrow |= newCell.canGrow;
cell.stretch = qMax( cell.stretch, newCell.stretch );
cell.hint.intersect( newCell.hint );
if ( !cell.isValid )
{
cell = newCell;
}
else
{
cell.canGrow |= newCell.canGrow;
cell.stretch = qMax( cell.stretch, newCell.stretch );
cell.hint.expandTo( newCell.hint );
}
}
void QskLayoutChain::finish()
@ -50,6 +61,7 @@ void QskLayoutChain::finish()
qreal maximum = 0.0;
m_sumStretches = 0;
m_validCells = 0;
if ( !m_cells.empty() )
{
@ -57,6 +69,9 @@ void QskLayoutChain::finish()
for ( auto& cell : m_cells )
{
if ( !cell.isValid )
continue;
minimum += cell.hint.minimum();
preferred += cell.hint.preferred();
@ -76,9 +91,10 @@ void QskLayoutChain::finish()
}
m_sumStretches += cell.stretch;
m_validCells++;
}
const qreal spacing = ( m_cells.size() - 1 ) * m_spacing;
const qreal spacing = ( m_validCells - 1 ) * m_spacing;
minimum += spacing;
preferred += spacing;
@ -105,6 +121,9 @@ bool QskLayoutChain::setSpacing( qreal spacing )
QVector< QskLayoutChain::Range > QskLayoutChain::geometries( qreal size ) const
{
if ( m_validCells == 0 )
return QVector< Range >();
QVector< Range > ranges;
if ( size <= m_boundingHint.minimum() )
@ -140,7 +159,7 @@ QVector< QskLayoutChain::Range > QskLayoutChain::geometries( qreal size ) const
}
else
{
extra = padding / m_cells.size();
extra = padding / m_validCells;
}
ranges = distributed( Qt::MaximumSize, offset, extra );
@ -158,15 +177,24 @@ QVector< QskLayoutChain::Range > QskLayoutChain::distributed(
for ( int i = 0; i < ranges.count(); i++ )
{
const auto& cell = m_cells[i];
auto& range = ranges[i];
offset += fillSpacing;
fillSpacing = m_spacing;
if ( !cell.isValid )
{
range.start = offset;
range.length = 0.0;
}
else
{
offset += fillSpacing;
fillSpacing = m_spacing;
range.start = offset;
range.length = m_cells[i].hint.size( which ) + extra;
range.start = offset;
range.length = cell.hint.size( which ) + extra;
offset += range.length;
offset += range.length;
}
}
return ranges;
@ -205,27 +233,41 @@ QVector< QskLayoutChain::Range > QskLayoutChain::minimumExpanded( qreal size ) c
for ( uint i = 0; i < m_cells.size(); i++ )
{
const auto& hint = m_cells[i].hint;
const auto& cell = m_cells[i];
if ( !cell.isValid )
{
factors[i] = 0.0;
}
else
{
const qreal l = cell.hint.preferred() - cell.hint.minimum();
const qreal l = hint.preferred() - hint.minimum();
factors[i] = l * std::pow( available / desired, l / desired );
sumFactors += factors[i];
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;
const auto& cell = m_cells[i];
auto& range = ranges[i];
offset += fillSpacing;
fillSpacing = m_spacing;
if ( !cell.isValid )
{
range.start = offset;
range.length = 0.0;
}
else
{
offset += fillSpacing;
fillSpacing = m_spacing;
range.start = offset;
range.length = hint.minimum() + available * ( factors[i] / sumFactors );
range.start = offset;
range.length = cell.hint.minimum()
+ available * ( factors[i] / sumFactors );
offset += range.length;
offset += range.length;
}
}
#else
const qreal factor = ( size - m_boundingHint.minimum() ) /
@ -233,17 +275,25 @@ QVector< QskLayoutChain::Range > QskLayoutChain::minimumExpanded( qreal size ) c
for ( uint i = 0; i < m_cells.size(); i++ )
{
const auto& hint = m_cells[i].hint;
const auto& cell = m_cells[i];
auto& range = ranges[i];
offset += fillSpacing;
fillSpacing = m_spacing;
if ( !cell.isValid )
{
range.start = offset;
range.length = 0.0;
}
else
{
offset += fillSpacing;
fillSpacing = m_spacing;
range.start = offset;
range.length = hint.minimum() + factor * ( hint.preferred() - hint.minimum() );
range.start = offset;
range.length = cell.hint.minimum()
+ factor * ( cell.hint.preferred() - cell.hint.minimum() );
offset += range.length;
offset += range.length;
}
}
#endif
@ -253,31 +303,40 @@ QVector< QskLayoutChain::Range > QskLayoutChain::minimumExpanded( qreal size ) c
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 );
QVector< Range > ranges( count );
for ( int i = 0; i < count; i++ )
{
const auto& hint = m_cells[i].hint;
const auto& cell = m_cells[i];
if ( hint.preferred() >= hint.maximum() )
if ( !cell.isValid )
{
ranges[i].length = 0.0;
factors[i] = -1.0;
continue;
}
if ( cell.hint.preferred() >= cell.hint.maximum() )
{
factors[i] = 0.0;
}
else
{
if ( m_sumStretches == 0 )
factors[i] = m_cells[i].canGrow ? 1.0 : 0.0;
factors[i] = cell.canGrow ? 1.0 : 0.0;
else
factors[i] = m_cells[i].stretch;
factors[i] = cell.stretch;
}
sumFactors += factors[i];
}
QVector< Range > ranges( count );
auto sumSizes = size - ( m_validCells - 1 ) * m_spacing;
Q_FOREVER
{
@ -314,11 +373,16 @@ QVector< QskLayoutChain::Range > QskLayoutChain::preferredStretched( qreal size
for ( int i = 0; i < count; i++ )
{
const auto& cell = m_cells[i];
auto& range = ranges[i];
const auto& factor = factors[i];
offset += fillSpacing;
fillSpacing = m_spacing;
if ( cell.isValid )
{
offset += fillSpacing;
fillSpacing = m_spacing;
}
range.start = offset;
@ -327,7 +391,7 @@ QVector< QskLayoutChain::Range > QskLayoutChain::preferredStretched( qreal size
if ( factor > 0.0 )
range.length = sumSizes * factor / sumFactors;
else
range.length = m_cells[i].hint.preferred();
range.length = cell.hint.preferred();
}
offset += range.length;
@ -355,8 +419,16 @@ QDebug operator<<( QDebug debug, const QskLayoutChain::Cell& cell )
QDebugStateSaver saver( debug );
debug.nospace();
debug << "( " << cell.hint << ", "
<< cell.stretch << ", " << cell.canGrow << " )";
if ( !cell.isValid )
{
debug << "( " << "Invalid " << " )";
}
else
{
debug << "( " << cell.hint << ", "
<< cell.stretch << ", " << cell.canGrow << " )";
}
return debug;
}

View File

@ -28,10 +28,21 @@ class QskLayoutChain
class Cell
{
public:
Cell()
{
}
Cell( QskLayoutHint hint, int stretch )
: hint( hint )
, stretch( stretch )
, isValid( true )
{
}
inline bool operator==( const Cell& other ) const
{
return ( canGrow == other.canGrow )
return ( isValid == other.isValid )
&& ( canGrow == other.canGrow )
&& ( stretch == other.stretch )
&& ( hint == other.hint );
}
@ -44,6 +55,7 @@ class QskLayoutChain
QskLayoutHint hint;
int stretch = 0;
bool canGrow = false;
bool isValid = false;
};
QskLayoutChain();
@ -82,6 +94,7 @@ class QskLayoutChain
Qt::Edges m_extraSpacingAt;
int m_sumStretches = 0;
int m_validCells = 0;
std::vector< Cell > m_cells;
};

View File

@ -53,20 +53,13 @@ void QskLayoutHint::setSize( int which, qreal size )
}
}
void QskLayoutHint::intersect( const QskLayoutHint& other )
void QskLayoutHint::expandTo( const QskLayoutHint& other )
{
m_minimum = qMax( m_minimum, other.m_minimum );
m_preferred = qMax( m_preferred, other.m_preferred );
const auto hint = other.normalized();
if ( other.m_maximum != QskLayoutConstraint::unlimited )
{
if ( m_maximum == QskLayoutConstraint::unlimited )
m_maximum = other.m_maximum;
else
m_maximum = qMax( m_maximum, other.m_maximum );
}
normalize();
m_minimum = qMax( m_minimum, hint.m_minimum );
m_preferred = qMax( m_preferred, hint.m_preferred );
m_maximum = qMax( m_maximum, hint.m_maximum );
}
void QskLayoutHint::normalize()

View File

@ -17,7 +17,7 @@ class QSK_EXPORT QskLayoutHint
QskLayoutHint();
QskLayoutHint( qreal minimum, qreal preferred, qreal maximum );
void intersect( const QskLayoutHint& );
void expandTo( const QskLayoutHint& );
void normalize();
QskLayoutHint normalized() const;

View File

@ -479,6 +479,7 @@ QskLayoutChain::Cell EntryTable::cell( const EntryData& entry,
{
QskLayoutChain::Cell cell;
cell.canGrow = true;
cell.isValid = true;
if ( const auto item = entry.item() )
{