Subversion Repositories tpanel

Rev

Rev 26 | Blame | Last modification | View Log | RSS feed

/*
 * Copyright (C) 2020, 2021 by Andreas Theofilu <andreas@theosys.at>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 */

#ifndef __TPAGEMANAGER_H__
#define __TPAGEMANAGER_H__

#include <functional>
#include <thread>

#include "tpagelist.h"
#include "tpage.h"
#include "tsubpage.h"
#include "tsettings.h"
#include "tpalette.h"
#include "tbutton.h"
#include "tfont.h"
#include "tamxnet.h"
#include "tamxcommands.h"

#define REG_CMD(func, name)     registerCommand(bind(&TPageManager::func, this,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3),name)

class TIcons;
class TPageManager;

extern bool prg_stopped;
extern TIcons *gIcons;
extern TPrjResources *gPrjResources;
extern TPageManager *gPageManager;

class TPageManager : public TAmxCommands
{
    public:
        TPageManager();
        ~TPageManager();

        bool readPages();                           // Read all pages and subpages
        bool readPage(const std::string& name);     // Read only one page
        bool readPage(int ID);
        bool readSubPage(const std::string& name);  // Read only one subpage
        bool readSubPage(int ID);

        TPageList *getPageList() { return mPageList; }
        TSettings *getSettings() { return mTSettings; }

        TPage *getActualPage();
        int getActualPageNumber() { return mActualPage; }
        int getPreviousPageNumber() { return mPreviousPage; }
        TSubPage *getFirstSubPage();
        TSubPage *getNextSubPage();
        TSubPage *getFirstSubPageGroup(const std::string& group);
        TSubPage *getNextSubPageGroup();
        TSubPage *getNextSubPageGroup(const std::string& group, TSubPage *pg);
        TSubPage *getTopPage();

        TPage *getPage(int pageID);
        TPage *getPage(const std::string& name);
        bool setPage(int PageID);
        bool setPage(const std::string& name);
        TSubPage *getSubPage(int pageID);
        TSubPage *getSubPage(const std::string& name);
        bool havePage(const std::string& name);
        bool haveSubPage(const std::string& name);
        bool haveSubPage(int id);
        bool haveSubPage(const std::string& page, const std::string& name);
        bool haveSubPage(const std::string& page, int id);

        void registerCallbackDB(std::function<void(ulong handle, ulong parent, unsigned char *buffer, int width, int height, int pixline, int left, int top)> displayButton) { _displayButton = displayButton; }
        void registerCallbackSP(std::function<void (ulong handle, int width, int height)> setPage) { _setPage = setPage; }
        void registerCallbackSSP(std::function<void (ulong handle, int left, int top, int width, int height)> setSubPage) { _setSubPage = setSubPage; }
        void registerCallbackSB(std::function<void (ulong handle, unsigned char *image, size_t size, size_t rowBytes, ulong color)> setBackground) {_setBackground = setBackground; }
        void deployCallbacks();

        /**
         * Call the frontend to write some text. The text must be written with
         * a given font and the defined style. The parameters are:
         *
         * @param handle
         * Handle that identifies the object the text belongs to
         * @param text
         * The text to draw
         * @param font
         * The path and name of the font to use. This is always a true type font.
         * @param size
         * The size in pixels. This is for the height.
         * @param color
         * The color the text should have
         * @param effectColor
         * The color the text effect should have.
         * @param ori
         * The text orientation
         * @param effect
         * The type of text effect
         * @param ww
         * TRUE = word wrap
         */
        void registerCallbackFT(std::function<void (ulong handle, const std::string& text, const std::string& font, const std::string& family, int size, int x, int y, ulong color, ulong effectColor, FONT_STYLE style, Button::TEXT_ORIENTATION ori, Button::TEXT_EFFECT effect, bool ww)> setText)
        { _setText = setText; }

        void regCallDropPage(std::function<void (ulong handle)> callDropPage) { _callDropPage = callDropPage; }
        void regCallDropSubPage(std::function<void (ulong handle)> callDropSubPage) { _callDropSubPage = callDropSubPage; }
        void regCallPlayVideo(std::function<void (ulong handle, ulong parent, int left, int top, int width, int height, const std::string& url, const std::string& user, const std::string& pw)> callPlayVideo) { _callPlayVideo = callPlayVideo; };

        /**
         * The following function must be called to start non graphics part
         * of the panel simulator. If everything worked well, it returns TRUE.
         * otherwise a FALSE is returned and the program should be terminated.
         */
        bool run();
        /**
         * Set an X value to add to the coordinated reported by the mouse catch
         * event. In case the X coordinate reported by the event is not the real
         * X coordinate, it's possible to set an X coordinate to translate the
         * internal used coordinates.
         *
         * @param x
         * The left most pixel which correspond to X = 0
         */
        void setFirstLeftPixel(int x) { mFirstLeftPixel = x; }
        /**
         * Set an Y value to add to the coordinated reported by the mouse catch
         * event. In case the Y coordinate reported by the event is not the real
         * Y coordinate, it's possible to set an Y coordinate to translate the
         * internal used coordinates.
         *
         * @param y
         * The left most pixel which correspond to Y = 0
         */
        void setFirstTopPixel(int y) { mFirstTopPixel = y; }
        /**
         * This function must be called from a GUI whenever the left mouse
         * button was pressed or released. Also if there was a touch event
         * this function must be called in the same way. It's up to any GUI
         * to handle the mouse and or touch events.
         *
         * @param x
         * the X coordinate of the mouse/touch event
         *
         * @param y
         * the y coordinate if the mouse/touch event
         *
         * @return
         * pressed TRUE = button was pressed; FALSE = button was released
         */
        void mouseEvent(int x, int y, bool pressed);

        void dropAllSubPages();
        void closeGroup(const std::string& group);
        void showSubPage(const std::string& name);
        void hideSubPage(const std::string& name);
        void setScaleFactor(double scale) { mScaleFactor = scale; }
        double getScaleFactor() { return mScaleFactor; }
        void setScaleFactorWidth(double scale) { mScaleFactorWidth = scale; }
        double getScaleFactorWidth() { return mScaleFactorWidth; }
        void setScaleFactorHeight(double scale) { mScaleFactorHeight = scale; }
        double getScaleFactorHeight() { return mScaleFactorHeight; }

        std::function<void (ulong handle, ulong parent, unsigned char *buffer, int width, int height, int pixline, int left, int top)> getCallbackDB() { return _displayButton; }
        std::function<void (ulong handle, unsigned char *image, size_t size, size_t rowBytes, ulong color)> getCallbackBG() { return _setBackground; }
        std::function<void (ulong handle, ulong parent, int left, int top, int width, int height, const std::string& url, const std::string& user, const std::string& pw)> getCallbackPV() { return _callPlayVideo; }

    protected:
        PAGELIST_T findPage(const std::string& name);
        PAGELIST_T findPage(int ID);
        SUBPAGELIST_T findSubPage(const std::string& name);
        SUBPAGELIST_T findSubPage(int ID);

        bool addPage(TPage *pg);
        bool addSubPage(TSubPage *pg);
        TSubPage *getCoordMatch(int x, int y);
        void initialize();
        void dropAllPages();

    private:
        std::function<void (ulong handle, ulong parent, unsigned char *buffer, int width, int height, int pixline, int left, int top)> _displayButton{nullptr};
        std::function<void (ulong handle, int width, int height)> _setPage{nullptr};
        std::function<void (ulong handle, int left, int top, int width, int height)> _setSubPage{nullptr};
        std::function<void (ulong handle, unsigned char *image, size_t size, size_t rowBytes, ulong color)> _setBackground{nullptr};
        std::function<void (ulong handle, const std::string& text, const std::string& font, const std::string& family, int size, int x, int y, ulong color, ulong effectColor, FONT_STYLE style, Button::TEXT_ORIENTATION ori, Button::TEXT_EFFECT effect, bool ww)> _setText{nullptr};
        std::function<void (ulong handle)> _callDropPage{nullptr};
        std::function<void (ulong handle)> _callDropSubPage{nullptr};
        std::function<void (ulong handle, ulong parent, int left, int top, int width, int height, const std::string& url, const std::string& user, const std::string& pw)> _callPlayVideo{nullptr};

        bool doOverlap(RECT_T r1, RECT_T r2);
        /**
         * Callback function for the AMX controller part. This function must
         * be registered to the class TAmxNet and is called from this module
         * every time an event occured from the controller.
         * This method handles the commands comming from the controller and
         * draws the necessary elements before they are sent to the GUI.
         *
         * @param cmd
         * An ANET_COMMAND structure containing the received command.
         */
        void doCommand(const amx::ANET_COMMAND& cmd);
        /**
         * The following function is used internaly. It searches in the map
         * table for the button corresponding to the port and channel number
         * and puts the result into a chain of buttons. This chain is returned.
         *
         * If there are some pages not yet in memory, they will be created just
         * to be able to set the button(s).
         */
        std::vector<Button::TButton *> collectButtons(std::vector<MAP_T>& map);
        TPage *loadPage(PAGELIST_T& pl);
        void setButtonCallbacks(Button::TButton *bt);

        // List of command functions
        void doFTR(int port, std::vector<int>&, std::vector<std::string>& pars);

        void doON(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doOFF(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doLEVEL(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doBLINK(int port, std::vector<int>& channels, std::vector<std::string>& pars);

        void doAPG(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doCPG(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doDPG(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doPHE(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doPHP(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doPHT(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doPPA(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doPPF(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doPPG(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doPPK(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doPPM(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doPPN(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doPPT(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doPPX(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doPSE(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doPSP(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doPST(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doPAGE(int port, std::vector<int>& channels, std::vector<std::string>& pars);

        void doAPF(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doBMP(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doBOP(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doBSP(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doBWW(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doCPF(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doDPF(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doENA(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doFON(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doICO(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doSHO(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doTXT(int port, std::vector<int>& channels, std::vector<std::string>& pars);

        void doBBR(int port, std::vector<int>& channels, std::vector<std::string>& pars);
        void doRMF(int port, std::vector<int>& channels, std::vector<std::string>& pars);

        int mActualPage{0};                             // The number of the actual visible page
        int mPreviousPage{0};                           // The number of the previous page
        int mFirstLeftPixel{0};                         // Pixels to add to left (x) mouse coordinate
        int mFirstTopPixel{0};                          // Pixels to add to top (y) mouse position
        std::string mActualGroupName;                   // The name of the actual group
        TSubPage *mActualGroupPage{nullptr};            // Pointer to subpage of a group whi is visible

        amx::TAmxNet *mAmxNet{nullptr};                 // Pointer to class TAmxNet; Handles the communication with the controller
        TPageList *mPageList{nullptr};                  // List of available pages and subpages
        PCHAIN_T *mPchain{nullptr};                     // Pointer to chain of pages in memory
        SPCHAIN_T *mSPchain{nullptr};                   // Pointer to chain of subpages in memory for the actual page
        TSettings *mTSettings{nullptr};                 // Pointer to basic settings for the panel
        TPalette *mPalette{nullptr};                    // Pointer to the color handler
        TFont *mFonts{nullptr};                         // Pointer to the font handler
        std::thread mThreadAmxNet;                      // The thread handle to the controler handler
        std::vector<amx::ANET_COMMAND> mCommands;       // Command queue of commands received from controller
        bool mBusy{false};                              // Internal used to block the command handler
        std::string mCmdBuffer;                         // Internal used buffer for commands who need more than one network package
        double mScaleFactor{1.0};                       // The scale factor to zoom or shrink all components
        double mScaleFactorWidth{1.0};                  // The individual scale factor for the width
        double mScaleFactorHeight{1.0};                 // The individual scale factor for the height
};

#endif