steering-wheel/Middlewares/ST/touchgfx_backup1/framework/include/touchgfx/Drawable.hpp

719 lines
22 KiB
C++

/******************************************************************************
* 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/Drawable.hpp
*
* Declares the touchgfx::Drawable class.
*/
#ifndef TOUCHGFX_DRAWABLE_HPP
#define TOUCHGFX_DRAWABLE_HPP
#include <touchgfx/Bitmap.hpp>
#include <touchgfx/events/ClickEvent.hpp>
#include <touchgfx/events/DragEvent.hpp>
#include <touchgfx/events/GestureEvent.hpp>
#include <touchgfx/hal/Types.hpp>
namespace touchgfx
{
/**
* The Drawable class is an abstract definition of something that can be drawn. In the composite
* design pattern, the Drawable is the component interface. Drawables can be added to a
* screen as a tree structure through the leaf node class Widget and the Container
* class. A Drawable contains a pointer to its next sibling and a pointer to its parent
* node. These are maintained by the Container to which the Drawable is added.
*
* The Drawable interface contains two pure virtual functions which must be implemented
* by widgets, namely draw() and getSolidRect(). In addition it contains general
* functionality for receiving events and navigating the tree structure.
*
* The coordinates of a Drawable are always relative to its parent node.
*
* @see Widget, Container
*/
class Drawable
{
public:
/** Initializes a new instance of the Drawable class. */
Drawable()
: rect(),
cachedVisibleRect(),
parent(0),
nextSibling(0),
nextDrawChainElement(0),
cachedAbsX(0),
cachedAbsY(0),
touchable(false),
visible(true)
{
}
/** Finalizes an instance of the Drawable class. */
virtual ~Drawable()
{
}
/**
* Draw this drawable. It is a requirement that the draw implementation does not draw
* outside the region specified by invalidatedArea.
*
* @param invalidatedArea The sub-region of this drawable that needs to be redrawn,
* expressed in coordinates relative to its parent (e.g. for a
* complete redraw, invalidatedArea will be (0, 0, width,
* height).
*/
virtual void draw(const Rect& invalidatedArea) const = 0;
/**
* Get (the largest possible) rectangle that is guaranteed to be solid (opaque). This
* information is important, as any Drawable underneath the solid area does not need to
* be drawn.
*
* @return The solid rectangle part of the Drawable.
*
* @note The rectangle returned must be relative to upper left corner of the Drawable, meaning
* that a completely solid widget should return the full size Rect(0, 0,
* getWidth(), getHeight()). If no area can be guaranteed to be solid, an empty
* Rect must be returned. Failing to return the correct rectangle
* may result in errors on the display.
*/
virtual Rect getSolidRect() const = 0;
/**
* Request that a region of this drawable is redrawn. All invalidated regions are collected
* and possibly merged with other regions that have been invalidated. Before the next tick,
* these regions will then be redrawn by the drawables, widgets and containers, covering the
* regions.
*
* To invalidate the entire Drawable, use invalidate()
*
* @param [in] invalidatedArea The area of this drawable to redraw expressed in relative
* coordinates.
*
* @see invalidate
*/
virtual void invalidateRect(Rect& invalidatedArea) const;
/**
* Tell the framework that this entire Drawable needs to be redrawn. It is the same as
* calling invalidateRect() with Rect(0, 0, getWidth(), getHeight()) as argument.
*
* @see invalidateRect
*/
virtual void invalidate() const;
/**
* Tell the framework that the contents of the Drawable needs to be redrawn. If the Drawable is
* invisible, nothing happens. Subclasses of Drawable are encouraged to implement this function
* and invalidate as little as possible, i.e. the smallest rectangle covering the visual element(s)
* drawn by the widget.
*/
virtual void invalidateContent() const
{
// Consider checking if *this is in the draw chain
if (visible)
{
invalidate();
}
}
/**
* Gets the next sibling node. This will be the next Drawable that has been added to the
* same Container as this Drawable.
*
* @return The next sibling. If there are no more siblings, the return value is 0.
*/
Drawable* getNextSibling()
{
return nextSibling;
}
/**
* Function for obtaining the first child of this drawable if any.
*
* @return A pointer on the first child drawable if any.
* @see Container::getFirstChild
*/
virtual Drawable* getFirstChild()
{
return 0;
}
/**
* Helper function for obtaining the largest solid rect (as implemented by
* getSolidRect()) expressed in absolute coordinates. Will recursively traverse to the
* root of the tree to find the proper location of the rectangle on the display.
*
* @return The (largest) solid rect (as implemented by getSolidRect()) expressed in absolute
* coordinates.
*/
virtual Rect getSolidRectAbsolute();
/**
* Function for obtaining the the last child of this drawable that intersects with the
* specified point. The last child is the Drawable that is drawn last and therefore the
* topmost child. Used in input event handling for obtaining the appropriate drawable
* that should receive the event.
*
* @param x The point of intersection expressed in coordinates relative to the
* parent.
* @param y The point of intersection expressed in coordinates relative to the
* parent.
* @param [out] last Last (topmost) Drawable on the given coordinate.
*
* @note Input events must be delegated to the last drawable of the tree (meaning highest z-
* order / front-most drawable).
*/
virtual void getLastChild(int16_t x, int16_t y, Drawable** last) = 0;
/**
* Function for finding the visible part of this drawable. If the parent node has a
* smaller area than this Drawable, or if the Drawable is placed "over the edge" of the
* parent, the parent will act as a view port, cutting off the parts of this Drawable
* that are outside the region. Traverses the tree and yields a result expressed in
* absolute coordinates.
*
* @param [out] rect The region of the Drawable that is visible.
*/
virtual void getVisibleRect(Rect& rect) const;
/**
* Gets the rectangle this Drawable covers, in coordinates relative to its parent.
*
* @return The rectangle this Drawable covers expressed in coordinates relative to its
* parent.
*
* @see getAbsoluteRect
*/
const Rect& getRect() const
{
return rect;
}
/**
* Helper function for obtaining the rectangle this Drawable covers, expressed in
* absolute coordinates.
*
* @return The rectangle this Drawable covers expressed in absolute coordinates.
*
* @see getRect, translateRectToAbsolute
*/
Rect getAbsoluteRect() const;
/**
* Helper function for converting a region of this Drawable to absolute coordinates.
*
* @param [in,out] r The Rect to translate.
*/
virtual void translateRectToAbsolute(Rect& r) const;
/**
* Sets the size and position of this Drawable, relative to its parent. The same as
* calling setXY(), setWidth() and setHeight() in that order.
*
* @param x The x coordinate of this Drawable relative to its parent.
* @param y The y coordinate of this Drawable relative to its parent.
* @param width The width of this Drawable.
* @param height The height of this Drawable.
*
* @note For most Drawable widgets, changing this does normally not automatically yield a redraw.
*
* @see setXY,setWidthHeight,setPosition(const Drawable&)
*/
void setPosition(int16_t x, int16_t y, int16_t width, int16_t height)
{
setXY(x, y);
setWidthHeight(width, height);
}
/**
* Expands the Drawable to have the same size as its parent with a given margin around
* the edge. If there is no parent, the position is set to the size of the entire display.
*
* @param margin (Optional) The margin.
*/
void expand(int margin = 0);
/** Centers the Drawable inside its parent. */
void center()
{
centerX();
centerY();
}
/** Center the Drawable horizontally inside its parent. */
void centerX()
{
assert(parent && "Cannot center a Drawable with no parent");
setX((parent->getWidth() - getWidth()) / 2);
}
/** Center the Drawable vertically inside its parent. */
void centerY()
{
assert(parent && "Cannot center a Drawable with no parent");
setY((parent->getHeight() - getHeight()) / 2);
}
/**
* Gets the x coordinate of this Drawable, relative to its parent.
*
* @return The x value, relative to the parent.
*/
int16_t getX() const
{
return rect.x;
}
/**
* Gets the y coordinate of this Drawable, relative to its parent.
*
* @return The y value, relative to the parent.
*/
int16_t getY() const
{
return rect.y;
}
/**
* Gets the width of this Drawable.
*
* @return The width of this Drawable.
*/
int16_t getWidth() const
{
return rect.width;
}
/**
* Gets the height of this Drawable.
*
* @return The height of this Drawable.
*/
int16_t getHeight() const
{
return rect.height;
}
/**
* Sets the x coordinate of this Drawable, relative to its parent.
*
* @param x The new x value, relative to the parent. A negative value is allowed.
*
* @note For most Drawable widgets, changing this does normally not automatically yield a redraw.
*/
virtual void setX(int16_t x)
{
rect.x = x;
}
/**
* Sets the y coordinate of this Drawable, relative to its parent.
*
* @param y The new y value, relative to the parent. A negative value is allowed.
*
* @note For most Drawable widgets, changing this does normally not automatically yield a redraw.
*/
virtual void setY(int16_t y)
{
rect.y = y;
}
/**
* Sets the x and y coordinates of this Drawable, relative to its parent. The same as
* calling setX() followed by calling setY().
*
* @param x The new x value, relative to the parent. A negative value is allowed.
* @param y The new y value, relative to the parent. A negative value is allowed.
*
* @see moveTo
*
* @note For most Drawable widgets, changing this does normally not automatically yield a redraw.
*/
void setXY(int16_t x, int16_t y)
{
setX(x);
setY(y);
}
/**
* Sets the width of this drawable.
*
* @param width The new width.
*
* @note For most Drawable widgets, changing this does normally not automatically yield a redraw.
*/
virtual void setWidth(int16_t width)
{
rect.width = width;
}
/**
* Sets the height of this drawable.
*
* @param height The new height.
*
* @note For most Drawable widgets, changing this does normally not automatically yield a redraw.
*/
virtual void setHeight(int16_t height)
{
rect.height = height;
}
/**
* This function can be called on parent nodes to signal that the size or position of
* one or more of its children has changed. Currently only used in ScrollableContainer
* to redraw scrollbars when the size of the scrolling contents changes.
*/
virtual void childGeometryChanged()
{
}
/**
* Defines the event handler interface for ClickEvents. The default implementation
* ignores the event. The event is only received if the Drawable is touchable and
* visible.
*
* @param event The ClickEvent received from the HAL.
*/
virtual void handleClickEvent(const ClickEvent& event)
{
(void)event; // Unused variable
}
/**
* Defines the event handler interface for GestureEvents. The default implementation
* ignores the event. The event is only received if the Drawable is touchable and
* visible.
*
* @param event The GestureEvent received from the HAL.
*/
virtual void handleGestureEvent(const GestureEvent& event)
{
(void)event; // Unused variable
}
/**
* Sets the dimensions (width and height) of the Drawable without changing the x and y
* coordinates).
*
* @param width The width.
* @param height The height.
*/
void setWidthHeight(int16_t width, int16_t height)
{
setWidth(width);
setHeight(height);
}
/**
* Sets the position of the Drawable to the same as the given Drawable. This will copy
* the x, y, width and height.
*
* @param drawable The Drawable.
*
* @see setPosition(int16_t,int16_t,int16_t,int16_t)
*/
void setPosition(const Drawable& drawable)
{
setPosition(drawable.getX(), drawable.getY(), drawable.getWidth(), drawable.getHeight());
}
/**
* Sets the x and y coordinates of this Drawable.
*
* @param drawable The Drawable to copy the x and y coordinates from.
*
* @see setXY(int16_t,int16_t)
*/
void setXY(const Drawable& drawable)
{
setXY(drawable.getX(), drawable.getY());
}
/**
* Sets the dimensions (width and height) of the Drawable without changing the x and y
* coordinates).
*
* @param drawable The Drawable to copy the width and height from.
*
* @see setWidthHeight(int16_t,int16_t)
*/
void setWidthHeight(const Drawable& drawable)
{
setWidthHeight(drawable.getWidth(), drawable.getHeight());
}
/**
* Sets the dimensions (width and height) of the Drawable without changing the x and y
* coordinates).
*
* @param bitmap The Bitmap to copy the width and height from.
*
* @see setWidthHeight(int16_t,int16_t)
*/
void setWidthHeight(const Bitmap& bitmap)
{
setWidthHeight(bitmap.getWidth(), bitmap.getHeight());
}
/**
* Sets the dimensions (width and height) of the Drawable without changing the x and y
* coordinates).
*
* @param other The Rect to copy the width and height from.
*
* @see setWidthHeight(int16_t,int16_t)
*/
void setWidthHeight(const Rect& other)
{
setWidthHeight(other.width, other.height);
}
/**
* Defines the event handler interface for DragEvents. The default implementation
* ignores the event. The event is only received if the drawable is touchable and
* visible.
*
* @param event The DragEvent received from the HAL.
*/
virtual void handleDragEvent(const DragEvent& event)
{
(void)event; // Unused variable
}
/**
* Called periodically by the framework if the Drawable instance has subscribed to timer
* ticks.
*
* @see Application::registerTimerWidget
*/
virtual void handleTickEvent()
{
}
/**
* Controls whether this Drawable should be visible. Only visible Drawables will have
* their draw function called. Additionally, invisible drawables will not receive input
* events.
*
* @param vis true if this Drawable should be visible. By default, drawables are visible
* unless this function has been called with false as argument.
*
* @note For most Drawable widgets, changing this does normally not automatically yield a redraw.
*/
void setVisible(bool vis)
{
visible = vis;
}
/**
* Controls whether this Drawable receives touch events or not.
*
* @param touch If true it will receive touch events, if false it will not.
*/
void setTouchable(bool touch)
{
touchable = touch;
}
/**
* Gets whether this Drawable is visible.
*
* @return true if the Drawable is visible.
*
* @see setVisible
*/
bool isVisible() const
{
return visible;
}
/**
* Gets whether this Drawable receives touch events or not.
*
* @return True if touch events are received.
*
* @see setTouchable
*/
bool isTouchable() const
{
return touchable;
}
/**
* Returns the parent node. For the root container, the return value is 0.
*
* @return The parent node. For the root container, the return value is 0.
*
* @note A disconnected Drawable also has parent 0 which may cause strange side effects.
*/
Drawable* getParent() const
{
return parent;
}
/**
* Moves the drawable.
*
* @param x The relative position to move to.
* @param y The relative position to move to.
*
* @see moveTo, setXY
*
* @note Will redraw the appropriate areas of the screen.
*/
virtual void moveRelative(int16_t x, int16_t y);
/**
* Moves the drawable.
*
* @param x The absolute position to move to.
* @param y The absolute position to move to.
*
* @see moveRelative, setXY
*
* @note Will redraw the appropriate areas of the screen.
*/
virtual void moveTo(int16_t x, int16_t y)
{
moveRelative(x - rect.x, y - rect.y);
}
/**
* Render the Drawable object into a dynamic bitmap.
*
* @param id The target dynamic bitmap to use for rendering.
*/
void drawToDynamicBitmap(BitmapId id);
protected:
Rect rect; ///< The coordinates of this Drawable, relative to its parent.
/// @cond
Rect cachedVisibleRect; ///< Cached representation of currently visible area. For TouchGFX internal use.
/// @endcond
Drawable* parent; ///< Pointer to this drawable's parent.
Drawable* nextSibling; ///< Pointer to the next Drawable. Maintained by containers.
/// @cond
Drawable* nextDrawChainElement; ///< Next in draw chain. For TouchGFX internal use.
int16_t cachedAbsX; ///< Cached value of absolute x coordinate. For TouchGFX internal use.
int16_t cachedAbsY; ///< Cached value of absolute y coordinate. For TouchGFX internal use.
/// @endcond
bool touchable; ///< True if this drawable should receive touch events.
bool visible; ///< True if this drawable should be drawn.
/// @cond
static const int16_t UNCACHED_INDICATOR = -1; ///< Constant representing uncached value. For TouchGFX internal use.
/**
* For TouchGFX internal use only.
*
* Reset cached coordinate data.
*
* @note For TouchGFX internal use only.
*/
void resetDrawChainCache()
{
// Resetting the cached indicators
cachedVisibleRect.x = UNCACHED_INDICATOR;
cachedAbsX = UNCACHED_INDICATOR;
cachedAbsY = UNCACHED_INDICATOR;
}
/**
* For TouchGFX internal use only.
*
* Obtain cached version of visible rect.
*
* @return The Visible rect for this drawable. Only calculated once.
*
* @note For TouchGFX internal use only.
*/
Rect& getCachedVisibleRect()
{
if (cachedVisibleRect.x == UNCACHED_INDICATOR)
{
Rect visibleRect(0, 0, getWidth(), getHeight());
getVisibleRect(visibleRect);
cachedVisibleRect = visibleRect;
}
return cachedVisibleRect;
}
/**
* For TouchGFX internal use only.
*
* Obtain cached version of absolute X-coord.
*
* @return The absolute x coordinate for this drawable. Only calculated once.
*
* @note For TouchGFX internal use only.
*/
int16_t getCachedAbsX()
{
if (cachedAbsX == UNCACHED_INDICATOR)
{
Rect absRect = getAbsoluteRect();
cachedAbsX = absRect.x;
cachedAbsY = absRect.y;
}
return cachedAbsX;
}
/**
* For TouchGFX internal use only.
*
* Obtain cached version of absolute Y-coord.
*
* @return The absolute y coordinate for this drawable. Only calculated once.
*
* @note For TouchGFX internal use only.
*/
int16_t getCachedAbsY()
{
if (cachedAbsY == UNCACHED_INDICATOR)
{
Rect absRect = getAbsoluteRect();
cachedAbsX = absRect.x;
cachedAbsY = absRect.y;
}
return cachedAbsY;
}
/**
* For TouchGFX internal use only.
*
* Configure linked list for draw chain.
*
* @param invalidatedArea Include drawables that intersect with this area only.
* @param [in,out] nextPreviousElement Modifiable element in linked list.
*
* @note For TouchGFX internal use only.
*/
virtual void setupDrawChain(const Rect& invalidatedArea, Drawable** nextPreviousElement)
{
(void)invalidatedArea; // Unused variable
resetDrawChainCache();
nextDrawChainElement = *nextPreviousElement;
*nextPreviousElement = this;
}
/// @endcond
friend class Container;
friend class Screen;
};
} // namespace touchgfx
#endif // TOUCHGFX_DRAWABLE_HPP