/****************************************************************************** * Copyright (c) 2018(-2023) STMicroelectronics. * All rights reserved. * * This file is part of the TouchGFX 4.22.0 distribution. * * This software is licensed under terms that can be found in the LICENSE file in * the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * *******************************************************************************/ /** * @file touchgfx/Application.hpp * * Declares the application class. */ #ifndef TOUCHGFX_APPLICATION_HPP #define TOUCHGFX_APPLICATION_HPP #include #include #include #include #include #include #include #include namespace touchgfx { class Drawable; class Screen; class Transition; /** * The Application class is the main interface for manipulating screen contents. It holds a * pointer to the currently displayed Screen, and delegates draw requests and events to * that Screen. Additionally it contains some global application settings. */ class Application : public UIEventListener { public: /** * Gets the single instance application. * * @return The instance of this application. */ static Application* getInstance(); /** * Gets the current screen. * * @return The current screen. */ static Screen* getCurrentScreen() { return currentScreen; } /** * This function can be called to send your application back to * the start screen. The simulator will call this function when F5 * is pressed. To make this work, please implement this function * in FrontendApplication. * * @note The application will not make a complete restart - if * your Model contains data, this will not be reset, unless * this is explicitly done in your * FrontendApplication::changeToStartScreen(). */ virtual void changeToStartScreen() { } /** * Switch to another Screen. Will call tearDownScreen on current Screen before switching, * and subsequently call setupScreen and draw automatically for the new Screen. * * @param [in] newScreen A pointer to the new screen. */ virtual void switchScreen(Screen* newScreen); /** * An application specific function for switching screen. Overloading this can provide a * means to switch screen from places that does not have access to a pointer to the new * screen. Base implementation is empty. * * @param screenId An id that maps to the desired screen. */ virtual void appSwitchScreen(uint8_t screenId) { (void)screenId; // Unused variable } /** An application specific function for requesting redraw of entire screen. */ virtual void requestRedraw(); /** * An application specific function for requesting redraw of given Rect. * * @param [in,out] rect The Rect that must be redrawn. */ virtual void requestRedraw(Rect& rect) { redraw = rect; } /** * Handle a click event. Standard implementation is to delegate the event to the current * screen. Called by the framework when a click is detected by some platform specific * means. * * @param event The ClickEvent. */ virtual void handleClickEvent(const ClickEvent& event); /** * Handle drag events. Called by the framework when a drag is detected by some platform * specific means. Standard implementation is to delegate drag event to current screen. * * @param event The drag event, expressed in absolute coordinates. */ virtual void handleDragEvent(const DragEvent& event); /** * Handle gestures. Called by the framework when a gesture is detected by some platform * specific means. Standard implementation is to delegate drag event to current screen. * * @param event The gesture event. */ virtual void handleGestureEvent(const GestureEvent& event); /** * Handle tick. Standard implementation is to delegate tick to the widgets that have * registered to receive one. Called by some platform specific means. */ virtual void handleTickEvent(); /** * Handle an incoming character received by the HAL layer. Standard implementation * delegates to current screen (which, in turn, does nothing). * * @param c The incoming character to handle. */ virtual void handleKeyEvent(uint8_t c); /** * Evaluates the pending Callback instances. If a callback is valid, it is executed and * a Screen transition is executed. This base implementation is empty and does nothing. */ virtual void handlePendingScreenTransition(); /** * Clears the cached areas so coming calls to invalidate are collected for future drawing. * * @see drawCachedAreas */ virtual void clearCachedAreas(); /** * Draws all cached, invalidated areas on the screen. * * @see clearCachedAreas */ virtual void drawCachedAreas(); /** * This function copies the parts that were updated in the * previous frame (in the TFT buffer) to the active framebuffer * (client buffer). * * This function only copies pixels in double buffering mode. */ void copyInvalidatedAreasFromTFTToClientBuffer(); /** * Adds a widget to the list of widgets receiving ticks every frame (typically * 16.67ms) * * @param [in] w The widget to add. * * @see unregisterTimerWidget * * @note The framework keeps track of the number of times a specific widget is registered. */ void registerTimerWidget(Drawable* w) { timerWidgets.add(w); } /** Clears all currently registered timer widgets. */ void clearAllTimerWidgets() { timerWidgets.clear(); } /** * Removes a widget from the list of widgets receiving ticks every frame (typically * 16.67ms) milliseconds. * * @param [in] w The widget to remove. * * @note If widget has been registered multiple times, an equal number of calls to unregister * are required to stop widget from receiving tick events. */ void unregisterTimerWidget(const Drawable* w) { timerWidgets.remove(w); } /** * gets the number of timer widgets that are registered and active. * * @return The size of timerWidgets. */ uint16_t getNumberOfRegisteredTimerWidgets() const { return timerWidgets.getNumberOfActiveTimerWidgets(); } /** * Gets the number of timer events registered to a widget, i.e. how many times a * drawable must be unregistered until it no longer receives timer ticks. * * @param w The widget to to get count from. * * @return 0 if the drawable is not registered as a timer widget, otherwise returns how * many times the drawable is currently registered. */ uint16_t getTimerWidgetCountForDrawable(const Drawable* w) const { return timerWidgets.getCounter(w); } static const uint8_t MAX_TIMER_WIDGETS = 32; ///< Maximum number of widgets receiving ticks. @remarks Memory impact: x * (sizeof(Drawable*)+1) static const uint16_t TICK_INTERVAL_MS = 10; ///< Deprecated, do not use this constant. Tick interval depends on VSYNC of your target platform. /** * Sets the DebugPrinter object to be used by the application to print debug messages. * * @param [in] printer The debug printer to configure. */ static void setDebugPrinter(DebugPrinter* printer) { debugPrinter = printer; } /** * Returns the DebugPrinter object associated with the application. * * @return DebugPrinter The DebugPrinter object. */ static DebugPrinter* getDebugPrinter() { return debugPrinter; } /** * Sets the debug string to be displayed onscreen on top of the framebuffer. */ static void invalidateDebugRegion() { if (debugPrinter) { debugRegionInvalidRect.expandToFit(debugPrinter->getRegion()); } } /** * Sets the debug string to be displayed onscreen on top of the framebuffer. * * @param [in] string The debug string to display onscreen. */ static void setDebugString(const char* string) { if (debugPrinter) { debugPrinter->setString(string); invalidateDebugRegion(); } } /** * Invalidates the entire screen. */ virtual void invalidate(); /** * Invalidates the given area. * * @param area The area to invalidate. */ virtual void invalidateArea(Rect area); /** * Get list of the invalidated areas in the current frame. * The list is cleared in the beginning of HAL::tick. * * The list can be usefull on some platforms where the information * can be used to reduce the amount of pixels sent to the display. * * @return Const reference to the list. */ const Vector& getInvalidatedAreas() { return cachedDirtyAreas; } protected: /** Protected constructor. */ Application(); /** * Initiate a draw operation of the entire screen. Standard implementation is to * delegate draw request to the current Screen. */ virtual void draw(); /** * Initiate a draw operation of the specified region of the screen. Standard * implementation is to delegate draw request to the current Screen. * * @param [in] rect The area to draw. * * @note Unlike Widget::draw this is safe to call from user code as it will properly traverse * widgets in z-order. * @note The coordinates given must be absolute coordinates. */ virtual void draw(Rect& rect); typedef Vector RectVector_t; ///< Type to ensure the same number of rects are in the Vector /** A class to handle and manage timer widgets. */ class TimerWidgets { public: /** * Tick all active timer widgets. Adding and removing timer widgets during ticks is supported. */ void tickActive(); /** * Adds timer widget. If a timer widget is added from a handleTickEvent(), the timer will not be * ticket until the next tick (unless that same widget is already registered, and has not yet * been ticked in this tick). * * @param [in] w The timer widget to add. */ void add(Drawable* w); /** * Removes the given timer widget. * * @param w The timer widget to remove. */ void remove(const Drawable* w); /** Clears all timer widgets. */ void clear(); /** * Gets a counter for a given timer widget. Normally the counter is 1 unless a timer widget has * been registered several times. * * @param w The timer widget to get the counter for. * * @return The counter. */ uint16_t getCounter(const Drawable* w) const; /** * Gets number of active timer widgets. * * @return The number of active timer widgets. */ uint16_t getNumberOfActiveTimerWidgets() const; /** * Compacts the timer widgets. All widgets with a counter of 0 will be removed from the list, * and the list will be compacted. Compacting the timer widgets during traversal (in * tickActive()) is handled properly. */ void compact(); private: Vector widgets; ///< List of widgets that receive timer ticks. uint8_t counters[MAX_TIMER_WIDGETS]; ///< A counter for each potentially registered timer widget. Increase when registering for timer events, decrease when unregistering. uint16_t currentWidget; ///< The current widget, used in tickActive(). uint16_t lastWidget; ///< The last widget, used in tickActive(). } timerWidgets; ///< The timer widgets RectVector_t cachedDirtyAreas; ///< When draw caching is enabled, these rects keeps track of the dirty screen area. RectVector_t lastRects; ///< The dirty areas from last frame that needs to be redrawn because we have swapped frame buffers. Rect redraw; ///< Rect describing application requested invalidate area bool transitionHandled; ///< True if the transition is done and Screen::afterTransition has been called. static Screen* currentScreen; ///< Pointer to currently displayed Screen. static Transition* currentTransition; ///< Pointer to current transition. static Application* instance; ///< Pointer to the instance of the Application-derived subclass. @note Must be set by subclass constructor! static DebugPrinter* debugPrinter; ///< Pointer to the DebugPrinter instance. static Rect debugRegionInvalidRect; ///< Invalidated Debug Region }; } // namespace touchgfx #endif // TOUCHGFX_APPLICATION_HPP