Subversion Repositories tpanel

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3 andreas 1
/*
21 andreas 2
 * Copyright (C) 2020, 2021 by Andreas Theofilu <andreas@theosys.at>
3 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 <vector>
14 andreas 20
#include <thread>
21
#include <mutex>
22
 
3 andreas 23
#include "tpagemanager.h"
4 andreas 24
#include "tcolor.h"
3 andreas 25
#include "terror.h"
8 andreas 26
#include "ticons.h"
14 andreas 27
#include "tbutton.h"
8 andreas 28
#include "tprjresources.h"
11 andreas 29
#include "tresources.h"
3 andreas 30
 
31
using std::vector;
32
using std::string;
11 andreas 33
using std::map;
34
using std::pair;
35
using std::to_string;
14 andreas 36
using std::thread;
37
using std::atomic;
38
using std::mutex;
21 andreas 39
using std::bind;
3 andreas 40
 
8 andreas 41
TIcons *gIcons = nullptr;
42
TPrjResources *gPrjResources = nullptr;
14 andreas 43
TPageManager *gPageManager = nullptr;
21 andreas 44
thread::id gPageManagerId;
14 andreas 45
extern amx::TAmxNet *gAmxNet;
8 andreas 46
 
14 andreas 47
mutex surface_mutex;
21 andreas 48
atomic<bool> runDoCommand;
49
bool prg_stopped = false;
14 andreas 50
 
3 andreas 51
TPageManager::TPageManager()
52
{
14 andreas 53
    surface_mutex.lock();
3 andreas 54
    DECL_TRACER("TPageManager::TPageManager()");
55
 
14 andreas 56
    gPageManager = this;
57
    gPageManagerId = thread::id();
21 andreas 58
    runDoCommand = false;
3 andreas 59
    mTSettings = new TSettings(TConfig::getProjectPath());
60
 
61
    if (TError::isError())
14 andreas 62
    {
23 andreas 63
        MSG_ERROR("Settings were not read successfull!");
14 andreas 64
        surface_mutex.unlock();
3 andreas 65
        return;
14 andreas 66
    }
3 andreas 67
 
8 andreas 68
    gPrjResources = new TPrjResources(mTSettings->getResourcesList());
69
 
4 andreas 70
    mPalette = new TPalette();
71
    vector<PALETTE_SETUP>::iterator iterPal;
72
    vector<PALETTE_SETUP> pal = mTSettings->getSettings().palettes;
73
 
74
    for (iterPal = pal.begin(); iterPal != pal.end(); iterPal++)
75
        mPalette->initialize(iterPal->file);
76
 
77
    if (!TError::isError())
78
        TColor::setPalette(mPalette);
79
 
7 andreas 80
    mFonts = new TFont();
81
 
82
    if (TError::isError())
83
    {
84
        MSG_ERROR("Initializing fonts was not successfull!");
14 andreas 85
        surface_mutex.unlock();
7 andreas 86
        return;
87
    }
88
 
8 andreas 89
    gIcons = new TIcons();
90
 
91
    if (TError::isError())
92
    {
93
        MSG_ERROR("Initializing icons was not successfull!");
14 andreas 94
        surface_mutex.unlock();
8 andreas 95
        return;
96
    }
97
 
3 andreas 98
    mPageList = new TPageList();
99
 
100
    if (TError::isError())
14 andreas 101
    {
102
        surface_mutex.unlock();
3 andreas 103
        return;
14 andreas 104
    }
3 andreas 105
 
4 andreas 106
    PAGELIST_T page;
107
 
3 andreas 108
    if (!mTSettings->getSettings().powerUpPage.empty())
109
    {
110
        if (readPage(mTSettings->getSettings().powerUpPage) == false)
14 andreas 111
        {
112
            surface_mutex.unlock();
3 andreas 113
            return;
14 andreas 114
        }
3 andreas 115
 
116
        MSG_TRACE("Found power up page " << mTSettings->getSettings().powerUpPage);
4 andreas 117
        page = findPage(mTSettings->getSettings().powerUpPage);
118
        mActualPage = page.pageID;
3 andreas 119
    }
23 andreas 120
    else
121
    {
122
        MSG_WARNING("No power up page defined! Setting default page to 1.");
123
        mActualPage = 1;
124
    }
3 andreas 125
 
4 andreas 126
    TPage *pg = getPage(mActualPage);
127
 
3 andreas 128
    vector<string> popups = mTSettings->getSettings().powerUpPopup;
129
    vector<string>::iterator iter;
130
 
131
    for (iter = popups.begin(); iter != popups.end(); iter++)
132
    {
133
        if (readSubPage(*iter) == false)
14 andreas 134
        {
135
            surface_mutex.unlock();
3 andreas 136
            return;
14 andreas 137
        }
3 andreas 138
 
139
        MSG_TRACE("Found power up popup " << *iter);
4 andreas 140
 
141
        if (pg)
142
        {
143
            TSubPage *spage = getSubPage(*iter);
144
            pg->addSubPage(spage);
145
        }
3 andreas 146
    }
11 andreas 147
 
13 andreas 148
    MSG_INFO("Registering commands ...");
14 andreas 149
    REG_CMD(doAPG, "@APG");
150
    REG_CMD(doCPG, "@CPG");
151
    REG_CMD(doDPG, "@DPG");
15 andreas 152
//    REG_CMD(doPDR, "@PDR");
153
    REG_CMD(doPHE, "@PHE");
154
    REG_CMD(doPHP, "@PHP");
155
    REG_CMD(doPHT, "@PHT");
14 andreas 156
    REG_CMD(doPPA, "@PPA");
157
    REG_CMD(doPPF, "@PPF");
158
    REG_CMD(doPPF, "PPOF");
159
    REG_CMD(doPPG, "@PPG");
160
    REG_CMD(doPPG, "PPOG");
161
    REG_CMD(doPPK, "@PPK");
162
    REG_CMD(doPPM, "@PPM");
163
    REG_CMD(doPPN, "@PPN");
164
    REG_CMD(doPPN, "PPON");
15 andreas 165
    REG_CMD(doPPT, "@PPT");
14 andreas 166
    REG_CMD(doPPX, "@PPX");
15 andreas 167
    REG_CMD(doPSE, "@PSE");
168
    REG_CMD(doPSP, "@PSP");
169
    REG_CMD(doPST, "@PSP");
14 andreas 170
    REG_CMD(doPAGE, "PAGE");
11 andreas 171
 
15 andreas 172
    REG_CMD(doAPF, "^APF");
173
    REG_CMD(doBMP, "^BMP");
16 andreas 174
    REG_CMD(doBOP, "^BOP");
175
    REG_CMD(doBSP, "^BSP");
176
    REG_CMD(doBWW, "^BWW");
177
    REG_CMD(doCPF, "^CPF");
178
    REG_CMD(doDPF, "^DPF");
179
    REG_CMD(doENA, "^ENA");
180
    REG_CMD(doFON, "^FON");
14 andreas 181
    REG_CMD(doICO, "^ICO");
16 andreas 182
    REG_CMD(doSHO, "^SHO");
14 andreas 183
    REG_CMD(doTXT, "^TXT");
184
 
21 andreas 185
    REG_CMD(doBBR, "^BBR");
186
    REG_CMD(doRMF, "^RMF");
187
 
14 andreas 188
    REG_CMD(doON, "ON");
189
    REG_CMD(doOFF, "OFF");
15 andreas 190
    REG_CMD(doLEVEL, "LEVEL");
191
    REG_CMD(doBLINK, "BLINK");
14 andreas 192
 
26 andreas 193
    REG_CMD(doFTR, "#FTR");     // File transfer (virtual internal command)
23 andreas 194
 
11 andreas 195
    // Registering callback to receive controller events.
13 andreas 196
    MSG_INFO("Starting communication with controller ...");
11 andreas 197
    mAmxNet = new amx::TAmxNet();
13 andreas 198
    MSG_INFO("Registering callback for received commands ...");
11 andreas 199
    mAmxNet->setCallback(bind(&TPageManager::doCommand, this, std::placeholders::_1));
13 andreas 200
    mAmxNet->setPanelID(TConfig::getChannel());
201
 
11 andreas 202
    try
203
    {
13 andreas 204
        MSG_INFO("Starting thread for communication with controller ...");
11 andreas 205
        mThreadAmxNet = std::thread([=] { mAmxNet->Run(); });
13 andreas 206
        MSG_INFO("Thread started. Detaching ...");
11 andreas 207
        mThreadAmxNet.detach();
13 andreas 208
        MSG_INFO("Thread is running and detached.");
11 andreas 209
    }
210
    catch (std::exception& e)
211
    {
212
        MSG_ERROR("Error starting the AmxNet thread: " << e.what());
213
    }
14 andreas 214
 
215
    surface_mutex.unlock();
3 andreas 216
}
217
 
218
TPageManager::~TPageManager()
219
{
220
    DECL_TRACER("TPageManager::~TPageManager()");
221
 
222
    PCHAIN_T *p = mPchain;
223
    PCHAIN_T *next = nullptr;
224
 
225
    try
226
    {
227
        while (p)
228
        {
229
            next = p->next;
230
 
231
            if (p->page)
232
                delete p->page;
233
 
234
            delete p;
235
            p = next;
236
        }
237
 
238
        SPCHAIN_T *sp = mSPchain;
239
        SPCHAIN_T *snext = nullptr;
240
 
241
        while (sp)
242
        {
243
            snext = sp->next;
244
 
245
            if (sp->page)
246
                delete sp->page;
247
 
248
            delete sp;
5 andreas 249
            sp = snext;
3 andreas 250
        }
251
 
252
        mPchain = nullptr;
253
        mSPchain = nullptr;
14 andreas 254
        setPChain(mPchain);
255
        setSPChain(mSPchain);
3 andreas 256
 
13 andreas 257
        if (mAmxNet)
258
        {
259
            delete mAmxNet;
260
            mAmxNet = nullptr;
261
        }
262
 
3 andreas 263
        if (mTSettings)
264
        {
265
            delete mTSettings;
266
            mTSettings = nullptr;
267
        }
268
 
269
        if (mPageList)
270
        {
271
            delete mPageList;
272
            mPageList = nullptr;
273
        }
5 andreas 274
 
275
        if (mPalette)
276
        {
277
            delete mPalette;
278
            mPalette = nullptr;
279
        }
7 andreas 280
 
281
        if (mFonts)
282
        {
283
            delete mFonts;
284
            mFonts = nullptr;
285
        }
8 andreas 286
 
287
        if (gIcons)
288
        {
289
            delete gIcons;
290
            gIcons = nullptr;
291
        }
292
 
293
        if (gPrjResources)
294
        {
295
            delete gPrjResources;
296
            gPrjResources = nullptr;
297
        }
3 andreas 298
    }
299
    catch (std::exception& e)
300
    {
301
        MSG_ERROR("Memory error: " << e.what());
302
    }
303
}
304
 
11 andreas 305
void TPageManager::initialize()
306
{
307
    DECL_TRACER("TPageManager::initialize()");
308
 
14 andreas 309
    surface_mutex.lock();
11 andreas 310
    dropAllSubPages();
311
    dropAllPages();
312
 
313
    if (mTSettings)
314
        mTSettings->loadSettings();
315
    else
316
        mTSettings = new TSettings(TConfig::getProjectPath());
317
 
318
    if (TError::isError())
14 andreas 319
    {
320
        surface_mutex.unlock();
11 andreas 321
        return;
14 andreas 322
    }
11 andreas 323
 
324
    if (!gPrjResources)
325
        gPrjResources = new TPrjResources(mTSettings->getResourcesList());
326
 
327
    if (!mPalette)
328
        mPalette = new TPalette();
329
    else
330
        mPalette->reset();
331
 
332
    vector<PALETTE_SETUP>::iterator iterPal;
333
    vector<PALETTE_SETUP> pal = mTSettings->getSettings().palettes;
334
 
335
    for (iterPal = pal.begin(); iterPal != pal.end(); iterPal++)
336
        mPalette->initialize(iterPal->file);
337
 
338
    if (!TError::isError())
339
        TColor::setPalette(mPalette);
340
 
341
    if (!mFonts)
342
        mFonts = new TFont();
343
    else
344
        mFonts->initialize();
345
 
346
    if (TError::isError())
347
    {
348
        MSG_ERROR("Initializing fonts was not successfull!");
14 andreas 349
        surface_mutex.unlock();
11 andreas 350
        return;
351
    }
352
 
353
    if (!gIcons)
354
        gIcons = new TIcons();
355
    else
356
        gIcons->initialize();
357
 
358
    if (TError::isError())
359
    {
360
        MSG_ERROR("Initializing icons was not successfull!");
14 andreas 361
        surface_mutex.unlock();
11 andreas 362
        return;
363
    }
364
 
365
    if (!mPageList)
366
        mPageList = new TPageList();
367
    else
368
        mPageList->initialize();
369
 
370
    if (TError::isError())
14 andreas 371
    {
372
        surface_mutex.unlock();
11 andreas 373
        return;
14 andreas 374
    }
11 andreas 375
 
376
    PAGELIST_T page;
377
 
378
    if (!mTSettings->getSettings().powerUpPage.empty())
379
    {
380
        if (readPage(mTSettings->getSettings().powerUpPage) == false)
14 andreas 381
        {
382
            surface_mutex.unlock();
11 andreas 383
            return;
14 andreas 384
        }
11 andreas 385
 
386
        MSG_TRACE("Found power up page " << mTSettings->getSettings().powerUpPage);
387
        page = findPage(mTSettings->getSettings().powerUpPage);
388
        mActualPage = page.pageID;
389
    }
390
 
391
    TPage *pg = getPage(mActualPage);
392
 
393
    vector<string> popups = mTSettings->getSettings().powerUpPopup;
394
    vector<string>::iterator iter;
395
 
396
    for (iter = popups.begin(); iter != popups.end(); iter++)
397
    {
398
        if (readSubPage(*iter) == false)
14 andreas 399
        {
400
            surface_mutex.unlock();
11 andreas 401
            return;
14 andreas 402
        }
11 andreas 403
 
404
        MSG_TRACE("Found power up popup " << *iter);
405
 
406
        if (pg)
407
        {
408
            TSubPage *spage = getSubPage(*iter);
409
            pg->addSubPage(spage);
410
        }
411
    }
412
 
413
    // Start the thread
13 andreas 414
    if (!mAmxNet || !mThreadAmxNet.joinable())
11 andreas 415
    {
13 andreas 416
        try
417
        {
418
            if (!mAmxNet)
419
            {
420
                mAmxNet = new amx::TAmxNet();
421
                mAmxNet->setCallback(bind(&TPageManager::doCommand, this, std::placeholders::_1));
422
            }
14 andreas 423
 
13 andreas 424
            if (!mThreadAmxNet.joinable())
425
            {
426
                MSG_INFO("Starting thread for communication with controller ...");
427
                mThreadAmxNet = std::thread([=] { mAmxNet->Run(); });
428
                MSG_INFO("Thread started. Detaching ...");
429
                mThreadAmxNet.detach();
430
                MSG_INFO("Thread is running and detached.");
431
            }
432
        }
433
        catch (std::exception& e)
434
        {
435
            MSG_ERROR("Error starting the AmxNet thread: " << e.what());
436
        }
11 andreas 437
    }
14 andreas 438
 
439
    surface_mutex.unlock();
11 andreas 440
}
441
 
442
/*
443
 * The following method is called by the class TAmxNet whenever an event from
444
 * the controller occured.
445
 */
446
void TPageManager::doCommand(const amx::ANET_COMMAND& cmd)
447
{
448
    DECL_TRACER("TPageManager::doCommand(const amx::ANET_COMMAND& cmd)");
449
 
450
    mCommands.push_back(cmd);
451
 
452
    if (mBusy)
453
        return;
454
 
455
    mBusy = true;
456
    string com;
457
 
458
    while (mCommands.size() > 0)
459
    {
460
        amx::ANET_COMMAND& bef = mCommands.at(0);
461
        mCommands.erase(mCommands.begin());
462
 
463
        switch (bef.MC)
464
        {
465
            case 0x0006:
466
            case 0x0018:	// feedback channel on
467
                com.assign("ON-");
468
                com.append(to_string(bef.data.chan_state.channel));
469
                parseCommand(bef.device1, bef.data.chan_state.port, com);
14 andreas 470
            break;
11 andreas 471
 
472
            case 0x0007:
473
            case 0x0019:	// feedback channel off
474
                com.assign("OFF-");
475
                com.append(to_string(bef.data.chan_state.channel));
476
                parseCommand(bef.device1, bef.data.chan_state.port, com);
14 andreas 477
            break;
11 andreas 478
 
479
            case 0x000a:	// level value change
480
                com = "LEVEL-";
481
                com += to_string(bef.data.message_value.value);
482
                com += ",";
483
 
484
                switch (bef.data.message_value.type)
485
                {
486
                    case 0x10: com += to_string(bef.data.message_value.content.byte); break;
487
                    case 0x11: com += to_string(bef.data.message_value.content.ch); break;
488
                    case 0x20: com += to_string(bef.data.message_value.content.integer); break;
489
                    case 0x21: com += to_string(bef.data.message_value.content.sinteger); break;
490
                    case 0x40: com += to_string(bef.data.message_value.content.dword); break;
491
                    case 0x41: com += to_string(bef.data.message_value.content.sdword); break;
492
                    case 0x4f: com += to_string(bef.data.message_value.content.fvalue); break;
493
                    case 0x8f: com += to_string(bef.data.message_value.content.dvalue); break;
494
                }
495
 
496
                parseCommand(bef.device1, bef.data.chan_state.port, com);
497
            break;
498
 
499
            case 0x000c:	// Command string
500
            {
501
                amx::ANET_MSG_STRING msg = bef.data.message_string;
502
 
503
                if (msg.length < strlen((char *)&msg.content))
504
                {
505
                    mCmdBuffer.append((char *)&msg.content);
506
                    break;
507
                }
508
                else if (mCmdBuffer.length() > 0)
509
                {
510
                    mCmdBuffer.append((char *)&msg.content);
511
                    size_t len = (mCmdBuffer.length() >= sizeof(msg.content)) ? (sizeof(msg.content)-1) : mCmdBuffer.length();
512
                    strncpy((char *)&msg.content, mCmdBuffer.c_str(), len);
513
                    msg.content[len] = 0;
514
                }
515
 
516
                com.assign(cp1250ToUTF8((char *)&msg.content));
14 andreas 517
                parseCommand( bef.device1, bef.data.chan_state.port, com);
11 andreas 518
                mCmdBuffer.clear();
519
            }
520
            break;
521
 
15 andreas 522
            case 0x0502:    // Blink message (contains date and time)
523
                com = "BLINK-" + to_string(bef.data.blinkMessage.hour) + ":";
524
                com += to_string(bef.data.blinkMessage.minute) + ":";
525
                com += to_string(bef.data.blinkMessage.second) + ",";
526
                com += to_string(bef.data.blinkMessage.year) + "-";
527
                com += to_string(bef.data.blinkMessage.month) + "-";
528
                com += to_string(bef.data.blinkMessage.day) + ",";
529
                com += to_string(bef.data.blinkMessage.weekday) + ",";
530
                com += ((bef.data.blinkMessage.LED & 0x0001) ? "ON" : "OFF");
531
                parseCommand(0, 0, com);
532
            break;
533
 
11 andreas 534
            case 0x1000:	// Filetransfer
535
            {
536
                amx::ANET_FILETRANSFER ftr = bef.data.filetransfer;
537
 
538
                if (ftr.ftype == 0)
539
                {
540
                    switch(ftr.function)
541
                    {
542
                        case 0x0100:	// Syncing directory
543
                            com = "#FTR-SYNC:0:";
544
                            com.append((char*)&ftr.data[0]);
545
                            parseCommand(bef.device1, bef.port1, com);
546
                        break;
547
 
548
                        case 0x0104:	// Delete file
549
                            com = "#FTR-SYNC:"+to_string(bef.count)+":Deleting files ... ("+to_string(bef.count)+"%)";
550
                            parseCommand(bef.device1, bef.port1, com);
551
                        break;
552
 
553
                        case 0x0105:	// start filetransfer
554
                            com = "#FTR-START";
555
                            parseCommand(bef.device1, bef.port1, com);
556
                        break;
557
                    }
558
                }
559
                else
560
                {
561
                    switch(ftr.function)
562
                    {
563
                        case 0x0003:	// Received part of file
564
                        case 0x0004:	// End of file
565
                            com = "#FTR-FTRPART:"+to_string(bef.count)+":"+to_string(ftr.info1);
566
                            parseCommand(bef.device1, bef.port1, com);
567
                        break;
568
 
569
                        case 0x0007:	// End of file transfer
570
                        {
571
                            initialize();
572
                            com = "#FTR-END";
573
                            parseCommand(bef.device1, bef.port1, com);
574
                        }
575
                        break;
576
 
577
                        case 0x0102:	// Receiving file
578
                            com = "#FTR-FTRSTART:"+to_string(bef.count)+":"+to_string(ftr.info1)+":";
579
                            com.append((char*)&ftr.data[0]);
580
                            parseCommand(bef.device1, bef.port1, com);
581
                        break;
582
                    }
583
                }
584
            }
585
            break;
586
        }
587
    }
588
 
14 andreas 589
    runDoCommand = false;
11 andreas 590
    mBusy = false;
591
}
592
 
26 andreas 593
void TPageManager::deployCallbacks()
594
{
595
    DECL_TRACER("TPageManager::deployCallbacks()");
596
 
597
    PCHAIN_T *p = mPchain;
598
 
599
    while (p)
600
    {
601
        if (p->page)
602
        {
603
            if (_setBackground)
604
                p->page->registerCallback(_setBackground);
605
 
606
            if (_setText)
607
                p->page->registerCallbackFT(_setText);
608
 
609
            if (_callPlayVideo)
610
                p->page->regCallPlayVideo(_callPlayVideo);
611
        }
612
 
613
        p = p->next;
614
    }
615
 
616
    SPCHAIN_T *sp = mSPchain;
617
 
618
    while (sp)
619
    {
620
        if (sp->page)
621
        {
622
            if (_setBackground)
623
                sp->page->registerCallback(_setBackground);
624
 
625
            if (_setText)
626
                sp->page->registerCallbackFT(_setText);
627
 
628
            if (_callPlayVideo)
629
                sp->page->regCallPlayVideo(_callPlayVideo);
630
        }
631
 
632
        sp = sp->next;
633
    }
634
}
11 andreas 635
/*
636
 * The following function must be called to start the "panel".
637
 */
5 andreas 638
bool TPageManager::run()
639
{
640
    DECL_TRACER("TPageManager::run()");
641
 
642
    if (mActualPage <= 0)
643
        return false;
644
 
14 andreas 645
    surface_mutex.lock();
5 andreas 646
    TPage *pg = getPage(mActualPage);
7 andreas 647
    pg->setFonts(mFonts);
5 andreas 648
    pg->registerCallback(_setBackground);
7 andreas 649
    pg->registerCallbackFT(_setText);
21 andreas 650
    pg->regCallPlayVideo(_callPlayVideo);
5 andreas 651
 
652
    if (!pg || !_setPage || !mTSettings)
14 andreas 653
    {
654
        surface_mutex.unlock();
5 andreas 655
        return false;
14 andreas 656
    }
5 andreas 657
 
26 andreas 658
    int width, height;
659
    width = mTSettings->getWith();
660
    height = mTSettings->getHeight();
661
 
662
    if (mScaleFactor != 1.0)
663
    {
664
        width = (int)((double)width * mScaleFactor);
665
        height = (int)((double)height * mScaleFactor);
666
    }
667
 
668
    _setPage((pg->getNumber() << 16) & 0xffff0000, width, height);
5 andreas 669
    pg->show();
670
 
671
    TSubPage *subPg = pg->getFirstSubPage();
672
 
673
    while (subPg)
674
    {
7 andreas 675
        subPg->setFonts(mFonts);
676
        subPg->registerCallback(_setBackground);
677
        subPg->registerCallbackDB(_displayButton);
11 andreas 678
        subPg->regCallDropSubPage(_callDropSubPage);
7 andreas 679
        subPg->registerCallbackFT(_setText);
21 andreas 680
        subPg->regCallPlayVideo(_callPlayVideo);
7 andreas 681
 
5 andreas 682
        if (_setSubPage)
6 andreas 683
        {
684
            MSG_DEBUG("Drawing page " << subPg->getNumber() << ": " << subPg->getName() << "...");
26 andreas 685
            width = subPg->getWidth();
686
            height = subPg->getHeight();
687
            int left = subPg->getLeft();
688
            int top = subPg->getTop();
689
 
690
            if (mScaleFactor != 1.0)
691
            {
692
                width = (int)((double)width * mScaleFactor);
693
                height = (int)((double)height * mScaleFactor);
694
                left = (int)((double)left * mScaleFactor);
695
                top = (int)((double)top * mScaleFactor);
696
            }
697
 
698
            _setSubPage(((subPg->getNumber() << 16) & 0xffff0000), left, top, width, height);
6 andreas 699
            subPg->show();
700
        }
5 andreas 701
 
702
        subPg = pg->getNextSubPage();
703
    }
704
 
14 andreas 705
    surface_mutex.unlock();
5 andreas 706
    return true;
707
}
708
 
4 andreas 709
TPage *TPageManager::getPage(int pageID)
710
{
711
    DECL_TRACER("TPageManager::getPage(int pageID)");
712
 
713
    PCHAIN_T *p = mPchain;
714
 
715
    while (p)
716
    {
717
        if (p->page->getNumber() == pageID)
718
            return p->page;
719
 
720
        p = p->next;
721
    }
722
 
14 andreas 723
    MSG_DEBUG("Page " << pageID << " not found!");
4 andreas 724
    return nullptr;
725
}
726
 
727
TPage *TPageManager::getPage(const string& name)
728
{
729
    DECL_TRACER("TPageManager::getPage(const string& name)");
730
 
731
    PCHAIN_T *p = mPchain;
732
 
733
    while (p)
734
    {
735
        if (p->page->getName().compare(name) == 0)
736
            return p->page;
737
 
738
        p = p->next;
739
    }
740
 
14 andreas 741
    MSG_DEBUG("Page " << name << " not found!");
4 andreas 742
    return nullptr;
743
}
744
 
15 andreas 745
TPage *TPageManager::loadPage(PAGELIST_T& pl)
746
{
747
    DECL_TRACER("TPageManager::loadPage(PAGELIST_T& pl)");
748
 
749
    if (!pl.isValid)
750
        return nullptr;
751
 
752
    TPage *pg = getPage(pl.pageID);
753
 
754
    if (!pg)
755
    {
756
        if (!readPage(pl.pageID))
757
            return nullptr;
758
 
759
        pg = getPage(pl.pageID);
760
 
761
        if (!pg)
762
        {
763
            MSG_ERROR("Error loading page " << pl.pageID << ", " << pl.name << " from file " << pl.file << "!");
764
            return nullptr;
765
        }
766
    }
767
 
768
    return pg;
769
}
770
 
771
bool TPageManager::setPage(int PageID)
772
{
773
    DECL_TRACER("TPageManager::setPage(int PageID)");
774
 
775
    if (mActualPage == PageID)
776
        return true;
777
 
778
    TPage *pg = getPage(mActualPage);
779
    mPreviousPage = mActualPage;
780
 
781
    if (pg)
782
        pg->drop();
783
 
784
    mActualPage = 0;
785
    PAGELIST_T listPg = findPage(PageID);
786
 
787
    if ((pg = loadPage(listPg)) == nullptr)
788
        return false;
789
 
790
    mActualPage = PageID;
791
    pg->show();
792
    return true;
793
}
794
 
795
bool TPageManager::setPage(const string& name)
796
{
797
    DECL_TRACER("TPageManager::setPage(const string& name)");
798
 
799
    TPage *pg = getPage(mActualPage);
800
 
801
    if (pg && pg->getName().compare(name) == 0)
802
        return true;
803
 
804
    mPreviousPage = mActualPage;
805
 
806
    if (pg)
807
        pg->drop();
808
 
809
    mActualPage = 0;
810
    PAGELIST_T listPg = findPage(name);
811
 
812
    if ((pg = loadPage(listPg)) == nullptr)
813
        return false;
814
 
815
    mActualPage = pg->getNumber();
816
    pg->show();
817
    return true;
818
}
819
 
4 andreas 820
TSubPage *TPageManager::getSubPage(int pageID)
821
{
822
    DECL_TRACER("TPageManager::getSubPage(int pageID)");
823
 
824
    SPCHAIN_T *p = mSPchain;
825
 
826
    while(p)
827
    {
828
        if (p->page->getNumber() == pageID)
829
            return p->page;
830
 
831
        p = p->next;
832
    }
833
 
834
    return nullptr;
835
}
836
 
837
TSubPage *TPageManager::getSubPage(const std::string& name)
838
{
839
    DECL_TRACER("TPageManager::getSubPage(const std::string& name)");
840
 
841
    SPCHAIN_T *p = mSPchain;
842
 
843
    while (p)
844
    {
845
        if (p->page->getName().compare(name) == 0)
846
            return p->page;
847
 
848
        p = p->next;
849
    }
850
 
851
    return nullptr;
852
}
853
 
3 andreas 854
bool TPageManager::readPages()
855
{
856
    DECL_TRACER("TPageManager::readPages()");
857
 
858
    if (!mPageList)
859
    {
860
        MSG_ERROR("Page list is not initialized!");
861
        TError::setError();
862
        return false;
863
    }
864
 
865
    // Read all pages
866
    vector<PAGELIST_T>::iterator pgIter;
867
    vector<PAGELIST_T> pageList = mPageList->getPagelist();
868
 
869
    for (pgIter = pageList.begin(); pgIter != pageList.end(); pgIter++)
870
    {
871
        TPage *page = new TPage(pgIter->name+".xml");
14 andreas 872
 
873
        if (TError::isError())
874
        {
875
            delete page;
876
            return false;
877
        }
878
 
4 andreas 879
        page->setPalette(mPalette);
7 andreas 880
        page->setFonts(mFonts);
881
        page->registerCallback(_setBackground);
882
        page->registerCallbackDB(_displayButton);
883
        page->registerCallbackFT(_setText);
21 andreas 884
        page->regCallPlayVideo(_callPlayVideo);
3 andreas 885
 
886
        if (!addPage(page))
887
            return false;
888
    }
889
 
890
    vector<SUBPAGELIST_T>::iterator spgIter;
891
    vector<SUBPAGELIST_T> subPageList = mPageList->getSupPageList();
892
 
893
    for (spgIter = subPageList.begin(); spgIter != subPageList.end(); spgIter++)
894
    {
895
        TSubPage *page = new TSubPage(spgIter->name+".xml");
14 andreas 896
 
897
        if (TError::isError())
898
        {
899
            delete page;
900
            return false;
901
        }
902
 
4 andreas 903
        page->setPalette(mPalette);
7 andreas 904
        page->setFonts(mFonts);
905
        page->registerCallback(_setBackground);
906
        page->registerCallbackDB(_displayButton);
11 andreas 907
        page->regCallDropSubPage(_callDropSubPage);
7 andreas 908
        page->registerCallbackFT(_setText);
21 andreas 909
        page->regCallPlayVideo(_callPlayVideo);
11 andreas 910
        page->setGroup(spgIter->group);
3 andreas 911
 
912
        if (!addSubPage(page))
913
            return false;
914
    }
915
 
916
    return true;
917
}
918
 
919
bool TPageManager::readPage(const std::string& name)
920
{
921
    DECL_TRACER("TPageManager::readPage(const std::string& name)");
922
 
923
    PAGELIST_T page = findPage(name);
924
 
925
    if (page.pageID <= 0)
926
    {
927
        MSG_ERROR("Page " << name << " not found!");
928
        return false;
929
    }
930
 
931
    TPage *pg = new TPage(page.name+".xml");
14 andreas 932
 
933
    if (TError::isError())
934
    {
935
        delete pg;
936
        return false;
937
    }
938
 
4 andreas 939
    pg->setPalette(mPalette);
7 andreas 940
    pg->setFonts(mFonts);
941
    pg->registerCallback(_setBackground);
942
    pg->registerCallbackDB(_displayButton);
943
    pg->registerCallbackFT(_setText);
21 andreas 944
    pg->regCallPlayVideo(_callPlayVideo);
3 andreas 945
 
946
    if (!addPage(pg))
947
        return false;
948
 
949
    return true;
950
}
951
 
952
bool TPageManager::readPage(int ID)
953
{
954
    DECL_TRACER("TPageManager::readPage(int ID)");
955
 
16 andreas 956
    TError::clear();
3 andreas 957
    PAGELIST_T page = findPage(ID);
958
 
959
    if (page.pageID <= 0)
960
    {
961
        MSG_ERROR("Page with ID " << ID << " not found!");
962
        return false;
963
    }
964
 
965
    TPage *pg = new TPage(page.name+".xml");
14 andreas 966
 
967
    if (TError::isError())
968
    {
969
        delete pg;
970
        return false;
971
    }
972
 
4 andreas 973
    pg->setPalette(mPalette);
7 andreas 974
    pg->setFonts(mFonts);
975
    pg->registerCallback(_setBackground);
976
    pg->registerCallbackDB(_displayButton);
977
    pg->registerCallbackFT(_setText);
21 andreas 978
    pg->regCallPlayVideo(_callPlayVideo);
3 andreas 979
 
980
    if (!addPage(pg))
981
        return false;
982
 
983
    return true;
984
}
985
 
986
bool TPageManager::readSubPage(const std::string& name)
987
{
988
    DECL_TRACER("TPageManager::readSubPage(const std::string& name)");
989
 
16 andreas 990
    TError::clear();
3 andreas 991
    SUBPAGELIST_T page = findSubPage(name);
992
 
993
    if (page.pageID <= 0)
994
    {
995
        MSG_ERROR("Subpage " << name << " not found!");
996
        return false;
997
    }
998
 
14 andreas 999
    if (haveSubPage(name))
1000
        return true;
1001
 
3 andreas 1002
    TSubPage *pg = new TSubPage(page.name+".xml");
14 andreas 1003
 
1004
    if (TError::isError())
1005
    {
1006
        delete pg;
1007
        return false;
1008
    }
1009
 
4 andreas 1010
    pg->setPalette(mPalette);
7 andreas 1011
    pg->setFonts(mFonts);
1012
    pg->registerCallback(_setBackground);
1013
    pg->registerCallbackDB(_displayButton);
11 andreas 1014
    pg->regCallDropSubPage(_callDropSubPage);
7 andreas 1015
    pg->registerCallbackFT(_setText);
21 andreas 1016
    pg->regCallPlayVideo(_callPlayVideo);
11 andreas 1017
    pg->setGroup(page.group);
3 andreas 1018
 
1019
    if (!addSubPage(pg))
14 andreas 1020
    {
1021
        delete pg;
3 andreas 1022
        return false;
14 andreas 1023
    }
3 andreas 1024
 
1025
    return true;
1026
}
1027
 
1028
bool TPageManager::readSubPage(int ID)
1029
{
1030
    DECL_TRACER("TPageManager::readSubPage(int ID)");
1031
 
16 andreas 1032
    TError::clear();
3 andreas 1033
    SUBPAGELIST_T page = findSubPage(ID);
1034
 
1035
    if (page.pageID <= 0)
1036
    {
1037
        MSG_ERROR("Subpage with ID " << ID << " not found!");
1038
        return false;
1039
    }
1040
 
1041
    TSubPage *pg = new TSubPage(page.name+".xml");
14 andreas 1042
 
1043
    if (TError::isError())
1044
    {
1045
        delete pg;
1046
        return false;
1047
    }
1048
 
4 andreas 1049
    pg->setPalette(mPalette);
7 andreas 1050
    pg->setFonts(mFonts);
1051
    pg->registerCallback(_setBackground);
1052
    pg->registerCallbackDB(_displayButton);
11 andreas 1053
    pg->regCallDropSubPage(_callDropSubPage);
7 andreas 1054
    pg->registerCallbackFT(_setText);
21 andreas 1055
    pg->regCallPlayVideo(_callPlayVideo);
11 andreas 1056
    pg->setGroup(page.group);
3 andreas 1057
 
1058
    if (!addSubPage(pg))
1059
        return false;
1060
 
1061
    return true;
1062
}
1063
 
1064
/******************** Internal private methods *********************/
1065
 
1066
PAGELIST_T TPageManager::findPage(const std::string& name)
1067
{
1068
    DECL_TRACER("TPageManager::findPage(const std::string& name)");
1069
 
1070
    vector<PAGELIST_T>::iterator pgIter;
1071
    vector<PAGELIST_T> pageList = mPageList->getPagelist();
1072
 
1073
    for (pgIter = pageList.begin(); pgIter != pageList.end(); pgIter++)
1074
    {
1075
        if (pgIter->name.compare(name) == 0)
1076
            return *pgIter;
1077
    }
1078
 
1079
    return PAGELIST_T();
1080
}
1081
 
1082
PAGELIST_T TPageManager::findPage(int ID)
1083
{
1084
    DECL_TRACER("TPageManager::findPage(int ID)");
1085
 
1086
    vector<PAGELIST_T>::iterator pgIter;
1087
    vector<PAGELIST_T> pageList = mPageList->getPagelist();
1088
 
1089
    for (pgIter = pageList.begin(); pgIter != pageList.end(); pgIter++)
1090
    {
1091
        if (pgIter->pageID == ID)
1092
            return *pgIter;
1093
    }
1094
 
1095
    return PAGELIST_T();
1096
}
1097
 
1098
SUBPAGELIST_T TPageManager::findSubPage(const std::string& name)
1099
{
1100
    DECL_TRACER("TPageManager::findSubPage(const std::string& name)");
1101
 
1102
    vector<SUBPAGELIST_T>::iterator pgIter;
1103
    vector<SUBPAGELIST_T> pageList = mPageList->getSupPageList();
1104
 
1105
    for (pgIter = pageList.begin(); pgIter != pageList.end(); pgIter++)
1106
    {
1107
        if (pgIter->name.compare(name) == 0)
1108
            return *pgIter;
1109
    }
1110
 
1111
    return SUBPAGELIST_T();
1112
}
1113
 
1114
SUBPAGELIST_T TPageManager::findSubPage(int ID)
1115
{
1116
    DECL_TRACER("TPageManager::findSubPage(int ID)");
1117
 
1118
    vector<SUBPAGELIST_T>::iterator pgIter;
1119
    vector<SUBPAGELIST_T> pageList = mPageList->getSupPageList();
1120
 
1121
    for (pgIter = pageList.begin(); pgIter != pageList.end(); pgIter++)
1122
    {
1123
        if (pgIter->pageID == ID)
1124
            return *pgIter;
1125
    }
1126
 
1127
    return SUBPAGELIST_T();
1128
}
1129
 
1130
bool TPageManager::addPage(TPage* pg)
1131
{
1132
    DECL_TRACER("TPageManager::addPage(TPage* pg)");
1133
 
1134
    if (!pg)
1135
    {
1136
        MSG_ERROR("Parameter is NULL!");
1137
        TError::setError();
1138
        return false;
1139
    }
1140
 
1141
    PCHAIN_T *chain = new PCHAIN_T;
1142
    chain->page = pg;
5 andreas 1143
    chain->next = nullptr;
3 andreas 1144
 
1145
    if (mPchain)
1146
    {
1147
        PCHAIN_T *p = mPchain;
1148
 
1149
        while (p->next)
1150
            p = p->next;
1151
 
1152
        p->next = chain;
1153
    }
1154
    else
14 andreas 1155
    {
3 andreas 1156
        mPchain = chain;
14 andreas 1157
        setPChain(mPchain);
1158
    }
3 andreas 1159
 
1160
    MSG_DEBUG("Added page " << chain->page->getName());
1161
    return true;
1162
}
1163
 
1164
bool TPageManager::addSubPage(TSubPage* pg)
1165
{
1166
    DECL_TRACER("TPageManager::addSubPage(TSubPage* pg)");
1167
 
1168
    if (!pg)
1169
    {
1170
        MSG_ERROR("Parameter is NULL!");
1171
        TError::setError();
1172
        return false;
1173
    }
1174
 
14 andreas 1175
    if (haveSubPage(pg->getNumber()))
1176
    {
1177
        MSG_ERROR("Subpage " << pg->getNumber() << ", " << pg->getName() << " is already in chain!");
1178
        return false;
1179
    }
1180
 
3 andreas 1181
    SPCHAIN_T *chain = new SPCHAIN_T;
1182
    chain->page = pg;
5 andreas 1183
    chain->next = nullptr;
3 andreas 1184
 
1185
    if (mSPchain)
1186
    {
1187
        SPCHAIN_T *p = mSPchain;
1188
 
1189
        while (p->next)
1190
            p = p->next;
1191
 
1192
        p->next = chain;
1193
    }
1194
    else
14 andreas 1195
    {
3 andreas 1196
        mSPchain = chain;
14 andreas 1197
        setSPChain(mSPchain);
1198
    }
3 andreas 1199
 
1200
    MSG_DEBUG("Added subpage " << chain->page->getName());
1201
    return true;
1202
}
4 andreas 1203
 
11 andreas 1204
void TPageManager::dropAllPages()
1205
{
1206
    DECL_TRACER("TPageManager::dropAllPages()");
1207
 
1208
    PCHAIN_T *pg = mPchain;
1209
    PCHAIN_T *next = nullptr;
1210
 
1211
    while (pg)
1212
    {
1213
        next = pg->next;
1214
 
1215
        if (pg->page)
1216
        {
1217
            if (_callDropPage)
1218
                _callDropPage((pg->page->getNumber() << 16) & 0xffff0000);
1219
 
1220
            delete pg->page;
1221
        }
1222
 
1223
        delete pg;
1224
        pg = next;
1225
    }
14 andreas 1226
 
1227
    mPchain = nullptr;
1228
    setPChain(mPchain);
11 andreas 1229
}
1230
 
1231
void TPageManager::dropAllSubPages()
1232
{
1233
    DECL_TRACER("TPageManager::dropAllSubPages()");
1234
 
1235
    SPCHAIN_T *spg = mSPchain;
1236
    SPCHAIN_T *next;
1237
 
1238
    while (spg)
1239
    {
1240
        next = spg->next;
1241
 
1242
        if (spg->page)
1243
        {
1244
            if (_callDropSubPage)
1245
                _callDropSubPage((spg->page->getNumber() << 16) & 0xffff0000);
1246
 
1247
            delete spg->page;
1248
        }
1249
 
1250
        delete spg;
1251
        spg = next;
1252
    }
14 andreas 1253
 
1254
    mSPchain = nullptr;
1255
    setSPChain(mSPchain);
11 andreas 1256
}
1257
 
4 andreas 1258
TPage *TPageManager::getActualPage()
1259
{
1260
    return getPage(mActualPage);
1261
}
1262
 
1263
TSubPage *TPageManager::getFirstSubPage()
1264
{
1265
    DECL_TRACER("TPageManager::getFirstSubPage()");
1266
    TPage *pg = getPage(mActualPage);
1267
 
1268
    if (!pg)
1269
        return nullptr;
1270
 
1271
    return pg->getFirstSubPage();
1272
}
1273
 
1274
TSubPage *TPageManager::getNextSubPage()
1275
{
1276
    DECL_TRACER("TPageManager::getNextSubPage()");
1277
 
1278
    TPage *pg = getPage(mActualPage);
1279
 
1280
    if (pg)
1281
        return pg->getNextSubPage();
1282
 
1283
    return nullptr;
1284
}
10 andreas 1285
 
11 andreas 1286
TSubPage *TPageManager::getFirstSubPageGroup(const string& group)
1287
{
1288
    DECL_TRACER("TPageManager::getFirstSubPageGroup(const string& group)");
1289
 
14 andreas 1290
    if (group.empty())
1291
    {
1292
        MSG_WARNING("Empty group name is invalid. Ignoring it!");
1293
        mActualGroupName.clear();
1294
        mActualGroupPage = nullptr;
1295
        return nullptr;
1296
    }
1297
 
11 andreas 1298
    mActualGroupName = group;
1299
    TSubPage *pg = getFirstSubPage();
1300
 
1301
    while (pg)
1302
    {
14 andreas 1303
        MSG_DEBUG("Evaluating group " << pg->getGroupName() << " with " << group);
1304
 
11 andreas 1305
        if (pg->getGroupName().compare(group) == 0)
1306
        {
1307
            mActualGroupPage = pg;
1308
            return pg;
1309
        }
1310
 
1311
        pg = getNextSubPage();
1312
    }
1313
 
1314
    mActualGroupName.clear();
1315
    mActualGroupPage = nullptr;
1316
    return nullptr;
1317
}
1318
 
1319
TSubPage *TPageManager::getNextSubPageGroup()
1320
{
1321
    DECL_TRACER("TPageManager::getNextSubPageGroup()");
1322
 
1323
    if (mActualGroupName.empty())
1324
        return nullptr;
1325
 
1326
    TSubPage *pg = getFirstSubPage();
1327
    bool found = false;
1328
 
1329
    while (pg)
1330
    {
14 andreas 1331
        MSG_DEBUG("Evaluating group " << pg->getGroupName() << " with " << mActualGroupName);
1332
 
1333
        if (!found && pg == mActualGroupPage)
11 andreas 1334
        {
1335
            pg = getNextSubPage();
14 andreas 1336
            found = true;
11 andreas 1337
            continue;
1338
        }
1339
 
14 andreas 1340
        if (found && pg->getGroupName().compare(mActualGroupName) == 0)
11 andreas 1341
        {
1342
            mActualGroupPage = pg;
1343
            return pg;
1344
        }
1345
 
1346
        pg = getNextSubPage();
1347
    }
1348
 
1349
    mActualGroupName.clear();
1350
    mActualGroupPage = nullptr;
1351
    return nullptr;
1352
}
1353
 
1354
TSubPage *TPageManager::getNextSubPageGroup(const string& group, TSubPage* pg)
1355
{
1356
    DECL_TRACER("TPageManager::getNextSubPageGroup(const string& group, TSubPage* pg)");
1357
 
1358
    if (group.empty() || !pg)
1359
        return nullptr;
1360
 
1361
    TSubPage *page = getFirstSubPage();
1362
    bool found = false;
1363
 
1364
    while (page)
1365
    {
14 andreas 1366
        MSG_DEBUG("Evaluating group " << pg->getGroupName() << " with " << group);
1367
 
1368
        if (!found && pg == page)
11 andreas 1369
        {
1370
            page = getNextSubPage();
14 andreas 1371
            found = true;
11 andreas 1372
            continue;
1373
        }
1374
 
14 andreas 1375
        if (found && page->getGroupName().compare(group) == 0)
11 andreas 1376
            return page;
1377
 
1378
        page = getNextSubPage();
1379
    }
1380
 
1381
    return nullptr;
1382
}
1383
 
1384
TSubPage *TPageManager::getTopPage()
1385
{
1386
    DECL_TRACER("TPageManager::getTopPage()");
1387
 
1388
    // Scan for all occupied regions
1389
    vector<RECT_T> regions;
1390
 
1391
    TSubPage *pg = getFirstSubPage();
1392
 
1393
    while (pg)
1394
    {
1395
        RECT_T r = pg->getRegion();
1396
        regions.push_back(r);
1397
        pg = getNextSubPage();
1398
    }
1399
 
1400
    // Now scan all pages against all regions to find the top most
1401
    pg = getFirstSubPage();
1402
    TSubPage *top = nullptr;
1403
    int zPos = 0;
1404
 
1405
    while (pg)
1406
    {
1407
        RECT_T r = pg->getRegion();
1408
        vector<RECT_T>::iterator iter;
1409
        int zo = 0;
1410
 
1411
        for (iter = regions.begin(); iter != regions.end(); iter++)
1412
        {
1413
            if (doOverlap(*iter, r) && zPos > zo)
1414
                top = pg;
1415
 
1416
            zo++;
1417
        }
1418
 
1419
        pg = getNextSubPage();
1420
        zPos++;
1421
    }
1422
 
1423
    return top;
1424
}
1425
 
1426
TSubPage *TPageManager::getCoordMatch(int x, int y)
1427
{
1428
    DECL_TRACER("TPageManager::getCoordMatch(int x, int y)");
1429
 
26 andreas 1430
    int realX = x;
1431
    int realY = y;
1432
 
11 andreas 1433
    // Reverse order of pages
1434
    map<int, TSubPage *> zOrder;
1435
    TSubPage *pg = getFirstSubPage();
1436
 
1437
    while (pg)
1438
    {
14 andreas 1439
        if (pg->isVisible())
1440
            zOrder.insert(pair<int, TSubPage *>(pg->getZOrder(), pg));
1441
 
11 andreas 1442
        pg = getNextSubPage();
1443
    }
1444
 
1445
    // Iterate in reverse order through array
1446
    map<int, TSubPage *>::reverse_iterator iter;
1447
 
1448
    for (iter = zOrder.rbegin(); iter != zOrder.rend(); iter++)
1449
    {
1450
        RECT_T r = iter->second->getRegion();
1451
 
26 andreas 1452
        if (r.left <= realX && (r.left + r.width) >= realX &&
1453
            r.top <= realY && (r.top + r.height) >= realY)
11 andreas 1454
        {
1455
            MSG_DEBUG("Click matches subpage " << iter->second->getNumber() << " (" << iter->second->getName() << ")");
1456
            return iter->second;
1457
        }
1458
    }
1459
 
1460
    return nullptr;
1461
}
1462
 
1463
bool TPageManager::doOverlap(RECT_T r1, RECT_T r2)
1464
{
1465
    DECL_TRACER("TPageManager::doOverlap(RECT_T r1, RECT_T r2)");
1466
 
1467
    // If one rectangle is on left side of other
1468
    if (r1.left >= r2.left || r2.left >= r1.left)
1469
        return false;
1470
 
1471
    // If one rectangle is above other
1472
    if (r1.top <= r2.top || r2.top <= r1.top)
1473
        return false;
1474
 
1475
    return true;
1476
}
1477
 
14 andreas 1478
bool TPageManager::havePage(const string& name)
11 andreas 1479
{
14 andreas 1480
    DECL_TRACER("TPageManager::havePage(const string& name)");
11 andreas 1481
 
14 andreas 1482
    if (name.empty())
1483
        return false;
1484
 
1485
    PCHAIN_T *pg = mPchain;
1486
 
1487
    while (pg)
1488
    {
1489
        if (pg->page && pg->page->getName().compare(name) == 0)
1490
            return true;
1491
 
1492
        pg = pg->next;
1493
    }
1494
 
1495
    return false;
1496
}
1497
 
1498
bool TPageManager::haveSubPage(const string& name)
1499
{
1500
    DECL_TRACER("TPageManager::haveSubPage(const string& name)");
1501
 
1502
    if (name.empty())
1503
        return false;
1504
 
11 andreas 1505
    SPCHAIN_T *pg = mSPchain;
1506
 
1507
    while (pg)
1508
    {
14 andreas 1509
        if (pg->page && pg->page->getName().compare(name) == 0)
1510
        {
1511
            MSG_DEBUG("Subpage " << pg->page->getNumber() << ", " << name << " found.");
1512
            return true;
1513
        }
1514
 
1515
        pg = pg->next;
1516
    }
1517
 
1518
    MSG_DEBUG("Subpage " << name << " not found.");
1519
    return false;
1520
}
1521
 
1522
bool TPageManager::haveSubPage(int id)
1523
{
1524
    DECL_TRACER("TPageManager::haveSubPage(int id)");
1525
 
1526
    SPCHAIN_T *pg = mSPchain;
1527
 
1528
    while (pg)
1529
    {
1530
        if (pg->page && pg->page->getNumber() == id)
1531
        {
1532
            MSG_DEBUG("Subpage " << pg->page->getNumber() << ", " << pg->page->getName() << " found.");
1533
            return true;
1534
        }
1535
 
1536
        pg = pg->next;
1537
    }
1538
 
1539
    MSG_DEBUG("Subpage " << id << " not found.");
1540
    return false;
1541
}
1542
 
1543
bool TPageManager::haveSubPage(const string& page, const string& name)
1544
{
1545
    DECL_TRACER("TPageManager::haveSubPage(const string& page, const string& name)");
1546
 
1547
    TPage *pg = getPage(page);
1548
 
1549
    if (!pg)
1550
        return false;
1551
 
1552
    TSubPage *spg = pg->getFirstSubPage();
1553
 
1554
    while (spg)
1555
    {
1556
        if (spg->getName().compare(name) == 0)
1557
        {
1558
            MSG_DEBUG("Subpage " << spg->getNumber() << ", " << name << " found.");
1559
            return true;
1560
        }
1561
 
1562
        spg = pg->getNextSubPage();
1563
    }
1564
 
1565
    MSG_DEBUG("Subpage " << name << " not found on page " << page << ".");
1566
    return false;
1567
}
1568
 
1569
bool TPageManager::haveSubPage(const string& page, int id)
1570
{
1571
    DECL_TRACER("TPageManager::haveSubPage(const string& page, int id)");
1572
 
1573
    TPage *pg = getPage(page);
1574
 
1575
    if (!pg)
1576
        return false;
1577
 
1578
    TSubPage *spg = pg->getFirstSubPage();
1579
 
1580
    while (spg)
1581
    {
1582
        if (spg->getNumber() == id)
1583
        {
1584
            MSG_DEBUG("Subpage " << spg->getNumber() << ", " << spg->getName() << " found.");
1585
            return true;
1586
        }
1587
 
1588
        spg = pg->getNextSubPage();
1589
    }
1590
 
1591
    MSG_DEBUG("Subpage " << id << " on page " << page << " not found.");
1592
    return false;
1593
}
1594
 
1595
void TPageManager::closeGroup(const string& group)
1596
{
1597
    DECL_TRACER("TPageManager::closeGroup(const string& group)");
1598
 
1599
    SPCHAIN_T *pg = mSPchain;
1600
 
1601
    while (pg)
1602
    {
11 andreas 1603
        if (pg->page->getGroupName().compare(group) == 0 && pg->page->isVisible())
1604
        {
1605
            pg->page->regCallDropSubPage(_callDropSubPage);
1606
            pg->page->drop();
1607
            break;
1608
        }
1609
 
1610
        pg = pg->next;
1611
    }
1612
}
1613
 
14 andreas 1614
void TPageManager::showSubPage(const string& name)
1615
{
1616
    DECL_TRACER("TPageManager::showSubPage(const string& name)");
1617
 
1618
    if (name.empty())
1619
        return;
1620
 
1621
    TPage *page = getActualPage();
1622
 
1623
    if (!page)
1624
    {
1625
        MSG_ERROR("No actual page loaded!");
1626
        return;
1627
    }
1628
 
1629
    TSubPage *pg = getSubPage(name);
1630
 
1631
    if (!pg)
1632
    {
1633
        MSG_DEBUG("Subpage " << name << " not in memory. Reading it ...");
1634
 
1635
        if (!readSubPage(name))
1636
            return;
1637
 
1638
        if ((pg = getSubPage(name)) == nullptr)
1639
            return;
1640
 
1641
        page->addSubPage(pg);
1642
    }
1643
 
1644
    string group = pg->getGroupName();
1645
 
1646
    if (!group.empty())
1647
    {
1648
        TSubPage *sub = getFirstSubPageGroup(group);
1649
 
1650
        while(sub)
1651
        {
1652
            if (sub->isVisible() && sub->getNumber() != pg->getNumber())
1653
                sub->drop();
1654
 
1655
            sub = getNextSubPageGroup(group, sub);
1656
        }
1657
    }
1658
 
1659
    if (!pg->isVisible())
1660
    {
1661
        TPage *page = getPage(mActualPage);
1662
 
1663
        if (!page)
1664
        {
1665
            MSG_ERROR("No active page found! Internal error.");
1666
            return;
1667
        }
1668
 
1669
        if (!haveSubPage(pg->getNumber()) && !page->addSubPage(pg))
1670
            return;
1671
 
1672
        pg->setZOrder(page->getNextZOrder());
1673
 
1674
        if (_setSubPage)
26 andreas 1675
        {
1676
            int left = pg->getLeft();
1677
            int top = pg->getTop();
1678
            int width = pg->getWidth();
1679
            int height = pg->getHeight();
1680
 
1681
            if (mScaleFactor != 1.0)
1682
            {
1683
                left = (int)((double)left * mScaleFactor);
1684
                top = (int)((double)top * mScaleFactor);
1685
                width = (int)((double)width * mScaleFactor);
1686
                height = (int)((double)height * mScaleFactor);
28 andreas 1687
                MSG_DEBUG("Scaled subpage: left=" << left << ", top=" << top << ", width=" << width << ", height=" << height);
26 andreas 1688
            }
1689
 
1690
            _setSubPage((pg->getNumber() << 16) & 0xffff0000, left, top, width, height);
1691
        }
14 andreas 1692
    }
1693
 
1694
    pg->show();
1695
}
1696
 
1697
void TPageManager::hideSubPage(const string& name)
1698
{
1699
    DECL_TRACER("TPageManager::hideSubPage(const string& name)");
1700
 
1701
    if (name.empty())
1702
        return;
1703
 
1704
    TPage *page = getPage(mActualPage);
1705
 
1706
    if (!page)
1707
    {
1708
        MSG_ERROR("No active page found! Internal error.");
1709
        return;
1710
    }
1711
 
1712
    TSubPage *pg = getSubPage(name);
1713
 
1714
    if (pg)
1715
    {
1716
        if (pg->getZOrder() == page->getActZOrder())
1717
            page->decZOrder();
1718
 
1719
        pg->drop();
1720
    }
1721
}
1722
 
11 andreas 1723
/*
1724
 * Catch the mouse presses and scan all pages and subpages for an element to
1725
 * receive the klick.
1726
 */
10 andreas 1727
void TPageManager::mouseEvent(int x, int y, bool pressed)
1728
{
14 andreas 1729
    surface_mutex.lock();
10 andreas 1730
    DECL_TRACER("TPageManager::mouseEvent(int x, int y, bool pressed)");
1731
 
16 andreas 1732
    TError::clear();
11 andreas 1733
    int realX = x - mFirstLeftPixel;
1734
    int realY = y - mFirstTopPixel;
31 andreas 1735
    MSG_DEBUG("Mouse at " << realX << ", " << realY << ", state " << ((pressed) ? "PRESSED" : "RELEASED") << ", [ " << x << " | " << y << " ]");
26 andreas 1736
 
1737
    if (mScaleFactor != 1.0 && mScaleFactor != 0.0)
1738
    {
1739
        realX = (int)((double)realX / mScaleFactor);
1740
        realY = (int)((double)realY / mScaleFactor);
31 andreas 1741
        MSG_DEBUG("Scaled coordinates: x=" << realX << ", y=" << realY);
26 andreas 1742
    }
1743
 
12 andreas 1744
    TSubPage *subPage = getCoordMatch(realX, realY);
11 andreas 1745
 
1746
    if (!subPage)
14 andreas 1747
    {
1748
        surface_mutex.unlock();
11 andreas 1749
        return;
14 andreas 1750
    }
11 andreas 1751
 
26 andreas 1752
    MSG_DEBUG("Subpage " << subPage->getNumber() << ": size: left=" << subPage->getLeft() << ", top=" << subPage->getTop() << ", width=" << subPage->getWidth() << ", height=" << subPage->getHeight());
11 andreas 1753
    subPage->doClick(realX - subPage->getLeft(), realY - subPage->getTop(), pressed);
14 andreas 1754
    surface_mutex.unlock();
10 andreas 1755
}
11 andreas 1756
 
14 andreas 1757
vector<Button::TButton *> TPageManager::collectButtons(vector<MAP_T>& map)
1758
{
1759
    DECL_TRACER("TPageManager::collectButtons(vector<MAP_T>& map)");
1760
 
1761
    vector<Button::TButton *> buttons;
1762
    vector<MAP_T>::iterator iter;
1763
 
1764
    for (iter = map.begin(); iter != map.end(); iter++)
1765
    {
1766
        if (iter->pg < 500)     // Main page?
1767
        {
1768
            TPage *page;
1769
 
1770
            if ((page = getPage(iter->pg)) == nullptr)
1771
            {
1772
                MSG_TRACE("Page " << iter->pg << ", " << iter->pn << " not found in memory. Reading it ...");
1773
 
1774
                if (!readPage(iter->pg))
1775
                    return buttons;
1776
 
1777
                page = getPage(iter->pg);
1778
                addPage(page);
1779
            }
1780
 
1781
            Button::TButton *bt = page->getButton(iter->bt);
1782
 
1783
            if (bt)
1784
                buttons.push_back(bt);
1785
        }
1786
        else
1787
        {
1788
            TSubPage *subpage;
1789
 
1790
            if ((subpage = getSubPage(iter->pg)) == nullptr)
1791
            {
1792
                MSG_TRACE("Subpage " << iter->pg << ", " << iter->pn << " not found in memory. Reading it ...");
1793
 
1794
                if (!readSubPage(iter->pg))
1795
                    return buttons;
1796
 
1797
                subpage = getSubPage(iter->pg);
1798
                TPage *page = getActualPage();
1799
 
1800
                if (!page)
1801
                {
1802
                    MSG_ERROR("No actual page loaded!");
1803
                    return buttons;
1804
                }
1805
 
1806
                page->addSubPage(subpage);
1807
            }
1808
 
1809
            Button::TButton *bt = subpage->getButton(iter->bt);
1810
 
1811
            if (bt)
1812
                buttons.push_back(bt);
1813
        }
1814
    }
1815
 
1816
    return buttons;
1817
}
1818
 
11 andreas 1819
/****************************************************************************
1820
 * The following functions implements one of the commands the panel accepts.
1821
 ****************************************************************************/
23 andreas 1822
void TPageManager::doFTR(int, vector<int>&, vector<string>& pars)
1823
{
1824
    DECL_TRACER("TPageManager::doFTR(int port, vector<int>&, vector<string>& pars)");
14 andreas 1825
 
23 andreas 1826
    if (pars.empty())
1827
    {
1828
        MSG_WARNING("Command #FTR needs at least 1 parameter! Ignoring command.");
1829
        return;
1830
    }
1831
 
1832
    if (pars.at(0).compare("SYNC") == 0)
1833
    {
1834
        MSG_INFO(pars.at(2));
1835
    }
1836
}
1837
 
22 andreas 1838
void TPageManager::doON(int port, vector<int>&, vector<string>& pars)
14 andreas 1839
{
1840
    DECL_TRACER("TPageManager::doON(int port, vector<int>& channels, vector<string>& pars)");
1841
 
1842
    if (pars.empty())
1843
    {
1844
        MSG_WARNING("Command ON needs 1 parameter! Ignoring command.");
1845
        return;
1846
    }
1847
 
16 andreas 1848
    TError::clear();
14 andreas 1849
    int c = atoi(pars[0].c_str());
1850
 
1851
    if (c <= 0)
1852
    {
1853
        MSG_WARNING("Invalid channel " << c << "! Ignoring command.");
1854
        return;
1855
    }
1856
 
1857
    vector<int> chans = { c };
19 andreas 1858
    vector<MAP_T> map = findButtons(port, chans, TYPE_CM);
14 andreas 1859
 
1860
    if (TError::isError() || map.empty())
1861
        return;
1862
 
1863
    vector<Button::TButton *> buttons = collectButtons(map);
1864
    vector<Button::TButton *>::iterator mapIter;
1865
 
1866
    for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
1867
    {
1868
        Button::TButton *bt = *mapIter;
1869
 
1870
        if (bt->getButtonType() == Button::GENERAL)
1871
            bt->setActive(1);
1872
    }
1873
}
1874
 
22 andreas 1875
void TPageManager::doOFF(int port, vector<int>&, vector<string>& pars)
14 andreas 1876
{
1877
    DECL_TRACER("TPageManager::doOFF(int port, vector<int>& channels, vector<string>& pars)");
1878
 
1879
    if (pars.empty())
1880
    {
1881
        MSG_WARNING("Command OFF needs 1 parameter! Ignoring command.");
1882
        return;
1883
    }
1884
 
16 andreas 1885
    TError::clear();
14 andreas 1886
    int c = atoi(pars[0].c_str());
1887
 
1888
    if (c <= 0)
1889
    {
1890
        MSG_WARNING("Invalid channel " << c << "! Ignoring command.");
1891
        return;
1892
    }
1893
 
1894
    vector<int> chans = { c };
19 andreas 1895
    vector<MAP_T> map = findButtons(port, chans, TYPE_CM);
14 andreas 1896
 
1897
    if (TError::isError() || map.empty())
1898
        return;
1899
 
1900
    vector<Button::TButton *> buttons = collectButtons(map);
1901
    vector<Button::TButton *>::iterator mapIter;
1902
 
1903
    for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
1904
    {
1905
        Button::TButton *bt = *mapIter;
1906
 
1907
        if (bt->getButtonType() == Button::GENERAL)
1908
            bt->setActive(0);
1909
    }
1910
}
1911
 
22 andreas 1912
void TPageManager::doLEVEL(int port, vector<int>&, vector<string>& pars)
15 andreas 1913
{
1914
    DECL_TRACER("TPageManager::doLEVEL(int port, vector<int>& channels, vector<string>& pars)");
1915
 
1916
    if (pars.size() < 2)
1917
    {
1918
        MSG_WARNING("Command LEVEL needs 2 parameters! Ignoring command.");
1919
        return;
1920
    }
1921
 
16 andreas 1922
    TError::clear();
15 andreas 1923
    int c = atoi(pars[0].c_str());
1924
    int level = atoi(pars[1].c_str());
1925
 
1926
    if (c <= 0)
1927
    {
1928
        MSG_WARNING("Invalid channel " << c << "! Ignoring command.");
1929
        return;
1930
    }
1931
 
1932
    vector<int> chans = { c };
1933
    vector<MAP_T> map = findBargraphs(port, chans);
1934
 
1935
    if (TError::isError() || map.empty())
1936
    {
1937
        MSG_WARNING("No bargraphs found!");
1938
        return;
1939
    }
1940
 
1941
    vector<Button::TButton *> buttons = collectButtons(map);
1942
    vector<Button::TButton *>::iterator mapIter;
1943
 
1944
    for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
1945
    {
1946
        Button::TButton *bt = *mapIter;
1947
 
1948
        if (bt->getButtonType() == Button::BARGRAPH)
1949
            bt->drawBargraph(bt->getActiveInstance(), level);
1950
        else if (bt->getButtonType() == Button::MULTISTATE_BARGRAPH)
1951
        {
1952
            int state = (int)((double)bt->getStateCount() / (double)(bt->getRangeHigh() - bt->getRangeLow()) * (double)level);
1953
            bt->setActive(state);
1954
        }
1955
    }
1956
}
1957
 
22 andreas 1958
void TPageManager::doBLINK(int, vector<int>&, vector<string>& pars)
15 andreas 1959
{
1960
    DECL_TRACER("TPageManager::doBLINK(int port, vector<int>& channels, vector<string>& pars)");
1961
 
1962
    if (pars.size() < 4)
1963
    {
1964
        MSG_WARNING("Command BLINK expects 4 parameters! Command ignored.");
1965
        return;
1966
    }
1967
 
16 andreas 1968
    TError::clear();
15 andreas 1969
    vector<int> sysButtons = { 141, 142, 143, 151, 152, 153, 154, 155, 156, 157, 158 };
1970
    vector<MAP_T> map = findButtons(0, sysButtons);
1971
 
1972
    if (TError::isError() || map.empty())
1973
    {
1974
        MSG_WARNING("No system buttons found.");
1975
        return;
1976
    }
1977
 
1978
    vector<Button::TButton *> buttons = collectButtons(map);
1979
    vector<Button::TButton *>::iterator mapIter;
1980
 
1981
    for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
1982
    {
1983
        Button::TButton *bt = *mapIter;
1984
        bt->setActive(0);
1985
    }
1986
}
1987
 
14 andreas 1988
/**
1989
 * Add a specific popup page to a specified popup group if it does not already
1990
 * exist. If the new popup is added to a group which has a popup displayed on
1991
 * the current page along with the new pop-up, the displayed popup will be
1992
 * hidden and the new popup will be displayed.
1993
 */
22 andreas 1994
void TPageManager::doAPG(int, std::vector<int>&, std::vector<std::string>& pars)
11 andreas 1995
{
1996
    DECL_TRACER("TPageManager::doAPG(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
1997
 
1998
    if (pars.size() < 2)
1999
    {
2000
        MSG_ERROR("Less than 2 parameters!");
2001
        return;
2002
    }
2003
 
16 andreas 2004
    TError::clear();
11 andreas 2005
    closeGroup(pars[1]);
14 andreas 2006
    TPage *page = getActualPage();
2007
 
2008
    if (!page)
2009
    {
2010
        MSG_ERROR("No actual page loaded!");
2011
        return;
2012
    }
2013
 
11 andreas 2014
    TSubPage *subPage = getSubPage(pars[0]);
2015
 
2016
    if (!subPage)
2017
    {
2018
        if (!readSubPage(pars[0]))
2019
        {
2020
            MSG_ERROR("Error reading subpage " << pars[0]);
2021
            return;
2022
        }
2023
 
2024
        subPage = getSubPage(pars[0]);
14 andreas 2025
        page->addSubPage(subPage);
11 andreas 2026
    }
2027
 
2028
    if (!subPage)
2029
    {
2030
        MSG_ERROR("Subpage " << pars[0] << " couldn't either found or created!");
2031
        return;
2032
    }
2033
 
2034
    subPage->setGroup(pars[1]);
14 andreas 2035
    subPage->setZOrder(page->getNextZOrder());
11 andreas 2036
    subPage->show();
2037
}
2038
 
14 andreas 2039
/**
2040
 * Clear all popup pages from specified popup group.
2041
 */
22 andreas 2042
void TPageManager::doCPG(int, std::vector<int>&, std::vector<std::string>& pars)
11 andreas 2043
{
2044
    DECL_TRACER("TPageManager::doCPG(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
2045
 
2046
    if (pars.size() < 1)
2047
    {
2048
        MSG_ERROR("Expecting 1 parameter but got only 1!");
2049
        return;
2050
    }
2051
 
16 andreas 2052
    TError::clear();
11 andreas 2053
    vector<SUBPAGELIST_T>::iterator pgIter;
2054
    vector<SUBPAGELIST_T> pageList = mPageList->getSupPageList();
2055
 
2056
    for (pgIter = pageList.begin(); pgIter != pageList.end(); pgIter++)
2057
    {
2058
        if (pgIter->group.compare(pars[0]) == 0)
2059
        {
2060
            pgIter->group.clear();
2061
            TSubPage *pg = getSubPage(pgIter->pageID);
2062
 
2063
            if (pg)
2064
                pg->setGroup(pgIter->group);
2065
        }
2066
    }
2067
}
2068
 
14 andreas 2069
/**
2070
 * Delete a specific popup page from specified popup group if it exists.
2071
 */
22 andreas 2072
void TPageManager::doDPG(int, std::vector<int>&, std::vector<std::string>& pars)
11 andreas 2073
{
2074
    DECL_TRACER("TPageManager::doDPG(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
2075
 
2076
    if (pars.size() < 2)
2077
    {
2078
        MSG_ERROR("Less than 2 parameters!");
2079
        return;
2080
    }
2081
 
16 andreas 2082
    TError::clear();
11 andreas 2083
    SUBPAGELIST_T listPg = findSubPage(pars[0]);
2084
 
2085
    if (!listPg.isValid)
2086
        return;
2087
 
2088
    if (listPg.group.compare(pars[1]) == 0)
2089
    {
2090
        listPg.group.clear();
2091
        TSubPage *pg = getSubPage(listPg.pageID);
2092
 
2093
        if (pg)
2094
            pg->setGroup(listPg.group);
2095
    }
2096
}
2097
 
14 andreas 2098
/**
15 andreas 2099
 * Set the hide effect for the specified popup page to the named hide effect.
2100
 */
22 andreas 2101
void TPageManager::doPHE(int, vector<int>&, vector<string>& pars)
15 andreas 2102
{
2103
    DECL_TRACER("TPageManager::doPHE(int port, vector<int>& channels, vector<string>& pars)");
2104
 
2105
    if (pars.size() < 2)
2106
    {
2107
        MSG_ERROR("Less than 2 parameters!");
2108
        return;
2109
    }
2110
 
16 andreas 2111
    TError::clear();
15 andreas 2112
    TSubPage *pg = getSubPage(pars[0]);
2113
 
2114
    if (!pg)
2115
    {
2116
        if (!readSubPage(pars[0]))
2117
            return;
2118
 
2119
        if ((pg = getSubPage(pars[0])) == nullptr)
2120
            return;
2121
 
2122
        TPage *page = getActualPage();
2123
 
2124
        if (page)
2125
            page->addSubPage(pg);
2126
    }
2127
 
2128
    if (pars[1].compare("fade") == 0)
2129
        pg->setHideEffect(SE_FADE);
2130
    else if (pars[1].compare("slide to left") == 0)
2131
        pg->setHideEffect(SE_SLIDE_LEFT);
2132
    else if (pars[1].compare("slide to right") == 0)
2133
        pg->setHideEffect(SE_SLIDE_RIGHT);
2134
    else if (pars[1].compare("slide to top") == 0)
2135
        pg->setHideEffect(SE_SLIDE_TOP);
2136
    else if (pars[1].compare("slide to bottom") == 0)
2137
        pg->setHideEffect(SE_SLIDE_BOTTOM);
2138
    else if (pars[1].compare("slide to left fade") == 0)
2139
        pg->setHideEffect(SE_SLIDE_LEFT_FADE);
2140
    else if (pars[1].compare("slide to right fade") == 0)
2141
        pg->setHideEffect(SE_SLIDE_RIGHT_FADE);
2142
    else if (pars[1].compare("slide to top fade") == 0)
2143
        pg->setHideEffect(SE_SLIDE_TOP_FADE);
2144
    else if (pars[1].compare("slide to bottom fade") == 0)
2145
        pg->setHideEffect(SE_SLIDE_BOTTOM_FADE);
2146
    else
2147
        pg->setHideEffect(SE_NONE);
2148
}
2149
 
2150
/**
2151
 * Set the hide effect position. Only 1 coordinate is ever needed for an effect;
2152
 * however, the command will specify both. This command sets the location at
2153
 * which the effect will end at.
2154
 */
22 andreas 2155
void TPageManager::doPHP(int, vector<int>&, vector<string>& pars)
15 andreas 2156
{
2157
    DECL_TRACER("TPageManager::doPHP(int port, vector<int>& channels, vector<string>& pars)");
2158
 
2159
    if (pars.size() < 2)
2160
    {
2161
        MSG_ERROR("Less than 2 parameters!");
2162
        return;
2163
    }
2164
 
16 andreas 2165
    TError::clear();
15 andreas 2166
    size_t pos = pars[1].find(",");
2167
    int x, y;
2168
 
2169
    if (pos == string::npos)
2170
    {
2171
        x = atoi(pars[1].c_str());
2172
        y = 0;
2173
    }
2174
    else
2175
    {
2176
        x = atoi(pars[1].substr(0, pos).c_str());
2177
        y = atoi(pars[1].substr(pos+1).c_str());
2178
    }
2179
 
2180
    TSubPage *pg = getSubPage(pars[0]);
2181
 
2182
    if (!pg)
2183
    {
2184
        if (!readSubPage(pars[0]))
2185
            return;
2186
 
2187
        if ((pg = getSubPage(pars[0])) == nullptr)
2188
            return;
2189
 
2190
        TPage *page = getActualPage();
2191
 
2192
        if (page)
2193
            page->addSubPage(pg);
2194
    }
2195
 
2196
    pg->setHideEndPosition(x, y);
2197
}
2198
 
2199
/**
2200
 * Set the hide effect time for the specified popup page.
2201
 */
22 andreas 2202
void TPageManager::doPHT(int, vector<int>&, vector<string>& pars)
15 andreas 2203
{
2204
    DECL_TRACER("TPageManager::doPHT(int port, vector<int>& channels, vector<string>& pars)");
2205
 
2206
    if (pars.size() < 2)
2207
    {
2208
        MSG_ERROR("Less than 2 parameters!");
2209
        return;
2210
    }
2211
 
16 andreas 2212
    TError::clear();
15 andreas 2213
    TSubPage *pg = getSubPage(pars[0]);
2214
 
2215
    if (!pg)
2216
    {
2217
        if (!readSubPage(pars[0]))
2218
            return;
2219
 
2220
        if ((pg = getSubPage(pars[0])) == nullptr)
2221
            return;
2222
 
2223
        TPage *page = getActualPage();
2224
 
2225
        if (page)
2226
            page->addSubPage(pg);
2227
    }
2228
 
2229
    pg->setHideTime(atoi(pars[1].c_str()));
2230
}
2231
 
2232
/**
14 andreas 2233
 * Close all popups on a specified page. If the page name is empty, the current
2234
 * page is used. Same as the ’Clear Page’ command in TPDesign4.
2235
 */
22 andreas 2236
void TPageManager::doPPA(int, std::vector<int>&, std::vector<std::string>& pars)
11 andreas 2237
{
2238
    DECL_TRACER("TPageManager::doPPA(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
2239
 
16 andreas 2240
    TError::clear();
11 andreas 2241
    TPage *pg;
2242
 
2243
    if (pars.size() == 0)
2244
        pg = getPage(mActualPage);
2245
    else
2246
        pg = getPage(pars[0]);
2247
 
2248
    if (!pg)
2249
        return;
2250
 
12 andreas 2251
    pg->drop();
14 andreas 2252
    pg->resetZOrder();
11 andreas 2253
}
2254
 
14 andreas 2255
/**
2256
 * Deactivate a specific popup page on either a specified page or the current
2257
 * page. If the page name is empty, the current page is used. If the popup page
2258
 * is part of a group, the whole group is deactivated. This command works in
2259
 * the same way as the ’Hide Popup’ command in TPDesign4.
2260
 */
22 andreas 2261
void TPageManager::doPPF(int, std::vector<int>&, std::vector<std::string>& pars)
12 andreas 2262
{
2263
    DECL_TRACER("TPageManager::doPPF(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
2264
 
2265
    if (pars.size() < 1)
2266
    {
2267
        MSG_ERROR("At least 1 parameter is expected!");
2268
        return;
2269
    }
2270
 
16 andreas 2271
    TError::clear();
14 andreas 2272
    hideSubPage(pars[0]);
12 andreas 2273
}
2274
 
14 andreas 2275
/**
2276
 * Toggle a specific popup page on either a specified page or the current page.
2277
 * If the page name is empty, the current page is used. Toggling refers to the
2278
 * activating/deactivating (On/Off) of a popup page. This command works in the
2279
 * same way as the ’Toggle Popup’ command in TPDesign4.
2280
 */
22 andreas 2281
void TPageManager::doPPG(int, std::vector<int>&, std::vector<std::string>& pars)
12 andreas 2282
{
2283
    DECL_TRACER("TPageManager::doPPG(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
14 andreas 2284
 
12 andreas 2285
    if (pars.size() < 1)
2286
    {
2287
        MSG_ERROR("At least 1 parameter is expected!");
2288
        return;
2289
    }
2290
 
16 andreas 2291
    TError::clear();
14 andreas 2292
    TPage *page = getPage(mActualPage);
2293
 
2294
    if (!page)
2295
    {
2296
        MSG_ERROR("No active page found! Internal error.");
2297
        return;
2298
    }
2299
 
12 andreas 2300
    TSubPage *pg = getSubPage(pars[0]);
14 andreas 2301
 
12 andreas 2302
    if (!pg)
2303
        return;
14 andreas 2304
 
12 andreas 2305
    if (pg->isVisible())
2306
    {
14 andreas 2307
        if (pg->getZOrder() == page->getActZOrder())
2308
            page->decZOrder();
2309
 
12 andreas 2310
        pg->drop();
2311
        return;
2312
    }
2313
 
2314
    TSubPage *sub = getFirstSubPageGroup(pg->getGroupName());
14 andreas 2315
 
12 andreas 2316
    while(sub)
2317
    {
2318
        if (sub->getGroupName().compare(pg->getGroupName()) == 0 && sub->isVisible())
2319
            sub->drop();
14 andreas 2320
 
12 andreas 2321
        sub = getNextSubPageGroup(pg->getGroupName(), sub);
2322
    }
2323
 
2324
    pg->show();
14 andreas 2325
    pg->setZOrder(page->getNextZOrder());
12 andreas 2326
}
2327
 
14 andreas 2328
/**
2329
 * Kill refers to the deactivating (Off) of a popup window from all pages. If
2330
 * the pop-up page is part of a group, the whole group is deactivated. This
2331
 * command works in the same way as the 'Clear Group' command in TPDesign 4.
2332
 */
22 andreas 2333
void TPageManager::doPPK(int, std::vector<int>&, std::vector<std::string>& pars)
12 andreas 2334
{
2335
    DECL_TRACER("TPageManager::doPPK(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
14 andreas 2336
 
12 andreas 2337
    if (pars.size() < 1)
2338
    {
2339
        MSG_ERROR("At least 1 parameter is expected!");
2340
        return;
2341
    }
2342
 
16 andreas 2343
    TError::clear();
14 andreas 2344
    TPage *page = getPage(mActualPage);
2345
 
2346
    if (!page)
2347
    {
2348
        MSG_ERROR("No active page found! Internal error.");
2349
        return;
2350
    }
2351
 
12 andreas 2352
    TSubPage *pg = getSubPage(pars[0]);
14 andreas 2353
 
12 andreas 2354
    if (pg)
14 andreas 2355
    {
2356
        if (pg->getZOrder() == page->getActZOrder())
2357
            page->decZOrder();
2358
 
2359
        pg->drop();
2360
    }
12 andreas 2361
}
2362
 
14 andreas 2363
/**
2364
 * Set the modality of a specific popup page to Modal or NonModal.
2365
 * A Modal popup page, when active, only allows you to use the buttons and
2366
 * features on that popup page. All other buttons on the panel page are
2367
 * inactivated.
2368
 */
22 andreas 2369
void TPageManager::doPPM(int, std::vector<int>&, std::vector<std::string>& pars)
12 andreas 2370
{
2371
    DECL_TRACER("TPageManager::doPPM(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
14 andreas 2372
 
12 andreas 2373
    if (pars.size() < 2)
2374
    {
2375
        MSG_ERROR("Expecting 2 parameters!");
2376
        return;
2377
    }
14 andreas 2378
 
16 andreas 2379
    TError::clear();
12 andreas 2380
    TSubPage *pg = getSubPage(pars[0]);
14 andreas 2381
 
12 andreas 2382
    if (pg)
2383
    {
2384
        if (pars[1] == "1" || pars[1].compare("modal") == 0 || pars[1].compare("MODAL") == 0)
2385
            pg->setModal(1);
2386
        else
2387
            pg->setModal(0);
2388
    }
2389
}
2390
 
14 andreas 2391
/**
2392
 * Activate a specific popup page to launch on either a specified page or the
2393
 * current page. If the page name is empty, the current page is used. If the
2394
 * popup page is already on, do not re-draw it. This command works in the same
2395
 * way as the ’Show Popup’ command in TPDesign4.
2396
 */
22 andreas 2397
void TPageManager::doPPN(int, std::vector<int>&, std::vector<std::string>& pars)
12 andreas 2398
{
2399
    DECL_TRACER("TPageManager::doPPN(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
2400
 
2401
    if (pars.size() < 1)
2402
    {
2403
        MSG_ERROR("At least 1 parameter is expected!");
2404
        return;
2405
    }
2406
 
16 andreas 2407
    TError::clear();
14 andreas 2408
    showSubPage(pars[0]);
12 andreas 2409
}
2410
 
14 andreas 2411
/**
15 andreas 2412
 * Set a specific popup page to timeout within a specified time. If timeout is
2413
 * empty, popup page will clear the timeout.
2414
 */
22 andreas 2415
void TPageManager::doPPT(int, vector<int>&, vector<string>& pars)
15 andreas 2416
{
2417
    DECL_TRACER("TPageManager::doPPT(int port, vector<int>& channels, vector<string>& pars)");
2418
 
2419
    if (pars.size() < 2)
2420
    {
2421
        MSG_ERROR("Expecting 2 parameters!");
2422
        return;
2423
    }
2424
 
16 andreas 2425
    TError::clear();
15 andreas 2426
    TSubPage *pg = getSubPage(pars[0]);
2427
 
2428
    if (!pg)
2429
    {
2430
        if (!readSubPage(pars[0]))
2431
            return;
2432
 
2433
        if ((pg = getSubPage(pars[0])) == nullptr)
2434
            return;
2435
 
2436
        TPage *page = getActualPage();
2437
 
2438
        if (page)
2439
            page->addSubPage(pg);
2440
    }
2441
 
2442
    pg->setTimeout(atoi(pars[1].c_str()));
2443
}
2444
 
2445
/**
14 andreas 2446
 * Close all popups on all pages. This command works in the same way as the
2447
 * 'Clear All' command in TPDesign 4.
2448
 */
22 andreas 2449
void TPageManager::doPPX(int, std::vector<int>&, std::vector<std::string>&)
12 andreas 2450
{
2451
    DECL_TRACER("TPageManager::doPPX(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
2452
 
16 andreas 2453
    TError::clear();
12 andreas 2454
    PCHAIN_T *chain = mPchain;
14 andreas 2455
 
12 andreas 2456
    while(chain)
2457
    {
2458
        TSubPage *sub = chain->page->getFirstSubPage();
14 andreas 2459
 
12 andreas 2460
        while (sub)
2461
        {
14 andreas 2462
            MSG_DEBUG("Dopping subpage " << sub->getNumber() << ", \"" << sub->getName() << "\".");
12 andreas 2463
            sub->drop();
2464
            sub = chain->page->getNextSubPage();
2465
        }
14 andreas 2466
 
12 andreas 2467
        chain = chain->next;
2468
    }
14 andreas 2469
 
2470
    TPage *page = getPage(mActualPage);
2471
 
2472
    if (!page)
2473
    {
2474
        MSG_ERROR("No active page found! Internal error.");
2475
        return;
2476
    }
2477
 
2478
    page->resetZOrder();
12 andreas 2479
}
2480
 
14 andreas 2481
/**
15 andreas 2482
 * Set the show effect for the specified popup page to the named show effect.
2483
 */
22 andreas 2484
void TPageManager::doPSE(int, vector<int>&, vector<string>& pars)
15 andreas 2485
{
2486
    DECL_TRACER("TPageManager::doPSE(int port, vector<int>& channels, vector<string>& pars)");
2487
 
2488
    if (pars.size() < 2)
2489
    {
2490
        MSG_ERROR("Less than 2 parameters!");
2491
        return;
2492
    }
2493
 
16 andreas 2494
    TError::clear();
15 andreas 2495
    TSubPage *pg = getSubPage(pars[0]);
2496
 
2497
    if (!pg)
2498
    {
2499
        if (!readSubPage(pars[0]))
2500
            return;
2501
 
2502
        if ((pg = getSubPage(pars[0])) == nullptr)
2503
            return;
2504
 
2505
        TPage *page = getActualPage();
2506
 
2507
        if (page)
2508
            page->addSubPage(pg);
2509
    }
2510
 
2511
    if (pars[1].compare("fade") == 0)
2512
        pg->setShowEffect(SE_FADE);
2513
    else if (pars[1].compare("slide to left") == 0)
2514
        pg->setShowEffect(SE_SLIDE_LEFT);
2515
    else if (pars[1].compare("slide to right") == 0)
2516
        pg->setShowEffect(SE_SLIDE_RIGHT);
2517
    else if (pars[1].compare("slide to top") == 0)
2518
        pg->setShowEffect(SE_SLIDE_TOP);
2519
    else if (pars[1].compare("slide to bottom") == 0)
2520
        pg->setShowEffect(SE_SLIDE_BOTTOM);
2521
    else if (pars[1].compare("slide to left fade") == 0)
2522
        pg->setShowEffect(SE_SLIDE_LEFT_FADE);
2523
    else if (pars[1].compare("slide to right fade") == 0)
2524
        pg->setShowEffect(SE_SLIDE_RIGHT_FADE);
2525
    else if (pars[1].compare("slide to top fade") == 0)
2526
        pg->setShowEffect(SE_SLIDE_TOP_FADE);
2527
    else if (pars[1].compare("slide to bottom fade") == 0)
2528
        pg->setShowEffect(SE_SLIDE_BOTTOM_FADE);
2529
    else
2530
        pg->setShowEffect(SE_NONE);
2531
}
2532
 
22 andreas 2533
void TPageManager::doPSP(int, vector<int>&, vector<string>& pars)
15 andreas 2534
{
2535
    DECL_TRACER("TPageManager::doPSP(int port, vector<int>& channels, vector<string>& pars)");
2536
 
2537
    if (pars.size() < 2)
2538
    {
2539
        MSG_ERROR("Less than 2 parameters!");
2540
        return;
2541
    }
2542
 
16 andreas 2543
    TError::clear();
15 andreas 2544
    size_t pos = pars[1].find(",");
2545
    int x, y;
2546
 
2547
    if (pos == string::npos)
2548
    {
2549
        x = atoi(pars[1].c_str());
2550
        y = 0;
2551
    }
2552
    else
2553
    {
2554
        x = atoi(pars[1].substr(0, pos).c_str());
2555
        y = atoi(pars[1].substr(pos+1).c_str());
2556
    }
2557
 
2558
    TSubPage *pg = getSubPage(pars[0]);
2559
 
2560
    if (!pg)
2561
    {
2562
        if (!readSubPage(pars[0]))
2563
            return;
2564
 
2565
        if ((pg = getSubPage(pars[0])) == nullptr)
2566
            return;
2567
 
2568
        TPage *page = getActualPage();
2569
 
2570
        if (page)
2571
            page->addSubPage(pg);
2572
    }
2573
 
2574
    pg->setShowEndPosition(x, y);
2575
}
2576
 
2577
/**
2578
 * Set the show effect time for the specified popup page.
2579
 */
22 andreas 2580
void TPageManager::doPST(int, vector<int>&, vector<string>& pars)
15 andreas 2581
{
2582
    DECL_TRACER("TPageManager::doPST(int port, vector<int>& channels, vector<string>& pars)");
2583
 
2584
    if (pars.size() < 2)
2585
    {
2586
        MSG_ERROR("Less than 2 parameters!");
2587
        return;
2588
    }
2589
 
16 andreas 2590
    TError::clear();
15 andreas 2591
    size_t pos = pars[1].find(",");
2592
    int x, y;
2593
 
2594
    if (pos == string::npos)
2595
    {
2596
        x = atoi(pars[1].c_str());
2597
        y = 0;
2598
    }
2599
    else
2600
    {
2601
        x = atoi(pars[1].substr(0, pos).c_str());
2602
        y = atoi(pars[1].substr(pos+1).c_str());
2603
    }
2604
 
2605
    TSubPage *pg = getSubPage(pars[0]);
2606
 
2607
    if (!pg)
2608
    {
2609
        if (!readSubPage(pars[0]))
2610
            return;
2611
 
2612
        if ((pg = getSubPage(pars[0])) == nullptr)
2613
            return;
2614
 
2615
        TPage *page = getActualPage();
2616
 
2617
        if (page)
2618
            page->addSubPage(pg);
2619
    }
2620
 
2621
    pg->setShowTime(atoi(pars[1].c_str()));
2622
}
2623
 
2624
/**
14 andreas 2625
 * Flips to a page with a specified page name. If the page is currently active,
2626
 * it will not redraw the page.
2627
 */
22 andreas 2628
void TPageManager::doPAGE(int, std::vector<int>&, std::vector<std::string>& pars)
12 andreas 2629
{
2630
    DECL_TRACER("TPageManager::doPAGE(int port, std::vector<int>& channels, std::vector<std::string>& pars)");
14 andreas 2631
 
15 andreas 2632
    if (pars.empty())
2633
    {
2634
        MSG_WARNING("Got no page parameter!");
2635
        return;
2636
    }
14 andreas 2637
 
16 andreas 2638
    TError::clear();
15 andreas 2639
    setPage(pars[0]);
2640
}
2641
 
2642
/**
2643
 * Add page flip action to a button if it does not already exist.
2644
 */
2645
void TPageManager::doAPF(int port, vector<int>& channels, vector<string>& pars)
2646
{
2647
    DECL_TRACER("TPageManager::doAPF(int port, vector<int>& channels, vector<string>& pars)");
2648
 
2649
    if (pars.size() < 2)
2650
    {
2651
        MSG_ERROR("Expecting 2 parameters but got " << pars.size() << "! Ignoring command.");
14 andreas 2652
        return;
15 andreas 2653
    }
14 andreas 2654
 
16 andreas 2655
    TError::clear();
15 andreas 2656
    string action = pars[0];
2657
    string pname = pars[1];
14 andreas 2658
 
15 andreas 2659
    vector<MAP_T> map = findButtons(port, channels);
14 andreas 2660
 
15 andreas 2661
    if (TError::isError() || map.empty())
2662
        return;
2663
 
2664
    vector<Button::TButton *> buttons = collectButtons(map);
2665
    vector<Button::TButton *>::iterator mapIter;
2666
 
2667
    for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
12 andreas 2668
    {
15 andreas 2669
        Button::TButton *bt = *mapIter;
18 andreas 2670
        setButtonCallbacks(bt);
15 andreas 2671
        bt->addPushFunction(action, pname);
2672
    }
2673
}
12 andreas 2674
 
15 andreas 2675
/**
2676
 * Assign a picture to those buttons with a defined address range.
2677
 */
2678
void TPageManager::doBMP(int port, vector<int>& channels, vector<string>& pars)
2679
{
2680
    DECL_TRACER("TPageManager::doBMP(int port, vector<int>& channels, vector<string>& pars)");
2681
 
2682
    if (pars.size() < 2)
2683
    {
2684
        MSG_ERROR("Expecting 2 parameters but got " << pars.size() << "! Ignoring command.");
12 andreas 2685
        return;
2686
    }
14 andreas 2687
 
16 andreas 2688
    TError::clear();
15 andreas 2689
    int btState = atoi(pars[0].c_str());
2690
    string bitmap = pars[1];
14 andreas 2691
 
15 andreas 2692
    vector<MAP_T> map = findButtons(port, channels);
2693
 
2694
    if (TError::isError() || map.empty())
2695
        return;
2696
 
2697
    vector<Button::TButton *> buttons = collectButtons(map);
2698
    vector<Button::TButton *>::iterator mapIter;
2699
 
2700
    for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
2701
    {
2702
        Button::TButton *bt = *mapIter;
18 andreas 2703
        setButtonCallbacks(bt);
15 andreas 2704
 
2705
        if (btState == 0)       // All instances?
2706
        {
2707
            int bst = bt->getNumberInstances();
2708
            MSG_DEBUG("Setting bitmal " << bitmap << " on all " << bst << " instances...");
2709
 
2710
            for (int i = 0; i < bst; i++)
2711
                bt->setBitmap(bitmap, i);
2712
        }
2713
        else
2714
            bt->setBitmap(bitmap, btState);
2715
    }
12 andreas 2716
}
2717
 
18 andreas 2718
void TPageManager::setButtonCallbacks(Button::TButton *bt)
2719
{
2720
    bt->registerCallback(_displayButton);
2721
    bt->registerCallbackFT(_setText);
21 andreas 2722
    bt->regCallPlayVideo(_callPlayVideo);
18 andreas 2723
    bt->setFonts(mFonts);
2724
    bt->setPalette(mPalette);
2725
}
2726
 
14 andreas 2727
/**
16 andreas 2728
 * Set the button opacity. The button opacity can be specified as a decimal
2729
 * between 0 - 255, where zero (0) is invisible and 255 is opaque, or as a
2730
 * HEX code, as used in the color commands by preceding the HEX code with
2731
 * the # sign. In this case, #00 becomes invisible and #FF becomes opaque.
2732
 * If the opacity is set to zero (0), this does not make the button inactive,
2733
 * only invisible.
2734
 */
2735
void TPageManager::doBOP(int port, vector<int>& channels, vector<string>& pars)
2736
{
2737
    DECL_TRACER("TPageManager::doBOP(int port, vector<int>& channels, vector<string>& pars)");
2738
 
2739
    if (pars.size() < 2)
2740
    {
2741
        MSG_ERROR("Expecting 2 parameters but got " << pars.size() << "! Ignoring command.");
2742
        return;
2743
    }
2744
 
2745
    TError::clear();
2746
    int btState = atoi(pars[0].c_str());
2747
    int btOpacity = 0;
2748
 
2749
    if (pars[1].at(0) == '#')
2750
        btOpacity = (int)strtol(pars[1].substr(1).c_str(), NULL, 16);
2751
    else
2752
        btOpacity = atoi(pars[1].c_str());
2753
 
2754
    vector<MAP_T> map = findButtons(port, channels);
2755
 
2756
    if (TError::isError() || map.empty())
2757
        return;
2758
 
2759
    vector<Button::TButton *> buttons = collectButtons(map);
2760
    vector<Button::TButton *>::iterator mapIter;
2761
 
2762
    for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
2763
    {
2764
        Button::TButton *bt = *mapIter;
18 andreas 2765
        setButtonCallbacks(bt);
16 andreas 2766
 
2767
        if (btState == 0)       // All instances?
2768
        {
2769
            int bst = bt->getNumberInstances();
2770
            MSG_DEBUG("Setting opacity " << btOpacity << " on all " << bst << " instances...");
2771
 
2772
            for (int i = 0; i < bst; i++)
2773
                bt->setOpacity(btOpacity, i);
2774
        }
2775
        else
2776
            bt->setOpacity(btOpacity, btState);
2777
    }
2778
}
2779
 
2780
/**
2781
 * Set the button size and its position on the page.
2782
 */
2783
void TPageManager::doBSP(int port, vector<int>& channels, vector<string>& pars)
2784
{
2785
    DECL_TRACER("TPageManager::doBSP(int port, vector<int>& channels, vector<string>& pars)");
2786
 
2787
    if (pars.size() < 1)
2788
    {
2789
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
2790
        return;
2791
    }
2792
 
2793
    TError::clear();
2794
    bool bLeft = false, bTop = false, bRight = false, bBottom = false;
2795
    int x, y;
2796
    vector<string>::iterator iter;
2797
 
2798
    for (iter = pars.begin(); iter != pars.end(); iter++)
2799
    {
2800
        if (iter->compare("left") == 0)
2801
            bLeft = true;
2802
        else if (iter->compare("top") == 0)
2803
            bTop = true;
2804
        else if (iter->compare("right") == 0)
2805
            bRight = true;
2806
        else if (iter->compare("bottom") == 0)
2807
            bBottom = true;
2808
    }
2809
 
2810
 
2811
    vector<MAP_T> map = findButtons(port, channels);
2812
 
2813
    if (TError::isError() || map.empty())
2814
        return;
2815
 
2816
    vector<Button::TButton *> buttons = collectButtons(map);
2817
    vector<Button::TButton *>::iterator mapIter;
2818
 
2819
    for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
2820
    {
2821
        Button::TButton *bt = *mapIter;
18 andreas 2822
        setButtonCallbacks(bt);
16 andreas 2823
 
2824
        if (bLeft)
2825
            x = 0;
2826
 
2827
        if (bTop)
2828
            y = 0;
2829
 
2830
        if (bRight)
2831
        {
2832
            ulong handle = bt->getHandle();
2833
            int parentID = (handle >> 16) & 0x0000ffff;
2834
            int pwidth = 0;
2835
 
2836
            if (parentID < 500)
2837
            {
2838
                TPage *pg = getPage(parentID);
2839
 
2840
                if (!pg)
2841
                {
2842
                    MSG_ERROR("Internal error: Page " << parentID << " not found!");
2843
                    return;
2844
                }
2845
 
2846
                pwidth = pg->getWidth();
2847
            }
2848
            else
2849
            {
2850
                TSubPage *spg = getSubPage(parentID);
2851
 
2852
                if (!spg)
2853
                {
2854
                    MSG_ERROR("Internal error: Subpage " << parentID << " not found!");
2855
                    return;
2856
                }
2857
 
2858
                pwidth = spg->getWidth();
2859
            }
2860
 
2861
            x = pwidth - bt->getWidth();
2862
        }
2863
 
2864
        if (bBottom)
2865
        {
2866
            ulong handle = bt->getHandle();
2867
            int parentID = (handle >> 16) & 0x0000ffff;
2868
            int pheight = 0;
2869
 
2870
            if (parentID < 500)
2871
            {
2872
                TPage *pg = getPage(parentID);
2873
 
2874
                if (!pg)
2875
                {
2876
                    MSG_ERROR("Internal error: Page " << parentID << " not found!");
2877
                    return;
2878
                }
2879
 
2880
                pheight = pg->getHeight();
2881
            }
2882
            else
2883
            {
2884
                TSubPage *spg = getSubPage(parentID);
2885
 
2886
                if (!spg)
2887
                {
2888
                    MSG_ERROR("Internal error: Subpage " << parentID << " not found!");
2889
                    return;
2890
                }
2891
 
2892
                pheight = spg->getHeight();
2893
            }
2894
 
2895
            y = pheight - bt->getHeight();
2896
        }
2897
 
2898
        bt->setLeftTop(x, y);
2899
    }
2900
}
2901
 
2902
/**
2903
 * Set the button word wrap feature to those buttons with a defined address
2904
 * range. By default, word-wrap is Off.
2905
 */
2906
void TPageManager::doBWW(int port, vector<int>& channels, vector<string>& pars)
2907
{
2908
    DECL_TRACER("TPageManager::doBWW(int port, vector<int>& channels, vector<string>& pars)");
2909
 
2910
    if (pars.size() < 1)
2911
    {
2912
        MSG_ERROR("Expecting 1 parameter but got " << pars.size() << "! Ignoring command.");
2913
        return;
2914
    }
2915
 
2916
    TError::clear();
2917
    int btState = atoi(pars[0].c_str());
2918
 
2919
    vector<MAP_T> map = findButtons(port, channels);
2920
 
2921
    if (TError::isError() || map.empty())
2922
        return;
2923
 
2924
    vector<Button::TButton *> buttons = collectButtons(map);
2925
    vector<Button::TButton *>::iterator mapIter;
2926
 
2927
    for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
2928
    {
2929
        Button::TButton *bt = *mapIter;
18 andreas 2930
        setButtonCallbacks(bt);
16 andreas 2931
 
2932
        if (btState == 0)       // All instances?
2933
        {
2934
            int bst = bt->getNumberInstances();
2935
            MSG_DEBUG("Setting word wrap on all " << bst << " instances...");
2936
 
2937
            for (int i = 0; i < bst; i++)
2938
                bt->setWorWrap(true, i);
2939
        }
2940
        else
2941
            bt->setWorWrap(true, btState - 1);
2942
    }
2943
}
2944
 
2945
/**
2946
 * Clear all page flips from a button.
2947
 */
22 andreas 2948
void TPageManager::doCPF(int port, vector<int>& channels, vector<string>&)
16 andreas 2949
{
2950
    DECL_TRACER("TPageManager::doCPF(int port, vector<int>& channels, vector<string>& pars)");
2951
 
2952
    TError::clear();
2953
    vector<MAP_T> map = findButtons(port, channels);
2954
 
2955
    if (TError::isError() || map.empty())
2956
        return;
2957
 
2958
    vector<Button::TButton *> buttons = collectButtons(map);
2959
    vector<Button::TButton *>::iterator mapIter;
2960
 
2961
    for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
2962
    {
2963
        Button::TButton *bt = *mapIter;
18 andreas 2964
        setButtonCallbacks(bt);
16 andreas 2965
        bt->clearPushFunctions();
2966
    }
2967
}
2968
 
2969
/**
2970
 * Delete page flips from button if it already exists.
2971
 */
2972
void TPageManager::doDPF(int port, vector<int>& channels, vector<string>& pars)
2973
{
2974
    DECL_TRACER("TPageManager::doDPF(int port, vector<int>& channels, vector<string>& pars)");
2975
 
2976
    if (pars.size() < 1)
2977
    {
2978
        MSG_ERROR("Expecting at least 1 parameter but got " << pars.size() << "! Ignoring command.");
2979
        return;
2980
    }
2981
 
2982
    TError::clear();
2983
    string action = pars[0];
2984
    string pname;
2985
 
2986
    if (pars.size() >= 2)
2987
    {
2988
        pname = pars[1];
2989
        vector<Button::TButton *> list;
2990
        // First we search for a subpage because this is more likely
2991
        TSubPage *spg = getSubPage(pname);
2992
 
2993
        if (spg)
2994
            list = spg->getButtons(port, channels[0]);
2995
        else    // Then for a page
2996
        {
2997
            TPage *pg = getPage(pname);
2998
 
2999
            if (pg)
3000
                list = pg->getButtons(port, channels[0]);
3001
            else
3002
            {
3003
                MSG_WARNING("The name " << pname << " doesn't name either a page or a subpage!");
3004
                return;
3005
            }
3006
        }
3007
 
3008
        if (list.empty())
3009
            return;
3010
 
3011
        vector<Button::TButton *>::iterator it;
3012
 
3013
        for (it = list.begin(); it != list.end(); it++)
3014
        {
3015
            Button::TButton *bt = *it;
18 andreas 3016
            setButtonCallbacks(bt);
16 andreas 3017
            bt->clearPushFunction(action);
3018
        }
3019
 
3020
        return;
3021
    }
3022
 
3023
    // Here we don't have a page name
3024
    vector<MAP_T> map = findButtons(port, channels);
3025
 
3026
    if (TError::isError() || map.empty())
3027
        return;
3028
 
3029
    vector<Button::TButton *> buttons = collectButtons(map);
3030
    vector<Button::TButton *>::iterator mapIter;
3031
 
3032
    for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
3033
    {
3034
        Button::TButton *bt = *mapIter;
18 andreas 3035
        setButtonCallbacks(bt);
16 andreas 3036
        bt->clearPushFunction(action);
3037
    }
3038
}
3039
 
3040
/**
3041
 * Enable or disable buttons with a set variable text range.
3042
 */
3043
void TPageManager::doENA(int port, vector<int>& channels, vector<string>& pars)
3044
{
3045
    DECL_TRACER("TPageManager::doENA(int port, vector<int>& channels, vector<string>& pars)");
3046
 
3047
    if (pars.empty())
3048
    {
3049
        MSG_ERROR("Expecting 1 parameter but got none! Ignoring command.");
3050
        return;
3051
    }
3052
 
3053
    TError::clear();
3054
    int cvalue = atoi(pars[0].c_str());
3055
 
3056
    vector<MAP_T> map = findButtons(port, channels);
3057
 
3058
    if (TError::isError() || map.empty())
3059
        return;
3060
 
3061
    vector<Button::TButton *> buttons = collectButtons(map);
3062
    vector<Button::TButton *>::iterator mapIter;
3063
 
3064
    for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
3065
    {
3066
        Button::TButton *bt = *mapIter;
18 andreas 3067
        setButtonCallbacks(bt);
16 andreas 3068
        bt->setEnable(((cvalue)?true:false));
3069
    }
3070
}
3071
 
3072
/**
3073
 * Set a font to a specific Font ID value for those buttons with a defined
3074
 * address range. Font ID numbers are generated by the TPDesign4 programmers
3075
 * report.
3076
 */
3077
void TPageManager::doFON(int port, vector<int>& channels, vector<string>& pars)
3078
{
3079
    DECL_TRACER("TPageManager::doFON(int port, vector<int>& channels, vector<string>& pars)");
3080
 
3081
    if (pars.size() < 2)
3082
    {
3083
        MSG_ERROR("Expecting 2 parameters but got " << pars.size() << "! Ignoring command.");
3084
        return;
3085
    }
3086
 
3087
    TError::clear();
3088
    int btState = atoi(pars[0].c_str());
3089
    int fvalue = atoi(pars[1].c_str());
3090
 
3091
    vector<MAP_T> map = findButtons(port, channels);
3092
 
3093
    if (TError::isError() || map.empty())
3094
        return;
3095
 
3096
    vector<Button::TButton *> buttons = collectButtons(map);
3097
    vector<Button::TButton *>::iterator mapIter;
3098
 
3099
    for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
3100
    {
3101
        Button::TButton *bt = *mapIter;
18 andreas 3102
        setButtonCallbacks(bt);
16 andreas 3103
 
3104
        if (btState == 0)       // All instances?
3105
        {
3106
            int bst = bt->getNumberInstances();
3107
            MSG_DEBUG("Setting font " << fvalue << " on all " << bst << " instances...");
3108
 
3109
            for (int i = 0; i < bst; i++)
3110
                bt->setFont(fvalue, i);
3111
        }
3112
        else
3113
            bt->setFont(fvalue, btState - 1);
3114
    }
3115
}
3116
 
3117
/**
14 andreas 3118
 * Set the icon to a button.
3119
 */
3120
void TPageManager::doICO(int port, vector<int>& channels, vector<string>& pars)
3121
{
3122
    DECL_TRACER("TPageManager::doICO(int port, vector<int>& channels, vector<string>& pars)");
3123
 
3124
    if (pars.size() < 2)
3125
    {
3126
        MSG_ERROR("Expecting 2 parameters but got " << pars.size() << "! Ignoring command.");
3127
        return;
3128
    }
3129
 
16 andreas 3130
    TError::clear();
14 andreas 3131
    int btState = atoi(pars[0].c_str());
3132
    int iconIdx = atoi(pars[1].c_str());
3133
 
3134
    vector<MAP_T> map = findButtons(port, channels);
3135
 
3136
    if (TError::isError() || map.empty())
3137
        return;
3138
 
3139
    vector<Button::TButton *> buttons = collectButtons(map);
3140
    vector<Button::TButton *>::iterator mapIter;
3141
 
3142
    for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
3143
    {
3144
        Button::TButton *bt = *mapIter;
18 andreas 3145
        setButtonCallbacks(bt);
14 andreas 3146
 
3147
        if (btState == 0)       // All instances?
3148
        {
3149
            int bst = bt->getNumberInstances();
3150
            MSG_DEBUG("Setting Icon on all " << bst << " instances...");
3151
 
3152
            for (int i = 0; i < bst; i++)
3153
            {
3154
                if (iconIdx > 0)
3155
                    bt->setIcon(iconIdx, i);
3156
                else
3157
                    bt->revokeIcon(i);
3158
            }
3159
        }
3160
        else if (iconIdx > 0)
3161
            bt->setIcon(iconIdx, btState - 1);
3162
        else
3163
            bt->revokeIcon(btState - 1);
3164
    }
3165
}
3166
 
3167
/**
16 andreas 3168
 * Show or hide a button with a set variable text range.
3169
 */
3170
void TPageManager::doSHO(int port, vector<int>& channels, vector<string>& pars)
3171
{
3172
    DECL_TRACER("TPageManager::doSHO(int port, vector<int>& channels, vector<string>& pars)");
3173
 
3174
    if (pars.empty())
3175
    {
3176
        MSG_ERROR("Expecting 1 parameter but got none! Ignoring command.");
3177
        return;
3178
    }
3179
 
3180
    TError::clear();
3181
    int cvalue = atoi(pars[0].c_str());
3182
 
3183
    vector<MAP_T> map = findButtons(port, channels);
3184
 
3185
    if (TError::isError() || map.empty())
3186
        return;
3187
 
3188
    vector<Button::TButton *> buttons = collectButtons(map);
3189
    vector<Button::TButton *>::iterator mapIter;
3190
 
3191
    for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
3192
    {
3193
        Button::TButton *bt = *mapIter;
18 andreas 3194
        setButtonCallbacks(bt);
16 andreas 3195
        bt->setVisible(((cvalue)?true:false));
3196
        bt->refresh();
3197
    }
3198
}
3199
 
3200
/**
14 andreas 3201
 * Assign a text string to those buttons with a defined address range.
3202
 * Sets Non-Unicode text.
3203
 */
3204
void TPageManager::doTXT(int port, vector<int>& channels, vector<string>& pars)
3205
{
3206
    DECL_TRACER("TPageManager::doTXT(int port, vector<int>& channels, vector<string>& pars)");
3207
 
3208
    if (pars.size() < 1)
3209
    {
3210
        MSG_ERROR("Expecting 1 parameters but got none! Ignoring command.");
3211
        return;
3212
    }
3213
 
16 andreas 3214
    TError::clear();
14 andreas 3215
    int btState = atoi(pars[0].c_str());
3216
    string text;
3217
 
3218
    if (pars.size() > 1)
3219
        text = pars[1];
3220
 
3221
    vector<MAP_T> map = findButtons(port, channels);
3222
 
3223
    if (TError::isError() || map.empty())
3224
        return;
3225
 
3226
    vector<Button::TButton *> buttons = collectButtons(map);
3227
    vector<Button::TButton *>::iterator mapIter;
3228
 
3229
    for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
3230
    {
3231
        Button::TButton *bt = *mapIter;
18 andreas 3232
        setButtonCallbacks(bt);
14 andreas 3233
 
3234
        if (btState == 0)       // All instances?
3235
        {
3236
            int bst = bt->getNumberInstances();
3237
            MSG_DEBUG("Setting TXT on all " << bst << " instances...");
3238
 
3239
            for (int i = 0; i < bst; i++)
3240
                bt->setText(text, i);
3241
        }
3242
        else
3243
            bt->setText(text, btState - 1);
3244
    }
3245
}
21 andreas 3246
 
3247
void TPageManager::doBBR(int port, vector<int>& channels, vector<string>& pars)
3248
{
3249
    DECL_TRACER("TPageManager::doBBR(int port, vector<int>& channels, vector<string>& pars)");
3250
 
3251
    if (pars.size() < 2)
3252
    {
3253
        MSG_ERROR("Expecting 2 parameters but got none! Ignoring command.");
3254
        return;
3255
    }
3256
 
3257
    TError::clear();
3258
    int btState = atoi(pars[0].c_str());
3259
    string resName = pars[1];
3260
 
3261
    vector<MAP_T> map = findButtons(port, channels);
3262
 
3263
    if (TError::isError() || map.empty())
3264
        return;
3265
 
3266
    vector<Button::TButton *> buttons = collectButtons(map);
3267
    vector<Button::TButton *>::iterator mapIter;
3268
 
3269
    for (mapIter = buttons.begin(); mapIter != buttons.end(); mapIter++)
3270
    {
3271
        Button::TButton *bt = *mapIter;
3272
        setButtonCallbacks(bt);
3273
 
3274
        if (btState == 0)       // All instances?
3275
        {
3276
            int bst = bt->getNumberInstances();
3277
            MSG_DEBUG("Setting BBR on all " << bst << " instances...");
3278
 
3279
            for (int i = 0; i < bst; i++)
3280
                bt->setResourceName(resName, i);
3281
        }
3282
        else
3283
            bt->setResourceName(resName, btState - 1);
3284
    }
3285
}
3286
 
22 andreas 3287
void TPageManager::doRMF(int, vector<int>&, vector<string>& pars)
21 andreas 3288
{
3289
    DECL_TRACER("TPageManager::doRMF(int port, vector<int>& channels, vector<string>& pars)");
3290
 
3291
    if (pars.size() < 2)
3292
    {
3293
        MSG_ERROR("Expecting 2 parameters but got none! Ignoring command.");
3294
        return;
3295
    }
3296
 
3297
    string name = pars[0];
3298
    string data = pars[1];
3299
 
3300
    vector<string> parts = StrSplit(data, "%");
3301
    RESOURCE_T res;
3302
    vector<string>::iterator sIter;
3303
 
3304
    for (sIter = parts.begin(); sIter != parts.end(); sIter++)
3305
    {
3306
        const char *s = sIter->c_str();
22 andreas 3307
        string ss = *sIter;
3308
        MSG_DEBUG("Parsing \"" << ss << "\" with token << " << ss[0]);
21 andreas 3309
 
3310
        switch(*s)
3311
        {
3312
            case 'P':
3313
                if (*(s+1) == '0')
3314
                    res.protocol = "HTTP";
3315
                else
3316
                    res.protocol = "FTP";
3317
            break;
3318
 
3319
            case 'U': res.user = sIter->substr(1); break;
3320
            case 'S': res.password = sIter->substr(1); break;
3321
            case 'H': res.host = sIter->substr(1); break;
3322
            case 'F': res.file = sIter->substr(1); break;
3323
            case 'A': res.path = sIter->substr(1); break;
3324
            case 'R': res.refresh = atoi(sIter->substr(1).c_str()); break;
3325
 
3326
            default:
3327
                MSG_WARNING("Option " << sIter->at(0) << " is currently not implemented!");
3328
        }
3329
    }
3330
 
3331
    if (gPrjResources)
3332
        gPrjResources->setResource(name, res.protocol, res.host, res.path, res.file, res.user, res.password, res.refresh);
3333
}