qwt_dyngrid_layout.cpp
Go to the documentation of this file.
00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
00002  * Qwt Widget Library
00003  * Copyright (C) 1997   Josef Wilgen
00004  * Copyright (C) 2002   Uwe Rathmann
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the Qwt License, Version 1.0
00008  *****************************************************************************/
00009 
00010 #include "qwt_dyngrid_layout.h"
00011 #include "qwt_math.h"
00012 #include <qvector.h>
00013 #include <qlist.h>
00014 
00015 class QwtDynGridLayout::PrivateData
00016 {
00017 public:
00018     PrivateData():
00019         isDirty( true )
00020     {
00021     }
00022 
00023     void updateLayoutCache();
00024 
00025     mutable QList<QLayoutItem*> itemList;
00026 
00027     uint maxColumns;
00028     uint numRows;
00029     uint numColumns;
00030 
00031     Qt::Orientations expanding;
00032 
00033     bool isDirty;
00034     QVector<QSize> itemSizeHints;
00035 };
00036 
00037 void QwtDynGridLayout::PrivateData::updateLayoutCache()
00038 {
00039     itemSizeHints.resize( itemList.count() );
00040 
00041     int index = 0;
00042 
00043     for ( QList<QLayoutItem*>::iterator it = itemList.begin();
00044         it != itemList.end(); ++it, index++ )
00045     {
00046         itemSizeHints[ index ] = ( *it )->sizeHint();
00047     }
00048 
00049     isDirty = false;
00050 }
00051 
00058 QwtDynGridLayout::QwtDynGridLayout( QWidget *parent,
00059         int margin, int spacing ):
00060     QLayout( parent )
00061 {
00062     init();
00063 
00064     setSpacing( spacing );
00065     setMargin( margin );
00066 }
00067 
00072 QwtDynGridLayout::QwtDynGridLayout( int spacing )
00073 {
00074     init();
00075     setSpacing( spacing );
00076 }
00077 
00081 void QwtDynGridLayout::init()
00082 {
00083     d_data = new QwtDynGridLayout::PrivateData;
00084     d_data->maxColumns = d_data->numRows = d_data->numColumns = 0;
00085     d_data->expanding = 0;
00086 }
00087 
00089 
00090 QwtDynGridLayout::~QwtDynGridLayout()
00091 {
00092     for ( int i = 0; i < d_data->itemList.size(); i++ )
00093         delete d_data->itemList[i];
00094 
00095     delete d_data;
00096 }
00097 
00099 void QwtDynGridLayout::invalidate()
00100 {
00101     d_data->isDirty = true;
00102     QLayout::invalidate();
00103 }
00104 
00110 void QwtDynGridLayout::setMaxColumns( uint maxColumns )
00111 {
00112     d_data->maxColumns = maxColumns;
00113 }
00114 
00123 uint QwtDynGridLayout::maxColumns() const
00124 {
00125     return d_data->maxColumns;
00126 }
00127 
00132 void QwtDynGridLayout::addItem( QLayoutItem *item )
00133 {
00134     d_data->itemList.append( item );
00135     invalidate();
00136 }
00137 
00141 bool QwtDynGridLayout::isEmpty() const
00142 {
00143     return d_data->itemList.isEmpty();
00144 }
00145 
00149 uint QwtDynGridLayout::itemCount() const
00150 {
00151     return d_data->itemList.count();
00152 }
00153 
00161 QLayoutItem *QwtDynGridLayout::itemAt( int index ) const
00162 {
00163     if ( index < 0 || index >= d_data->itemList.count() )
00164         return NULL;
00165 
00166     return d_data->itemList.at( index );
00167 }
00168 
00176 QLayoutItem *QwtDynGridLayout::takeAt( int index )
00177 {
00178     if ( index < 0 || index >= d_data->itemList.count() )
00179         return NULL;
00180 
00181     d_data->isDirty = true;
00182     return d_data->itemList.takeAt( index );
00183 }
00184 
00186 int QwtDynGridLayout::count() const
00187 {
00188     return d_data->itemList.count();
00189 }
00190 
00200 void QwtDynGridLayout::setExpandingDirections( Qt::Orientations expanding )
00201 {
00202     d_data->expanding = expanding;
00203 }
00204 
00215 Qt::Orientations QwtDynGridLayout::expandingDirections() const
00216 {
00217     return d_data->expanding;
00218 }
00219 
00226 void QwtDynGridLayout::setGeometry( const QRect &rect )
00227 {
00228     QLayout::setGeometry( rect );
00229 
00230     if ( isEmpty() )
00231         return;
00232 
00233     d_data->numColumns = columnsForWidth( rect.width() );
00234     d_data->numRows = itemCount() / d_data->numColumns;
00235     if ( itemCount() % d_data->numColumns )
00236         d_data->numRows++;
00237 
00238     QList<QRect> itemGeometries = layoutItems( rect, d_data->numColumns );
00239 
00240     int index = 0;
00241     for ( QList<QLayoutItem*>::iterator it = d_data->itemList.begin();
00242         it != d_data->itemList.end(); ++it )
00243     {
00244         ( *it )->setGeometry( itemGeometries[index] );
00245         index++;
00246     }
00247 }
00248 
00260 uint QwtDynGridLayout::columnsForWidth( int width ) const
00261 {
00262     if ( isEmpty() )
00263         return 0;
00264 
00265     uint maxColumns = itemCount();
00266     if ( d_data->maxColumns > 0 ) 
00267         maxColumns = qMin( d_data->maxColumns, maxColumns );
00268 
00269     if ( maxRowWidth( maxColumns ) <= width )
00270         return maxColumns;
00271 
00272     for ( uint numColumns = 2; numColumns <= maxColumns; numColumns++ )
00273     {
00274         const int rowWidth = maxRowWidth( numColumns );
00275         if ( rowWidth > width )
00276             return numColumns - 1;
00277     }
00278 
00279     return 1; // At least 1 column
00280 }
00281 
00289 int QwtDynGridLayout::maxRowWidth( int numColumns ) const
00290 {
00291     int col;
00292 
00293     QVector<int> colWidth( numColumns );
00294     for ( col = 0; col < numColumns; col++ )
00295         colWidth[col] = 0;
00296 
00297     if ( d_data->isDirty )
00298         d_data->updateLayoutCache();
00299 
00300     for ( int index = 0;
00301         index < d_data->itemSizeHints.count(); index++ )
00302     {
00303         col = index % numColumns;
00304         colWidth[col] = qMax( colWidth[col],
00305             d_data->itemSizeHints[int( index )].width() );
00306     }
00307 
00308     int rowWidth = 2 * margin() + ( numColumns - 1 ) * spacing();
00309     for ( col = 0; col < numColumns; col++ )
00310         rowWidth += colWidth[col];
00311 
00312     return rowWidth;
00313 }
00314 
00318 int QwtDynGridLayout::maxItemWidth() const
00319 {
00320     if ( isEmpty() )
00321         return 0;
00322 
00323     if ( d_data->isDirty )
00324         d_data->updateLayoutCache();
00325 
00326     int w = 0;
00327     for ( int i = 0; i < d_data->itemSizeHints.count(); i++ )
00328     {
00329         const int itemW = d_data->itemSizeHints[i].width();
00330         if ( itemW > w )
00331             w = itemW;
00332     }
00333 
00334     return w;
00335 }
00336 
00346 QList<QRect> QwtDynGridLayout::layoutItems( const QRect &rect,
00347     uint numColumns ) const
00348 {
00349     QList<QRect> itemGeometries;
00350     if ( numColumns == 0 || isEmpty() )
00351         return itemGeometries;
00352 
00353     uint numRows = itemCount() / numColumns;
00354     if ( numColumns % itemCount() )
00355         numRows++;
00356 
00357     if ( numRows == 0 )
00358         return itemGeometries;
00359 
00360     QVector<int> rowHeight( numRows );
00361     QVector<int> colWidth( numColumns );
00362 
00363     layoutGrid( numColumns, rowHeight, colWidth );
00364 
00365     bool expandH, expandV;
00366     expandH = expandingDirections() & Qt::Horizontal;
00367     expandV = expandingDirections() & Qt::Vertical;
00368 
00369     if ( expandH || expandV )
00370         stretchGrid( rect, numColumns, rowHeight, colWidth );
00371 
00372     const int maxColumns = d_data->maxColumns;
00373     d_data->maxColumns = numColumns;
00374     const QRect alignedRect = alignmentRect( rect );
00375     d_data->maxColumns = maxColumns;
00376 
00377     const int xOffset = expandH ? 0 : alignedRect.x();
00378     const int yOffset = expandV ? 0 : alignedRect.y();
00379 
00380     QVector<int> colX( numColumns );
00381     QVector<int> rowY( numRows );
00382 
00383     const int xySpace = spacing();
00384 
00385     rowY[0] = yOffset + margin();
00386     for ( uint r = 1; r < numRows; r++ )
00387         rowY[r] = rowY[r-1] + rowHeight[r-1] + xySpace;
00388 
00389     colX[0] = xOffset + margin();
00390     for ( uint c = 1; c < numColumns; c++ )
00391         colX[c] = colX[c-1] + colWidth[c-1] + xySpace;
00392 
00393     const int itemCount = d_data->itemList.size();
00394     for ( int i = 0; i < itemCount; i++ )
00395     {
00396         const int row = i / numColumns;
00397         const int col = i % numColumns;
00398 
00399         QRect itemGeometry( colX[col], rowY[row],
00400             colWidth[col], rowHeight[row] );
00401         itemGeometries.append( itemGeometry );
00402     }
00403 
00404     return itemGeometries;
00405 }
00406 
00407 
00417 void QwtDynGridLayout::layoutGrid( uint numColumns,
00418     QVector<int>& rowHeight, QVector<int>& colWidth ) const
00419 {
00420     if ( numColumns <= 0 )
00421         return;
00422 
00423     if ( d_data->isDirty )
00424         d_data->updateLayoutCache();
00425 
00426     for ( int index = 0; index < d_data->itemSizeHints.count(); index++ )
00427     {
00428         const int row = index / numColumns;
00429         const int col = index % numColumns;
00430 
00431         const QSize &size = d_data->itemSizeHints[int( index )];
00432 
00433         rowHeight[row] = ( col == 0 )
00434             ? size.height() : qMax( rowHeight[row], size.height() );
00435         colWidth[col] = ( row == 0 )
00436             ? size.width() : qMax( colWidth[col], size.width() );
00437     }
00438 }
00439 
00444 bool QwtDynGridLayout::hasHeightForWidth() const
00445 {
00446     return true;
00447 }
00448 
00453 int QwtDynGridLayout::heightForWidth( int width ) const
00454 {
00455     if ( isEmpty() )
00456         return 0;
00457 
00458     const uint numColumns = columnsForWidth( width );
00459     uint numRows = itemCount() / numColumns;
00460     if ( itemCount() % numColumns )
00461         numRows++;
00462 
00463     QVector<int> rowHeight( numRows );
00464     QVector<int> colWidth( numColumns );
00465 
00466     layoutGrid( numColumns, rowHeight, colWidth );
00467 
00468     int h = 2 * margin() + ( numRows - 1 ) * spacing();
00469     for ( uint row = 0; row < numRows; row++ )
00470         h += rowHeight[row];
00471 
00472     return h;
00473 }
00474 
00487 void QwtDynGridLayout::stretchGrid( const QRect &rect,
00488     uint numColumns, QVector<int>& rowHeight, QVector<int>& colWidth ) const
00489 {
00490     if ( numColumns == 0 || isEmpty() )
00491         return;
00492 
00493     bool expandH, expandV;
00494     expandH = expandingDirections() & Qt::Horizontal;
00495     expandV = expandingDirections() & Qt::Vertical;
00496 
00497     if ( expandH )
00498     {
00499         int xDelta = rect.width() - 2 * margin() - ( numColumns - 1 ) * spacing();
00500         for ( uint col = 0; col < numColumns; col++ )
00501             xDelta -= colWidth[col];
00502 
00503         if ( xDelta > 0 )
00504         {
00505             for ( uint col = 0; col < numColumns; col++ )
00506             {
00507                 const int space = xDelta / ( numColumns - col );
00508                 colWidth[col] += space;
00509                 xDelta -= space;
00510             }
00511         }
00512     }
00513 
00514     if ( expandV )
00515     {
00516         uint numRows = itemCount() / numColumns;
00517         if ( itemCount() % numColumns )
00518             numRows++;
00519 
00520         int yDelta = rect.height() - 2 * margin() - ( numRows - 1 ) * spacing();
00521         for ( uint row = 0; row < numRows; row++ )
00522             yDelta -= rowHeight[row];
00523 
00524         if ( yDelta > 0 )
00525         {
00526             for ( uint row = 0; row < numRows; row++ )
00527             {
00528                 const int space = yDelta / ( numRows - row );
00529                 rowHeight[row] += space;
00530                 yDelta -= space;
00531             }
00532         }
00533     }
00534 }
00535 
00544 QSize QwtDynGridLayout::sizeHint() const
00545 {
00546     if ( isEmpty() )
00547         return QSize();
00548 
00549     uint numColumns = itemCount();
00550     if ( d_data->maxColumns > 0 )
00551         numColumns = qMin( d_data->maxColumns, numColumns );
00552 
00553     uint numRows = itemCount() / numColumns;
00554     if ( itemCount() % numColumns )
00555         numRows++;
00556 
00557     QVector<int> rowHeight( numRows );
00558     QVector<int> colWidth( numColumns );
00559 
00560     layoutGrid( numColumns, rowHeight, colWidth );
00561 
00562     int h = 2 * margin() + ( numRows - 1 ) * spacing();
00563     for ( uint row = 0; row < numRows; row++ )
00564         h += rowHeight[row];
00565 
00566     int w = 2 * margin() + ( numColumns - 1 ) * spacing();
00567     for ( uint col = 0; col < numColumns; col++ )
00568         w += colWidth[col];
00569 
00570     return QSize( w, h );
00571 }
00572 
00578 uint QwtDynGridLayout::numRows() const
00579 {
00580     return d_data->numRows;
00581 }
00582 
00588 uint QwtDynGridLayout::numColumns() const
00589 {
00590     return d_data->numColumns;
00591 }


plotjuggler
Author(s): Davide Faconti
autogenerated on Fri Sep 1 2017 02:41:56