00001
00002
00003
00004
00005
00006
00007
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;
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