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

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 
00012 class QwtDynGridLayoutIterator :public QGLayoutIterator
00013 {
00014 public:
00015     QwtDynGridLayoutIterator(QList<QLayoutItem> *);
00016 
00017     virtual QLayoutItem *current();
00018     virtual QLayoutItem *next();
00019     virtual QLayoutItem *takeCurrent();
00020 
00021 private:
00022     uint d_index;
00023     QList<QLayoutItem> *d_itemList;
00024 };
00025 
00026 QwtDynGridLayoutIterator::QwtDynGridLayoutIterator(QList<QLayoutItem> *l): 
00027     d_index(0), 
00028     d_itemList(l)  
00029 {
00030 }
00031 
00032 QLayoutItem *QwtDynGridLayoutIterator::current()
00033 { 
00034     QLayoutItem *item = (d_index < d_itemList->count()) 
00035         ? d_itemList->at(d_index) : 0;  
00036 
00037     return item;
00038 }
00039 
00040 QLayoutItem *QwtDynGridLayoutIterator::next()
00041 { 
00042     d_index++; 
00043     return current(); 
00044 }
00045 
00046 QLayoutItem *QwtDynGridLayoutIterator::takeCurrent()
00047 { 
00048     QLayoutItem *item = (d_index < d_itemList->count()) 
00049         ? d_itemList->take(d_index) : 0;  
00050 
00051     return item;
00052 }
00053 
00061 QwtDynGridLayout::QwtDynGridLayout(QWidget *parent, 
00062         int margin, int space, const char *name):
00063     QLayout(parent, margin, space, name)
00064 {
00065     init();
00066 }
00067 
00074 QwtDynGridLayout::QwtDynGridLayout(QLayout *parent, 
00075         int space, const char *name):
00076     QLayout(parent, space, name)
00077 {
00078     init();
00079 }
00080 
00086 QwtDynGridLayout::QwtDynGridLayout(int space, const char *name):
00087     QLayout(space, name)
00088 {
00089     init();
00090 }
00091 
00095 void QwtDynGridLayout::init()
00096 {
00097     d_maxCols = d_numRows = d_numCols = 0;
00098     d_expanding = QSizePolicy::NoDirection;
00099 
00100     setSupportsMargin(TRUE);
00101 }
00102 
00104 
00105 QwtDynGridLayout::~QwtDynGridLayout()
00106 {
00107     deleteAllItems();
00108 }
00109 
00116 void QwtDynGridLayout::setMaxCols(uint maxCols)
00117 {
00118     d_maxCols = maxCols;
00119 }
00120 
00127 uint QwtDynGridLayout::maxCols() const 
00128 { 
00129     return d_maxCols; 
00130 }
00131 
00133 
00134 void QwtDynGridLayout::addItem(QLayoutItem *item)
00135 {
00136     d_itemList.append(item);
00137 }
00138 
00140 
00141 bool QwtDynGridLayout::isEmpty() const
00142 {
00143     return d_itemList.isEmpty();
00144 }
00145 
00147 
00148 QLayoutIterator QwtDynGridLayout::iterator()
00149 {       
00150     return QLayoutIterator( new QwtDynGridLayoutIterator(&d_itemList) );
00151 }
00152 
00158 void QwtDynGridLayout::setGeometry(const QRect &rect)
00159 {
00160     QLayout::setGeometry(rect);
00161 
00162     if ( d_itemList.isEmpty() )
00163         return;
00164 
00165     d_numCols = columnsForWidth(rect.width());
00166     d_numRows = d_itemList.count() / d_numCols;
00167     if ( d_itemList.count() % d_numCols )
00168         d_numRows++;
00169 
00170     QValueList<QRect> itemGeometries = layoutItems(rect, d_numCols);
00171 
00172     int index;
00173 
00174     QLayoutItem *item;
00175     QListIterator<QLayoutItem> it(d_itemList);
00176     for ( index = 0, item = it.toFirst(); item != 0; item = ++it )
00177     {
00178         QWidget *w = item->widget();
00179         if ( w )
00180         {
00181             w->setGeometry(itemGeometries[index]);
00182             index++;
00183         }
00184     }
00185 }
00186 
00195 uint QwtDynGridLayout::columnsForWidth(int width) const
00196 {
00197     if ( d_itemList.isEmpty() )
00198         return 0;
00199 
00200     for (uint numCols = (d_maxCols > 0) ? d_maxCols : d_itemList.count();
00201         numCols > 1; numCols--)
00202     {
00203         int col;
00204 
00205         QwtArray<int> colWidth(numCols);
00206         for ( col = 0; col < (int)numCols; col++ )
00207             colWidth[col] = 0;
00208 
00209         int index = 0;
00210 
00211         QListIterator<QLayoutItem> it(d_itemList);
00212         for (const QLayoutItem *item = it.toFirst(); item != 0; 
00213             item = ++it, index++ )
00214         {
00215             const int w = item->sizeHint().width();
00216 
00217             col = index % numCols;
00218             colWidth[col] = QMAX(colWidth[col], w);
00219         }
00220 
00221         int rowWidth = 2 * margin() + (numCols - 1) * spacing();
00222         for ( col = 0; col < (int)numCols; col++ )
00223             rowWidth += colWidth[col];
00224 
00225         if ( rowWidth <= width )
00226             return numCols;
00227     }
00228 
00229     return 1; // At least 1 column
00230 }
00231 
00236 int QwtDynGridLayout::maxItemWidth() const
00237 {
00238     if ( d_itemList.isEmpty() )
00239         return 0;
00240 
00241     int w = 0;
00242     QListIterator<QLayoutItem> it(d_itemList);
00243     for (const QLayoutItem *item = it.toFirst(); item != 0; item = ++it )
00244     {
00245         const int itemW = item->sizeHint().width();
00246         if ( itemW > w )
00247             w = itemW;
00248     }
00249 
00250     return w;
00251 }
00252 
00261 QValueList<QRect> QwtDynGridLayout::layoutItems(const QRect &rect,
00262     uint numCols) const
00263 {
00264     QValueList<QRect> itemGeometries;
00265     if ( numCols == 0 || d_itemList.isEmpty() )
00266         return itemGeometries;
00267 
00268     uint numRows = d_itemList.count() / numCols;
00269     if ( numRows % d_itemList.count() )
00270         numRows++;
00271  
00272     QwtArray<int> rowHeight(numRows);
00273     QwtArray<int> colWidth(numCols);
00274  
00275     layoutGrid(numCols, rowHeight, colWidth);
00276 
00277     if ( expanding() != QSizePolicy::NoDirection )
00278         stretchGrid(rect, numCols, rowHeight, colWidth);
00279 
00280     QwtDynGridLayout *that = (QwtDynGridLayout *)this;
00281     const int maxCols = d_maxCols;
00282     that->d_maxCols = numCols;
00283     const QRect alignedRect = alignmentRect(rect);
00284     that->d_maxCols = maxCols;
00285 
00286     const int xOffset = ( expanding() & QSizePolicy::Horizontal ) 
00287         ? 0 : alignedRect.x();
00288     const int yOffset = ( expanding() & QSizePolicy::Vertical ) 
00289         ? 0 : alignedRect.y();
00290 
00291     QwtArray<int> colX(numCols);
00292     QwtArray<int> rowY(numRows);
00293 
00294     const int xySpace = spacing();
00295 
00296     rowY[0] = yOffset + margin();
00297     for ( int r = 1; r < (int)numRows; r++ )
00298         rowY[r] = rowY[r-1] + rowHeight[r-1] + xySpace;
00299 
00300     colX[0] = xOffset + margin();
00301     for ( int c = 1; c < (int)numCols; c++ )
00302         colX[c] = colX[c-1] + colWidth[c-1] + xySpace;
00303     
00304     int index;
00305     QLayoutItem *item;
00306 
00307     QListIterator<QLayoutItem> it(d_itemList);
00308     for ( item = it.toFirst(), index = 0; item != 0; item = ++it, index++ )
00309     {
00310         const int row = index / numCols;
00311         const int col = index % numCols;
00312 
00313         QRect itemGeometry(colX[col], rowY[row], 
00314             colWidth[col], rowHeight[row]);
00315         itemGeometries.append(itemGeometry);
00316     }
00317 
00318     return itemGeometries;
00319 }
00320 
00321 
00330 void QwtDynGridLayout::layoutGrid(uint numCols, 
00331     QwtArray<int>& rowHeight, QwtArray<int>& colWidth) const
00332 {
00333     if ( numCols <= 0 )
00334         return;
00335 
00336     int index = 0;
00337 
00338     QListIterator<QLayoutItem> it(d_itemList);
00339     for (const QLayoutItem *item = it.toFirst(); item != 0; 
00340         item = ++it, index++ )
00341     {
00342         const int row = index / numCols;
00343         const int col = index % numCols;
00344 
00345         const QSize size = item->sizeHint();
00346 
00347         rowHeight[row] = (col == 0) 
00348             ? size.height() : QMAX(rowHeight[row], size.height());
00349         colWidth[col] = (row == 0) 
00350             ? size.width() : QMAX(colWidth[col], size.width());
00351     }
00352 }
00353 
00362 void QwtDynGridLayout::setExpanding(QSizePolicy::ExpandData expanding)
00363 {
00364     d_expanding = expanding;
00365 }
00366 
00375 QSizePolicy::ExpandData QwtDynGridLayout::expanding() const
00376 {
00377     return d_expanding;
00378 }
00379 
00385 bool QwtDynGridLayout::hasHeightForWidth() const
00386 {
00387     return TRUE;
00388 }
00389 
00395 int QwtDynGridLayout::heightForWidth(int width) const
00396 {
00397     if ( d_itemList.isEmpty() )
00398         return 0;
00399 
00400     const uint numCols = columnsForWidth(width);
00401     uint numRows = d_itemList.count() / numCols;
00402     if ( d_itemList.count() % numCols )
00403         numRows++;
00404 
00405     QwtArray<int> rowHeight(numRows);
00406     QwtArray<int> colWidth(numCols);
00407 
00408     layoutGrid(numCols, rowHeight, colWidth);
00409 
00410     int h = 2 * margin() + (numRows - 1) * spacing();
00411     for ( int row = 0; row < (int)numRows; row++ )
00412         h += rowHeight[row];
00413 
00414     return h;
00415 }
00416 
00424 void QwtDynGridLayout::stretchGrid(const QRect &rect, 
00425     uint numCols, QwtArray<int>& rowHeight, QwtArray<int>& colWidth) const
00426 {
00427     if ( numCols == 0 || d_itemList.isEmpty() )
00428         return;
00429 
00430     if ( expanding() & QSizePolicy::Horizontal )
00431     {
00432         int xDelta = rect.width() - 2 * margin() - (numCols - 1) * spacing();
00433         for ( int col = 0; col < (int)numCols; col++ )
00434             xDelta -= colWidth[col];
00435 
00436         if ( xDelta > 0 )
00437         {
00438             for ( int col = 0; col < (int)numCols; col++ )
00439             {
00440                 const int space = xDelta / (numCols - col);
00441                 colWidth[col] += space;
00442                 xDelta -= space;
00443             }
00444         }
00445     }
00446 
00447     if ( expanding() & QSizePolicy::Vertical )
00448     {
00449         uint numRows = d_itemList.count() / numCols;
00450         if ( d_itemList.count() % numCols )
00451             numRows++;
00452 
00453         int yDelta = rect.height() - 2 * margin() - (numRows - 1) * spacing();
00454         for ( int row = 0; row < (int)numRows; row++ )
00455             yDelta -= rowHeight[row];
00456 
00457         if ( yDelta > 0 )
00458         {
00459             for ( int row = 0; row < (int)numRows; row++ )
00460             {
00461                 const int space = yDelta / (numRows - row);
00462                 rowHeight[row] += space;
00463                 yDelta -= space;
00464             }
00465         }
00466     }
00467 }
00468 
00476 QSize QwtDynGridLayout::sizeHint() const
00477 {
00478     if ( d_itemList.isEmpty() )
00479         return QSize();
00480 
00481     const uint numCols = (d_maxCols > 0 ) ? d_maxCols : d_itemList.count();
00482     uint numRows = d_itemList.count() / numCols;
00483     if ( d_itemList.count() % numCols )
00484         numRows++;
00485 
00486     QwtArray<int> rowHeight(numRows);
00487     QwtArray<int> colWidth(numCols);
00488 
00489     layoutGrid(numCols, rowHeight, colWidth);
00490 
00491     int h = 2 * margin() + (numRows - 1) * spacing();
00492     for ( int row = 0; row < (int)numRows; row++ )
00493         h += rowHeight[row];
00494 
00495     int w = 2 * margin() + (numCols - 1) * spacing(); 
00496     for ( int col = 0; col < (int)numCols; col++ )
00497         w += colWidth[col];
00498 
00499     return QSize(w, h);
00500 }
00501 
00507 uint QwtDynGridLayout::numRows() const 
00508 { 
00509     return d_numRows; 
00510 }
00511 
00517 uint QwtDynGridLayout::numCols() const 
00518 { 
00519     return d_numCols; 
00520 }
00521 

Generated on Fri Nov 7 14:11:45 2003 for Qwt Developer's Guide by doxygen 1.3.2