/*! \file piscreen.h * \ingroup Console * \~\brief * \~english Console screen manager and tile host * \~russian Менеджер консольного экрана и контейнер тайлов */ /* PIP - Platform Independent Primitives Console GUI Ivan Pelipenko peri4ko@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef PISCREEN_H #define PISCREEN_H #include "pip_console_export.h" #include "piscreendrawer.h" #include "piscreentile.h" //! \ingroup Console //! \~\brief //! \~english Console screen manager with tile layout, drawing, and input routing. //! \~russian Менеджер консольного экрана с раскладкой тайлов, отрисовкой и маршрутизацией ввода. class PIP_CONSOLE_EXPORT PIScreen : public PIThread , public PIScreenTypes::PIScreenBase { PIOBJECT_SUBCLASS(PIScreen, PIThread); class SystemConsole; public: //! \~english Constructs a screen with an internal keyboard listener, optional callback, and auto-start mode. //! \~russian Создает экран со встроенным слушателем клавиатуры, необязательным обратным вызовом и режимом автозапуска. PIScreen(bool startNow = true, PIKbdListener::KBFunc slot = 0); //! \~english Stops the drawing thread and destroys the listener. //! \~russian Останавливает поток отрисовки и уничтожает слушатель. ~PIScreen(); //! \~english Enables exit key capture in the internal listener used by \a waitForFinish(). //! \~russian Включает перехват клавиши выхода во внутреннем слушателе, используемом методом \a waitForFinish(). void enableExitCapture(int key = 'Q') { listener->enableExitCapture(key); } //! \~english Disables exit key capture in the internal keyboard listener. //! \~russian Выключает перехват клавиши выхода во внутреннем слушателе клавиатуры. void disableExitCapture() { listener->disableExitCapture(); } //! \~english Returns whether exit key capture is enabled. //! \~russian Возвращает, включен ли перехват клавиши выхода. bool exitCaptured() const { return listener->exitCaptured(); } //! \~english Returns the configured exit key. //! \~russian Возвращает настроенную клавишу выхода. int exitKey() const { return listener->exitKey(); } //! \~english Returns the current console width in cells. //! \~russian Возвращает текущую ширину консоли в ячейках. int windowWidth() const { return console.width; } //! \~english Returns the current console height in cells. //! \~russian Возвращает текущую высоту консоли в ячейках. int windowHeight() const { return console.height; } //! \~english Returns whether mouse hit-testing and routing are enabled. //! \~russian Возвращает, включены ли проверка попадания и маршрутизация событий мыши. bool isMouseEnabled() const { return mouse_; } //! \~english Enables or disables mouse routing and tile hit-testing. //! \~russian Включает или выключает маршрутизацию мыши и проверку попадания по тайлам. void setMouseEnabled(bool on); //! \~english Returns the root tile covering the whole screen. //! \~russian Возвращает корневой тайл, покрывающий весь экран. PIScreenTile * rootTile() { return &root; } //! \~english Searches the root tile subtree by object name. //! \~russian Ищет тайл по имени объекта в поддереве корневого тайла. PIScreenTile * tileByName(const PIString & name); //! \~english Sets a dialog tile drawn above the root tree, centered on screen, and focused first. Pass \c nullptr to remove it. //! \~russian Задает диалоговый тайл, рисуемый поверх корневого дерева, центрируемый на экране и первым получающий фокус. Передайте \c nullptr, чтобы убрать его. void setDialogTile(PIScreenTile * t); //! \~english Returns the currently active dialog tile or \c nullptr. //! \~russian Возвращает активный диалоговый тайл или \c nullptr. PIScreenTile * dialogTile() const { return tile_dialog; } //! \~english Returns the drawer used to fill the off-screen cell buffer for the next frame. //! \~russian Возвращает рисовальщик, используемый для заполнения внеэкранного буфера ячеек следующего кадра. PIScreenDrawer * drawer() { return &drawer_; } //! \~english Clears the off-screen cell buffer. The terminal is updated on the next draw cycle. //! \~russian Очищает внеэкранный буфер ячеек. Терминал обновится на следующем цикле отрисовки. void clear() { drawer_.clear(); } //! \~english Resizes the internal console buffers used for subsequent frames. //! \~russian Изменяет размер внутренних консольных буферов, используемых в следующих кадрах. void resize(int w, int h) { console.resize(w, h); } EVENT_HANDLER0(void, waitForFinish); EVENT_HANDLER0(void, start) { start(false); } EVENT_HANDLER1(void, start, bool, wait); EVENT_HANDLER0(void, stop) { stop(false); } EVENT_HANDLER1(void, stop, bool, clear); EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void *, data); EVENT2(tileEvent, PIScreenTile *, tile, PIScreenTypes::TileEvent, e); //! \handlers //! \{ //! \fn void waitForFinish() //! \~english Blocks until the captured exit key is pressed and then stops the screen. //! \~russian Блокирует выполнение, пока не будет нажата перехватываемая клавиша выхода, затем останавливает экран. //! \fn void start(bool wait = false) //! \~english Starts the screen thread and optionally waits until the configured exit key is captured. //! \~russian Запускает поток экрана и при необходимости ждет, пока не будет перехвачена настроенная клавиша выхода. //! \fn void stop(bool clear = false) //! \~english Stops the screen thread, restores console state, and optionally clears the terminal. //! \~russian Останавливает поток экрана, восстанавливает состояние консоли и при необходимости очищает терминал. //! \} //! \events //! \{ //! \fn void keyPressed(PIKbdListener::KeyEvent key, void * data) //! \~english Raised when a key was not consumed by focus navigation or the focused tile. \a data is the screen user data pointer. //! \~russian Вызывается, когда клавиша не была поглощена навигацией фокуса или тайлом с фокусом. \a data содержит пользовательский указатель экрана. //! \fn void tileEvent(PIScreenTile * tile, PIScreenTypes::TileEvent e) //! \~english Raised when a tile reports a custom event \a e. //! \~russian Вызывается, когда тайл сообщает пользовательское событие \a e. //! \} private: class PIP_CONSOLE_EXPORT SystemConsole { public: SystemConsole(); ~SystemConsole(); void begin(); void end(); void prepare(); void clear(); void print(); void resize(int w, int h); void toUpperLeft(); void moveTo(int x = 0, int y = 0); void hideCursor(); void showCursor(); void clearScreen(); void clearScreenLower(); #ifdef WINDOWS void getWinCurCoord(); void clearLine(); void newLine(); ushort attributes(const PIScreenTypes::Cell & c); #else PIString formatString(const PIScreenTypes::Cell & c); #endif PRIVATE_DECLARATION(PIP_CONSOLE_EXPORT) int width, height, pwidth, pheight; int mouse_x, mouse_y; PIVector> cells, pcells; }; void begin() override; void run() override; void end() override; void key_event(PIKbdListener::KeyEvent key); EVENT_HANDLER1(void, mouse_event, PIKbdListener::MouseEvent, me); EVENT_HANDLER1(void, wheel_event, PIKbdListener::WheelEvent, we); static void key_eventS(PIKbdListener::KeyEvent key, void * t) { ((PIScreen *)t)->key_event(key); } PIVector tiles() { return root.children(); } PIVector prepareMouse(PIKbdListener::MouseEvent * e); PIVector tilesUnderMouse(int x, int y); bool nextFocus(PIScreenTile * rt, PIKbdListener::KeyEvent key = PIKbdListener::KeyEvent()); void tileEventInternal(PIScreenTile * t, PIScreenTypes::TileEvent e) override; void tileRemovedInternal(PIScreenTile * t) override; void tileSetFocusInternal(PIScreenTile * t) override; bool mouse_; SystemConsole console; PIScreenDrawer drawer_; PIKbdListener * listener; PIKbdListener::KBFunc ret_func; PIScreenTile root; PIScreenTile *tile_focus, *tile_dialog; }; #endif // PISCREEN_H