GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/widgets/extendedlistbox.cpp Lines: 14 126 11.1 %
Date: 2017-11-29 Branches: 11 96 11.5 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2012-2017  The ManaPlus Developers
4
 *
5
 *  This file is part of The ManaPlus Client.
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
 *  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, see <http://www.gnu.org/licenses/>.
19
 */
20
21
#include "gui/widgets/extendedlistbox.h"
22
23
#include "gui/models/extendedlistmodel.h"
24
25
#include "gui/skin.h"
26
27
#include "gui/fonts/font.h"
28
29
#include "render/graphics.h"
30
31
#include "debug.h"
32
33
10
ExtendedListBox::ExtendedListBox(const Widget2 *const widget,
34
                                 ListModel *const listModel,
35
                                 const std::string &skin,
36
10
                                 const unsigned int rowHeight) :
37
    ListBox(widget, listModel, skin),
38


40
    mImagePadding(mSkin != nullptr ? mSkin->getOption("imagePadding") : 0),
39


40
    mSpacing(mSkin != nullptr ? mSkin->getOption("spacing") : 0),
40
    mHeight(0),
41
    mListItems(),
42
60
    mSelectedItems()
43
{
44
10
    if (rowHeight != 0u)
45
4
        mRowHeight = rowHeight;
46
10
}
47
48
20
ExtendedListBox::~ExtendedListBox()
49
{
50
20
}
51
52
void ExtendedListBox::draw(Graphics *const graphics)
53
{
54
    if (mListModel == nullptr)
55
        return;
56
57
    BLOCK_START("ExtendedListBox::draw")
58
    ExtendedListModel *const model = static_cast<ExtendedListModel *>(
59
        mListModel);
60
61
    updateAlpha();
62
    Font *const font = getFont();
63
64
    const int height = CAST_S32(mRowHeight);
65
    const int pad2 = 2 + mPadding;
66
    const int width = mDimension.width;
67
    int textPos = (height - font->getHeight()) / 2 + mPadding;
68
    if (textPos < 0)
69
        textPos = 0;
70
71
    const int sz = mListModel->getNumberOfElements();
72
    mListItems.clear();
73
    mSelectedItems.clear();
74
    int y = 0;
75
    const int insideWidth = width - pad2;
76
    for (int f = 0; f < sz; f ++)
77
    {
78
        int row = f;
79
        bool useImage = true;
80
        std::string str = mListModel->getElementAt(f);
81
        int strWidth = font->getWidth(str) + 8;
82
83
        const Image *const image = model->getImageAt(row);
84
        if (image != nullptr)
85
            strWidth += image->getWidth() + mImagePadding;
86
87
        STD_VECTOR<ExtendedListBoxItem> &list =
88
            row == mSelected ? mSelectedItems : mListItems;
89
90
        if (insideWidth < strWidth)
91
        {
92
            const size_t strSize = str.size();
93
            size_t divPos = strSize / 2;
94
            if (divPos > 0 && CAST_U8(
95
                str[divPos - 1]) >= 0xc0)
96
            {
97
                divPos --;
98
            }
99
            for (size_t d = divPos; d > 10; d --)
100
            {
101
                if (str[d] == 32)
102
                {
103
                    divPos = d + 1;
104
                    break;
105
                }
106
            }
107
            list.push_back(ExtendedListBoxItem(row,
108
                str.substr(0, divPos), useImage, y));
109
            str = str.substr(divPos);
110
            y += height;
111
            useImage = false;
112
        }
113
        list.push_back(ExtendedListBoxItem(row, str, useImage, y));
114
115
        y += height;
116
    }
117
    mHeight = y + height;
118
119
    const size_t itemsSz = mListItems.size();
120
    const size_t selSz = mSelectedItems.size();
121
    int minY = -1;
122
    int maxY = -1;
123
    for (size_t f = 0; f < selSz; f ++)
124
    {
125
        const ExtendedListBoxItem &item = mSelectedItems[f];
126
        const int y1 = item.y;
127
        if (minY == -1)
128
            minY = y1;
129
        if (maxY < y1)
130
            maxY = y1;
131
    }
132
133
    if (minY != -1)
134
    {
135
        mHighlightColor.a = CAST_U32(mAlpha * 255.0F);
136
        graphics->setColor(mHighlightColor);
137
        graphics->fillRectangle(Rect(mPadding, minY + mPadding,
138
            width - pad2, maxY - minY + height));
139
    }
140
141
    for (size_t f = 0; f < itemsSz; ++f)
142
    {
143
        const ExtendedListBoxItem &item = mListItems[f];
144
        const int row1 = item.row;
145
        if (item.image)
146
        {
147
            const Image *const image = model->getImageAt(row1);
148
            if (image != nullptr)
149
            {
150
                graphics->drawImage(image,
151
                    mImagePadding,
152
                    item.y + (height - image->getHeight()) / 2 + mPadding);
153
            }
154
        }
155
    }
156
157
    for (size_t f = 0; f < itemsSz; ++f)
158
    {
159
        const ExtendedListBoxItem &item = mListItems[f];
160
        const int row1 = item.row;
161
        const int y1 = item.y;
162
        const Image *const image = model->getImageAt(row1);
163
        if ((image == nullptr) || !item.image)
164
        {
165
            font->drawString(graphics,
166
                mForegroundColor, mForegroundColor2,
167
                item.text,
168
                mPadding, y1 + textPos);
169
        }
170
        else
171
        {
172
            font->drawString(graphics,
173
                mForegroundColor, mForegroundColor2,
174
                item.text,
175
                image->getWidth() + mImagePadding + mSpacing, y1 + textPos);
176
        }
177
    }
178
179
    for (size_t f = 0; f < selSz; ++f)
180
    {
181
        const ExtendedListBoxItem &item = mSelectedItems[f];
182
        const int row1 = item.row;
183
        const int y1 = item.y;
184
        const Image *const image = model->getImageAt(row1);
185
        if ((image == nullptr) || !item.image)
186
        {
187
            font->drawString(graphics,
188
                mForegroundSelectedColor, mForegroundSelectedColor2,
189
                item.text,
190
                mPadding, y1 + textPos);
191
        }
192
        else
193
        {
194
            font->drawString(graphics,
195
                mForegroundSelectedColor, mForegroundSelectedColor2,
196
                item.text,
197
                image->getWidth() + mImagePadding + mSpacing, y1 + textPos);
198
        }
199
    }
200
201
    for (size_t f = 0; f < selSz; ++f)
202
    {
203
        const ExtendedListBoxItem &item = mSelectedItems[f];
204
        const int row1 = item.row;
205
        if (item.image)
206
        {
207
            const Image *const image = model->getImageAt(row1);
208
            if (image != nullptr)
209
            {
210
                graphics->drawImage(image,
211
                    mImagePadding,
212
                    item.y + (height - image->getHeight()) / 2 + mPadding);
213
            }
214
        }
215
    }
216
217
    BLOCK_END("ExtendedListBox::draw")
218
}
219
220
void ExtendedListBox::safeDraw(Graphics *const graphics)
221
{
222
    ExtendedListBox::draw(graphics);
223
}
224
225
26
void ExtendedListBox::adjustSize()
226
{
227
26
    if (mHeight != 0)
228
        setHeight(mHeight + 2 * mPadding);
229
    else
230
26
        ListBox::adjustSize();
231
26
}
232
233
int ExtendedListBox::getSelectionByMouse(const int y) const
234
{
235
    if (mListItems.empty() && mSelectedItems.empty())
236
        return ListBox::getSelectionByMouse(y);
237
238
    const int height = CAST_S32(mRowHeight);
239
    const size_t itemsSz = mListItems.size();
240
    for (size_t f = 0; f < itemsSz; f ++)
241
    {
242
        const ExtendedListBoxItem &item = mListItems[f];
243
        const int y2 = item.y + mPadding;
244
        if (y2 <= y && y2 + height > y)
245
            return item.row;
246
    }
247
248
    const size_t selSz = mSelectedItems.size();
249
    for (size_t f = 0; f < selSz; f ++)
250
    {
251
        const ExtendedListBoxItem &item = mSelectedItems[f];
252
        const int y2 = item.y + mPadding;
253
        if (y2 <= y && y2 + height > y)
254
            return item.row;
255
    }
256
    return 0;
257
}