Subversion Repositories tpanel

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 andreas 1
/*
258 andreas 2
 * Copyright (C) 2020 to 2023 by Andreas Theofilu <andreas@theosys.at>
2 andreas 3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software Foundation,
16
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
17
 */
18
 
19
#include <sys/types.h>
20
#include <sys/stat.h>
21
#include <unistd.h>
368 andreas 22
#ifdef __ANDROID__
23
#include <android/log.h>
24
#endif
55 andreas 25
 
26
#include <include/core/SkFont.h>
27
#include <include/core/SkFontMetrics.h>
28
#include <include/core/SkTextBlob.h>
29
 
365 andreas 30
#include "tlock.h"
5 andreas 31
#include "tresources.h"
26 andreas 32
#include "tpagemanager.h"
2 andreas 33
#include "tpage.h"
66 andreas 34
#include "tdrawimage.h"
76 andreas 35
#include "texpat++.h"
211 andreas 36
#include "tconfig.h"
303 andreas 37
#include "terror.h"
343 andreas 38
#if TESTMODE == 1
39
#include "testmode.h"
40
#endif
2 andreas 41
 
186 andreas 42
#if __cplusplus < 201402L
43
#   error "This module requires at least C++14 standard!"
44
#else
45
#   if __cplusplus < 201703L
46
#       include <experimental/filesystem>
47
namespace fs = std::experimental::filesystem;
48
#       warning "Support for C++14 and experimental filesystem will be removed in a future version!"
49
#   else
50
#       include <filesystem>
51
#       ifdef __ANDROID__
52
namespace fs = std::__fs::filesystem;
53
#       else
54
namespace fs = std::filesystem;
55
#       endif
56
#   endif
57
#endif
58
 
3 andreas 59
using std::string;
55 andreas 60
using std::vector;
151 andreas 61
using std::map;
62
using std::pair;
3 andreas 63
using namespace Button;
76 andreas 64
using namespace Expat;
3 andreas 65
 
26 andreas 66
extern TPageManager *gPageManager;
67
 
3 andreas 68
TPage::TPage(const string& name)
2 andreas 69
{
3 andreas 70
    DECL_TRACER("TPage::TPage(const string& name)");
14 andreas 71
    TError::clear();
38 andreas 72
 
73
    if (gPageManager)
74
    {
75
        if (!_setBackground)
76
            _setBackground = gPageManager->getCallbackBG();
77
 
78
        if (!_displayButton)
79
            _displayButton = gPageManager->getCallbackDB();
80
 
81
        if (!_callDropPage)
82
            _callDropPage = gPageManager->getCallDropPage();
83
 
84
        if (!_callDropSubPage)
85
            _callDropSubPage = gPageManager->getCallDropSubPage();
86
 
87
        if (!_playVideo)
88
            _playVideo = gPageManager->getCallbackPV();
89
    }
90
 
43 andreas 91
    if (name.compare("_progress") == 0)
92
    {
93
        addProgress();
94
        return ;
95
    }
96
 
3 andreas 97
    initialize(name);
98
}
2 andreas 99
 
3 andreas 100
TPage::~TPage()
101
{
5 andreas 102
    DECL_TRACER("TPage::~TPage()");
103
 
201 andreas 104
    MSG_DEBUG("Destroing page " << mPage.pageID << ": " << mPage.name);
105
    BUTTONS_T *p = getButtons();
3 andreas 106
    BUTTONS_T *next = nullptr;
2 andreas 107
 
3 andreas 108
    while (p)
109
    {
110
        next = p->next;
111
        delete p->button;
112
        delete p;
113
        p = next;
114
    }
2 andreas 115
 
201 andreas 116
    setButtons(nullptr);
349 andreas 117
    mSubPages.clear();
118
/*
3 andreas 119
    PAGECHAIN_T *pc = mSubPages;
120
    PAGECHAIN_T *pc_next = nullptr;
121
 
122
    // We're not allowd to delete the subpages here, because they're managed
123
    // by the TPageManager.
124
    while (pc)
125
    {
126
        pc_next = pc->next;
127
        delete pc;
128
        pc = pc_next;
129
    }
130
 
131
    mSubPages = nullptr;
349 andreas 132
*/
3 andreas 133
}
134
 
135
void TPage::initialize(const string& nm)
136
{
137
    DECL_TRACER("TPage::initialize(const string& name)");
138
 
197 andreas 139
    string projectPath = ((gPageManager && gPageManager->isSetupActive()) ? TConfig::getSystemProjectPath() : TConfig::getProjectPath());
186 andreas 140
 
141
    if (!fs::exists(projectPath + "/prj.xma"))
197 andreas 142
    {
143
        MSG_ERROR("Directory " << projectPath << " doesn't exist!");
144
        return;
145
    }
186 andreas 146
 
147
    makeFileName(projectPath, nm);
148
 
194 andreas 149
    MSG_DEBUG("Using path: " << projectPath << " and file: " << nm);
150
 
3 andreas 151
    if (isValidFile())
152
        mPath = getFileName();
153
 
76 andreas 154
    TExpat xml(mPath);
155
    xml.setEncoding(ENC_CP1250);
3 andreas 156
 
76 andreas 157
    if (!xml.parse())
3 andreas 158
        return;
159
 
76 andreas 160
    int depth = 0;
161
    size_t index = 0;
162
    size_t oldIndex = 0;
163
    vector<ATTRIBUTE_t> attrs;
3 andreas 164
 
76 andreas 165
    if ((index = xml.getElementIndex("page", &depth)) == TExpat::npos)
3 andreas 166
    {
167
        MSG_ERROR("Element \"page\" with attribute \"type\" was not found!");
168
        TError::setError();
169
        return;
170
    }
171
 
76 andreas 172
    attrs = xml.getAttributes();
173
    string type = xml.getAttribute("type", attrs);
3 andreas 174
 
175
    if (type.compare("page") != 0)
176
    {
177
        MSG_ERROR("Invalid page type \"" << type << "\"!");
178
        TError::setError();
179
        return;
180
    }
181
 
76 andreas 182
    depth++;
183
    string ename, content;
3 andreas 184
 
76 andreas 185
    while ((index = xml.getNextElementFromIndex(index, &ename, &content, &attrs)) != TExpat::npos)
3 andreas 186
    {
76 andreas 187
        string e = ename;
3 andreas 188
 
189
        if (e.compare("pageID") == 0)
201 andreas 190
            mPage.pageID = xml.convertElementToInt(content);
3 andreas 191
        else if (e.compare("name") == 0)
201 andreas 192
            mPage.name = content;
3 andreas 193
        else if (e.compare("width") == 0)
201 andreas 194
            mPage.width = xml.convertElementToInt(content);
3 andreas 195
        else if (e.compare("height") == 0)
201 andreas 196
            mPage.height = xml.convertElementToInt(content);
3 andreas 197
        else if (e.compare("button") == 0)
198
        {
199
            TButton *button = new TButton();
204 andreas 200
            TPageInterface::registerListCallback<TPage>(button, this);
198 andreas 201
 
4 andreas 202
            button->setPalette(mPalette);
201 andreas 203
            button->setFonts(getFonts());
7 andreas 204
            button->registerCallback(_displayButton);
21 andreas 205
            button->regCallPlayVideo(_playVideo);
76 andreas 206
            index = button->initialize(&xml, index);
201 andreas 207
            button->setParentSize(mPage.width, mPage.height);
3 andreas 208
 
209
            if (TError::isError())
210
            {
23 andreas 211
                MSG_WARNING("Button \"" << button->getButtonName() << "\" deleted because of an error!");
3 andreas 212
                delete button;
213
                return;
214
            }
215
 
201 andreas 216
            button->setHandle(((mPage.pageID << 16) & 0xffff0000) | button->getButtonIndex());
14 andreas 217
            button->createButtons();
3 andreas 218
            addButton(button);
76 andreas 219
            index++;        // Jump over the end tag of the button.
3 andreas 220
        }
221
        else if (e.compare("sr") == 0)
222
        {
223
            SR_T bsr;
76 andreas 224
            bsr.number = xml.getAttributeInt("number", attrs);
225
            index++;
3 andreas 226
 
76 andreas 227
            while ((index = xml.getNextElementFromIndex(index, &ename, &content, &attrs)) != TExpat::npos)
3 andreas 228
            {
229
                if (ename.compare("bs") == 0)
76 andreas 230
                    bsr.bs = content;
3 andreas 231
                else if (ename.compare("cb") == 0)
76 andreas 232
                    bsr.cb = content;
3 andreas 233
                else if (ename.compare("cf") == 0)
76 andreas 234
                    bsr.cf = content;
3 andreas 235
                else if (ename.compare("ct") == 0)
76 andreas 236
                    bsr.ct = content;
3 andreas 237
                else if (ename.compare("ec") == 0)
76 andreas 238
                    bsr.ec = content;
3 andreas 239
                else if (ename.compare("bm") == 0)
76 andreas 240
                    bsr.bm = content;
65 andreas 241
                else if (ename.compare("mi") == 0)
76 andreas 242
                    bsr.mi = content;
3 andreas 243
                else if (ename.compare("fi") == 0)
76 andreas 244
                    bsr.fi = xml.convertElementToInt(content);
55 andreas 245
                else if (ename.compare("te") == 0)
76 andreas 246
                    bsr.te = content;
55 andreas 247
                else if (ename.compare("tx") == 0)
76 andreas 248
                    bsr.tx = xml.convertElementToInt(content);
55 andreas 249
                else if (ename.compare("ty") == 0)
76 andreas 250
                    bsr.ty = xml.convertElementToInt(content);
55 andreas 251
                else if (ename.compare("et") == 0)
76 andreas 252
                    bsr.et = xml.convertElementToInt(content);
55 andreas 253
                else if (ename.compare("ww") == 0)
76 andreas 254
                    bsr.ww = xml.convertElementToInt(content);
55 andreas 255
                else if (ename.compare("jt") == 0)
76 andreas 256
                    bsr.jt = (Button::TEXT_ORIENTATION)xml.convertElementToInt(content);
65 andreas 257
                else if (ename.compare("jb") == 0)
76 andreas 258
                    bsr.jb = (Button::TEXT_ORIENTATION)xml.convertElementToInt(content);
3 andreas 259
 
76 andreas 260
                oldIndex = index;
3 andreas 261
            }
262
 
263
            sr.push_back(bsr);
76 andreas 264
 
265
            if (index == TExpat::npos)
266
                index = oldIndex + 1;
3 andreas 267
        }
76 andreas 268
    }
3 andreas 269
 
204 andreas 270
    setSR(sr);
349 andreas 271
/*
76 andreas 272
    if (TStreamError::checkFilter(HLOG_DEBUG))
273
    {
201 andreas 274
        MSG_DEBUG("PageID: " << mPage.pageID);
275
        MSG_DEBUG("Name  : " << mPage.name);
276
        MSG_DEBUG("Width : " << mPage.width);
277
        MSG_DEBUG("Height: " << mPage.height);
76 andreas 278
 
279
        vector<SR_T>::iterator iter;
280
        size_t pos = 1;
281
 
282
        for (iter = sr.begin(); iter != sr.end(); ++iter)
283
        {
284
            MSG_DEBUG("   " << pos << ": bs: " << iter->bs);
285
            MSG_DEBUG("   " << pos << ": cb: " << iter->cb);
286
            MSG_DEBUG("   " << pos << ": cf: " << iter->cf);
287
            MSG_DEBUG("   " << pos << ": ct: " << iter->ct);
288
            MSG_DEBUG("   " << pos << ": ec: " << iter->ec);
289
            MSG_DEBUG("   " << pos << ": bm: " << iter->bm);
290
            MSG_DEBUG("   " << pos << ": mi: " << iter->mi);
291
            MSG_DEBUG("   " << pos << ": fi: " << iter->fi);
292
            pos++;
293
        }
3 andreas 294
    }
349 andreas 295
*/
203 andreas 296
    if (TPageInterface::getButtons())
76 andreas 297
        sortButtons();
3 andreas 298
}
199 andreas 299
 
43 andreas 300
void TPage::addProgress()
301
{
302
    DECL_TRACER("TPage::addProgress()");
303
 
304
    if (!gPageManager)
305
    {
306
        MSG_WARNING("The page manager is still not initialized!");
307
        return;
308
    }
309
 
310
    Button::SR_T bsr;
201 andreas 311
    mPage.pageID = 300;
312
    mPage.name = "_progress";
217 andreas 313
    mPage.width = gPageManager->getSettings()->getWidth();
201 andreas 314
    mPage.height = gPageManager->getSettings()->getHeight();
315
    double unit = (double)mPage.height / 10.0;
43 andreas 316
    MSG_DEBUG("One unit is " << unit);
317
    // Background of page
318
    bsr.number = 1;
319
    bsr.cf = "#106010ff";
320
    bsr.ct = "#ffffffff";
321
    bsr.cb = "#009000ff";
322
    bsr.ec = "#ffffffff";
323
    bsr.fi = 21;
324
    sr.push_back(bsr);
325
    // Text field 1 to show status messages
326
    Button::EXTBUTTON_t bt;
195 andreas 327
    bt.type = GENERAL;
43 andreas 328
    bt.bi = 1;
329
    bt.na = "Line1";
330
    bt.tp = (int)(unit * 2.0);
201 andreas 331
    bt.lt = (int)(((double)mPage.width - ((double)mPage.width / 100.0 * 80.0)) / 2.0);
332
    bt.wt = (int)((double)mPage.width / 100.0 * 80.0);    // Line take 80% of available width
43 andreas 333
    bt.ht = (int)(unit / 100.0 * 80.0);
334
    MSG_DEBUG("Dimensions button 1: lt: " << bt.lt << ", tp: " << bt.tp << ", wt: " << bt.wt << ", ht: " << bt.ht);
335
    bt.zo = 1;
336
    bt.ap = 0;
337
    bt.ad = 160;
338
    bsr.cf = "#000000ff";
339
    bt.sr.push_back(bsr);
340
    bsr.number = 2;
341
    bt.sr.push_back(bsr);
342
    TButton *button = new TButton();
343
    button->setPalette(mPalette);
201 andreas 344
    button->setFonts(getFonts());
43 andreas 345
    button->registerCallback(_displayButton);
346
    button->regCallPlayVideo(_playVideo);
347
    button->createSoftButton(bt);
201 andreas 348
    button->setParentSize(mPage.width, mPage.height);
43 andreas 349
 
350
    if (TError::isError())
351
    {
352
        MSG_WARNING("Button \"" << button->getButtonName() << "\" deleted because of an error!");
353
        delete button;
354
        return;
355
    }
356
 
201 andreas 357
    button->setHandle(((mPage.pageID << 16) & 0xffff0000) | bt.bi);
43 andreas 358
    button->createButtons();
359
    addButton(button);
360
    // Text field 2 to show status messages
361
    bt.bi = 2;
362
    bt.na = "Line2";
363
    bt.tp = (int)(unit * 7.0);
364
    MSG_DEBUG("Dimensions button 2: lt: " << bt.lt << ", tp: " << bt.tp << ", wt: " << bt.wt << ", ht: " << bt.ht);
365
    bt.zo = 2;
366
    bt.ad = 161;
367
    button = new TButton();
368
    button->setPalette(mPalette);
201 andreas 369
    button->setFonts(getFonts());
43 andreas 370
    button->registerCallback(_displayButton);
371
    button->regCallPlayVideo(_playVideo);
372
    button->createSoftButton(bt);
201 andreas 373
    button->setParentSize(mPage.width, mPage.height);
43 andreas 374
 
375
    if (TError::isError())
376
    {
377
        MSG_WARNING("Button \"" << button->getButtonName() << "\" deleted because of an error!");
378
        delete button;
379
        return;
380
    }
381
 
201 andreas 382
    button->setHandle(((mPage.pageID << 16) & 0xffff0000) | bt.bi);
43 andreas 383
    button->createButtons();
384
    addButton(button);
385
    // Progress bar 1 (overall status)
195 andreas 386
    bt.type = BARGRAPH;
43 andreas 387
    bt.bi = 3;
388
    bt.na = "Bar1";
389
    bt.tp = (int)(unit * 3.0);
201 andreas 390
    bt.lt = (int)(((double)mPage.width - ((double)mPage.width / 100.0 * 80.0)) / 2.0);
391
    bt.wt = (int)((double)mPage.width / 100.0 * 80.0);    // Line take 80% of available width
43 andreas 392
    bt.ht = (int)unit;
393
    MSG_DEBUG("Dimensions bargraph 1: lt: " << bt.lt << ", tp: " << bt.tp << ", wt: " << bt.wt << ", ht: " << bt.ht);
394
    bt.zo = 3;
395
    bt.ap = 0;
396
    bt.ad = 162;
397
    bt.lp = 0;
398
    bt.lv = 162;
399
    bt.rl = 1;
400
    bt.rh = 100;
401
    bt.sc = "#ffffffff";
402
    bt.dr = "horizontal";
403
    bsr.number = 1;
404
    bsr.cf = "#0e0e0eff";
405
    bsr.ct = "#ffffffff";
406
    bsr.cb = "#009000ff";
407
    bt.sr.clear();
408
    bt.sr.push_back(bsr);
409
    bsr.number = 2;
410
    bsr.cf = "#ffffffff";
411
    bt.sr.push_back(bsr);
412
    button = new TButton();
413
    button->setPalette(mPalette);
201 andreas 414
    button->setFonts(getFonts());
43 andreas 415
    button->registerCallback(_displayButton);
416
    button->regCallPlayVideo(_playVideo);
417
    button->createSoftButton(bt);
201 andreas 418
    button->setParentSize(mPage.width, mPage.height);
43 andreas 419
 
420
    if (TError::isError())
421
    {
422
        MSG_WARNING("Button \"" << button->getButtonName() << "\" deleted because of an error!");
423
        delete button;
424
        return;
425
    }
426
 
203 andreas 427
    button->setHandle(((mPage.pageID << 16) & 0xffff0000) | bt.bi);
43 andreas 428
    button->createButtons();
429
    addButton(button);
430
    // Progress bar 2 (details)
431
    bt.bi = 4;
432
    bt.na = "Bar2";
433
    bt.tp = (int)(unit * 5.0);
434
    MSG_DEBUG("Dimensions bargraph 2: lt: " << bt.lt << ", tp: " << bt.tp << ", wt: " << bt.wt << ", ht: " << bt.ht);
435
    bt.zo = 4;
436
    bt.ad = 163;
437
    bt.lv = 163;
438
    button = new TButton();
439
    button->setPalette(mPalette);
201 andreas 440
    button->setFonts(getFonts());
43 andreas 441
    button->registerCallback(_displayButton);
442
    button->regCallPlayVideo(_playVideo);
443
    button->createSoftButton(bt);
201 andreas 444
    button->setParentSize(mPage.width, mPage.height);
43 andreas 445
 
446
    if (TError::isError())
447
    {
448
        MSG_WARNING("Button \"" << button->getButtonName() << "\" deleted because of an error!");
449
        delete button;
450
        return;
451
    }
452
 
201 andreas 453
    button->setHandle(((mPage.pageID << 16) & 0xffff0000) | bt.bi);
43 andreas 454
    button->createButtons();
455
    addButton(button);
456
}
457
 
300 andreas 458
SkBitmap& TPage::getBgImage()
459
{
460
    DECL_TRACER("TPage::getBgImage()");
461
 
462
    if (!mBgImage.empty())
463
        return mBgImage;
464
 
465
    bool haveImage = false;
466
    MSG_DEBUG("Creating image for page " << mPage.pageID << ": " << mPage.name);
467
    SkBitmap target;
468
 
469
    if (!allocPixels(mPage.width, mPage.height, &target))
470
        return mBgImage;
471
 
472
    target.eraseColor(TColor::getSkiaColor(mPage.sr[0].cf));
473
    // Draw the background, if any
474
    if (mPage.sr.size() > 0 && (!mPage.sr[0].bm.empty() || !mPage.sr[0].mi.empty()))
475
    {
476
        TDrawImage dImage;
477
        dImage.setWidth(mPage.width);
478
        dImage.setHeight(mPage.height);
479
 
480
        if (!mPage.sr[0].bm.empty())
481
        {
482
            MSG_DEBUG("Loading image " << mPage.sr[0].bm);
483
            sk_sp<SkData> rawImage = readImage(mPage.sr[0].bm);
484
            SkBitmap bm;
485
 
486
            if (rawImage)
487
            {
488
                MSG_DEBUG("Decoding image BM ...");
489
 
490
                if (!DecodeDataToBitmap(rawImage, &bm))
491
                {
492
                    MSG_WARNING("Problem while decoding image " << mPage.sr[0].bm);
493
                }
494
                else if (!bm.empty())
495
                {
496
                    dImage.setImageBm(bm);
497
                    SkImageInfo info = bm.info();
498
                    mPage.sr[0].bm_width = info.width();
499
                    mPage.sr[0].bm_height = info.height();
500
                    haveImage = true;
501
                }
502
                else
503
                {
504
                    MSG_WARNING("BM image " << mPage.sr[0].bm << " seems to be empty!");
505
                }
506
            }
507
        }
508
 
509
        if (!mPage.sr[0].mi.empty())
510
        {
511
            MSG_DEBUG("Loading image " << mPage.sr[0].mi);
512
            sk_sp<SkData> rawImage = readImage(mPage.sr[0].mi);
513
            SkBitmap mi;
514
 
515
            if (rawImage)
516
            {
517
                MSG_DEBUG("Decoding image MI ...");
518
 
519
                if (!DecodeDataToBitmap(rawImage, &mi))
520
                {
521
                    MSG_WARNING("Problem while decoding image " << mPage.sr[0].mi);
522
                }
523
                else if (!mi.empty())
524
                {
525
                    dImage.setImageMi(mi);
526
                    SkImageInfo info = mi.info();
527
                    mPage.sr[0].mi_width = info.width();
528
                    mPage.sr[0].mi_height = info.height();
529
                    haveImage = true;
530
                }
531
                else
532
                {
533
                    MSG_WARNING("MI image " << mPage.sr[0].mi << " seems to be empty!");
534
                }
535
            }
536
        }
537
 
538
        if (haveImage)
539
        {
540
            dImage.setSr(mPage.sr);
541
 
542
            if (!dImage.drawImage(&target))
543
                return mBgImage;
544
 
545
            if (!mPage.sr[0].te.empty())
546
            {
547
                if (!drawText(mPage, &target))
548
                    return mBgImage;
549
            }
550
 
551
            if (mPage.sr[0].oo < 255 && mPage.sr[0].te.empty() && mPage.sr[0].bs.empty())
552
                setOpacity(&target, mPage.sr[0].oo);
553
 
554
#ifdef _SCALE_SKIA_
555
            size_t rowBytes = info.minRowBytes();
556
            size_t size = info.computeByteSize(rowBytes);
557
            SkImageInfo info = target.info();
558
 
559
            if (gPageManager && gPageManager->getScaleFactor() != 1.0)
560
            {
561
                SkPaint paint;
562
                int left, top;
563
 
564
                paint.setBlendMode(SkBlendMode::kSrc);
565
                paint.setFilterQuality(kHigh_SkFilterQuality);
566
                // Calculate new dimension
567
                double scaleFactor = gPageManager->getScaleFactor();
568
                MSG_DEBUG("Using scale factor " << scaleFactor);
569
                int lwidth = (int)((double)info.width() * scaleFactor);
570
                int lheight = (int)((double)info.height() * scaleFactor);
571
                int twidth = (int)((double)mPage.width * scaleFactor);
572
                int theight = (int)((double)mPage.height * scaleFactor);
573
                calcPosition(lwidth, lheight, &left, &top);
574
                // Create a canvas and draw new image
575
                sk_sp<SkImage> im = SkImage::MakeFromBitmap(target);
576
 
577
                if (!allocPixels(twidth, theight, &target))
578
                    return;
579
 
580
                target.eraseColor(TColor::getSkiaColor(mPage.sr[0].cf));
581
                SkCanvas can(target, SkSurfaceProps());
582
                SkRect rect = SkRect::MakeXYWH(left, top, lwidth, lheight);
583
                can.drawImageRect(im, rect, &paint);
584
                MSG_DEBUG("Scaled size of background image: " << left << ", " << top << ", " << lwidth << ", " << lheight);
585
            }
586
#endif
587
        }
588
    }
589
 
590
    if (mPage.sr.size() > 0 && !mPage.sr[0].te.empty())
591
    {
592
        MSG_DEBUG("Drawing a text only on background image ...");
593
 
594
        if (drawText(mPage, &target))
595
            haveImage = true;
596
    }
597
 
598
    // Check for a frame and draw it if there is one.
599
    if (!mPage.sr[0].bs.empty())
600
    {
601
        if (drawFrame(mPage, &target))
602
            haveImage = true;
603
    }
604
 
605
    if (haveImage)
606
    {
607
        if (mPage.sr[0].oo < 255)
608
            setOpacity(&target, mPage.sr[0].oo);
609
 
610
        mBgImage = target;
611
    }
612
 
613
    return mBgImage;
614
}
615
 
5 andreas 616
void TPage::show()
617
{
618
    DECL_TRACER("TPage::show()");
365 andreas 619
    TLOCKER(mutex_init);
5 andreas 620
 
621
    if (!_setBackground)
622
    {
31 andreas 623
        if (gPageManager && gPageManager->getCallbackBG())
624
            _setBackground = gPageManager->getCallbackBG();
625
        else
626
        {
627
            MSG_WARNING("No callback \"setBackground\" was set!");
343 andreas 628
#if TESTMODE == 1
629
            setScreenDone();
630
#endif
31 andreas 631
            return;
632
        }
5 andreas 633
    }
634
 
217 andreas 635
    bool haveImage = false;
201 andreas 636
    ulong handle = (mPage.pageID << 16) & 0xffff0000;
637
    MSG_DEBUG("Processing page " << mPage.pageID);
66 andreas 638
    SkBitmap target;
254 andreas 639
 
640
    if (!allocPixels(mPage.width, mPage.height, &target))
343 andreas 641
    {
642
#if TESTMODE == 1
643
        setScreenDone();
644
#endif
254 andreas 645
        return;
343 andreas 646
    }
254 andreas 647
 
66 andreas 648
    target.eraseColor(TColor::getSkiaColor(sr[0].cf));
649
    // Draw the background, if any
650
    if (sr.size() > 0 && (!sr[0].bm.empty() || !sr[0].mi.empty()))
5 andreas 651
    {
66 andreas 652
        TDrawImage dImage;
201 andreas 653
        dImage.setWidth(mPage.width);
654
        dImage.setHeight(mPage.height);
5 andreas 655
 
66 andreas 656
        if (!sr[0].bm.empty())
5 andreas 657
        {
66 andreas 658
            MSG_DEBUG("Loading image " << sr[0].bm);
659
            sk_sp<SkData> rawImage = readImage(sr[0].bm);
5 andreas 660
            SkBitmap bm;
28 andreas 661
 
365 andreas 662
            if (rawImage && !rawImage->isEmpty())
66 andreas 663
            {
664
                MSG_DEBUG("Decoding image BM ...");
55 andreas 665
 
66 andreas 666
                if (!DecodeDataToBitmap(rawImage, &bm))
667
                {
668
                    MSG_WARNING("Problem while decoding image " << sr[0].bm);
669
                }
365 andreas 670
                else if (!bm.isNull() && !bm.empty())
66 andreas 671
                {
672
                    dImage.setImageBm(bm);
673
                    SkImageInfo info = bm.info();
674
                    sr[0].bm_width = info.width();
675
                    sr[0].bm_height = info.height();
676
                    haveImage = true;
368 andreas 677
                    MSG_DEBUG("Image " << sr[0].bm << " has dimension " << sr[0].bm_width << " x " << sr[0].bm_height);
66 andreas 678
                }
679
                else
680
                {
681
                    MSG_WARNING("BM image " << sr[0].bm << " seems to be empty!");
682
                }
683
            }
684
        }
685
 
368 andreas 686
        MSG_DEBUG("haveImage: " << (haveImage ? "TRUE" : "FALSE"));
687
 
66 andreas 688
        if (!sr[0].mi.empty())
689
        {
690
            MSG_DEBUG("Loading image " << sr[0].mi);
691
            sk_sp<SkData> rawImage = readImage(sr[0].mi);
692
            SkBitmap mi;
693
 
365 andreas 694
            if (rawImage && !rawImage->isEmpty())
66 andreas 695
            {
696
                MSG_DEBUG("Decoding image MI ...");
697
 
698
                if (!DecodeDataToBitmap(rawImage, &mi))
699
                {
700
                    MSG_WARNING("Problem while decoding image " << sr[0].mi);
701
                }
365 andreas 702
                else if (!mi.isNull() && !mi.empty())
66 andreas 703
                {
704
                    dImage.setImageMi(mi);
705
                    SkImageInfo info = mi.info();
706
                    sr[0].mi_width = info.width();
707
                    sr[0].mi_height = info.height();
708
                    haveImage = true;
709
                }
710
                else
711
                {
712
                    MSG_WARNING("MI image " << sr[0].mi << " seems to be empty!");
713
                }
714
            }
715
        }
716
 
717
        if (haveImage)
718
        {
719
            dImage.setSr(sr);
720
 
721
            if (!dImage.drawImage(&target))
343 andreas 722
            {
723
#if TESTMODE == 1
724
                setScreenDone();
725
#endif
66 andreas 726
                return;
343 andreas 727
            }
66 andreas 728
 
55 andreas 729
            if (!sr[0].te.empty())
730
            {
201 andreas 731
                if (!drawText(mPage, &target))
343 andreas 732
                {
733
#if TESTMODE == 1
734
                    setScreenDone();
735
#endif
55 andreas 736
                    return;
343 andreas 737
                }
55 andreas 738
            }
66 andreas 739
 
43 andreas 740
#ifdef _SCALE_SKIA_
26 andreas 741
            if (gPageManager && gPageManager->getScaleFactor() != 1.0)
742
            {
66 andreas 743
                SkPaint paint;
744
                int left, top;
289 andreas 745
                SkImageInfo info = target.info();
66 andreas 746
 
747
                paint.setBlendMode(SkBlendMode::kSrc);
26 andreas 748
                paint.setFilterQuality(kHigh_SkFilterQuality);
28 andreas 749
                // Calculate new dimension
31 andreas 750
                double scaleFactor = gPageManager->getScaleFactor();
751
                MSG_DEBUG("Using scale factor " << scaleFactor);
752
                int lwidth = (int)((double)info.width() * scaleFactor);
753
                int lheight = (int)((double)info.height() * scaleFactor);
754
                int twidth = (int)((double)width * scaleFactor);
755
                int theight = (int)((double)height * scaleFactor);
66 andreas 756
                calcPosition(lwidth, lheight, &left, &top);
28 andreas 757
                // Create a canvas and draw new image
66 andreas 758
                sk_sp<SkImage> im = SkImage::MakeFromBitmap(target);
254 andreas 759
 
760
                if (!allocPixels(twidth, theight, &target))
343 andreas 761
                {
762
#if TESTMODE == 1
763
                    setScreenDone();
764
#endif
254 andreas 765
                    return;
343 andreas 766
                }
254 andreas 767
 
66 andreas 768
                target.eraseColor(TColor::getSkiaColor(sr[0].cf));
254 andreas 769
                SkCanvas can(target, SkSurfaceProps());
66 andreas 770
                SkRect rect = SkRect::MakeXYWH(left, top, lwidth, lheight);
771
                can.drawImageRect(im, rect, &paint);
772
                MSG_DEBUG("Scaled size of background image: " << left << ", " << top << ", " << lwidth << ", " << lheight);
26 andreas 773
            }
43 andreas 774
#endif
277 andreas 775
/*
289 andreas 776
            TBitmap image((unsigned char *)target.getPixels(), target.info().width(), target.info().height());
262 andreas 777
#ifdef _OPAQUE_SKIA_
258 andreas 778
            if (sr[0].te.empty() && sr[0].bs.empty())
289 andreas 779
                _setBackground(handle, image, target.info().width(), target.info().height(), TColor::getColor(sr[0].cf));
262 andreas 780
#else
781
            if (sr[0].te.empty() && sr[0].bs.empty())
289 andreas 782
                _setBackground(handle, image, target.info().width(), target.info().height(), TColor::getColor(sr[0].cf), sr[0].oo);
262 andreas 783
#endif
277 andreas 784
*/
5 andreas 785
        }
786
    }
66 andreas 787
 
788
    if (sr.size() > 0 && !sr[0].te.empty())
55 andreas 789
    {
66 andreas 790
        MSG_DEBUG("Drawing text on background image ...");
55 andreas 791
 
258 andreas 792
        if (drawText(mPage, &target))
793
            haveImage = true;
794
    }
55 andreas 795
 
258 andreas 796
    // Check for a frame and draw it if there is one.
797
    if (!sr[0].bs.empty())
798
    {
799
        if (drawFrame(mPage, &target))
800
            haveImage = true;
801
    }
802
 
803
    if (haveImage)
804
    {
66 andreas 805
        SkImageInfo info = target.info();
289 andreas 806
        TBitmap image((unsigned char *)target.getPixels(), info.width(), info.height());
262 andreas 807
#ifdef _OPAQUE_SKIA_
289 andreas 808
        _setBackground(handle, image, target.info().width(), target.info().height(), TColor::getColor(sr[0].cf));
262 andreas 809
#else
289 andreas 810
        _setBackground(handle, image, target.info().width(), target.info().height(), TColor::getColor(sr[0].cf), sr[0].oo);
262 andreas 811
#endif
55 andreas 812
    }
258 andreas 813
    else if (sr.size() > 0 && !haveImage)
5 andreas 814
    {
26 andreas 815
        MSG_DEBUG("Calling \"setBackground\" with no image ...");
262 andreas 816
#ifdef _OPAQUE_SKIA_
289 andreas 817
        _setBackground(handle, TBitmap(), 0, 0, TColor::getColor(sr[0].cf));
262 andreas 818
#else
289 andreas 819
        _setBackground(handle, TBitmap(), 0, 0, TColor::getColor(sr[0].cf), sr[0].oo);
262 andreas 820
#endif
5 andreas 821
    }
822
 
26 andreas 823
    // Draw the buttons
201 andreas 824
    BUTTONS_T *button = TPageInterface::getButtons();
26 andreas 825
 
826
    while (button)
827
    {
828
        if (button->button)
829
        {
830
            MSG_DEBUG("Drawing button " << button->button->getButtonIndex() << ": " << button->button->getButtonName());
831
            button->button->registerCallback(_displayButton);
832
            button->button->regCallPlayVideo(_playVideo);
204 andreas 833
            TPageInterface::registerListCallback<TPage>(button->button, this);
201 andreas 834
            button->button->setFonts(getFonts());
26 andreas 835
            button->button->setPalette(mPalette);
836
            button->button->createButtons();
837
 
838
            if (sr.size() > 0)
839
                button->button->setGlobalOpacity(sr[0].oo);
840
 
841
            button->button->show();
842
        }
843
 
844
        button = button->next;
845
    }
846
 
66 andreas 847
    // Mark page as visible
14 andreas 848
    mVisible = true;
271 andreas 849
 
850
    if (gPageManager && gPageManager->getPageFinished())
851
        gPageManager->getPageFinished()(handle);
5 andreas 852
}
853
 
349 andreas 854
bool TPage::addSubPage(TSubPage* pg)
3 andreas 855
{
14 andreas 856
    DECL_TRACER("TPage::addSubPage(TSubPage* pg)");
3 andreas 857
 
858
    if (!pg)
859
    {
860
        MSG_ERROR("Parameter is NULL!");
861
        TError::setError();
349 andreas 862
        return false;
3 andreas 863
    }
864
 
349 andreas 865
    if (mSubPages.empty())
866
        mZOrder = 0;
3 andreas 867
 
349 andreas 868
#if __cplusplus < 201703L
869
    map<int, TSubPage *>::iterator iter = mSubPages.find(pg->getNumber());
3 andreas 870
 
349 andreas 871
    if (iter != mSubPages.end() && iter->second != pg)
872
        iter->second = pg;
3 andreas 873
    else
349 andreas 874
        mSubPages.insert(pair<int, TSubPage *>(pg->getNumber(), pg));
875
#else
876
    mSubPages.insert_or_assign(pg->getNumber(), pg);
877
#endif
5 andreas 878
    mLastSubPage = 0;
349 andreas 879
    return true;
3 andreas 880
}
881
 
882
bool TPage::removeSubPage(int ID)
883
{
884
    DECL_TRACER("TPage::removeSubPage(int ID)");
885
 
349 andreas 886
    map<int, TSubPage *>::iterator iter = mSubPages.find(ID);
3 andreas 887
 
349 andreas 888
    if (iter != mSubPages.end())
3 andreas 889
    {
349 andreas 890
        mSubPages.erase(iter);
891
        return true;
3 andreas 892
    }
893
 
894
    return false;
895
}
896
 
897
bool TPage::removeSubPage(const std::string& nm)
898
{
899
    DECL_TRACER("TPage::removeSubPage(const std::string& nm)");
900
 
349 andreas 901
    if (mSubPages.empty())
902
        return false;
3 andreas 903
 
349 andreas 904
    map<int, TSubPage *>::iterator iter;
905
 
906
    for (iter = mSubPages.begin(); iter != mSubPages.end(); ++iter)
3 andreas 907
    {
349 andreas 908
        if (iter->second->getName() == nm)
3 andreas 909
        {
349 andreas 910
            mSubPages.erase(iter);
3 andreas 911
            return true;
912
        }
913
    }
914
 
915
    return false;
916
}
917
 
4 andreas 918
TSubPage *TPage::getSubPage(int pageID)
919
{
920
    DECL_TRACER("TPage::getSubPage(int pageID)");
921
 
349 andreas 922
    map<int, TSubPage *>::iterator iter = mSubPages.find(pageID);
4 andreas 923
 
349 andreas 924
    if (iter != mSubPages.end())
925
        return iter->second;
4 andreas 926
 
5 andreas 927
    mLastSubPage = 0;
4 andreas 928
    return nullptr;
929
}
930
 
931
TSubPage *TPage::getSubPage(const std::string& name)
932
{
933
    DECL_TRACER("TPage::getSubPage(const std::string& name)");
934
 
349 andreas 935
    if (mSubPages.empty())
936
        return nullptr;
4 andreas 937
 
349 andreas 938
    map<int, TSubPage *>::iterator iter;
939
 
940
    for (iter = mSubPages.begin(); iter != mSubPages.end(); ++iter)
4 andreas 941
    {
349 andreas 942
        if (iter->second->getName() == name)
943
            return iter->second;
4 andreas 944
    }
945
 
5 andreas 946
    mLastSubPage = 0;
4 andreas 947
    return nullptr;
948
}
949
 
950
TSubPage *TPage::getFirstSubPage()
951
{
952
    DECL_TRACER("TPage::getFirstSubPage()");
953
 
349 andreas 954
    if (mSubPages.empty())
955
    {
956
        MSG_DEBUG("No subpages in chain.");
957
        mLastSubPage = 0;
958
        return nullptr;
959
    }
14 andreas 960
 
349 andreas 961
    TSubPage *pg = mSubPages.begin()->second;
962
 
963
    if (!pg)
4 andreas 964
    {
349 andreas 965
        MSG_ERROR("The pointer to the subpage " << mSubPages.begin()->first << " is NULL!");
966
        return nullptr;
4 andreas 967
    }
968
 
349 andreas 969
    mLastSubPage = pg->getNumber();
970
    MSG_DEBUG("Subpage (Z: " << pg->getZOrder() << "): " << pg->getNumber() << ". " << pg->getName());
971
    return pg;
4 andreas 972
}
973
 
974
TSubPage *TPage::getNextSubPage()
975
{
976
    DECL_TRACER("TPage::getNextSubPage()");
977
 
349 andreas 978
    if (mSubPages.empty())
4 andreas 979
    {
349 andreas 980
        MSG_DEBUG("No subpages in chain.");
981
        mLastSubPage = 0;
982
        return nullptr;
983
    }
4 andreas 984
 
349 andreas 985
    if (mLastSubPage <= 0)
986
        mLastSubPage = mSubPages.begin()->second->getNumber();
4 andreas 987
 
349 andreas 988
    map<int, TSubPage *>::iterator iter = mSubPages.find(mLastSubPage);
989
 
990
    if (iter != mSubPages.end())
991
        iter++;
992
    else
993
    {
994
        MSG_DEBUG("No more subpages in chain.");
995
        mLastSubPage = 0;
996
        return nullptr;
4 andreas 997
    }
998
 
349 andreas 999
    if (iter != mSubPages.end())
1000
    {
1001
        TSubPage *page = iter->second;
1002
        mLastSubPage = page->getNumber();
1003
        MSG_DEBUG("Subpage (Z: " << page->getZOrder() << "): " << page->getNumber() << ". " << page->getName());
1004
        return page;
1005
    }
1006
 
14 andreas 1007
    MSG_DEBUG("No more subpages in chain.");
5 andreas 1008
    mLastSubPage = 0;
4 andreas 1009
    return nullptr;
1010
}
1011
 
154 andreas 1012
TSubPage *TPage::getPrevSubPage()
1013
{
1014
    DECL_TRACER("TPage::getPrevSubPage()");
1015
 
349 andreas 1016
    if (mSubPages.empty())
1017
    {
1018
        MSG_DEBUG("No last subpage or no subpages at all!");
1019
        mLastSubPage = 0;
154 andreas 1020
        return nullptr;
349 andreas 1021
    }
154 andreas 1022
 
349 andreas 1023
    if (mLastSubPage < MAX_PAGE_ID)
154 andreas 1024
    {
349 andreas 1025
        map<int, TSubPage *>::iterator iter = mSubPages.end();
1026
        iter--;
1027
        mLastSubPage = iter->first;
1028
    }
154 andreas 1029
 
349 andreas 1030
    map<int, TSubPage *>::iterator iter = mSubPages.find(mLastSubPage);
154 andreas 1031
 
349 andreas 1032
    if (iter != mSubPages.end() && iter != mSubPages.begin())
1033
        iter--;
1034
    else
1035
    {
1036
        MSG_DEBUG("No more subpages in chain.");
1037
        mLastSubPage = 0;
1038
        return nullptr;
154 andreas 1039
    }
1040
 
349 andreas 1041
    TSubPage *page = iter->second;
1042
    mLastSubPage = page->getNumber();
1043
    MSG_DEBUG("Subpage (Z: " << page->getZOrder() << "): " << page->getNumber() << ". " << page->getName());
1044
    return page;
154 andreas 1045
}
1046
 
1047
TSubPage *TPage::getLastSubPage()
1048
{
1049
    DECL_TRACER("TPage::getLastSubPage()");
1050
 
349 andreas 1051
    if (mSubPages.empty())
154 andreas 1052
    {
1053
        mLastSubPage = 0;
1054
        MSG_DEBUG("No subpages in cache!");
1055
        return nullptr;
1056
    }
1057
 
349 andreas 1058
    map<int, TSubPage *>::iterator iter = mSubPages.end();
1059
    iter--;
1060
    TSubPage *pg = iter->second;
1061
    mLastSubPage = pg->getNumber();
1062
    MSG_DEBUG("Subpage (Z: " << pg->getZOrder() << "): " << pg->getNumber() << ". " << pg->getName());
1063
    return pg;
154 andreas 1064
}
1065
 
12 andreas 1066
void TPage::drop()
1067
{
1068
    DECL_TRACER("TPage::drop()");
1069
 
147 andreas 1070
    // remove all subpages, if there are any
348 andreas 1071
#if TESTMODE == 1
1072
    _block_screen = true;
1073
#endif
349 andreas 1074
    if (!mSubPages.empty())
12 andreas 1075
    {
349 andreas 1076
        map<int, TSubPage *>::iterator iter;
1077
 
1078
        for (iter = mSubPages.begin(); iter != mSubPages.end(); ++iter)
295 andreas 1079
        {
349 andreas 1080
            if (iter->second)
1081
                iter->second->drop();
295 andreas 1082
        }
12 andreas 1083
    }
348 andreas 1084
#if TESTMODE == 1
1085
    _block_screen = false;
1086
#endif
14 andreas 1087
 
147 andreas 1088
    // remove all buttons, if there are any
201 andreas 1089
    BUTTONS_T *bt = TPageInterface::getButtons();
147 andreas 1090
 
1091
    while (bt)
1092
    {
271 andreas 1093
        MSG_DEBUG("Dropping button " << handleToString(bt->button->getHandle()));
1094
        bt->button->invalidate();
147 andreas 1095
        bt = bt->next;
1096
    }
1097
 
271 andreas 1098
    if (gPageManager && gPageManager->getCallDropPage())
1099
    {
1100
        ulong handle = (mPage.pageID << 16) & 0xffff0000;
1101
        gPageManager->getCallDropPage()(handle);
1102
    }
1103
 
14 andreas 1104
    mZOrder = ZORDER_INVALID;
1105
    mVisible = false;
12 andreas 1106
}
43 andreas 1107
#ifdef _SCALE_SKIA_
31 andreas 1108
void TPage::calcPosition(int im_width, int im_height, int *left, int *top, bool scale)
43 andreas 1109
#else
1110
void TPage::calcPosition(int im_width, int im_height, int *left, int *top)
1111
#endif
28 andreas 1112
{
1113
    DECL_TRACER("TPage::calcPosition(int im_width, int im_height, int *left, int *top)");
1114
 
201 andreas 1115
    int nw = mPage.width;
1116
    int nh = mPage.height;
43 andreas 1117
#ifdef _SCALE_SKIA_
31 andreas 1118
    if (scale && gPageManager && gPageManager->getScaleFactor() != 1.0)
28 andreas 1119
    {
1120
        nw = (int)((double)width * gPageManager->getScaleFactor());
1121
        nh = (int)((double)height * gPageManager->getScaleFactor());
1122
    }
43 andreas 1123
#endif
28 andreas 1124
    switch (sr[0].jb)
1125
    {
1126
        case 0: // absolute position
1127
            *left = sr[0].bx;
1128
            *top = sr[0].by;
43 andreas 1129
#ifdef _SCALE_SKIA_
31 andreas 1130
            if (scale && gPageManager && gPageManager->getScaleFactor() != 1.0)
28 andreas 1131
            {
1132
                *left = (int)((double)sr[0].bx * gPageManager->getScaleFactor());
1133
                *left = (int)((double)sr[0].by * gPageManager->getScaleFactor());
1134
            }
43 andreas 1135
#endif
28 andreas 1136
        break;
1137
 
1138
        case 1: // top, left
1139
            *left = 0;
1140
            *top = 0;
1141
        break;
1142
 
1143
        case 2: // center, top
1144
            *left = (nw - im_width) / 2;
1145
            *top = 0;
1146
        break;
1147
 
1148
        case 3: // right, top
1149
            *left = nw - im_width;
1150
            *top = 0;
1151
        break;
1152
 
1153
        case 4: // left, middle
1154
            *left = 0;
1155
            *top = (nh - im_height) / 2;
1156
        break;
1157
 
1158
        case 6: // right, middle
1159
            *left = nw - im_width;
1160
            *top = (nh - im_height) / 2;
1161
        break;
1162
 
1163
        case 7: // left, bottom
1164
            *left = 0;
1165
            *top = nh - im_height;
1166
        break;
1167
 
1168
        case 8: // center, bottom
1169
            *left = (nw - im_width) / 2;
1170
            *top = nh - im_height;
1171
        break;
1172
 
1173
        case 9: // right, bottom
1174
            *left = nw - im_width;
1175
            *top = nh - im_height;
1176
        break;
31 andreas 1177
 
1178
        default:    // center middle
1179
            *left = (nw - im_width) / 2;
1180
            *top = (nh - im_height) / 2;
28 andreas 1181
    }
1182
 
1183
    if (*left < 0)
1184
        *left = 0;
1185
 
1186
    if (*top < 0)
1187
        *top = 0;
1188
}
1189
 
151 andreas 1190
void TPage::sortSubpages()
1191
{
1192
    DECL_TRACER("TPage::sortSubpage()");
1193
 
349 andreas 1194
    mSubPagesSorted.clear();
151 andreas 1195
 
349 andreas 1196
    if (mSubPages.empty())
1197
        return;
1198
 
1199
    map<int, TSubPage *>::iterator iter;
1200
 
1201
    for (iter = mSubPages.begin(); iter != mSubPages.end(); ++iter)
151 andreas 1202
    {
349 andreas 1203
        if (iter->second->getZOrder() >= 0)
154 andreas 1204
        {
349 andreas 1205
            mSubPagesSorted.insert(pair<int, TSubPage *>(iter->second->getZOrder(), iter->second));
1206
            MSG_DEBUG("Page " << iter->second->getNumber() << " (" << iter->second->getName() << "): sorted in with Z-Order " << iter->second->getZOrder());
1207
        }
1208
    }
1209
}
151 andreas 1210
 
349 andreas 1211
map<int, TSubPage *>& TPage::getSortedSubpages(bool force)
1212
{
1213
    DECL_TRACER("TPage::getSortedSubpages(bool force)");
151 andreas 1214
 
349 andreas 1215
    if (mSubPagesSorted.empty() || force)
1216
        sortSubpages();
151 andreas 1217
 
349 andreas 1218
    return mSubPagesSorted;
151 andreas 1219
}
1220
 
152 andreas 1221
int TPage::getNextZOrder()
1222
{
1223
    DECL_TRACER("TPage::getNextZOrder()");
1224
 
1225
    // Find highest z-order number
154 andreas 1226
    int cnt = 0;
349 andreas 1227
    map<int, TSubPage *>::iterator iter;
152 andreas 1228
 
349 andreas 1229
    for (iter = mSubPages.begin(); iter != mSubPages.end(); ++iter)
152 andreas 1230
    {
349 andreas 1231
        int zo = iter->second->getZOrder();
1232
 
1233
        if (iter->second && zo != ZORDER_INVALID)
154 andreas 1234
        {
349 andreas 1235
            if (cnt < zo)
1236
                cnt = zo;
154 andreas 1237
        }
152 andreas 1238
    }
1239
 
154 andreas 1240
    mZOrder = cnt + 1;
152 andreas 1241
    MSG_DEBUG("New Z-order: " << mZOrder);
1242
    return mZOrder;
1243
}
1244
 
151 andreas 1245
int TPage::decZOrder()
1246
{
1247
    DECL_TRACER("TPage::decZOrder()");
1248
 
1249
    // Find highest z-order number
349 andreas 1250
    int cnt = 0;
1251
    map<int, TSubPage *>::iterator iter;
151 andreas 1252
 
349 andreas 1253
    for (iter = mSubPages.begin(); iter != mSubPages.end(); ++iter)
151 andreas 1254
    {
349 andreas 1255
        int zo = iter->second->getZOrder();
1256
 
1257
        if (iter->second && zo != ZORDER_INVALID)
154 andreas 1258
        {
349 andreas 1259
            if (cnt < zo)
1260
                cnt = zo;
154 andreas 1261
        }
151 andreas 1262
    }
1263
 
349 andreas 1264
    mZOrder = cnt;
151 andreas 1265
    return mZOrder;
1266
}