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
#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 "QskLayoutHint.h"
#include "QskLayoutConstraint.h"
#include "QskLayoutChain.h"
#include "QskSizePolicy.h"
#include "QskQuick.h"
#include <qvector.h>
#include <qvarlengtharray.h>
#include <vector>
#ifdef QSK_LAYOUT_COMPAT
#include <cmath>
#endif
static constexpr qreal qskDefaultSpacing()
{
@ -21,58 +21,6 @@ static constexpr qreal qskDefaultSpacing()
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
{
public:
@ -92,313 +40,10 @@ namespace
QSizeF boundingSize;
QVector< Range > rows;
QVector< Range > columns;
QVector< QskLayoutChain::Range > rows;
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
{
public:
@ -478,15 +123,16 @@ namespace
int effectiveCount() const;
int effectiveCount( Qt::Orientation orientation ) const;
void updateCellTable( Qt::Orientation,
const QVector< Range >& constraints, CellTable& ) const;
void resetChain( Qt::Orientation,
const QVector< QskLayoutChain::Range >& constraints,
QskLayoutChain& ) const;
QskLayoutConstraint::Type constraintType() const;
void invalidate();
private:
CellData cellData( const EntryData&,
QskLayoutChain::Cell cell( const EntryData&,
Qt::Orientation, qreal constraint ) const;
inline EntryData* entryAt( int index ) const
@ -504,7 +150,7 @@ namespace
uint m_dimension;
mutable int m_sumIgnored : 19;
mutable int m_constrainedType : 3;
mutable int m_constraintType : 3;
unsigned int m_defaultAlignment : 8;
unsigned int m_orientation : 2;
@ -575,7 +221,7 @@ bool EntryData::isConstrained( Qt::Orientation orientation ) const
EntryTable::EntryTable( Qt::Orientation orientation, uint dimension )
: m_dimension( dimension )
, m_sumIgnored( -1 )
, m_constrainedType( -1 )
, m_constraintType( -1 )
, m_defaultAlignment( Qt::AlignLeft | Qt::AlignVCenter )
, m_orientation( orientation )
{
@ -782,7 +428,7 @@ bool EntryTable::retainSizeWhenHiddenAt( int index ) const
void EntryTable::invalidate()
{
m_sumIgnored = -1;
m_constrainedType = -1;
m_constraintType = -1;
}
int EntryTable::effectiveCount() const
@ -821,9 +467,9 @@ int EntryTable::effectiveCount( Qt::Orientation orientation ) 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 )
{
@ -831,23 +477,23 @@ QskLayoutConstraint::Type EntryTable::constraintType() const
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");
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
{
int stretch = 0;
@ -934,28 +580,29 @@ CellData EntryTable::cellData( const EntryData& entry,
}
}
CellData cellData;
cellData.hint = QskLayoutHint( minimum, preferred, maximum );
cellData.stretch = stretch;
cellData.canGrow = canGrow;
QskLayoutChain::Cell cell;
cell.hint = QskLayoutHint( minimum, preferred, maximum );
cell.stretch = stretch;
cell.canGrow = canGrow;
return cellData;
return cell;
}
void EntryTable::updateCellTable( Qt::Orientation orientation,
const QVector< Range >& constraints, CellTable& cellTable ) const
void EntryTable::resetChain( Qt::Orientation orientation,
const QVector< QskLayoutChain::Range >& constraints,
QskLayoutChain& chain ) const
{
const auto count = effectiveCount( orientation );
const qreal constraint =
constraints.isEmpty() ? -1.0 : constraints.last().end();
if ( ( cellTable.constraint() == constraint )
&& ( cellTable.count() == count ) )
if ( ( chain.constraint() == constraint )
&& ( chain.count() == count ) )
{
return; // already up to date
}
cellTable.reset( count, constraint );
chain.reset( count, constraint );
uint index1 = 0;
uint index2 = 0;
@ -968,8 +615,8 @@ void EntryTable::updateCellTable( Qt::Orientation orientation,
const qreal cellConstraint =
constraints.isEmpty() ? -1.0 : constraints[index1].length;
const auto data = cellData( entry, orientation, cellConstraint );
cellTable.addCellData( index2, data );
const auto cell = this->cell( entry, orientation, cellConstraint );
chain.addCell( index2, cell );
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,
const QVector< Range >& constraints,
const EntryTable& entryTable, CellTable& cellTable )
static inline void qskResetChain( Qt::Orientation orientation,
const QVector< QskLayoutChain::Range >& constraints,
const EntryTable& entryTable, QskLayoutChain& chain )
{
entryTable.updateCellTable( orientation, constraints, cellTable );
entryTable.resetChain( orientation, constraints, chain );
}
static inline void qskUpdateCellTable( Qt::Orientation orientation,
const EntryTable& entryTable, CellTable& cellTable )
static inline void qskResetChain( Qt::Orientation orientation,
const EntryTable& entryTable, QskLayoutChain& chain )
{
entryTable.updateCellTable( orientation, QVector< Range >(), cellTable );
const QVector< QskLayoutChain::Range > constraints;
entryTable.resetChain( orientation, constraints, chain );
}
class QskLinearLayoutEngine::PrivateData
@ -1015,8 +663,8 @@ class QskLinearLayoutEngine::PrivateData
: entryTable( orientation, dimension )
, blockInvalidate( false )
{
rowTable.setSpacing( qskDefaultSpacing() );
colTable.setSpacing( qskDefaultSpacing() );
rowChain.setSpacing( qskDefaultSpacing() );
colChain.setSpacing( qskDefaultSpacing() );
}
EntryTable entryTable;
@ -1024,8 +672,8 @@ class QskLinearLayoutEngine::PrivateData
Qt::LayoutDirection visualDirection = Qt::LeftToRight;
Qt::Edges extraSpacingAt;
CellTable colTable;
CellTable rowTable;
QskLayoutChain colChain;
QskLayoutChain rowChain;
CellGeometries geometries;
@ -1127,10 +775,10 @@ void QskLinearLayoutEngine::setSpacing( qreal spacing, Qt::Orientations orientat
bool doInvalidate = false;
if ( orientations & Qt::Horizontal )
doInvalidate |= m_data->colTable.setSpacing( spacing );
doInvalidate |= m_data->colChain.setSpacing( spacing );
if ( orientations & Qt::Vertical )
doInvalidate |= m_data->rowTable.setSpacing( spacing );
doInvalidate |= m_data->rowChain.setSpacing( spacing );
if ( doInvalidate )
invalidate( CellCache | LayoutCache );
@ -1139,9 +787,9 @@ void QskLinearLayoutEngine::setSpacing( qreal spacing, Qt::Orientations orientat
qreal QskLinearLayoutEngine::spacing( Qt::Orientation orientation ) const
{
if ( orientation == Qt::Horizontal )
return m_data->colTable.spacing();
return m_data->colChain.spacing();
else
return m_data->rowTable.spacing();
return m_data->rowChain.spacing();
}
void QskLinearLayoutEngine::setExtraSpacingAt( Qt::Edges edges )
@ -1152,7 +800,7 @@ void QskLinearLayoutEngine::setExtraSpacingAt( Qt::Edges edges )
m_data->extraSpacingAt = edges;
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
@ -1167,7 +815,7 @@ void QskLinearLayoutEngine::setExtraSpacingAt( Qt::Edges edges )
if ( edges & Qt::BottomEdge )
rowEdges |= Qt::RightEdge;
m_data->rowTable.setExtraSpacingAt( rowEdges );
m_data->rowChain.setExtraSpacingAt( rowEdges );
invalidate( LayoutCache );
}
@ -1235,8 +883,8 @@ void QskLinearLayoutEngine::invalidate( int what )
if ( what & CellCache )
{
m_data->rowTable.invalidate();
m_data->colTable.invalidate();
m_data->rowChain.invalidate();
m_data->colChain.invalidate();
}
if ( what & LayoutCache )
@ -1315,37 +963,37 @@ QSizeF QskLinearLayoutEngine::sizeHint( Qt::SizeHint which, const QSizeF& constr
const auto constraintType = m_data->entryTable.constraintType();
auto& colTable = m_data->colTable;
auto& rowTable = m_data->rowTable;
auto& colChain = m_data->colChain;
auto& rowChain = m_data->rowChain;
m_data->blockInvalidate = true;
if ( ( constraint.width() >= 0 ) &&
( constraintType == QskLayoutConstraint::HeightForWidth ) )
{
qskUpdateCellTable( Qt::Horizontal, entryTable, colTable );
qskResetChain( Qt::Horizontal, entryTable, colChain );
const auto cellConstraints = colTable.cellRanges( constraint.width() );
qskUpdateCellTable( Qt::Vertical, cellConstraints, entryTable, rowTable );
const auto cellConstraints = colChain.geometries( constraint.width() );
qskResetChain( Qt::Vertical, cellConstraints, entryTable, rowChain );
}
else if ( ( constraint.height() >= 0 ) &&
( constraintType == QskLayoutConstraint::WidthForHeight ) )
{
qskUpdateCellTable( Qt::Vertical, entryTable, rowTable );
qskResetChain( Qt::Vertical, entryTable, rowChain );
const auto cellConstraints = rowTable.cellRanges( constraint.height() );
qskUpdateCellTable( Qt::Horizontal, cellConstraints, entryTable, colTable );
const auto cellConstraints = rowChain.geometries( constraint.height() );
qskResetChain( Qt::Horizontal, cellConstraints, entryTable, colChain );
}
else
{
qskUpdateCellTable( Qt::Horizontal, entryTable, colTable );
qskUpdateCellTable( Qt::Vertical, entryTable, rowTable );
qskResetChain( Qt::Horizontal, entryTable, colChain );
qskResetChain( Qt::Vertical, entryTable, rowChain );
}
m_data->blockInvalidate = false;
const qreal width = colTable.boundingHint().size( which );
const qreal height = rowTable.boundingHint().size( which );
const qreal width = colChain.boundingHint().size( which );
const qreal height = rowChain.boundingHint().size( which );
return QSizeF( width, height );
}
@ -1377,41 +1025,41 @@ void QskLinearLayoutEngine::updateCellGeometries( const QSizeF& size )
auto& geometries = m_data->geometries;
geometries.boundingSize = size;
auto& colTable = m_data->colTable;
auto& rowTable = m_data->rowTable;
auto& colChain = m_data->colChain;
auto& rowChain = m_data->rowChain;
auto& entryTable = m_data->entryTable;
const QVector< Range > noConstraints;
const QVector< QskLayoutChain::Range > noConstraints;
switch( entryTable.constraintType() )
{
case QskLayoutConstraint::WidthForHeight:
{
qskUpdateCellTable( Qt::Vertical, entryTable, rowTable );
geometries.rows = rowTable.cellRanges( size.height() );
qskResetChain( Qt::Vertical, entryTable, rowChain );
geometries.rows = rowChain.geometries( size.height() );
qskUpdateCellTable( Qt::Horizontal, geometries.rows, entryTable, colTable );
geometries.columns = colTable.cellRanges( size.width() );
qskResetChain( Qt::Horizontal, geometries.rows, entryTable, colChain );
geometries.columns = colChain.geometries( size.width() );
break;
}
case QskLayoutConstraint::HeightForWidth:
{
qskUpdateCellTable( Qt::Horizontal, entryTable, colTable );
geometries.columns = colTable.cellRanges( size.width() );
qskResetChain( Qt::Horizontal, entryTable, colChain );
geometries.columns = colChain.geometries( size.width() );
qskUpdateCellTable( Qt::Vertical, geometries.columns, entryTable, rowTable );
geometries.rows = rowTable.cellRanges( size.height() );
qskResetChain( Qt::Vertical, geometries.columns, entryTable, rowChain );
geometries.rows = rowChain.geometries( size.height() );
break;
}
default:
{
qskUpdateCellTable( Qt::Horizontal, entryTable, colTable );
geometries.columns = colTable.cellRanges( size.width() );
qskResetChain( Qt::Horizontal, entryTable, colChain );
geometries.columns = colChain.geometries( size.width() );
qskUpdateCellTable( Qt::Vertical, entryTable, rowTable );
geometries.rows = rowTable.cellRanges( size.height() );
qskResetChain( Qt::Vertical, entryTable, rowChain );
geometries.rows = rowChain.geometries( size.height() );
}
}
}

View File

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