00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "kexiflowlayout.h"
00021
00022 #include <kdebug.h>
00023
00025
00026 class KexiFlowLayoutIterator : public QGLayoutIterator
00027 {
00028 public:
00029 KexiFlowLayoutIterator( QPtrList<QLayoutItem> *list )
00030 : m_idx(0), m_list( list )
00031 {}
00032 uint count() const;
00033 QLayoutItem *current();
00034 QLayoutItem *next();
00035 QLayoutItem *takeCurrent();
00036
00037 private:
00038 int m_idx;
00039 QPtrList<QLayoutItem> *m_list;
00040 };
00041
00042 uint
00043 KexiFlowLayoutIterator::count() const
00044 {
00045 return m_list->count();
00046 }
00047
00048 QLayoutItem *
00049 KexiFlowLayoutIterator::current()
00050 {
00051 return (m_idx < (int)count()) ? m_list->at(m_idx) : 0;
00052 }
00053
00054 QLayoutItem *
00055 KexiFlowLayoutIterator::next()
00056 {
00057 m_idx++;
00058 return current();
00059 }
00060
00061 QLayoutItem *
00062 KexiFlowLayoutIterator::takeCurrent()
00063 {
00064 return (m_idx < (int)count()) ? m_list->take(m_idx) : 0;
00065 }
00066
00068
00069 KexiFlowLayout::KexiFlowLayout(QWidget *parent, int border, int space, const char *name)
00070 : QLayout(parent, border, space, name)
00071 {
00072 m_orientation = Horizontal;
00073 m_justify = false;
00074 m_cached_width = 0;
00075 }
00076
00077 KexiFlowLayout::KexiFlowLayout(QLayout* parent, int space, const char *name)
00078 : QLayout( parent, space, name )
00079 {
00080 m_orientation = Horizontal;
00081 m_justify = false;
00082 m_cached_width = 0;
00083 }
00084
00085 KexiFlowLayout::KexiFlowLayout(int space, const char *name)
00086 : QLayout(space, name)
00087 {
00088 m_orientation = Horizontal;
00089 m_justify = false;
00090 m_cached_width = 0;
00091 }
00092
00093 KexiFlowLayout::~KexiFlowLayout()
00094 {
00095 deleteAllItems();
00096 }
00097
00098 void
00099 KexiFlowLayout::addItem(QLayoutItem *item)
00100 {
00101 m_list.append(item);
00102 }
00103
00104 void
00105 KexiFlowLayout::addSpacing(int size)
00106 {
00107 if (m_orientation == Horizontal)
00108 addItem( new QSpacerItem( size, 0, QSizePolicy::Fixed, QSizePolicy::Minimum ) );
00109 else
00110 addItem( new QSpacerItem( 0, size, QSizePolicy::Minimum, QSizePolicy::Fixed ) );
00111 }
00112
00113 QLayoutIterator
00114 KexiFlowLayout::iterator()
00115 {
00116 return QLayoutIterator( new KexiFlowLayoutIterator(&m_list) );
00117 }
00118
00119 QPtrList<QWidget>*
00120 KexiFlowLayout::widgetList() const
00121 {
00122 QPtrList<QWidget> *list = new QPtrList<QWidget>();
00123 for (QPtrListIterator<QLayoutItem> it(m_list); it.current(); ++it) {
00124 if(it.current()->widget())
00125 list->append(it.current()->widget());
00126 }
00127 return list;
00128 }
00129
00130 void
00131 KexiFlowLayout::invalidate()
00132 {
00133 QLayout::invalidate();
00134 m_cached_sizeHint = QSize();
00135 m_cached_minSize = QSize();
00136 m_cached_width = 0;
00137 }
00138
00139 bool
00140 KexiFlowLayout::isEmpty()
00141 {
00142 return m_list.isEmpty();
00143 }
00144
00145 bool
00146 KexiFlowLayout::hasHeightForWidth() const
00147 {
00148 return (m_orientation == Horizontal);
00149 }
00150
00151 int
00152 KexiFlowLayout::heightForWidth(int w) const
00153 {
00154 if(m_cached_width != w) {
00155
00156 KexiFlowLayout *mthis = (KexiFlowLayout*)this;
00157 int h = mthis->simulateLayout( QRect(0,0,w,0) );
00158 mthis->m_cached_hfw = h;
00159 mthis->m_cached_width = w;
00160 return h;
00161 }
00162 return m_cached_hfw;
00163 }
00164
00165 QSize
00166 KexiFlowLayout::sizeHint() const
00167 {
00168 if(m_cached_sizeHint.isEmpty()) {
00169 KexiFlowLayout *mthis = (KexiFlowLayout*)this;
00170 QRect r = QRect(0, 0, 2000, 2000);
00171 mthis->simulateLayout(r);
00172 }
00173 return m_cached_sizeHint;
00174 }
00175
00176 QSize
00177 KexiFlowLayout::minimumSize() const
00178 {
00179
00180
00181
00182 #if 0
00183 if(m_cached_minSize.isEmpty()) {
00184 KexiFlowLayout *mthis = (KexiFlowLayout*)this;
00185 QRect r = QRect(0, 0, 2000, 2000);
00186 mthis->simulateLayout(r);
00187 }
00188 #endif
00189 return m_cached_minSize;
00190 }
00191
00192 QSizePolicy::ExpandData
00193 KexiFlowLayout::expanding() const
00194 {
00195 if(m_orientation == Vertical)
00196 return QSizePolicy::Vertically;
00197 else
00198 return QSizePolicy::Horizontally;
00199 }
00200
00201 void
00202 KexiFlowLayout::setGeometry(const QRect &r)
00203 {
00204 QLayout::setGeometry(r);
00205 if(m_orientation == Horizontal)
00206 doHorizontalLayout(r);
00207 else
00208 doVerticalLayout(r);
00209 }
00210
00211 int
00212 KexiFlowLayout::simulateLayout(const QRect &r)
00213 {
00214 if(m_orientation == Horizontal)
00215 return doHorizontalLayout(r, true);
00216 else
00217 return doVerticalLayout(r, true);
00218 }
00219
00220 int
00221 KexiFlowLayout::doHorizontalLayout(const QRect &r, bool testOnly)
00222 {
00223 int x = r.x();
00224 int y = r.y();
00225 int h = 0;
00226 int availableSpace = r.width() + spacing();
00227 int expandingWidgets=0;
00228 QPtrListIterator<QLayoutItem> it(m_list);
00229 QPtrList<QLayoutItem> currentLine;
00230 QLayoutItem *o;
00231 QSize minSize, sizeHint(20, 20);
00232 int minSizeHeight = 0 - spacing();
00233
00234 while ( (o = it.current()) != 0 ) {
00235 if(o->isEmpty()) {
00236 ++it;
00237 continue;
00238 }
00239
00240
00241 QSize oSizeHint = o->sizeHint();
00242 if ((x + oSizeHint.width()) > r.right() && h > 0) {
00243
00244 QPtrListIterator<QLayoutItem> it2(currentLine);
00245 QLayoutItem *item;
00246 int wx = r.x();
00247 int sizeHintWidth = 0 -spacing(), minSizeWidth=0 - spacing(), lineMinHeight=0;
00248 while( (item = it2.current()) != 0 ) {
00249 QSize itemSizeHint = item->sizeHint();
00250 QSize itemMinSize = item->minimumSize();
00251 QSize s;
00252 if(m_justify) {
00253 if(expandingWidgets != 0) {
00254 if(item->expanding() == QSizePolicy::Horizontally || item->expanding() == QSizePolicy::BothDirections)
00255 s = QSize( QMIN(itemSizeHint.width() + availableSpace / expandingWidgets
00256 , r.width()), itemSizeHint.height() );
00257 else
00258 s = QSize( QMIN(itemSizeHint.width(), r.width()), itemSizeHint.height() );
00259 }
00260 else
00261 s = QSize( QMIN(itemSizeHint.width() + availableSpace / (int)currentLine.count()
00262 , r.width()), itemSizeHint.height() );
00263 }
00264 else
00265 s = QSize ( QMIN(itemSizeHint.width(), r.width()), itemSizeHint.height() );
00266 if(!testOnly)
00267 item->setGeometry( QRect(QPoint(wx, y), s) );
00268 wx = wx + s.width() + spacing();
00269 minSizeWidth = minSizeWidth + spacing() + itemMinSize.width();
00270 sizeHintWidth = sizeHintWidth + spacing() + itemSizeHint.width();
00271 lineMinHeight = QMAX( lineMinHeight, itemMinSize.height() );
00272 ++it2;
00273 }
00274 sizeHint = sizeHint.expandedTo( QSize(sizeHintWidth, 0) );
00275 minSize = minSize.expandedTo( QSize(minSizeWidth, 0) );
00276 minSizeHeight = minSizeHeight + spacing() + lineMinHeight;
00277
00278 y = y + spacing() + h;
00279 h = 0;
00280 x = r.x();
00281 currentLine.clear();
00282 expandingWidgets = 0;
00283 availableSpace = r.width() + spacing();
00284 }
00285
00286 x = x + spacing() + oSizeHint.width();
00287 h = QMAX( h, oSizeHint.height() );
00288 currentLine.append(o);
00289 if(o->expanding() == QSizePolicy::Horizontally || o->expanding() == QSizePolicy::BothDirections)
00290 ++expandingWidgets;
00291 availableSpace = QMAX(0, availableSpace - spacing() - oSizeHint.width());
00292 ++it;
00293 }
00294
00295
00296 QPtrListIterator<QLayoutItem> it2(currentLine);
00297 QLayoutItem *item;
00298 int wx = r.x();
00299 int sizeHintWidth = 0 -spacing(), minSizeWidth=0 - spacing(), lineMinHeight=0;
00300 while( (item = it2.current()) != 0 ) {
00301 QSize itemSizeHint = item->sizeHint();
00302 QSize itemMinSize = item->minimumSize();
00303 QSize s;
00304 if(m_justify) {
00305 if(expandingWidgets != 0) {
00306 if(item->expanding() == QSizePolicy::Horizontally || item->expanding() == QSizePolicy::BothDirections)
00307 s = QSize( QMIN(itemSizeHint.width() + availableSpace / expandingWidgets
00308 , r.width()), itemSizeHint.height() );
00309 else
00310 s = QSize( QMIN(itemSizeHint.width(), r.width()), itemSizeHint.height() );
00311 }
00312 else
00313 s = QSize( QMIN(itemSizeHint.width() + availableSpace / (int)currentLine.count()
00314 , r.width()), itemSizeHint.height() );
00315 }
00316 else
00317 s = QSize ( QMIN(itemSizeHint.width(), r.width()), itemSizeHint.height() );
00318 if(!testOnly)
00319 item->setGeometry( QRect(QPoint(wx, y), s) );
00320 wx = wx + s.width() + spacing();
00321 minSizeWidth = minSizeWidth + spacing() + itemMinSize.width();
00322 sizeHintWidth = sizeHintWidth + spacing() + itemSizeHint.width();
00323 lineMinHeight = QMAX( lineMinHeight, itemMinSize.height() );
00324 ++it2;
00325 }
00326 sizeHint = sizeHint.expandedTo( QSize(sizeHintWidth, y + spacing() + h) );
00327 minSizeHeight = minSizeHeight + spacing() + lineMinHeight;
00328 minSize = minSize.expandedTo( QSize(minSizeWidth, minSizeHeight) );
00329
00330
00331 m_cached_sizeHint = sizeHint + QSize(2* margin(), 2*margin());
00332 m_cached_minSize = minSize + QSize(2* margin() , 2*margin());
00333
00334 return y + h - r.y();
00335 }
00336
00337 int
00338 KexiFlowLayout::doVerticalLayout(const QRect &r, bool testOnly)
00339 {
00340 int x = r.x();
00341 int y = r.y();
00342 int w = 0;
00343 int availableSpace = r.height() + spacing();
00344 int expandingWidgets=0;
00345 QPtrListIterator<QLayoutItem> it(m_list);
00346 QPtrList<QLayoutItem> currentLine;
00347 QLayoutItem *o;
00348 QSize minSize, sizeHint(20, 20);
00349 int minSizeWidth = 0 - spacing();
00350
00351 while ( (o = it.current()) != 0 ) {
00352 if(o->isEmpty()) {
00353 ++it;
00354 continue;
00355 }
00356
00357 QSize oSizeHint = o->sizeHint();
00358 if (y + oSizeHint.height() > r.bottom() && w > 0) {
00359
00360 QPtrListIterator<QLayoutItem> it2(currentLine);
00361 QLayoutItem *item;
00362 int wy = r.y();
00363 int sizeHintHeight = 0 - spacing(), minSizeHeight = 0 - spacing(), colMinWidth=0;
00364 while( (item = it2.current()) != 0 ) {
00365 QSize itemSizeHint = item->sizeHint();
00366 QSize itemMinSize = item->minimumSize();
00367 QSize s;
00368 if(m_justify) {
00369 if(expandingWidgets != 0) {
00370 if(item->expanding() == QSizePolicy::Vertically || item->expanding() == QSizePolicy::BothDirections)
00371 s = QSize( itemSizeHint.width(), QMIN(itemSizeHint.height() + availableSpace / expandingWidgets
00372 , r.height()) );
00373 else
00374 s = QSize( itemSizeHint.width(), QMIN(itemSizeHint.height(), r.height()) );
00375 }
00376 else
00377 s = QSize( itemSizeHint.width(), QMIN(itemSizeHint.height() + availableSpace / (int)currentLine.count()
00378 , r.height()) );
00379 }
00380 else
00381 s = QSize ( itemSizeHint.width(), QMIN(itemSizeHint.height(), r.height()) );
00382 if(!testOnly)
00383 item->setGeometry( QRect(QPoint(x, wy), s) );
00384 wy = wy + s.height() + spacing();
00385 minSizeHeight = minSizeHeight + spacing() + itemMinSize.height();
00386 sizeHintHeight = sizeHintHeight + spacing() + itemSizeHint.height();
00387 colMinWidth = QMAX( colMinWidth, itemMinSize.width() );
00388 ++it2;
00389 }
00390 sizeHint = sizeHint.expandedTo( QSize(0, sizeHintHeight) );
00391 minSize = minSize.expandedTo( QSize(0, minSizeHeight) );
00392 minSizeWidth = minSizeWidth + spacing() + colMinWidth;
00393
00394 x = x + spacing() + w;
00395 w = 0;
00396 y = r.y();
00397 currentLine.clear();
00398 expandingWidgets = 0;
00399 availableSpace = r.height() + spacing();
00400 }
00401
00402 y = y + spacing() + oSizeHint.height();
00403 w = QMAX( w, oSizeHint.width() );
00404 currentLine.append(o);
00405 if(o->expanding() == QSizePolicy::Vertically || o->expanding() == QSizePolicy::BothDirections)
00406 ++expandingWidgets;
00407 availableSpace = QMAX(0, availableSpace - spacing() - oSizeHint.height());
00408 ++it;
00409 }
00410
00411
00412 QPtrListIterator<QLayoutItem> it2(currentLine);
00413 QLayoutItem *item;
00414 int wy = r.y();
00415 int sizeHintHeight = 0 - spacing(), minSizeHeight = 0 - spacing(), colMinWidth=0;
00416 while( (item = it2.current()) != 0 ) {
00417 QSize itemSizeHint = item->sizeHint();
00418 QSize itemMinSize = item->minimumSize();
00419 QSize s;
00420 if(m_justify) {
00421 if(expandingWidgets != 0) {
00422 if(item->expanding() == QSizePolicy::Vertically || item->expanding() == QSizePolicy::BothDirections)
00423 s = QSize( itemSizeHint.width(), QMIN(itemSizeHint.height() + availableSpace / expandingWidgets
00424 , r.height()) );
00425 else
00426 s = QSize( itemSizeHint.width(), QMIN(itemSizeHint.height(), r.height()) );
00427 }
00428 else
00429 s = QSize( itemSizeHint.width(), QMIN(itemSizeHint.height() + availableSpace / (int)currentLine.count()
00430 , r.height()) );
00431 }
00432 else
00433 s = QSize ( itemSizeHint.width(), QMIN(itemSizeHint.height(), r.height()) );
00434 if(!testOnly)
00435 item->setGeometry( QRect(QPoint(x, wy), s) );
00436 wy = wy + s.height() + spacing();
00437 minSizeHeight = minSizeHeight + spacing() + itemMinSize.height();
00438 sizeHintHeight = sizeHintHeight + spacing() + itemSizeHint.height();
00439 colMinWidth = QMAX( colMinWidth, itemMinSize.width() );
00440 ++it2;
00441 }
00442 sizeHint = sizeHint.expandedTo( QSize( x + spacing() + w, sizeHintHeight) );
00443 minSizeWidth = minSizeWidth + spacing() + colMinWidth;
00444 minSize = minSize.expandedTo( QSize(minSizeWidth, minSizeHeight) );
00445
00446
00447 m_cached_sizeHint = sizeHint + QSize(2* margin(), 2*margin());
00448 m_cached_minSize = minSize + QSize(2* margin(), 2*margin());
00449
00450 return x + w - r.x();
00451 }
00452