2
* Copyright (C) 2003 by Unai Garro <ugarro@users.sourceforge.net>
3
* Copyright (C) 2004 by Enrico Ros <rosenric@dei.unipd.it>
4
* Copyright (C) 2004 by Stephan Kulow <coolo@kde.org>
5
* Copyright (C) 2004 by Oswald Buddenhagen <ossi@kde.org>
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22
#include "kdmlayout.h"
25
KdmLayoutFixed::KdmLayoutFixed(const QDomNode &/*node*/)
27
//Parsing FIXED parameters on 'node' [NONE!]
31
KdmLayoutFixed::update(QStack<QSize> &parentSizes, const QRect &parentGeometry, bool force)
33
enter("Fixed::update") << parentGeometry << "depth" << parentSizes.size();
35
// I can't layout children if the parent rectangle is not valid
36
if (parentGeometry.width() < 0 || parentGeometry.height() < 0) {
37
leave() << "invalid geometry";
40
// For each child in list I ask their hinted size and set it!
41
parentSizes.push(parentGeometry.size());
43
itm->setGeometry(parentSizes, itm->placementHint(parentSizes, parentGeometry.topLeft()), force);
48
KdmLayoutBox::KdmLayoutBox(const QDomNode &node)
50
//Parsing BOX parameters
52
QDomElement el = n.toElement();
53
box.isVertical = el.attribute("orientation", "vertical") != "horizontal";
54
box.xpadding = el.attribute("xpadding", "0").toInt();
55
box.ypadding = el.attribute("ypadding", "0").toInt();
56
box.spacing = el.attribute("spacing", "0").toInt();
57
box.minwidth = el.attribute("min-width", "0").toInt();
58
box.minheight = el.attribute("min-height", "0").toInt();
59
box.homogeneous = el.attribute("homogeneous", "false") == "true";
63
int min, opt, max, set;
66
LayoutHint() : done(false)
72
KdmLayoutBox::update(QStack<QSize> &parentSizes, const QRect &parentGeometry, bool force)
74
enter("Box::update") << parentGeometry << "depth" << parentSizes.size();
76
// I can't layout children if the parent rectangle is not valid
77
if (!parentGeometry.isValid() || parentGeometry.isEmpty()) {
78
leave() << "invalid geometry";
82
QRect childrenRect = parentGeometry;
83
// Begin cutting the parent rectangle to attach children on the right place
84
childrenRect.adjust(box.xpadding, box.ypadding, -box.xpadding, -box.ypadding);
86
debug() << "childrenRect" << childrenRect;
88
// For each child in list ...
89
if (box.homogeneous) {
91
forEachVisibleChild (itm)
93
forEachVisibleChild (itm) {
94
QRect temp = childrenRect;
96
int height = (temp.height() - (ccnt - 1) * box.spacing) / ccnt;
97
temp.setHeight(height);
98
childrenRect.setTop(childrenRect.top() + height + box.spacing);
100
int width = (temp.width() - (ccnt - 1) * box.spacing) / ccnt;
101
temp.setWidth(width);
102
childrenRect.setLeft(childrenRect.left() + width + box.spacing);
104
parentSizes.push(temp.size());
105
QRect itemRect = itm->placementHint(parentSizes, temp.topLeft());
107
parentSizes.push(parentGeometry.size());
108
itm->setGeometry(parentSizes, itemRect, force);
113
QVector<LayoutHint> lhs;
114
int ccnt = 0, mintot = 0, opttot = 0, esum = 0;
115
parentSizes.push(QSize(0, 0));
116
forEachVisibleChild (itm) {
118
itm->sizingHint(parentSizes, sh);
119
lhs.resize(ccnt + 1);
120
if (box.isVertical) {
121
lhs[ccnt].min = sh.min.height();
122
lhs[ccnt].opt = sh.opt.height();
123
lhs[ccnt].max = sh.max.height();
125
lhs[ccnt].min = sh.min.width();
126
lhs[ccnt].opt = sh.opt.width();
127
lhs[ccnt].max = sh.max.width();
129
mintot += lhs[ccnt].min;
130
opttot += lhs[ccnt].opt;
131
if (itm->geom.expand) {
132
esum += itm->geom.expand;
134
lhs[ccnt].done = true;
135
lhs[ccnt].set = lhs[ccnt].opt;
140
int havetot = box.isVertical ? childrenRect.size().height() : childrenRect.size().width();
142
if (havetot < opttot) {
143
// fix your theme, dude
144
if (havetot < mintot) {
145
for (int i = 0; i < ccnt; i++) {
146
lhs[i].set = lhs[i].min * havetot / mintot;
147
havetot -= lhs[i].set;
148
mintot -= lhs[i].min;
151
for (int i = 0; i < ccnt; i++) {
152
lhs[i].set = lhs[i].opt * havetot / opttot;
153
havetot -= lhs[i].set;
154
opttot -= lhs[i].opt;
159
spacing = box.spacing;
160
if (havetot < opttot + (ccnt - 1) * spacing)
161
spacing = (havetot - opttot) / (ccnt - 1);
162
int extra = havetot - opttot - (ccnt - 1) * spacing;
163
int tesum, wesum, textra, wextra;
165
tesum = wesum = esum;
166
textra = wextra = extra;
168
forEachVisibleChild (itm) {
169
if (!lhs[idx].done) {
170
int mex = itm->geom.expand * wextra / wesum;
172
wesum -= itm->geom.expand;
173
if (lhs[idx].opt + mex > lhs[idx].max) {
174
lhs[idx].set = lhs[idx].max;
175
lhs[idx].done = true;
176
esum -= itm->geom.expand;
177
extra -= lhs[idx].opt;
179
lhs[idx].set = lhs[idx].opt + mex;
184
} while (tesum != esum);
187
forEachVisibleChild (itm) {
188
QRect temp = childrenRect;
189
if (box.isVertical) {
190
temp.setHeight(lhs[idx].set);
191
childrenRect.setTop(childrenRect.top() + lhs[idx].set + spacing);
193
temp.setWidth(lhs[idx].set);
194
childrenRect.setLeft(childrenRect.left() + lhs[idx].set + spacing);
196
parentSizes.push(temp.size());
197
QRect itemRect = itm->placementHint(parentSizes, temp.topLeft());
199
debug() << "placementHint for" << itm << "temp" << temp << "final"
200
<< itemRect << "childrenRect now" << childrenRect;
201
parentSizes.push(parentGeometry.size());
202
itm->setGeometry(parentSizes, itemRect, force);
211
KdmLayoutBox::sizeHint(QStack<QSize> &parentSizes)
213
enter("Box::sizeHint") << NoSpace << "parentSize #" << parentSizes.size()
214
<< Space << parentSizes.top();
217
QSize bounds(0, 0), sum(0, 0);
219
// Sum up area taken by children
220
parentSizes.push(QSize(0, 0));
221
forEachVisibleChild (itm) {
223
itm->sizingHint(parentSizes, sh);
224
bounds = bounds.expandedTo(sh.opt);
230
if (box.homogeneous) {
232
bounds.rheight() *= ccnt;
234
bounds.rwidth() *= ccnt;
237
bounds.rheight() = sum.height();
239
bounds.rwidth() = sum.width();
242
// Add padding and items spacing
243
int totspc = box.spacing * (ccnt - 1);
245
bounds.rheight() += totspc;
247
bounds.rwidth() += totspc;
248
bounds += QSize(2 * box.xpadding, 2 * box.ypadding);
250
leave() << "bounds" << bounds;
252
// Make hint at least equal to minimum size (if set)
253
return bounds.expandedTo(QSize(box.minwidth, box.minheight));