libplasma
flowlayout.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "flowlayout.h"
00021
00022 #include <limits.h>
00023 #include <math.h>
00024
00025 #include <QtCore/QList>
00026 #include <QtCore/QRectF>
00027 #include <QtCore/QTimeLine>
00028
00029 #include <QtDebug>
00030
00031 #include "layoutanimator.h"
00032
00033 using namespace Plasma;
00034
00035 class FlowLayout::Private
00036 {
00037 public:
00038 Private() : columnWidth( -1 ) {}
00039 QList<LayoutItem*> items;
00040 qreal columnWidth;
00041 };
00042
00043 FlowLayout::FlowLayout(LayoutItem* parent)
00044 : Layout(parent)
00045 , d(new Private)
00046 {
00047 }
00048 FlowLayout::~FlowLayout()
00049 {
00050 delete d;
00051 }
00052
00053 int FlowLayout::count() const
00054 {
00055 return d->items.count();
00056 }
00057
00058 void FlowLayout::addItem(LayoutItem* item)
00059 {
00060 if (!item || d->items.contains(item)) {
00061 return;
00062 }
00063
00064 item->setManagingLayout(this);
00065 d->items << item;
00066
00067 if (animator()) {
00068 animator()->setCurrentState(item,LayoutAnimator::InsertedState);
00069 }
00070
00071 updateGeometry();
00072 }
00073 void FlowLayout::removeItem(LayoutItem* item)
00074 {
00075 if (!item) {
00076 return;
00077 }
00078
00079 item->unsetManagingLayout(this);
00080 d->items.removeAll(item);
00081
00082 if (animator()) {
00083 animator()->setCurrentState(item,LayoutAnimator::RemovedState);
00084 }
00085
00086 updateGeometry();
00087 }
00088 int FlowLayout::indexOf(LayoutItem* item) const
00089 {
00090 if (!item) {
00091 return -1;
00092 }
00093
00094 return d->items.indexOf(item);
00095 }
00096 LayoutItem* FlowLayout::itemAt(int i) const
00097 {
00098 if (i >= d->items.count()) {
00099 return 0;
00100 }
00101
00102 return d->items[i];
00103 }
00104
00105 QSizeF FlowLayout::sizeHint() const
00106 {
00107
00108
00109
00110
00111
00112
00113
00114
00115 return QSizeF(500,500);
00116 }
00117
00118 LayoutItem* FlowLayout::takeAt(int i)
00119 {
00120 if (i >= d->items.count()) {
00121 return 0;
00122 }
00123
00124 return d->items.takeAt(i);
00125
00126 }
00127
00128 template <class T>
00129 T qSum(const QList<T>& container)
00130 {
00131 T total = 0;
00132 foreach( const T& item , container ) {
00133 total += item;
00134 }
00135 return total;
00136 }
00137
00138 void FlowLayout::relayout()
00139 {
00140 QRectF rect = geometry().adjusted(margin(LeftMargin), margin(TopMargin), -margin(RightMargin), -margin(BottomMargin));
00141
00142 qDebug() << "Flow layout geometry set to " << geometry();
00143
00144
00145 qreal totalWidth = 0;
00146 qreal totalHeight = 0;
00147
00148 foreach(LayoutItem *item , d->items) {
00149 totalWidth += item->sizeHint().width();
00150 totalHeight += item->sizeHint().height();
00151 }
00152
00153
00154
00155
00156
00157 qreal averageWidth;
00158 if (d->columnWidth == -1) {
00159 averageWidth = totalWidth / d->items.count() + 2*spacing();
00160 } else {
00161 averageWidth = d->columnWidth;
00162 }
00163
00164 const int columnCount = (int)(rect.width() / averageWidth);
00165
00166 int insertColumn = 0;
00167 qreal rowPos = 0;
00168 qreal rowHeight = 0;
00169
00170
00171 foreach(LayoutItem *item , d->items) {
00172 const QSizeF& itemSize = item->sizeHint();
00173
00174 int columnSpan = (int)ceil(itemSize.width() / averageWidth);
00175
00176 if ( insertColumn + columnSpan > columnCount ) {
00177
00178 insertColumn = 0;
00179 rowPos += rowHeight + spacing();
00180 }
00181
00182
00183
00184
00185
00186
00187
00188 qreal itemWidth = itemSize.width();
00189 const qreal idealWidth = columnSpan * averageWidth - spacing();
00190 if ( itemWidth < idealWidth &&
00191 idealWidth < item->maximumSize().width() ) {
00192 itemWidth = idealWidth;
00193 }
00194
00195
00196 qreal offset = (columnSpan * averageWidth) - itemWidth;
00197 if ( insertColumn == 0 )
00198 offset -= spacing();
00199 offset /= 2;
00200
00201
00202
00203 if ( itemWidth > rect.width() ) {
00204 itemWidth = qMax(rect.width(),item->minimumSize().width());
00205 offset = 0;
00206 }
00207
00208
00209 const QRectF newGeometry(rect.left() + insertColumn * averageWidth + offset,
00210 rect.top() + rowPos,
00211 itemWidth,
00212 itemSize.height());
00213
00214 rowHeight = qMax(rowHeight,itemSize.height());
00215 insertColumn += columnSpan;
00216
00217 if ( animator() )
00218 animator()->setGeometry( item , newGeometry );
00219 else
00220 item->setGeometry( newGeometry );
00221 }
00222
00223 startAnimation();
00224 }
00225
00226 Qt::Orientations FlowLayout::expandingDirections() const
00227 {
00228 return Qt::Vertical | Qt::Horizontal;
00229 }
00230
00231 qreal FlowLayout::columnWidth() const
00232 {
00233 return d->columnWidth;
00234 }
00235
00236 void FlowLayout::setColumnWidth( const qreal width )
00237 {
00238 d->columnWidth = width;
00239 }