00001
00002
00003
00004
00005
00006
00007
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;
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
00572
00573
00574
00575
00576