Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

qwt_dyngrid_layout.cpp

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 
00012 #if QT_VERSION >= 300
00013 #include <qptrlist.h>
00014 #else
00015 #include <qlist.h>
00016 #ifndef QPtrList
00017 #define QPtrList QList
00018 #define QPtrListIterator QListIterator
00019 #endif
00020 #endif
00021 
00022 
00023 class QwtDynGridLayoutPrivate
00024 {
00025 public:
00026    QPtrList<QLayoutItem> itemList;
00027 };
00028 
00029 class QwtDynGridLayoutIterator: public QGLayoutIterator
00030 {
00031 public:
00032     QwtDynGridLayoutIterator(QPtrList<QLayoutItem> *);
00033 
00034     virtual QLayoutItem *current();
00035     virtual QLayoutItem *next();
00036     virtual QLayoutItem *takeCurrent();
00037 
00038 private:
00039     uint d_index;
00040     QPtrList<QLayoutItem> *d_itemList;
00041 };
00042 
00043 QwtDynGridLayoutIterator::QwtDynGridLayoutIterator(
00044         QPtrList<QLayoutItem> *itemList):
00045     d_index(0), 
00046     d_itemList(itemList)  
00047 {
00048 }
00049 
00050 QLayoutItem *QwtDynGridLayoutIterator::current()
00051 { 
00052     QLayoutItem *item = (d_index < d_itemList->count()) 
00053         ? d_itemList->at(d_index) : 0;  
00054 
00055     return item;
00056 }
00057 
00058 QLayoutItem *QwtDynGridLayoutIterator::next()
00059 { 
00060     d_index++; 
00061     return current(); 
00062 }
00063 
00064 QLayoutItem *QwtDynGridLayoutIterator::takeCurrent()
00065 { 
00066     QLayoutItem *item = (d_index < d_itemList->count()) 
00067         ? d_itemList->take(d_index) : 0;  
00068 
00069     return item;
00070 }
00071 
00079 QwtDynGridLayout::QwtDynGridLayout(QWidget *parent, 
00080         int margin, int space, const char *name):
00081     QLayout(parent, margin, space, name)
00082 {
00083     init();
00084 }
00085 
00092 QwtDynGridLayout::QwtDynGridLayout(QLayout *parent, 
00093         int space, const char *name):
00094     QLayout(parent, space, name)
00095 {
00096     init();
00097 }
00098 
00104 QwtDynGridLayout::QwtDynGridLayout(int space, const char *name):
00105     QLayout(space, name)
00106 {
00107     init();
00108 }
00109 
00113 void QwtDynGridLayout::init()
00114 {
00115     d_layoutData = new QwtDynGridLayoutPrivate;
00116     d_maxCols = d_numRows = d_numCols = 0;
00117     d_expanding = QSizePolicy::NoDirection;
00118 
00119     setSupportsMargin(TRUE);
00120 }
00121 
00123 
00124 QwtDynGridLayout::~QwtDynGridLayout()
00125 {
00126     deleteAllItems();
00127     delete d_layoutData;
00128 }
00129 
00136 void QwtDynGridLayout::setMaxCols(uint maxCols)
00137 {
00138     d_maxCols = maxCols;
00139 }
00140 
00147 uint QwtDynGridLayout::maxCols() const 
00148 { 
00149     return d_maxCols; 
00150 }
00151 
00153 
00154 void QwtDynGridLayout::addItem(QLayoutItem *item)
00155 {
00156     d_layoutData->itemList.append(item);
00157 }
00158 
00163 bool QwtDynGridLayout::isEmpty() const
00164 {
00165     return d_layoutData->itemList.isEmpty();
00166 }
00167 
00172 uint QwtDynGridLayout::itemCount() const
00173 {
00174     return d_layoutData->itemList.count();
00175 }
00176 
00181 QLayoutIterator QwtDynGridLayout::iterator()
00182 {       
00183     return QLayoutIterator( 
00184         new QwtDynGridLayoutIterator(&d_layoutData->itemList) );
00185 }
00186 
00192 void QwtDynGridLayout::setGeometry(const QRect &rect)
00193 {
00194     QLayout::setGeometry(rect);
00195 
00196     if ( isEmpty() )
00197         return;
00198 
00199     d_numCols = columnsForWidth(rect.width());
00200     d_numRows = itemCount() / d_numCols;
00201     if ( itemCount() % d_numCols )
00202         d_numRows++;
00203 
00204     QValueList<QRect> itemGeometries = layoutItems(rect, d_numCols);
00205 
00206     int index;
00207 
00208     QLayoutItem *item;
00209     QPtrListIterator<QLayoutItem> it(d_layoutData->itemList);
00210     for ( index = 0, item = it.toFirst(); item != 0; item = ++it )
00211     {
00212         QWidget *w = item->widget();
00213         if ( w )
00214         {
00215             w->setGeometry(itemGeometries[index]);
00216             index++;
00217         }
00218     }
00219 }
00220 
00229 uint QwtDynGridLayout::columnsForWidth(int width) const
00230 {
00231     if ( isEmpty() )
00232         return 0;
00233 
00234     for (uint numCols = (d_maxCols > 0) ? d_maxCols : itemCount();
00235         numCols > 1; numCols--)
00236     {
00237         int col;
00238 
00239         QwtArray<int> colWidth(numCols);
00240         for ( col = 0; col < (int)numCols; col++ )
00241             colWidth[col] = 0;
00242 
00243         int index = 0;
00244 
00245         QPtrListIterator<QLayoutItem> it(d_layoutData->itemList);
00246         for (const QLayoutItem *item = it.toFirst(); item != 0; 
00247             item = ++it, index++ )
00248         {
00249             const int w = item->sizeHint().width();
00250 
00251             col = index % numCols;
00252             colWidth[col] = QMAX(colWidth[col], w);
00253         }
00254 
00255         int rowWidth = 2 * margin() + (numCols - 1) * spacing();
00256         for ( col = 0; col < (int)numCols; col++ )
00257             rowWidth += colWidth[col];
00258 
00259         if ( rowWidth <= width )
00260             return numCols;
00261     }
00262 
00263     return 1; // At least 1 column
00264 }
00265 
00270 int QwtDynGridLayout::maxItemWidth() const
00271 {
00272     if ( isEmpty() )
00273         return 0;
00274 
00275     int w = 0;
00276     QPtrListIterator<QLayoutItem> it(d_layoutData->itemList);
00277     for (const QLayoutItem *item = it.toFirst(); item != 0; item = ++it )
00278     {
00279         const int itemW = item->sizeHint().width();
00280         if ( itemW > w )
00281             w = itemW;
00282     }
00283 
00284     return w;
00285 }
00286 
00295 QValueList<QRect> QwtDynGridLayout::layoutItems(const QRect &rect,
00296     uint numCols) const
00297 {
00298     QValueList<QRect> itemGeometries;
00299     if ( numCols == 0 || isEmpty() )
00300         return itemGeometries;
00301 
00302     uint numRows = itemCount() / numCols;
00303     if ( numRows % itemCount() )
00304         numRows++;
00305  
00306     QwtArray<int> rowHeight(numRows);
00307     QwtArray<int> colWidth(numCols);
00308  
00309     layoutGrid(numCols, rowHeight, colWidth);
00310 
00311     if ( expanding() != QSizePolicy::NoDirection )
00312         stretchGrid(rect, numCols, rowHeight, colWidth);
00313 
00314     QwtDynGridLayout *that = (QwtDynGridLayout *)this;
00315     const int maxCols = d_maxCols;
00316     that->d_maxCols = numCols;
00317     const QRect alignedRect = alignmentRect(rect);
00318     that->d_maxCols = maxCols;
00319 
00320 #if QT_VERSION < 300
00321     const int xOffset = ( expanding() & QSizePolicy::Horizontal ) 
00322         ? 0 : alignedRect.x();
00323     const int yOffset = ( expanding() & QSizePolicy::Vertical ) 
00324         ? 0 : alignedRect.y();
00325 #else
00326     const int xOffset = ( expanding() & QSizePolicy::Horizontally ) 
00327         ? 0 : alignedRect.x();
00328     const int yOffset = ( expanding() & QSizePolicy::Vertically ) 
00329         ? 0 : alignedRect.y();
00330 #endif
00331 
00332     QwtArray<int> colX(numCols);
00333     QwtArray<int> rowY(numRows);
00334 
00335     const int xySpace = spacing();
00336 
00337     rowY[0] = yOffset + margin();
00338     for ( int r = 1; r < (int)numRows; r++ )
00339         rowY[r] = rowY[r-1] + rowHeight[r-1] + xySpace;
00340 
00341     colX[0] = xOffset + margin();
00342     for ( int c = 1; c < (int)numCols; c++ )
00343         colX[c] = colX[c-1] + colWidth[c-1] + xySpace;
00344     
00345     int index;
00346     QLayoutItem *item;
00347 
00348     QPtrListIterator<QLayoutItem> it(d_layoutData->itemList);
00349     for ( item = it.toFirst(), index = 0; item != 0; item = ++it, index++ )
00350     {
00351         const int row = index / numCols;
00352         const int col = index % numCols;
00353 
00354         QRect itemGeometry(colX[col], rowY[row], 
00355             colWidth[col], rowHeight[row]);
00356         itemGeometries.append(itemGeometry);
00357     }
00358 
00359     return itemGeometries;
00360 }
00361 
00362 
00371 void QwtDynGridLayout::layoutGrid(uint numCols, 
00372     QwtArray<int>& rowHeight, QwtArray<int>& colWidth) const
00373 {
00374     if ( numCols <= 0 )
00375         return;
00376 
00377     int index = 0;
00378 
00379     QPtrListIterator<QLayoutItem> it(d_layoutData->itemList);
00380     for (const QLayoutItem *item = it.toFirst(); item != 0; 
00381         item = ++it, index++ )
00382     {
00383         const int row = index / numCols;
00384         const int col = index % numCols;
00385 
00386         const QSize size = item->sizeHint();
00387 
00388         rowHeight[row] = (col == 0) 
00389             ? size.height() : QMAX(rowHeight[row], size.height());
00390         colWidth[col] = (row == 0) 
00391             ? size.width() : QMAX(colWidth[col], size.width());
00392     }
00393 }
00394 
00403 void QwtDynGridLayout::setExpanding(QSizePolicy::ExpandData expanding)
00404 {
00405     d_expanding = expanding;
00406 }
00407 
00416 QSizePolicy::ExpandData QwtDynGridLayout::expanding() const
00417 {
00418     return d_expanding;
00419 }
00420 
00426 bool QwtDynGridLayout::hasHeightForWidth() const
00427 {
00428     return TRUE;
00429 }
00430 
00436 int QwtDynGridLayout::heightForWidth(int width) const
00437 {
00438     if ( isEmpty() )
00439         return 0;
00440 
00441     const uint numCols = columnsForWidth(width);
00442     uint numRows = itemCount() / numCols;
00443     if ( itemCount() % numCols )
00444         numRows++;
00445 
00446     QwtArray<int> rowHeight(numRows);
00447     QwtArray<int> colWidth(numCols);
00448 
00449     layoutGrid(numCols, rowHeight, colWidth);
00450 
00451     int h = 2 * margin() + (numRows - 1) * spacing();
00452     for ( int row = 0; row < (int)numRows; row++ )
00453         h += rowHeight[row];
00454 
00455     return h;
00456 }
00457 
00465 void QwtDynGridLayout::stretchGrid(const QRect &rect, 
00466     uint numCols, QwtArray<int>& rowHeight, QwtArray<int>& colWidth) const
00467 {
00468     if ( numCols == 0 || isEmpty() )
00469         return;
00470 
00471 #if QT_VERSION < 300
00472     if ( expanding() & QSizePolicy::Horizontal )
00473 #else
00474     if ( expanding() & QSizePolicy::Horizontally )
00475 #endif
00476     {
00477         int xDelta = rect.width() - 2 * margin() - (numCols - 1) * spacing();
00478         for ( int col = 0; col < (int)numCols; col++ )
00479             xDelta -= colWidth[col];
00480 
00481         if ( xDelta > 0 )
00482         {
00483             for ( int col = 0; col < (int)numCols; col++ )
00484             {
00485                 const int space = xDelta / (numCols - col);
00486                 colWidth[col] += space;
00487                 xDelta -= space;
00488             }
00489         }
00490     }
00491 
00492 #if QT_VERSION < 300
00493     if ( expanding() & QSizePolicy::Vertical )
00494 #else
00495     if ( expanding() & QSizePolicy::Vertically )
00496 #endif
00497     {
00498         uint numRows = itemCount() / numCols;
00499         if ( itemCount() % numCols )
00500             numRows++;
00501 
00502         int yDelta = rect.height() - 2 * margin() - (numRows - 1) * spacing();
00503         for ( int row = 0; row < (int)numRows; row++ )
00504             yDelta -= rowHeight[row];
00505 
00506         if ( yDelta > 0 )
00507         {
00508             for ( int row = 0; row < (int)numRows; row++ )
00509             {
00510                 const int space = yDelta / (numRows - row);
00511                 rowHeight[row] += space;
00512                 yDelta -= space;
00513             }
00514         }
00515     }
00516 }
00517 
00525 QSize QwtDynGridLayout::sizeHint() const
00526 {
00527     if ( isEmpty() )
00528         return QSize();
00529 
00530     const uint numCols = (d_maxCols > 0 ) ? d_maxCols : itemCount();
00531     uint numRows = itemCount() / numCols;
00532     if ( itemCount() % numCols )
00533         numRows++;
00534 
00535     QwtArray<int> rowHeight(numRows);
00536     QwtArray<int> colWidth(numCols);
00537 
00538     layoutGrid(numCols, rowHeight, colWidth);
00539 
00540     int h = 2 * margin() + (numRows - 1) * spacing();
00541     for ( int row = 0; row < (int)numRows; row++ )
00542         h += rowHeight[row];
00543 
00544     int w = 2 * margin() + (numCols - 1) * spacing(); 
00545     for ( int col = 0; col < (int)numCols; col++ )
00546         w += colWidth[col];
00547 
00548     return QSize(w, h);
00549 }
00550 
00556 uint QwtDynGridLayout::numRows() const 
00557 { 
00558     return d_numRows; 
00559 }
00560 
00566 uint QwtDynGridLayout::numCols() const 
00567 { 
00568     return d_numCols; 
00569 }
00570 
00571 // Local Variables:
00572 // mode: C++
00573 // c-file-style: "stroustrup"
00574 // indent-tabs-mode: nil
00575 // End:
00576 

Generated on Sun Sep 26 23:24:36 2004 for Qwt User's Guide by doxygen 1.3.6