Subversion Repositories tpanel

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 andreas 1
/*
21 andreas 2
 * Copyright (C) 2020, 2021 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>
5 andreas 22
#include "tresources.h"
2 andreas 23
#include "tpage.h"
24
 
3 andreas 25
using std::string;
26
using namespace Button;
27
 
28
TPage::TPage(const string& name)
2 andreas 29
{
3 andreas 30
    DECL_TRACER("TPage::TPage(const string& name)");
14 andreas 31
    TError::clear();
3 andreas 32
    initialize(name);
33
}
2 andreas 34
 
3 andreas 35
TPage::~TPage()
36
{
5 andreas 37
    DECL_TRACER("TPage::~TPage()");
38
 
39
    MSG_DEBUG("Destroing page " << pageID << ": " << name);
3 andreas 40
    BUTTONS_T *p = mButtons;
41
    BUTTONS_T *next = nullptr;
2 andreas 42
 
3 andreas 43
    while (p)
44
    {
45
        next = p->next;
46
        delete p->button;
47
        delete p;
48
        p = next;
49
    }
2 andreas 50
 
3 andreas 51
    mButtons = nullptr;
52
 
53
    PAGECHAIN_T *pc = mSubPages;
54
    PAGECHAIN_T *pc_next = nullptr;
55
 
56
    // We're not allowd to delete the subpages here, because they're managed
57
    // by the TPageManager.
58
    while (pc)
59
    {
60
        pc_next = pc->next;
61
        delete pc;
62
        pc = pc_next;
63
    }
64
 
65
    mSubPages = nullptr;
66
}
67
 
68
void TPage::initialize(const string& nm)
69
{
70
    DECL_TRACER("TPage::initialize(const string& name)");
71
    makeFileName(TConfig::getProjectPath(), nm);
72
 
73
    if (isValidFile())
74
        mPath = getFileName();
75
 
76
    TReadXML reader(mPath);
77
 
78
    if (TError::isError())
79
        return;
80
 
81
    reader.findElement("page", "type");
82
 
83
    if (!reader.success())
84
    {
85
        MSG_ERROR("Element \"page\" with attribute \"type\" was not found!");
86
        TError::setError();
87
        return;
88
    }
89
 
90
    string type = reader.getAttribute("type");
91
 
92
    if (type.compare("page") != 0)
93
    {
94
        MSG_ERROR("Invalid page type \"" << type << "\"!");
95
        TError::setError();
96
        return;
97
    }
98
 
99
    mxml_node_t *node = reader.getFirstChild();
100
 
101
    while (node)
102
    {
103
        string e = reader.getElementName(node);
104
 
105
        if (e.compare("pageID") == 0)
106
            pageID = reader.getIntFromNode(node);
107
        else if (e.compare("name") == 0)
108
            name = reader.getTextFromNode(node);
109
        else if (e.compare("width") == 0)
110
            width = reader.getIntFromNode(node);
111
        else if (e.compare("height") == 0)
112
            height = reader.getIntFromNode(node);
113
        else if (e.compare("button") == 0)
114
        {
115
            TButton *button = new TButton();
4 andreas 116
            button->setPalette(mPalette);
7 andreas 117
            button->setFonts(mFonts);
118
            button->registerCallback(_displayButton);
119
            button->registerCallbackFT(_setText);
21 andreas 120
            button->regCallPlayVideo(_playVideo);
3 andreas 121
            button->initialize(&reader, node);
122
 
123
            if (TError::isError())
124
            {
125
                delete button;
126
                return;
127
            }
128
 
5 andreas 129
            button->setHandle(((pageID << 16) & 0xffff0000) | button->getButtonIndex());
14 andreas 130
            button->createButtons();
3 andreas 131
            addButton(button);
132
        }
133
        else if (e.compare("sr") == 0)
134
        {
135
            SR_T bsr;
136
            bsr.number = atoi(reader.getAttributeFromNode(node, "number").c_str());
137
            mxml_node_t *n = reader.getFirstChild(node);
138
 
139
            while (n)
140
            {
141
                string ename = reader.getElementName(n);
142
 
143
                if (ename.compare("bs") == 0)
144
                    bsr.bs = reader.getTextFromNode(n);
145
                else if (ename.compare("cb") == 0)
146
                    bsr.cb = reader.getTextFromNode(n);
147
                else if (ename.compare("cf") == 0)
148
                    bsr.cf = reader.getTextFromNode(n);
149
                else if (ename.compare("ct") == 0)
150
                    bsr.ct = reader.getTextFromNode(n);
151
                else if (ename.compare("ec") == 0)
152
                    bsr.ec = reader.getTextFromNode(n);
153
                else if (ename.compare("bm") == 0)
154
                    bsr.bm = reader.getTextFromNode(n);
155
                else if (ename.compare("fi") == 0)
156
                    bsr.fi = reader.getIntFromNode(n);
157
 
5 andreas 158
                n = reader.getNextChild(n);
3 andreas 159
            }
160
 
161
            sr.push_back(bsr);
162
        }
163
 
164
        node = reader.getNextChild();
165
    }
166
 
167
    sortButtons();
168
}
169
 
5 andreas 170
void TPage::show()
171
{
172
    DECL_TRACER("TPage::show()");
173
 
174
    if (!_setBackground)
175
    {
176
        MSG_WARNING("No callback \"setBackground\" was set!");
177
        return;
178
    }
179
 
180
    ulong handle = (pageID << 16) & 0xffff0000;
181
    MSG_DEBUG("Processing page " << pageID);
182
 
183
    if (!sr[0].bm.empty())
184
    {
185
        sk_sp<SkData> rawImage = readImage(sr[0].bm);
186
 
187
        if (rawImage)
188
        {
189
            SkBitmap bm;
190
            DecodeDataToBitmap(rawImage, &bm);
191
            SkImageInfo info = bm.info();
192
            size_t rowBytes = info.minRowBytes();
193
            size_t size = info.computeByteSize(rowBytes);
194
            MSG_DEBUG("Setting background with image of size " << size);
195
            _setBackground(handle, (unsigned char *)bm.getPixels(), size, rowBytes, TColor::getColor(sr[0].cf));
196
            return;
197
        }
198
        else
199
        {
200
            MSG_WARNING("Couldn't read image " << sr[0].bm);
201
        }
202
    }
203
    else
204
    {
205
        MSG_DEBUG("No background image defined!");
206
    }
207
 
208
    MSG_DEBUG("Calling \"setBackground\" with no image ...");
209
    _setBackground(handle, nullptr, 0, 0, TColor::getColor(sr[0].cf));
14 andreas 210
    mVisible = true;
5 andreas 211
}
212
 
3 andreas 213
PAGECHAIN_T *TPage::addSubPage(TSubPage* pg)
214
{
14 andreas 215
    DECL_TRACER("TPage::addSubPage(TSubPage* pg)");
3 andreas 216
 
217
    if (!pg)
218
    {
219
        MSG_ERROR("Parameter is NULL!");
220
        TError::setError();
221
        return nullptr;
222
    }
223
 
224
    PAGECHAIN_T *chain = new PAGECHAIN_T;
225
    chain->subpage = pg;
14 andreas 226
    chain->next = nullptr;
227
    PAGECHAIN_T *spg = mSubPages;
3 andreas 228
 
14 andreas 229
    if (spg)
3 andreas 230
    {
14 andreas 231
        // First make sure that the new page is not already in the chain.
232
        PAGECHAIN_T *p = spg;
3 andreas 233
 
14 andreas 234
        while (p)
13 andreas 235
        {
236
            if (p->subpage->getNumber() == pg->getNumber())
237
            {
14 andreas 238
                MSG_TRACE("Page " << pg->getNumber() << " is already in chain. Don't add it again.");
13 andreas 239
                delete chain;
240
                return p;
241
            }
242
 
3 andreas 243
            p = p->next;
13 andreas 244
        }
3 andreas 245
 
14 andreas 246
        // The subpage is not in chain. So we add it now.
247
        p = spg;
248
        // Find the last element in chain
249
        while (p->next)
250
            p = p->next;
251
 
3 andreas 252
        p->next = chain;
253
    }
254
    else
14 andreas 255
    {
256
        mZOrder = 0;
3 andreas 257
        mSubPages = chain;
14 andreas 258
    }
3 andreas 259
 
5 andreas 260
    mLastSubPage = 0;
3 andreas 261
    return chain;
262
}
263
 
264
bool TPage::removeSubPage(int ID)
265
{
266
    DECL_TRACER("TPage::removeSubPage(int ID)");
267
 
268
    PAGECHAIN_T *p = mSubPages;
269
    PAGECHAIN_T *prev = nullptr;
270
 
271
    while (p)
272
    {
273
        if (p->subpage->getNumber() == ID)
274
        {
275
            PAGECHAIN_T *next = p->next;
276
 
277
            if (prev)
278
                prev->next = next;
279
            else
280
                mSubPages = next;
281
 
282
            delete p;
5 andreas 283
            mLastSubPage = 0;
3 andreas 284
            return true;
285
        }
286
 
287
        prev = p;
288
        p = p->next;
289
    }
290
 
291
    return false;
292
}
293
 
294
bool TPage::removeSubPage(const std::string& nm)
295
{
296
    DECL_TRACER("TPage::removeSubPage(const std::string& nm)");
297
 
298
    PAGECHAIN_T *p = mSubPages;
299
    PAGECHAIN_T *prev = nullptr;
300
 
301
    while (p)
302
    {
303
        if (p->subpage->getName().compare(nm) == 0)
304
        {
305
            PAGECHAIN_T *next = p->next;
306
 
307
            if (prev)
308
                prev->next = next;
309
            else
310
                mSubPages = next;
311
 
312
            delete p;
5 andreas 313
            mLastSubPage = 0;
3 andreas 314
            return true;
315
        }
316
 
317
        prev = p;
318
        p = p->next;
319
    }
320
 
321
    return false;
322
}
323
 
4 andreas 324
TSubPage *TPage::getSubPage(int pageID)
325
{
326
    DECL_TRACER("TPage::getSubPage(int pageID)");
327
 
328
    PAGECHAIN_T *pg = mSubPages;
329
 
330
    while (pg)
331
    {
332
        if (pg->subpage->getNumber() == pageID)
333
        {
334
            mLastSubPage = pageID;
335
            return pg->subpage;
336
        }
337
 
338
        pg = pg->next;
339
    }
340
 
5 andreas 341
    mLastSubPage = 0;
4 andreas 342
    return nullptr;
343
}
344
 
345
TSubPage *TPage::getSubPage(const std::string& name)
346
{
347
    DECL_TRACER("TPage::getSubPage(const std::string& name)");
348
 
349
    PAGECHAIN_T *pg = mSubPages;
350
 
351
    while (pg)
352
    {
353
        if (pg->subpage->getName().compare(name) == 0)
354
        {
14 andreas 355
            mLastSubPage = pg->subpage->getNumber();
4 andreas 356
            return pg->subpage;
357
        }
358
 
359
        pg = pg->next;
360
    }
361
 
5 andreas 362
    mLastSubPage = 0;
4 andreas 363
    return nullptr;
364
}
365
 
366
TSubPage *TPage::getFirstSubPage()
367
{
368
    DECL_TRACER("TPage::getFirstSubPage()");
369
 
14 andreas 370
    PAGECHAIN_T *pg = mSubPages;
371
 
372
    if (pg)
4 andreas 373
    {
14 andreas 374
        if (pg->subpage)
4 andreas 375
        {
14 andreas 376
            mLastSubPage = pg->subpage->getNumber();
377
            MSG_DEBUG("Subpage " << pg->subpage->getNumber() << ". " << pg->subpage->getName());
378
            return pg->subpage;
4 andreas 379
        }
380
    }
381
 
14 andreas 382
    MSG_DEBUG("No subpages in chain.");
5 andreas 383
    mLastSubPage = 0;
4 andreas 384
    return nullptr;
385
}
386
 
387
TSubPage *TPage::getNextSubPage()
388
{
389
    DECL_TRACER("TPage::getNextSubPage()");
390
 
391
    if (mLastSubPage > 0)
392
    {
393
        PAGECHAIN_T *p = mSubPages;
394
 
395
        while (p)
396
        {
397
            if (p->subpage->getNumber() == mLastSubPage)
398
            {
14 andreas 399
                if (p->next && p->next->subpage)
4 andreas 400
                {
14 andreas 401
                    TSubPage *page = p->next->subpage;
402
                    mLastSubPage = page->getNumber();
15 andreas 403
                    MSG_DEBUG("Subpage " << page->getNumber() << ". " << page->getName());
14 andreas 404
                    return page;
4 andreas 405
                }
406
            }
407
 
408
            p = p->next;
409
        }
410
    }
411
 
14 andreas 412
    MSG_DEBUG("No more subpages in chain.");
5 andreas 413
    mLastSubPage = 0;
4 andreas 414
    return nullptr;
415
}
416
 
3 andreas 417
BUTTONS_T *TPage::addButton(TButton* button)
418
{
419
    DECL_TRACER("*TPage::addButton(TButton* button)");
420
 
421
    if (!button)
422
    {
423
        MSG_ERROR("Parameter is NULL!");
424
        TError::setError();
425
        return nullptr;
426
    }
427
 
428
    BUTTONS_T *chain = new BUTTONS_T;
14 andreas 429
    BUTTONS_T *bts = mButtons;
3 andreas 430
    chain->button = button;
431
 
14 andreas 432
    if (bts)
3 andreas 433
    {
14 andreas 434
        BUTTONS_T *p = bts;
3 andreas 435
 
436
        while (p->next)
437
            p = p->next;
438
 
439
        p->next = chain;
440
        chain->previous = p;
441
    }
442
    else
443
        mButtons = chain;
444
 
445
    return chain;
446
}
447
 
14 andreas 448
bool TPage::hasButton(int id)
449
{
450
    DECL_TRACER("TPage::hasButton(int id)");
451
 
452
    BUTTONS_T *bt = mButtons;
453
 
454
    while (bt)
455
    {
456
        if (bt->button && bt->button->getButtonIndex() == id)
457
            return true;
458
 
459
        bt = bt->next;
460
    }
461
 
462
    return false;
463
}
464
 
465
TButton *TPage::getButton(int id)
466
{
467
    DECL_TRACER("TPage::getButton(int id)");
468
 
469
    BUTTONS_T *bt = mButtons;
470
 
471
    while (bt)
472
    {
473
        if (bt->button && bt->button->getButtonIndex() == id)
474
            return bt->button;
475
 
476
        bt = bt->next;
477
    }
478
 
479
    return nullptr;
480
}
481
 
16 andreas 482
std::vector<TButton *> TPage::getButtons(int ap, int ad)
483
{
484
    DECL_TRACER("TSubPage::getButtons(int ap, int ad)");
485
 
486
    std::vector<TButton *> list;
487
    BUTTONS_T *bt = mButtons;
488
 
489
    while (bt)
490
    {
491
        if (bt->button->getAddressPort() == ap && bt->button->getAddressChannel() == ad)
492
            list.push_back(bt->button);
493
 
494
        bt = bt->next;
495
    }
496
 
497
    return list;
498
}
499
 
12 andreas 500
void TPage::drop()
501
{
502
    DECL_TRACER("TPage::drop()");
503
 
504
    PAGECHAIN_T *pc = mSubPages;
14 andreas 505
 
12 andreas 506
    while (pc)
507
    {
13 andreas 508
        pc->subpage->drop();
12 andreas 509
        pc = pc->next;
510
    }
14 andreas 511
 
512
    mZOrder = ZORDER_INVALID;
513
    mVisible = false;
12 andreas 514
}
515
 
3 andreas 516
/*
517
 * Sort the button according to their Z-order.
518
 * The button with the highest Z-order will be the last button in the chain.
519
 * The algorithm is a bubble sort algorithm.
520
 */
521
bool TPage::sortButtons()
522
{
523
    DECL_TRACER("TPage::sortButtons()");
524
 
525
    bool turned = true;
526
 
527
    while (turned)
528
    {
529
        BUTTONS_T *button = mButtons;
530
        turned = false;
531
 
532
        while (button)
533
        {
534
            int zo = button->button->getZOrder();
535
 
536
            if (button->previous)
537
            {
538
                if (zo < button->previous->button->getZOrder())
539
                {
540
                    BUTTONS_T *pprev = button->previous->previous;
541
                    BUTTONS_T *prev = button->previous;
542
                    BUTTONS_T *next = button->next;
543
 
544
                    if (pprev)
545
                        pprev->next = button;
546
 
547
                    prev->next = next;
548
                    prev->previous = button;
549
                    button->next = prev;
550
                    button->previous = pprev;
14 andreas 551
 
552
                    if (!pprev)
553
                        mButtons = button;
554
 
3 andreas 555
                    button = next;
14 andreas 556
 
557
                    if (next)
558
                        next->previous = prev;
559
 
3 andreas 560
                    turned = true;
561
                    continue;
562
                }
563
            }
564
 
565
            button = button->next;
566
        }
567
    }
568
 
569
    return true;
570
}