GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/widgets/staticbrowserbox.cpp Lines: 211 381 55.4 %
Date: 2018-05-24 20:11:55 Branches: 131 333 39.3 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2004-2009  The Mana World Development Team
4
 *  Copyright (C) 2009-2010  The Mana Developers
5
 *  Copyright (C) 2011-2018  The ManaPlus Developers
6
 *  Copyright (C) 2009  Aethyra Development Team
7
 *
8
 *  This file is part of The ManaPlus Client.
9
 *
10
 *  This program is free software; you can redistribute it and/or modify
11
 *  it under the terms of the GNU General Public License as published by
12
 *  the Free Software Foundation; either version 2 of the License, or
13
 *  any later version.
14
 *
15
 *  This program is distributed in the hope that it will be useful,
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 *  GNU General Public License for more details.
19
 *
20
 *  You should have received a copy of the GNU General Public License
21
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
 */
23
24
#include "gui/widgets/staticbrowserbox.h"
25
26
#include "enums/gui/linkhighlightmode.h"
27
28
#include "gui/gui.h"
29
#include "gui/mouseoverlink.h"
30
#include "gui/skin.h"
31
32
#include "gui/fonts/font.h"
33
34
#include "gui/widgets/browserbox.inc"
35
#include "gui/widgets/linkhandler.h"
36
37
#include "render/graphics.h"
38
39
#include "resources/imageset.h"
40
41
#include "resources/image/image.h"
42
43
#include "resources/loaders/imageloader.h"
44
#include "resources/loaders/imagesetloader.h"
45
46
#include "utils/browserboxtools.h"
47
#include "utils/checkutils.h"
48
#include "utils/foreach.h"
49
#include "utils/stdmove.h"
50
#include "utils/stringutils.h"
51
#include "utils/translation/podict.h"
52
53
#include <algorithm>
54
55
#include "debug.h"
56
57
ImageSet *StaticBrowserBox::mEmotes = nullptr;
58
int StaticBrowserBox::mInstances = 0;
59
60
24
StaticBrowserBox::StaticBrowserBox(const Widget2 *const widget,
61
                                   const Opaque opaque,
62
24
                                   const std::string &skin) :
63
    Widget(widget),
64
    MouseListener(),
65
    mTextRows(),
66
    mTextRowLinksCount(),
67
    mLineParts(),
68
    mLinks(),
69
    mLinkHandler(nullptr),
70
    mSkin(nullptr),
71
    mHighlightMode(0),
72
    mSelectedLink(-1),
73
    mHeight(0),
74
    mWidth(0),
75
    mYStart(0),
76
    mPadding(0),
77
    mNewLinePadding(15U),
78
    mItemPadding(0),
79
48
    mHighlightColor(getThemeColor(ThemeColorId::HIGHLIGHT, 255U)),
80
48
    mHyperLinkColor(getThemeColor(ThemeColorId::HYPERLINK, 255U)),
81
    mOpaque(opaque),
82
    mUseLinksAndUserColors(true),
83
    mUseEmotes(true),
84
    mProcessVars(false),
85
    mEnableImages(false),
86
    mEnableKeys(false),
87
    mEnableTabs(false),
88
192
    mSeparator(false)
89
{
90
24
    mAllowLogic = false;
91
92
24
    setFocusable(true);
93
24
    addMouseListener(this);
94
95
48
    mBackgroundColor = getThemeColor(ThemeColorId::BACKGROUND, 255U);
96
97
24
    if (theme != nullptr)
98
    {
99

96
        mSkin = theme->load(skin,
100
            "browserbox.xml",
101
            true,
102
24
            Theme::getThemePath());
103
    }
104
24
    if (mInstances == 0)
105
    {
106

80
        mEmotes = Loader::getImageSet(
107
            "graphics/sprites/chatemotes.png", 17, 18);
108
    }
109
24
    mInstances ++;
110
111
24
    if (mSkin != nullptr)
112
    {
113
48
        mPadding = mSkin->getPadding();
114
24
        mNewLinePadding = CAST_U32(
115

96
            mSkin->getOption("newLinePadding", 15));
116

96
        mItemPadding = mSkin->getOption("itemPadding");
117

96
        if (mSkin->getOption("highlightBackground") != 0)
118
24
            mHighlightMode |= LinkHighlightMode::BACKGROUND;
119

96
        if (mSkin->getOption("highlightUnderline") != 0)
120
18
            mHighlightMode |= LinkHighlightMode::UNDERLINE;
121
    }
122
123
72
    readColor(BLACK);
124
72
    readColor(RED);
125
72
    readColor(GREEN);
126
72
    readColor(BLUE);
127
72
    readColor(ORANGE);
128
72
    readColor(YELLOW);
129
72
    readColor(PINK);
130
72
    readColor(PURPLE);
131
72
    readColor(GRAY);
132
72
    readColor(BROWN);
133
134
48
    mForegroundColor = getThemeColor(ThemeColorId::BROWSERBOX, 255U);
135
48
    mForegroundColor2 = getThemeColor(ThemeColorId::BROWSERBOX_OUTLINE, 255U);
136
24
}
137
138
144
StaticBrowserBox::~StaticBrowserBox()
139
{
140
24
    if (gui != nullptr)
141
24
        gui->removeDragged(this);
142
143
24
    if (theme != nullptr)
144
    {
145
24
        theme->unload(mSkin);
146
24
        mSkin = nullptr;
147
    }
148
149
24
    mInstances --;
150
24
    if (mInstances == 0)
151
    {
152
20
        if (mEmotes != nullptr)
153
        {
154
20
            mEmotes->decRef();
155
20
            mEmotes = nullptr;
156
        }
157
    }
158
48
}
159
160
20
void StaticBrowserBox::setLinkHandler(LinkHandler* linkHandler)
161
{
162
20
    mLinkHandler = linkHandler;
163
20
}
164
165
void StaticBrowserBox::addSeparator(const std::string &row)
166
{
167
    if (mSeparator)
168
        return;
169
    addRow(row, false);
170
    mSeparator = true;
171
}
172
173
100
void StaticBrowserBox::addRow(const std::string &row,
174
                              const bool atTop)
175
{
176
200
    std::string tmp = row;
177
200
    std::string newRow;
178
    size_t idx1;
179
100
    const Font *const font = getFont();
180
100
    int linksCount = 0;
181
182
200
    if (getWidth() < 0)
183
        return;
184
185
100
    mSeparator = false;
186
187
100
    if (mProcessVars)
188
    {
189
4
        BrowserBoxTools::replaceVars(tmp);
190
    }
191
192
    // Use links and user defined colors
193
100
    if (mUseLinksAndUserColors)
194
    {
195
200
        BrowserLink bLink;
196
197
        // Check for links in format "@@link|[email protected]@"
198
200
        const uint32_t sz = CAST_U32(mTextRows.size());
199
200
100
        if (mEnableKeys)
201
        {
202
            BrowserBoxTools::replaceKeys(tmp);
203
        }
204
205
100
        idx1 = tmp.find("@@");
206
184
        while (idx1 != std::string::npos)
207
        {
208
62
            const size_t idx2 = tmp.find('|', idx1);
209
62
            const size_t idx3 = tmp.find("@@", idx2);
210
211
62
            if (idx2 == std::string::npos || idx3 == std::string::npos)
212
                break;
213
84
            bLink.link = tmp.substr(idx1 + 2, idx2 - (idx1 + 2));
214
84
            bLink.caption = tmp.substr(idx2 + 1, idx3 - (idx2 + 1));
215
42
            bLink.y1 = CAST_S32(sz) * font->getHeight();
216
42
            bLink.y2 = bLink.y1 + font->getHeight();
217
42
            if (bLink.caption.empty())
218
            {
219
4
                bLink.caption = BrowserBoxTools::replaceLinkCommands(
220
                    bLink.link);
221
2
                if (translator != nullptr)
222
                    bLink.caption = translator->getStr(bLink.caption);
223
            }
224
225
126
            newRow.append(tmp.substr(0, idx1));
226
227
84
            std::string tmp2 = newRow;
228
42
            idx1 = tmp2.find("##");
229
54
            while (idx1 != std::string::npos)
230
            {
231
6
                tmp2.erase(idx1, 3);
232
6
                idx1 = tmp2.find("##");
233
            }
234
42
            bLink.x1 = font->getWidth(tmp2) - 1;
235
42
            bLink.x2 = bLink.x1 + font->getWidth(bLink.caption) + 1;
236
237
42
            if (atTop)
238
                mLinks.insert(mLinks.begin(), bLink);
239
            else
240
42
                mLinks.push_back(bLink);
241
42
            linksCount ++;
242
243
84
            newRow.append("##<").append(bLink.caption);
244
245
42
            tmp.erase(0, idx3 + 2);
246
42
            if (!tmp.empty())
247
6
                newRow.append("##>");
248
249
42
            idx1 = tmp.find("@@");
250
        }
251
252
100
        newRow.append(tmp);
253
    }
254
    // Don't use links and user defined colors
255
    else
256
    {
257
        newRow = row;
258
    }
259
260
100
    if (mEnableTabs)
261
    {
262
4
        BrowserBoxTools::replaceTabs(newRow);
263
    }
264
265
100
    if (atTop)
266
    {
267
        mTextRows.push_front(newRow);
268
        mTextRowLinksCount.push_front(linksCount);
269
    }
270
    else
271
    {
272
100
        mTextRows.push_back(newRow);
273
100
        mTextRowLinksCount.push_back(linksCount);
274
    }
275
276
300
    std::string plain = STD_MOVE(newRow);
277
    // workaround if used only one string started from bold
278
    // width for this string can be calculated wrong
279
    // this workaround fix width if string start from bold sign
280
100
    const bool startBold = (plain.find("##B") == 0);
281
210
    for (idx1 = plain.find("##");
282
210
         idx1 != std::string::npos;
283
         idx1 = plain.find("##"))
284
    {
285
110
        plain.erase(idx1, 3);
286
    }
287
288
    // Adjust the StaticBrowserBox size. This need only for implementing "---"
289

200
    const int w = startBold ?
290
200
        boldFont->getWidth(plain) : font->getWidth(plain) + 2 * mPadding;
291
200
    if (w > getWidth())
292
18
        setWidth(w);
293
}
294
295
2
void StaticBrowserBox::addRow(const std::string &cmd,
296
                              const char *const text)
297
{
298

12
    addRow(strprintf("@@%s|%[email protected]@", encodeLinkText(cmd).c_str(),
299

10
        encodeLinkText(text).c_str()),
300
        false);
301
2
}
302
303
void StaticBrowserBox::addImage(const std::string &path)
304
{
305
    if (!mEnableImages)
306
        return;
307
308
    mTextRows.push_back("~~~" + path);
309
    mTextRowLinksCount.push_back(0);
310
}
311
312
2
void StaticBrowserBox::clearRows()
313
{
314
4
    mTextRows.clear();
315
4
    mTextRowLinksCount.clear();
316
4
    mLinks.clear();
317
2
    setWidth(0);
318
2
    setHeight(0);
319
2
    mSelectedLink = -1;
320
2
}
321
322
void StaticBrowserBox::mousePressed(MouseEvent &event)
323
{
324
    if (mLinkHandler == nullptr)
325
        return;
326
327
    const LinkIterator i = std::find_if(mLinks.begin(), mLinks.end(),
328
        MouseOverLink(event.getX(), event.getY()));
329
330
    if (i != mLinks.end())
331
    {
332
        mLinkHandler->handleLink(i->link, &event);
333
        event.consume();
334
    }
335
}
336
337
void StaticBrowserBox::mouseMoved(MouseEvent &event)
338
{
339
    const LinkIterator i = std::find_if(mLinks.begin(), mLinks.end(),
340
        MouseOverLink(event.getX(), event.getY()));
341
342
    mSelectedLink = (i != mLinks.end())
343
        ? CAST_S32(i - mLinks.begin()) : -1;
344
}
345
346
void StaticBrowserBox::mouseExited(MouseEvent &event A_UNUSED)
347
{
348
    mSelectedLink = -1;
349
}
350
351
4
void StaticBrowserBox::draw(Graphics *const graphics)
352
{
353
    BLOCK_START("StaticBrowserBox::draw")
354
4
    const ClipRect &cr = graphics->getTopClip();
355
4
    mYStart = cr.y - cr.yOffset;
356
4
    const int yEnd = mYStart + cr.height;
357
4
    if (mYStart < 0)
358
        mYStart = 0;
359
360
4
    if (mDimension.width != mWidth)
361
    {
362
        updateHeight();
363
        reportAlways("browserbox resize in draw: %d, %d",
364
            mDimension.width,
365
            mWidth);
366
    }
367
368
4
    if (mOpaque == Opaque_true)
369
    {
370
        graphics->setColor(mBackgroundColor);
371
        graphics->fillRectangle(Rect(0, 0,
372
            mDimension.width, mDimension.height));
373
    }
374
375

4
    if (mSelectedLink >= 0 &&
376
        mSelectedLink < CAST_S32(mLinks.size()))
377
    {
378
        if ((mHighlightMode & LinkHighlightMode::BACKGROUND) != 0u)
379
        {
380
            BrowserLink &link = mLinks[CAST_SIZE(mSelectedLink)];
381
            graphics->setColor(mHighlightColor);
382
            graphics->fillRectangle(Rect(
383
                link.x1,
384
                link.y1,
385
                link.x2 - link.x1,
386
                link.y2 - link.y1));
387
        }
388
389
        if ((mHighlightMode & LinkHighlightMode::UNDERLINE) != 0u)
390
        {
391
            BrowserLink &link = mLinks[CAST_SIZE(mSelectedLink)];
392
            graphics->setColor(mHyperLinkColor);
393
            graphics->drawLine(
394
                link.x1,
395
                link.y2,
396
                link.x2,
397
                link.y2);
398
        }
399
    }
400
401
4
    Font *const font = getFont();
402
403
24
    FOR_EACH (LinePartCIter, i, mLineParts)
404
    {
405
2
        const LinePart &part = *i;
406
2
        if (part.mY + 50 < mYStart)
407
            continue;
408
2
        if (part.mY > yEnd)
409
            break;
410
        if (part.mType == 0u)
411
        {
412
            if (part.mBold)
413
            {
414
                boldFont->drawString(graphics,
415
                    part.mColor,
416
                    part.mColor2,
417
                    part.mText,
418
                    part.mX, part.mY);
419
            }
420
            else
421
            {
422
                font->drawString(graphics,
423
                    part.mColor,
424
                    part.mColor2,
425
                    part.mText,
426
                    part.mX, part.mY);
427
            }
428
        }
429
        else if (part.mImage != nullptr)
430
        {
431
            graphics->drawImage(part.mImage, part.mX, part.mY);
432
        }
433
    }
434
435
    BLOCK_END("StaticBrowserBox::draw")
436
4
}
437
438
void StaticBrowserBox::safeDraw(Graphics *const graphics)
439
{
440
    StaticBrowserBox::draw(graphics);
441
}
442
443
4
void StaticBrowserBox::updateHeight()
444
{
445
4
    unsigned int y = CAST_U32(mPadding);
446
4
    int moreHeight = 0;
447
4
    int link = 0;
448
4
    bool bold = false;
449
4
    const unsigned int wWidth = CAST_U32(mDimension.width - mPadding);
450
4
    const Font *const font = getFont();
451
4
    const int fontHeight = font->getHeight() + 2 * mItemPadding;
452

16
    const int fontWidthMinus = font->getWidth("-");
453
454
4
    Color selColor[2] = {mForegroundColor, mForegroundColor2};
455
4
    const Color textColor[2] = {mForegroundColor, mForegroundColor2};
456
8
    mLineParts.clear();
457
4
    uint32_t dataWidth = 0;
458
459
4
    if (mSeparator)
460
    {
461
        mSeparator = false;
462
        mTextRows.pop_back();
463
    }
464
465
20
    FOR_EACH (TextRowCIter, i, mTextRows)
466
    {
467
8
        unsigned int x = CAST_U32(mPadding);
468
24
        const std::string row = *(i);
469
8
        int objects = 0;
470
471
        // Check for separator lines
472
8
        if (row.find("---", 0) == 0)
473
        {
474
            const int dashWidth = fontWidthMinus;
475
            for (x = CAST_U32(mPadding); x < wWidth; x ++)
476
            {
477
                mLineParts.push_back(LinePart(CAST_S32(x),
478
                    CAST_S32(y) + mItemPadding,
479
                    selColor[0], selColor[1], "-", false));
480
                x += CAST_U32(CAST_S32(
481
                    dashWidth) - 2);
482
            }
483
484
            y += CAST_U32(fontHeight);
485
            continue;
486
        }
487

8
        else if (mEnableImages && row.find("~~~", 0) == 0)
488
        {
489
            std::string str = row.substr(3);
490
            const size_t sz = str.size();
491
            if (sz > 2 && str.substr(sz - 1) == "~")
492
                str = str.substr(0, sz - 1);
493
            Image *const img = Loader::getImage(str);
494
            if (img != nullptr)
495
            {
496
                img->incRef();
497
                mLineParts.push_back(LinePart(CAST_S32(x),
498
                    CAST_S32(y) + mItemPadding,
499
                    selColor[0], selColor[1], img));
500
                y += CAST_U32(img->getHeight() + 2);
501
                moreHeight += img->getHeight();
502
                if (img->getWidth() + mPadding + 2 > CAST_S32(dataWidth))
503
                    dataWidth = img->getWidth() + 2 + mPadding;
504
            }
505
            continue;
506
        }
507
508
        Color prevColor[2];
509
        prevColor[0] = selColor[0];
510
        prevColor[1] = selColor[1];
511
        bold = false;
512
513
6
        for (size_t start = 0, end = std::string::npos;
514
14
             start != std::string::npos;
515
6
             start = end, end = std::string::npos)
516
        {
517
8
            size_t idx1 = end;
518
8
            size_t idx2 = end;
519
520
            // "Tokenize" the string at control sequences
521
8
            if (mUseLinksAndUserColors)
522
16
                idx1 = row.find("##", start + 1);
523

8
            if (start == 0 || mUseLinksAndUserColors)
524
            {
525
                // Check for color change in format "##x", x = [L,P,0..9]
526

8
                if (row.find("##", start) == start && row.size() > start + 2)
527
                {
528
8
                    const signed char c = row.at(start + 2);
529
530
4
                    bool valid(false);
531
                    const Color col[2] =
532
                    {
533
8
                        getThemeCharColor(c, valid),
534
                        getThemeCharColor(CAST_S8(
535
8
                            c | 0x80), valid)
536
8
                    };
537
538
4
                    if (c == '>')
539
                    {
540
                        selColor[0] = prevColor[0];
541
                        selColor[1] = prevColor[1];
542
                    }
543
4
                    else if (c == '<')
544
                    {
545
                        prevColor[0] = selColor[0];
546
                        prevColor[1] = selColor[1];
547
                        selColor[0] = col[0];
548
                        selColor[1] = col[1];
549
                    }
550
2
                    else if (c == 'B')
551
                    {
552
                        bold = true;
553
                    }
554
                    else if (c == 'b')
555
                    {
556
                        bold = false;
557
                    }
558
                    else if (valid)
559
                    {
560
                        selColor[0] = col[0];
561
                        selColor[1] = col[1];
562
                    }
563
                    else
564
                    {
565
                        switch (c)
566
                        {
567
                            case '0':
568
                                selColor[0] = mColors[0][ColorName::BLACK];
569
                                selColor[1] = mColors[1][ColorName::BLACK];
570
                                break;
571
                            case '1':
572
                                selColor[0] = mColors[0][ColorName::RED];
573
                                selColor[1] = mColors[1][ColorName::RED];
574
                                break;
575
                            case '2':
576
                                selColor[0] = mColors[0][ColorName::GREEN];
577
                                selColor[1] = mColors[1][ColorName::GREEN];
578
                                break;
579
                            case '3':
580
                                selColor[0] = mColors[0][ColorName::BLUE];
581
                                selColor[1] = mColors[1][ColorName::BLUE];
582
                                break;
583
                            case '4':
584
                                selColor[0] = mColors[0][ColorName::ORANGE];
585
                                selColor[1] = mColors[1][ColorName::ORANGE];
586
                                break;
587
                            case '5':
588
                                selColor[0] = mColors[0][ColorName::YELLOW];
589
                                selColor[1] = mColors[1][ColorName::YELLOW];
590
                                break;
591
                            case '6':
592
                                selColor[0] = mColors[0][ColorName::PINK];
593
                                selColor[1] = mColors[1][ColorName::PINK];
594
                                break;
595
                            case '7':
596
                                selColor[0] = mColors[0][ColorName::PURPLE];
597
                                selColor[1] = mColors[1][ColorName::PURPLE];
598
                                break;
599
                            case '8':
600
                                selColor[0] = mColors[0][ColorName::GRAY];
601
                                selColor[1] = mColors[1][ColorName::GRAY];
602
                                break;
603
                            case '9':
604
                                selColor[0] = mColors[0][ColorName::BROWN];
605
                                selColor[1] = mColors[1][ColorName::BROWN];
606
                                break;
607
                            default:
608
                                selColor[0] = textColor[0];
609
                                selColor[1] = textColor[1];
610
                                break;
611
                        }
612
                    }
613
614

6
                    if (c == '<' && link < CAST_S32(mLinks.size()))
615
                    {
616
                        int size;
617
2
                        if (bold)
618
                        {
619
                            size = boldFont->getWidth(
620
                                mLinks[CAST_SIZE(link)].caption) + 1;
621
                        }
622
                        else
623
                        {
624
2
                            size = font->getWidth(
625
4
                                mLinks[CAST_SIZE(link)].caption) + 1;
626
                        }
627
628
                        BrowserLink &linkRef = mLinks[CAST_SIZE(
629
4
                            link)];
630
2
                        linkRef.x1 = CAST_S32(x);
631
2
                        linkRef.y1 = CAST_S32(y);
632
2
                        linkRef.x2 = linkRef.x1 + size;
633
2
                        linkRef.y2 = CAST_S32(y) + fontHeight - 1;
634
2
                        link++;
635
                    }
636
637
4
                    start += 3;
638
4
                    if (start == row.size())
639
                        break;
640
                }
641
            }
642
8
            if (mUseEmotes)
643
16
                idx2 = row.find("%%", start + 1);
644
8
            if (idx1 < idx2)
645
                end = idx1;
646
            else
647
8
                end = idx2;
648
8
            if (mUseEmotes)
649
            {
650
                // check for emote icons
651


22
                if (row.size() > start + 2 && row.substr(start, 2) == "%%")
652
                {
653
                    if (objects < 5)
654
                    {
655
                        const int cid = row.at(start + 2) - '0';
656
                        if (cid >= 0)
657
                        {
658
                            if (mEmotes != nullptr)
659
                            {
660
                                const size_t sz = mEmotes->size();
661
                                if (CAST_SIZE(cid) < sz)
662
                                {
663
                                    Image *const img = mEmotes->get(
664
                                        CAST_SIZE(cid));
665
                                    if (img != nullptr)
666
                                    {
667
                                        mLineParts.push_back(LinePart(
668
                                            CAST_S32(x),
669
                                            CAST_S32(y) + mItemPadding,
670
                                            selColor[0], selColor[1], img));
671
                                        x += 18;
672
                                    }
673
                                }
674
                            }
675
                        }
676
                        objects ++;
677
                    }
678
679
                    start += 3;
680
                    if (start == row.size())
681
                    {
682
                        if (x > dataWidth)
683
                            dataWidth = x;
684
                        break;
685
                    }
686
                }
687
            }
688
8
            const size_t len = (end == std::string::npos) ? end : end - start;
689
690
8
            if (start >= row.length())
691
                break;
692
693
12
            std::string part = row.substr(start, len);
694
695
48
            mLineParts.push_back(LinePart(CAST_S32(x),
696
6
                CAST_S32(y) + mItemPadding,
697
                selColor[0], selColor[1], part.c_str(), bold));
698
699
6
            int width = 0;
700
6
            if (bold)
701
2
                width = boldFont->getWidth(part);
702
            else
703
4
                width = font->getWidth(part);
704
705
6
            x += CAST_U32(width);
706
6
            if (x > dataWidth)
707
4
                dataWidth = x;
708
        }
709
8
        y += CAST_U32(fontHeight);
710
    }
711
4
    mWidth = dataWidth + mPadding;
712
12
    mHeight = CAST_S32(mTextRows.size())
713
4
        * fontHeight + moreHeight + 2 * mPadding;
714
4
    setSize(mWidth,
715
        mHeight);
716
4
}
717
718
std::string StaticBrowserBox::getTextAtPos(const int x,
719
                                           const int y) const
720
{
721
    int textX = 0;
722
    int textY = 0;
723
724
    getAbsolutePosition(textX, textY);
725
    if (x < textX || y < textY)
726
        return std::string();
727
728
    textY = y - textY;
729
    std::string str;
730
    int lastY = 0;
731
732
    FOR_EACH (LinePartCIter, i, mLineParts)
733
    {
734
        const LinePart &part = *i;
735
        if (part.mY + 50 < mYStart)
736
            continue;
737
        if (part.mY > textY)
738
            break;
739
740
        if (part.mY > lastY)
741
        {
742
            str = part.mText;
743
            lastY = part.mY;
744
        }
745
        else
746
        {
747
            str.append(part.mText);
748
        }
749
    }
750
751
    return str;
752
}
753
754
2
void StaticBrowserBox::setForegroundColorAll(const Color &color1,
755
                                             const Color &color2)
756
{
757
2
    mForegroundColor = color1;
758
2
    mForegroundColor2 = color2;
759
2
}
760
761
void StaticBrowserBox::moveSelectionUp()
762
{
763
    if (mSelectedLink <= 0)
764
        mSelectedLink = CAST_S32(mLinks.size()) - 1;
765
    else
766
        mSelectedLink --;
767
}
768
769
void StaticBrowserBox::moveSelectionDown()
770
{
771
    mSelectedLink ++;
772
    if (mSelectedLink >= static_cast<signed int>(mLinks.size()))
773
        mSelectedLink = 0;
774
}
775
776
void StaticBrowserBox::selectSelection()
777
{
778
    if ((mLinkHandler == nullptr) ||
779
        mSelectedLink < 0 ||
780
        mSelectedLink >= static_cast<signed int>(mLinks.size()))
781
    {
782
        return;
783
    }
784
785
    mLinkHandler->handleLink(mLinks[CAST_SIZE(mSelectedLink)].link,
786
        nullptr);
787
}