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 class QwtDynGridLayoutPrivate 00023 { 00024 public: 00025 QwtDynGridLayoutPrivate(): 00026 isDirty(TRUE) 00027 { 00028 } 00029 00030 QPtrList<QLayoutItem> itemList; 00031 00032 bool isDirty; 00033 QwtArray<QSize> itemSizeHints; 00034 }; 00035 00036 class QwtDynGridLayoutIterator: public QGLayoutIterator 00037 { 00038 public: 00039 QwtDynGridLayoutIterator(QwtDynGridLayoutPrivate *); 00040 00041 virtual QLayoutItem *current(); 00042 virtual QLayoutItem *next(); 00043 virtual QLayoutItem *takeCurrent(); 00044 00045 private: 00046 QwtDynGridLayoutPrivate *d_data; 00047 }; 00048 00049 QwtDynGridLayoutIterator::QwtDynGridLayoutIterator( 00050 QwtDynGridLayoutPrivate *data): 00051 d_data(data) 00052 { 00053 (void)d_data->itemList.first(); 00054 } 00055 00056 QLayoutItem *QwtDynGridLayoutIterator::current() 00057 { 00058 return d_data->itemList.current(); 00059 } 00060 00061 QLayoutItem *QwtDynGridLayoutIterator::next() 00062 { 00063 return d_data->itemList.next(); 00064 } 00065 00066 QLayoutItem *QwtDynGridLayoutIterator::takeCurrent() 00067 { 00068 d_data->isDirty = TRUE; 00069 return d_data->itemList.take(); 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 00130 void QwtDynGridLayout::invalidate() 00131 { 00132 d_layoutData->isDirty = TRUE; 00133 QLayout::invalidate(); 00134 } 00135 00136 void QwtDynGridLayout::updateLayoutCache() 00137 { 00138 d_layoutData->itemSizeHints.resize(itemCount()); 00139 00140 int index = 0; 00141 00142 QPtrListIterator<QLayoutItem> it(d_layoutData->itemList); 00143 for (const QLayoutItem *item = it.toFirst(); item != 0; 00144 item = ++it, index++ ) 00145 { 00146 d_layoutData->itemSizeHints[int(index)] = item->sizeHint(); 00147 } 00148 00149 d_layoutData->isDirty = FALSE; 00150 } 00151 00158 void QwtDynGridLayout::setMaxCols(uint maxCols) 00159 { 00160 d_maxCols = maxCols; 00161 } 00162 00169 uint QwtDynGridLayout::maxCols() const 00170 { 00171 return d_maxCols; 00172 } 00173 00175 00176 void QwtDynGridLayout::addItem(QLayoutItem *item) 00177 { 00178 d_layoutData->itemList.append(item); 00179 invalidate(); 00180 } 00181 00186 bool QwtDynGridLayout::isEmpty() const 00187 { 00188 return d_layoutData->itemList.isEmpty(); 00189 } 00190 00195 uint QwtDynGridLayout::itemCount() const 00196 { 00197 return d_layoutData->itemList.count(); 00198 } 00199 00204 QLayoutIterator QwtDynGridLayout::iterator() 00205 { 00206 return QLayoutIterator( 00207 new QwtDynGridLayoutIterator(d_layoutData) ); 00208 } 00209 00215 void QwtDynGridLayout::setGeometry(const QRect &rect) 00216 { 00217 QLayout::setGeometry(rect); 00218 00219 if ( isEmpty() ) 00220 return; 00221 00222 d_numCols = columnsForWidth(rect.width()); 00223 d_numRows = itemCount() / d_numCols; 00224 if ( itemCount() % d_numCols ) 00225 d_numRows++; 00226 00227 QValueList<QRect> itemGeometries = layoutItems(rect, d_numCols); 00228 00229 int index; 00230 00231 QLayoutItem *item; 00232 QPtrListIterator<QLayoutItem> it(d_layoutData->itemList); 00233 for ( index = 0, item = it.toFirst(); item != 0; item = ++it ) 00234 { 00235 QWidget *w = item->widget(); 00236 if ( w ) 00237 { 00238 w->setGeometry(itemGeometries[index]); 00239 index++; 00240 } 00241 } 00242 } 00243 00252 uint QwtDynGridLayout::columnsForWidth(int width) const 00253 { 00254 if ( isEmpty() ) 00255 return 0; 00256 00257 const int maxCols = (d_maxCols > 0) ? d_maxCols : itemCount(); 00258 if ( maxRowWidth(maxCols) <= width ) 00259 return maxCols; 00260 00261 for (int numCols = 2; numCols <= maxCols; numCols++ ) 00262 { 00263 const int rowWidth = maxRowWidth(numCols); 00264 if ( rowWidth > width ) 00265 return numCols - 1; 00266 } 00267 00268 return 1; // At least 1 column 00269 } 00270 00278 int QwtDynGridLayout::maxRowWidth(int numCols) const 00279 { 00280 int col; 00281 00282 QwtArray<int> colWidth(numCols); 00283 for ( col = 0; col < (int)numCols; col++ ) 00284 colWidth[col] = 0; 00285 00286 if ( d_layoutData->isDirty ) 00287 ((QwtDynGridLayout*)this)->updateLayoutCache(); 00288 00289 for ( uint index = 0; 00290 index < d_layoutData->itemSizeHints.count(); index++ ) 00291 { 00292 col = index % numCols; 00293 colWidth[col] = QMAX(colWidth[col], 00294 d_layoutData->itemSizeHints[int(index)].width()); 00295 } 00296 00297 int rowWidth = 2 * margin() + (numCols - 1) * spacing(); 00298 for ( col = 0; col < (int)numCols; col++ ) 00299 rowWidth += colWidth[col]; 00300 00301 return rowWidth; 00302 } 00303 00308 int QwtDynGridLayout::maxItemWidth() const 00309 { 00310 if ( isEmpty() ) 00311 return 0; 00312 00313 if ( d_layoutData->isDirty ) 00314 ((QwtDynGridLayout*)this)->updateLayoutCache(); 00315 00316 int w = 0; 00317 for ( uint i = 0; i < d_layoutData->itemSizeHints.count(); i++ ) 00318 { 00319 const int itemW = d_layoutData->itemSizeHints[int(i)].width(); 00320 if ( itemW > w ) 00321 w = itemW; 00322 } 00323 00324 return w; 00325 } 00326 00335 QValueList<QRect> QwtDynGridLayout::layoutItems(const QRect &rect, 00336 uint numCols) const 00337 { 00338 QValueList<QRect> itemGeometries; 00339 if ( numCols == 0 || isEmpty() ) 00340 return itemGeometries; 00341 00342 uint numRows = itemCount() / numCols; 00343 if ( numRows % itemCount() ) 00344 numRows++; 00345 00346 QwtArray<int> rowHeight(numRows); 00347 QwtArray<int> colWidth(numCols); 00348 00349 layoutGrid(numCols, rowHeight, colWidth); 00350 00351 if ( expanding() != QSizePolicy::NoDirection ) 00352 stretchGrid(rect, numCols, rowHeight, colWidth); 00353 00354 QwtDynGridLayout *that = (QwtDynGridLayout *)this; 00355 const int maxCols = d_maxCols; 00356 that->d_maxCols = numCols; 00357 const QRect alignedRect = alignmentRect(rect); 00358 that->d_maxCols = maxCols; 00359 00360 #if QT_VERSION < 300 00361 const int xOffset = ( expanding() & QSizePolicy::Horizontal ) 00362 ? 0 : alignedRect.x(); 00363 const int yOffset = ( expanding() & QSizePolicy::Vertical ) 00364 ? 0 : alignedRect.y(); 00365 #else 00366 const int xOffset = ( expanding() & QSizePolicy::Horizontally ) 00367 ? 0 : alignedRect.x(); 00368 const int yOffset = ( expanding() & QSizePolicy::Vertically ) 00369 ? 0 : alignedRect.y(); 00370 #endif 00371 00372 QwtArray<int> colX(numCols); 00373 QwtArray<int> rowY(numRows); 00374 00375 const int xySpace = spacing(); 00376 00377 rowY[0] = yOffset + margin(); 00378 for ( int r = 1; r < (int)numRows; r++ ) 00379 rowY[r] = rowY[r-1] + rowHeight[r-1] + xySpace; 00380 00381 colX[0] = xOffset + margin(); 00382 for ( int c = 1; c < (int)numCols; c++ ) 00383 colX[c] = colX[c-1] + colWidth[c-1] + xySpace; 00384 00385 int index; 00386 QLayoutItem *item; 00387 00388 QPtrListIterator<QLayoutItem> it(d_layoutData->itemList); 00389 for ( item = it.toFirst(), index = 0; item != 0; item = ++it, index++ ) 00390 { 00391 const int row = index / numCols; 00392 const int col = index % numCols; 00393 00394 QRect itemGeometry(colX[col], rowY[row], 00395 colWidth[col], rowHeight[row]); 00396 itemGeometries.append(itemGeometry); 00397 } 00398 00399 return itemGeometries; 00400 } 00401 00402 00411 void QwtDynGridLayout::layoutGrid(uint numCols, 00412 QwtArray<int>& rowHeight, QwtArray<int>& colWidth) const 00413 { 00414 if ( numCols <= 0 ) 00415 return; 00416 00417 if ( d_layoutData->isDirty ) 00418 ((QwtDynGridLayout*)this)->updateLayoutCache(); 00419 00420 for ( uint index = 0; 00421 index < d_layoutData->itemSizeHints.count(); index++ ) 00422 { 00423 const int row = index / numCols; 00424 const int col = index % numCols; 00425 00426 const QSize &size = d_layoutData->itemSizeHints[int(index)]; 00427 00428 rowHeight[row] = (col == 0) 00429 ? size.height() : QMAX(rowHeight[row], size.height()); 00430 colWidth[col] = (row == 0) 00431 ? size.width() : QMAX(colWidth[col], size.width()); 00432 } 00433 } 00434 00443 void QwtDynGridLayout::setExpanding(QSizePolicy::ExpandData expanding) 00444 { 00445 d_expanding = expanding; 00446 } 00447 00456 QSizePolicy::ExpandData QwtDynGridLayout::expanding() const 00457 { 00458 return d_expanding; 00459 } 00460 00466 bool QwtDynGridLayout::hasHeightForWidth() const 00467 { 00468 return TRUE; 00469 } 00470 00476 int QwtDynGridLayout::heightForWidth(int width) const 00477 { 00478 if ( isEmpty() ) 00479 return 0; 00480 00481 const uint numCols = columnsForWidth(width); 00482 uint numRows = itemCount() / numCols; 00483 if ( itemCount() % 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 return h; 00496 } 00497 00505 void QwtDynGridLayout::stretchGrid(const QRect &rect, 00506 uint numCols, QwtArray<int>& rowHeight, QwtArray<int>& colWidth) const 00507 { 00508 if ( numCols == 0 || isEmpty() ) 00509 return; 00510 00511 #if QT_VERSION < 300 00512 if ( expanding() & QSizePolicy::Horizontal ) 00513 #else 00514 if ( expanding() & QSizePolicy::Horizontally ) 00515 #endif 00516 { 00517 int xDelta = rect.width() - 2 * margin() - (numCols - 1) * spacing(); 00518 for ( int col = 0; col < (int)numCols; col++ ) 00519 xDelta -= colWidth[col]; 00520 00521 if ( xDelta > 0 ) 00522 { 00523 for ( int col = 0; col < (int)numCols; col++ ) 00524 { 00525 const int space = xDelta / (numCols - col); 00526 colWidth[col] += space; 00527 xDelta -= space; 00528 } 00529 } 00530 } 00531 00532 #if QT_VERSION < 300 00533 if ( expanding() & QSizePolicy::Vertical ) 00534 #else 00535 if ( expanding() & QSizePolicy::Vertically ) 00536 #endif 00537 { 00538 uint numRows = itemCount() / numCols; 00539 if ( itemCount() % numCols ) 00540 numRows++; 00541 00542 int yDelta = rect.height() - 2 * margin() - (numRows - 1) * spacing(); 00543 for ( int row = 0; row < (int)numRows; row++ ) 00544 yDelta -= rowHeight[row]; 00545 00546 if ( yDelta > 0 ) 00547 { 00548 for ( int row = 0; row < (int)numRows; row++ ) 00549 { 00550 const int space = yDelta / (numRows - row); 00551 rowHeight[row] += space; 00552 yDelta -= space; 00553 } 00554 } 00555 } 00556 } 00557 00565 QSize QwtDynGridLayout::sizeHint() const 00566 { 00567 if ( isEmpty() ) 00568 return QSize(); 00569 00570 const uint numCols = (d_maxCols > 0 ) ? d_maxCols : itemCount(); 00571 uint numRows = itemCount() / numCols; 00572 if ( itemCount() % numCols ) 00573 numRows++; 00574 00575 QwtArray<int> rowHeight(numRows); 00576 QwtArray<int> colWidth(numCols); 00577 00578 layoutGrid(numCols, rowHeight, colWidth); 00579 00580 int h = 2 * margin() + (numRows - 1) * spacing(); 00581 for ( int row = 0; row < (int)numRows; row++ ) 00582 h += rowHeight[row]; 00583 00584 int w = 2 * margin() + (numCols - 1) * spacing(); 00585 for ( int col = 0; col < (int)numCols; col++ ) 00586 w += colWidth[col]; 00587 00588 return QSize(w, h); 00589 } 00590 00596 uint QwtDynGridLayout::numRows() const 00597 { 00598 return d_numRows; 00599 } 00600 00606 uint QwtDynGridLayout::numCols() const 00607 { 00608 return d_numCols; 00609 } 00610 00611 // Local Variables: 00612 // mode: C++ 00613 // c-file-style: "stroustrup" 00614 // indent-tabs-mode: nil 00615 // End: 00616

Generated on Tue Nov 16 21:12:20 2004 for Qwt User's Guide by doxygen 1.3.8