2 * Copyright 2007 by Robert Knight <robertknight@gmail.com>
3 * Copyright 2007 by Leo Franchi <lfranchi@gmail.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Library General Public License
7 * as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details
15 * You should have received a copy of the GNU Library General Public
16 * License along with this program; if not, write to the
17 * Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "ContextLayout.h"
27 #include <QtCore/QList>
28 #include <QtCore/QRectF>
29 #include <QtCore/QTimeLine>
33 #include "plasma/layouts/layoutanimator.h"
35 using namespace Context
;
37 class ContextLayout::Private
40 Private() : columnWidth( -1 ) {}
41 QList
<LayoutItem
*> items
;
45 ContextLayout::ContextLayout(LayoutItem
* parent
)
50 ContextLayout::~ContextLayout()
55 int ContextLayout::count() const
57 return d
->items
.count();
60 void ContextLayout::addItem(LayoutItem
* item
)
62 if (d
->items
.contains(item
)) {
69 animator()->setCurrentState(item
,Plasma::LayoutAnimator::InsertedState
);
72 item
->setManagingLayout(this);
74 void ContextLayout::removeItem(LayoutItem
* item
)
76 item
->unsetManagingLayout(this);
77 d
->items
.removeAll(item
);
80 animator()->setCurrentState(item
,Plasma::LayoutAnimator::RemovedState
);
83 int ContextLayout::indexOf(LayoutItem
* item
) const
85 return d
->items
.indexOf(item
);
88 Plasma::LayoutItem
* ContextLayout::itemAt(int i
) const
92 QSizeF
ContextLayout::sizeHint() const
94 // TODO A proper algorithm here
96 // Idea: Return a size hint based on the golden ratio to
97 // make it aesthetically good
98 // eg. Longer side is 1.61x the length of the shorter side
102 return QSizeF(500,500);
105 Plasma::LayoutItem
* ContextLayout::takeAt(int i
)
107 return d
->items
.takeAt(i
);
111 T
qSum(const QList
<T
>& container
)
114 foreach( const T
& item
, container
) {
120 void ContextLayout::relayout()
122 QRectF rect
= geometry().adjusted(margin(LeftMargin
), margin(TopMargin
), -margin(RightMargin
), -margin(BottomMargin
));
124 qDebug() << "Context layout geometry set to " << geometry() << " using column width: " << d
->columnWidth
;
125 const int columnCount
= qMax( (int)(rect
.width() / d
->columnWidth
), 1 ); //use at least one column
127 int insertColumn
= 0;
131 // lay the items out in left-to-right , top-to-bottom order
132 foreach( LayoutItem
*item
, d
->items
) {
134 const QSizeF
& itemSize
= item
->sizeHint();
136 int columnSpan
= (int)ceil(itemSize
.width() / d
->columnWidth
);
138 if ( insertColumn
+ columnSpan
> columnCount
) {
141 rowPos
+= rowHeight
+ spacing();
144 // qDebug() << "Inserting item at column" << insertColumn
145 // << "spanning" << columnSpan << "columns"
146 // << "with offset" << offset;
149 // try to expand the item to fill its allocated number of columns
150 qreal itemWidth
= itemSize
.width();
151 const qreal idealWidth
= columnSpan
* d
->columnWidth
- spacing();
152 if ( itemWidth
< idealWidth
&&
153 idealWidth
< item
->maximumSize().width() ) {
154 itemWidth
= idealWidth
;
157 // calculate offset to horizontally center item
158 //if there is space for only one column,
159 //center the item relative to the whole available rectangle
161 if( columnCount
> 1 ) {
162 offset
= (columnSpan
* d
->columnWidth
) - itemWidth
;
164 offset
= rect
.width() - itemWidth
;
166 if( columnCount
> 1 ) { //no need for spacing if there is only one column
167 offset
-= spacing() / 4;
175 // try to restrict the item width to the available geometry's
177 if ( itemWidth
> rect
.width() ) {
178 itemWidth
= qMax(rect
.width(),item
->minimumSize().width());
184 if( item
->hasHeightForWidth() )
185 itemHeight
= item
->heightForWidth( itemWidth
);
187 itemHeight
= itemSize
.height(); // this is not good, applets should provide heightForWidth
189 const QRectF
newGeometry(rect
.left() + insertColumn
* d
->columnWidth
+ offset
,
190 rect
.top() + margin( TopMargin
) + rowPos
,
194 rowHeight
= qMax(rowHeight
,itemHeight
);
195 insertColumn
+= columnSpan
;
197 kDebug() << "Setting a child item geometry to:" << newGeometry
;
199 animator()->setGeometry( item
, newGeometry
);
201 item
->setGeometry( newGeometry
);
207 Qt::Orientations
ContextLayout::expandingDirections() const
209 return Qt::Vertical
| Qt::Horizontal
;
212 qreal
ContextLayout::columnWidth() const
214 return d
->columnWidth
;
217 void ContextLayout::setColumnWidth( const qreal width
)
219 d
->columnWidth
= width
;