~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to kdm/kfrontend/themer/kdmlayout.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
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>
 
6
 *
 
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.
 
11
 *
 
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.
 
16
 *
 
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.
 
20
 */
 
21
 
 
22
#include "kdmlayout.h"
 
23
#include "kdmitem.h"
 
24
 
 
25
KdmLayoutFixed::KdmLayoutFixed(const QDomNode &/*node*/)
 
26
{
 
27
    //Parsing FIXED parameters on 'node' [NONE!]
 
28
}
 
29
 
 
30
void
 
31
KdmLayoutFixed::update(QStack<QSize> &parentSizes, const QRect &parentGeometry, bool force)
 
32
{
 
33
    enter("Fixed::update") << parentGeometry << "depth" << parentSizes.size();
 
34
 
 
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";
 
38
        return;
 
39
    }
 
40
    // For each child in list I ask their hinted size and set it!
 
41
    parentSizes.push(parentGeometry.size());
 
42
    forEachChild (itm)
 
43
        itm->setGeometry(parentSizes, itm->placementHint(parentSizes, parentGeometry.topLeft()), force);
 
44
    parentSizes.pop();
 
45
    leave() << "done";
 
46
}
 
47
 
 
48
KdmLayoutBox::KdmLayoutBox(const QDomNode &node)
 
49
{
 
50
    //Parsing BOX parameters
 
51
    QDomNode n = node;
 
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";
 
60
}
 
61
 
 
62
struct LayoutHint {
 
63
    int min, opt, max, set;
 
64
    bool done;
 
65
 
 
66
    LayoutHint() : done(false)
 
67
    {
 
68
    }
 
69
};
 
70
 
 
71
void
 
72
KdmLayoutBox::update(QStack<QSize> &parentSizes, const QRect &parentGeometry, bool force)
 
73
{
 
74
    enter("Box::update") << parentGeometry << "depth" << parentSizes.size();
 
75
 
 
76
    // I can't layout children if the parent rectangle is not valid
 
77
    if (!parentGeometry.isValid() || parentGeometry.isEmpty()) {
 
78
        leave() << "invalid geometry";
 
79
        return;
 
80
    }
 
81
 
 
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);
 
85
 
 
86
    debug() << "childrenRect" << childrenRect;
 
87
 
 
88
    // For each child in list ...
 
89
    if (box.homogeneous) {
 
90
        int ccnt = 0;
 
91
        forEachVisibleChild (itm)
 
92
            ccnt++;
 
93
        forEachVisibleChild (itm) {
 
94
            QRect temp = childrenRect;
 
95
            if (box.isVertical) {
 
96
                int height = (temp.height() - (ccnt - 1) * box.spacing) / ccnt;
 
97
                temp.setHeight(height);
 
98
                childrenRect.setTop(childrenRect.top() + height + box.spacing);
 
99
            } else {
 
100
                int width = (temp.width() - (ccnt - 1) * box.spacing) / ccnt;
 
101
                temp.setWidth(width);
 
102
                childrenRect.setLeft(childrenRect.left() + width + box.spacing);
 
103
            }
 
104
            parentSizes.push(temp.size());
 
105
            QRect itemRect = itm->placementHint(parentSizes, temp.topLeft());
 
106
            parentSizes.pop();
 
107
            parentSizes.push(parentGeometry.size());
 
108
            itm->setGeometry(parentSizes, itemRect, force);
 
109
            parentSizes.pop();
 
110
            ccnt--;
 
111
        }
 
112
    } else {
 
113
        QVector<LayoutHint> lhs;
 
114
        int ccnt = 0, mintot = 0, opttot = 0, esum = 0;
 
115
        parentSizes.push(QSize(0, 0));
 
116
        forEachVisibleChild (itm) {
 
117
            SizeHint sh;
 
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();
 
124
            } else {
 
125
                lhs[ccnt].min = sh.min.width();
 
126
                lhs[ccnt].opt = sh.opt.width();
 
127
                lhs[ccnt].max = sh.max.width();
 
128
            }
 
129
            mintot += lhs[ccnt].min;
 
130
            opttot += lhs[ccnt].opt;
 
131
            if (itm->geom.expand) {
 
132
                esum += itm->geom.expand;
 
133
            } else {
 
134
                lhs[ccnt].done = true;
 
135
                lhs[ccnt].set = lhs[ccnt].opt;
 
136
            }
 
137
            ccnt++;
 
138
        }
 
139
        parentSizes.pop();
 
140
        int havetot = box.isVertical ? childrenRect.size().height() : childrenRect.size().width();
 
141
        int spacing;
 
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;
 
149
                }
 
150
            } else {
 
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;
 
155
                }
 
156
            }
 
157
            spacing = 0;
 
158
        } else {
 
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;
 
164
            do {
 
165
                tesum = wesum = esum;
 
166
                textra = wextra = extra;
 
167
                int idx = 0;
 
168
                forEachVisibleChild (itm) {
 
169
                    if (!lhs[idx].done) {
 
170
                        int mex = itm->geom.expand * wextra / wesum;
 
171
                        wextra -= mex;
 
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;
 
178
                        } else {
 
179
                            lhs[idx].set = lhs[idx].opt + mex;
 
180
                        }
 
181
                    }
 
182
                    idx++;
 
183
                }
 
184
            } while (tesum != esum);
 
185
        }
 
186
        int idx = 0;
 
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);
 
192
            } else {
 
193
                temp.setWidth(lhs[idx].set);
 
194
                childrenRect.setLeft(childrenRect.left() + lhs[idx].set + spacing);
 
195
            }
 
196
            parentSizes.push(temp.size());
 
197
            QRect itemRect = itm->placementHint(parentSizes, temp.topLeft());
 
198
            parentSizes.pop();
 
199
            debug() << "placementHint for" << itm << "temp" << temp << "final"
 
200
                << itemRect << "childrenRect now" << childrenRect;
 
201
            parentSizes.push(parentGeometry.size());
 
202
            itm->setGeometry(parentSizes, itemRect, force);
 
203
            parentSizes.pop();
 
204
            idx++;
 
205
        }
 
206
    }
 
207
    leave() << "done";
 
208
}
 
209
 
 
210
QSize
 
211
KdmLayoutBox::sizeHint(QStack<QSize> &parentSizes)
 
212
{
 
213
    enter("Box::sizeHint") << NoSpace << "parentSize #" << parentSizes.size()
 
214
        << Space << parentSizes.top();
 
215
 
 
216
    int ccnt = 0;
 
217
    QSize bounds(0, 0), sum(0, 0);
 
218
 
 
219
    // Sum up area taken by children
 
220
    parentSizes.push(QSize(0, 0));
 
221
    forEachVisibleChild (itm) {
 
222
        SizeHint sh;
 
223
        itm->sizingHint(parentSizes, sh);
 
224
        bounds = bounds.expandedTo(sh.opt);
 
225
        sum += sh.opt;
 
226
        ccnt++;
 
227
    }
 
228
    parentSizes.pop();
 
229
 
 
230
    if (box.homogeneous) {
 
231
        if (box.isVertical)
 
232
            bounds.rheight() *= ccnt;
 
233
        else
 
234
            bounds.rwidth() *= ccnt;
 
235
    } else {
 
236
        if (box.isVertical)
 
237
            bounds.rheight() = sum.height();
 
238
        else
 
239
            bounds.rwidth() = sum.width();
 
240
    }
 
241
 
 
242
    // Add padding and items spacing
 
243
    int totspc = box.spacing * (ccnt - 1);
 
244
    if (box.isVertical)
 
245
        bounds.rheight() += totspc;
 
246
    else
 
247
        bounds.rwidth() += totspc;
 
248
    bounds += QSize(2 * box.xpadding, 2 * box.ypadding);
 
249
 
 
250
    leave() << "bounds" << bounds;
 
251
 
 
252
    // Make hint at least equal to minimum size (if set)
 
253
    return bounds.expandedTo(QSize(box.minwidth, box.minheight));
 
254
}