GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/widgets/layoutarray.cpp Lines: 159 165 96.4 %
Date: 2018-12-09 Branches: 103 115 89.6 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2007-2009  The Mana World Development Team
4
 *  Copyright (C) 2009-2010  The Mana Developers
5
 *  Copyright (C) 2011-2018  The ManaPlus Developers
6
 *
7
 *  This file is part of The ManaPlus Client.
8
 *
9
 *  This program is free software; you can redistribute it and/or modify
10
 *  it under the terms of the GNU General Public License as published by
11
 *  the Free Software Foundation; either version 2 of the License, or
12
 *  any later version.
13
 *
14
 *  This program is distributed in the hope that it will be useful,
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *  GNU General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU General Public License
20
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
#include "gui/widgets/layoutarray.h"
24
25
#include "enums/gui/layouttype.h"
26
27
#include "gui/widgets/layoutcell.h"
28
#include "gui/widgets/widget.h"
29
30
#include <cassert>
31
32
#include "debug.h"
33
34
161
LayoutArray::LayoutArray() :
35
    mCells(),
36
644
    mSpacing(4)
37
{
38
161
}
39
40

483
LayoutArray::~LayoutArray()
41
{
42
    STD_VECTOR <STD_VECTOR <LayoutCell *> >::iterator
43
322
        i = mCells.begin();
44
    const STD_VECTOR <STD_VECTOR <LayoutCell *> >::iterator
45
322
        i_end = mCells.end();
46
1641
    while (i != i_end)
47
    {
48
1480
        STD_VECTOR< LayoutCell * >::iterator j = i->begin();
49
1480
        const STD_VECTOR< LayoutCell * >::iterator j_end = i->end();
50
5180
        while (j != j_end)
51
        {
52
4440
            delete *j;
53
            ++j;
54
        }
55
740
        ++i;
56
    }
57
161
}
58
59
701
LayoutCell &LayoutArray::at(const int x, const int y,
60
                            const int w, const int h)
61
{
62
701
    resizeGrid(x + w, y + h);
63
2103
    LayoutCell *&cell = mCells[CAST_SIZE(y)][static_cast<size_t>(x)];
64
701
    if (cell == nullptr)
65
1400
        cell = new LayoutCell;
66
701
    return *cell;
67
}
68
69
740
void LayoutArray::resizeGrid(int w, const int h)
70
{
71

1451
    const bool extW = (w != 0) && w > CAST_S32(mSizes[0].size());
72

1470
    const bool extH = (h != 0) && h > CAST_S32(mSizes[1].size());
73
74
740
    if (!extW && !extH)
75
        return;
76
77
486
    if (extH)
78
    {
79
440
        mSizes[1].resize(CAST_SIZE(h), LayoutType::DEF);
80
440
        mCells.resize(CAST_SIZE(h));
81
440
        if (!extW)
82
552
            w = CAST_S32(mSizes[0].size());
83
    }
84
85
486
    if (extW)
86
210
        mSizes[0].resize(CAST_SIZE(w), LayoutType::DEF);
87
88
    STD_VECTOR <STD_VECTOR <LayoutCell *> >::iterator
89
972
        i = mCells.begin();
90
    const STD_VECTOR <STD_VECTOR <LayoutCell *> >::iterator
91
972
        i_end = mCells.end();
92
2820
    while (i != i_end)
93
    {
94
2334
        i->resize(CAST_SIZE(w), nullptr);
95
        ++i;
96
    }
97
}
98
99
3
void LayoutArray::setColWidth(const int n, const int w)
100
{
101
3
    resizeGrid(n + 1, 0);
102
6
    mSizes[0U][CAST_SIZE(n)] = w;
103
3
}
104
105
29
void LayoutArray::setRowHeight(const int n, const int h)
106
{
107
29
    resizeGrid(0, n + 1);
108
58
    mSizes[1][CAST_SIZE(n)] = h;
109
29
}
110
111
7
void LayoutArray::matchColWidth(const int n1, const int n2)
112
{
113
7
    resizeGrid(std::max(n1, n2) + 1, 0);
114
14
    const STD_VECTOR<int> widths = getSizes(0, LayoutType::DEF);
115
14
    const int s = std::max(widths[CAST_SIZE(n1)],
116
21
        widths[CAST_SIZE(n2)]);
117
14
    mSizes[0][CAST_SIZE(n1)] = s;
118
14
    mSizes[0][CAST_SIZE(n2)] = s;
119
7
}
120
121
1
void LayoutArray::extend(const int x, const int y, const int w, const int h)
122
{
123
1
    LayoutCell &cell = at(x, y, w, h);
124
1
    cell.mExtent[0] = w;
125
1
    cell.mExtent[1] = h;
126
1
}
127
128
623
LayoutCell &LayoutArray::place(Widget *const widget, const int x,
129
                               const int y, const int w, const int h)
130
{
131
623
    LayoutCell &cell = at(x, y, w, h);
132
623
    assert(cell.mType == LayoutCell::NONE);
133
623
    cell.mType = LayoutCell::WIDGET;
134
623
    cell.mWidget = widget;
135
623
    if (widget != nullptr)
136
    {
137
881
        cell.mSize[0] = w == 1 ? widget->getWidth() : 0;
138
1185
        cell.mSize[1] = h == 1 ? widget->getHeight() : 0;
139
    }
140
    else
141
    {
142
        cell.mSize[0] = 1;
143
        cell.mSize[1] = 1;
144
    }
145
623
    cell.mExtent[0] = w;
146
623
    cell.mExtent[1] = h;
147
623
    cell.mHPadding = 0;
148
623
    cell.mVPadding = 0;
149
623
    cell.mAlign[0] = LayoutCell::FILL;
150
623
    cell.mAlign[1] = LayoutCell::FILL;
151
1246
    int &cs = mSizes[0][CAST_SIZE(x)];
152
1246
    int &rs = mSizes[1][CAST_SIZE(y)];
153

623
    if (cs == LayoutType::DEF && w == 1)
154
158
        cs = 0;
155

623
    if (rs == LayoutType::DEF && h == 1)
156
326
        rs = 0;
157
623
    return cell;
158
}
159
160
1798
void LayoutArray::align(int &restrict pos, int &restrict size, const int dim,
161
                        LayoutCell const &restrict cell,
162
                        const int *restrict const sizes,
163
                        const int sizeCount) const
164
{
165
1798
    if (dim < 0 || dim >= 2)
166
        return;
167
1798
    int size_max = sizes[0];
168
1798
    int cnt = cell.mExtent[dim];
169

1798
    if ((sizeCount != 0) && cell.mExtent[dim] > sizeCount)
170
1
        cnt = sizeCount;
171
172
3835
    for (int i = 1; i < cnt; ++i)
173
2037
        size_max += sizes[i] + mSpacing;
174
3596
    size = std::min<int>(cell.mSize[dim], size_max);
175
176

1798
    switch (cell.mAlign[dim])
177
    {
178
        case LayoutCell::LEFT:
179
            return;
180
        case LayoutCell::RIGHT:
181
            pos += size_max - size;
182
            return;
183
        case LayoutCell::CENTER:
184
1
            pos += (size_max - size) / 2;
185
1
            return;
186
        case LayoutCell::FILL:
187
1793
            size = size_max;
188
1793
            return;
189
        default:
190
            logger->log1("LayoutArray::align unknown layout");
191
            return;
192
    }
193
}
194
195
751
STD_VECTOR<int> LayoutArray::getSizes(const int dim, int upp) const
196
{
197
751
    if (dim < 0 || dim >= 2)
198
        return mSizes[1];
199
200
1502
    const int gridW = CAST_S32(mSizes[0].size());
201
1502
    const int gridH = CAST_S32(mSizes[1].size());
202
751
    STD_VECTOR<int> sizes = mSizes[dim];
203
204
    // Compute minimum sizes.
205
7693
    for (int gridY = 0; gridY < gridH; ++gridY)
206
    {
207
43271
        for (int gridX = 0; gridX < gridW; ++gridX)
208
        {
209
39800
            const LayoutCell *const cell = mCells[CAST_SIZE(gridY)]
210
59700
                [CAST_SIZE(gridX)];
211

19900
            if ((cell == nullptr) || cell->mType == LayoutCell::NONE)
212
                continue;
213
214
3241
            if (cell->mExtent[dim] == 1)
215
            {
216
2184
                const int n = (dim == 0 ? gridX : gridY);
217
2184
                const int s = cell->mSize[dim] + cell->mVPadding * 2;
218
4368
                if (s > sizes[CAST_SIZE(n)])
219
1658
                    sizes[CAST_SIZE(n)] = s;
220
            }
221
        }
222
    }
223
224
751
    if (upp == LayoutType::DEF)
225
        return sizes;
226
227
    // Compute the FILL sizes.
228
856
    const int nb = CAST_S32(sizes.size());
229
428
    int nbFill = 0;
230
2204
    for (int i = 0; i < nb; ++i)
231
    {
232
5328
        if (mSizes[CAST_SIZE(dim)][static_cast<size_t>(i)]
233
1776
            <= LayoutType::DEF)
234
        {
235
1157
            ++nbFill;
236
2314
            if (mSizes[CAST_SIZE(dim)][static_cast<size_t>(i)] ==
237

2281
                LayoutType::SET ||
238
2248
                sizes[CAST_SIZE(i)] <= LayoutType::DEF)
239
            {
240
1986
                sizes[CAST_SIZE(i)] = 0;
241
            }
242
        }
243
3552
        upp -= sizes[CAST_SIZE(i)] + mSpacing;
244
    }
245
428
    upp = upp + mSpacing;
246
247
428
    if (nbFill == 0)
248
        return sizes;
249
250
3425
    for (int i = 0; i < nb; ++i)
251
    {
252
3042
        if (mSizes[CAST_SIZE(dim)][static_cast<size_t>(i)] >
253
            LayoutType::DEF)
254
        {
255
            continue;
256
        }
257
258
1157
        const int s = upp / nbFill;
259
2314
        sizes[CAST_SIZE(i)] += s;
260
1157
        upp -= s;
261
1157
        --nbFill;
262
    }
263
264
    return sizes;
265
}
266
267
316
int LayoutArray::getSize(const int dim) const
268
{
269
632
    STD_VECTOR<int> sizes = getSizes(dim, LayoutType::DEF);
270
316
    int size = 0;
271
632
    const int nb = CAST_S32(sizes.size());
272
1672
    for (int i = 0; i < nb; ++i)
273
    {
274
2712
        if (sizes[CAST_SIZE(i)] > LayoutType::DEF)
275
623
            size += sizes[CAST_SIZE(i)];
276
1356
        size += mSpacing;
277
    }
278
632
    return size - mSpacing;
279
}
280
281
214
void LayoutArray::reflow(const int nx, const int ny,
282
                         const int nw, const int nh)
283
{
284
428
    const int gridW = CAST_S32(mSizes[0].size());
285
428
    const int gridH = CAST_S32(mSizes[1].size());
286
287
428
    STD_VECTOR<int> widths  = getSizes(0, nw);
288
428
    STD_VECTOR<int> heights = getSizes(1, nh);
289
290
428
    const int szW = CAST_S32(widths.size());
291
428
    const int szH = CAST_S32(heights.size());
292
214
    int y = ny;
293
1186
    for (int gridY = 0; gridY < gridH; ++gridY)
294
    {
295
        int x = nx;
296
11928
        for (int gridX = 0; gridX < gridW; ++gridX)
297
        {
298
10956
            LayoutCell *const cell = mCells[CAST_SIZE(gridY)]
299
16434
                [CAST_SIZE(gridX)];
300

5478
            if ((cell != nullptr) && cell->mType != LayoutCell::NONE)
301
            {
302
899
                int dx = x;
303
899
                int dy = y;
304
899
                int dw = 0;
305
899
                int dh = 0;
306
899
                align(dx, dw, 0, *cell,
307
1798
                    &widths[CAST_SIZE(gridX)], szW - gridX);
308
899
                align(dy, dh, 1, *cell,
309
1798
                    &heights[CAST_SIZE(gridY)], szH - gridY);
310
899
                cell->reflow(dx, dy, dw, dh);
311
            }
312
10956
            x += widths[CAST_SIZE(gridX)] + mSpacing;
313
        }
314
1944
        y += heights[CAST_SIZE(gridY)] + mSpacing;
315
    }
316
214
}