TouchGFX框架中的所有控件均为Drawable类的子类。 该类别包含控制大小和位置的一般方法。
#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
{
/* 可绘制类抽象接口 */
class Drawable
{
public:
/* 构造函数 */
Drawable()
: rect(),
cachedVisibleRect(),
parent(0),
nextSibling(0),
nextDrawChainElement(0),
cachedAbsX(0),
cachedAbsY(0),
touchable(false),
visible(true)
{
}
/* 析构函数 */
virtual ~Drawable()
{
}
/* 绘制该图。仅绘制包含在矩形内部分。
以相对于其父节点的坐标表示(例如,对于完全重绘,invalidatedArea将是(0, 0, width, height) */
virtual void draw(const Rect& invalidatedArea) const = 0;
/* 获取可以保证为实心的(不透明的)最大矩形。任何在这个实心区域下方的Drawable都不需要被绘制。
返回的矩形相对于Drawable,完全实心的widget应该返回Rect(0, 0, getWidth(), getHeight()) */
virtual Rect getSolidRect() const = 0;
/* 请求重绘此Drawable的一个区域,以相对坐标表示 */
virtual void invalidateRect(Rect& invalidatedArea) const;
/* 整个Drawable重新绘制。与调用invalidateRect()并传递Rect(0, 0, getWidth(), getHeight())相同 */
virtual void invalidate() const;
/* Drawable的内容重新绘制。如果Drawable是不可见的,则什么也不会发生 */
virtual void invalidateContent() const
{
if(visible)
{
invalidate();
}
}
/* 获取父级容器中的下一个Drawable指针 */
Drawable *getNextSibling()
{
return nextSibling;
}
/* 获取父级容器中的第一个Drawable指针 */
virtual Drawable *getFirstChild()
{
return 0;
}
/* 获取Drawable的最大的实心矩形,并将其转换为绝对坐标 */
virtual Rect getSolidRectAbsolute();
/* 获取此绘图所在容器中最上面与指定点相交的子项(以相对于父对象的坐标表示的交点)
用于输入事件处理,以确定应接收事件的适当Drawable */
virtual void getLastChild(int16_t x, int16_t y, Drawable **last) = 0;
/* 查找此Drawable的可见部分。如果Drawable在父节点的“边缘之外”,切掉此区域外的部分
返回rect:绝对坐标 */
virtual void getVisibleRect(Rect& rect) const;
/* 获取此Drawable覆盖的矩形区域,坐标相对于其父Drawable */
const Rect& getRect() const
{
return rect;
}
/* 获取此Drawable覆盖的矩形区域,并将其转换为绝对坐标 */
Rect getAbsoluteRect() const;
/* 将此Drawable的一个区域转换为绝对坐标
@param [in,out] r 要转换的矩形区域 */
virtual void translateRectToAbsolute(Rect& r) const;
/* 设置此Drawable的大小和位置,相对于其父Drawable(不会重绘) */
void setPosition(int16_t x, int16_t y, int16_t width, int16_t height)
{
setXY(x, y);
setWidthHeight(width, height);
}
/* 扩展此Drawable,使其与父Drawable具有相同的大小,并在边缘周围具有给定的边距。
如果没有父Drawable,则位置被设置为整个显示屏的大小。
@param margin (可选)边距 */
void expand(int margin = 0);
/* 在其父Drawable内居中此Drawable */
void center()
{
centerX();
centerY();
}
/* 在其父Drawable内水平居中此Drawable */
void centerX()
{
assert(parent && "Cannot center a Drawable with no parent");
setX((parent->getWidth() - getWidth()) / 2);
}
/* 在其父Drawable内垂直居中此Drawable */
void centerY()
{
assert(parent && "Cannot center a Drawable with no parent");
setY((parent->getHeight() - getHeight()) / 2);
}
/* 获取此Drawable的x坐标,相对于其父Drawable */
int16_t getX() const
{
return rect.x;
}
/* 获取此Drawable的y坐标,相对于其父Drawable */
int16_t getY() const
{
return rect.y;
}
/* 获取此Drawable的宽度 */
int16_t getWidth() const
{
return rect.width;
}
/* 获取此Drawable的高度 */
int16_t getHeight() const
{
return rect.height;
}
/* 设置此Drawable的x坐标,相对于其父对象(允许负值)(不会重绘) */
virtual void setX(int16_t x)
{
rect.x = x;
}
/* 设置此Drawable的y坐标,相对于其父对象(允许负值)(不会重绘) */
virtual void setY(int16_t y)
{
rect.y = y;
}
/* 同时设置此Drawable的x和y坐标,相对于其父对象(允许负值)(不会重绘) */
void setXY(int16_t x, int16_t y)
{
setX(x);
setY(y);
}
/* 设置此Drawable的宽度(不会重绘) */
virtual void setWidth(int16_t width)
{
rect.width = width;
}
/* 设置此Drawable的高度(不会重绘) */
virtual void setHeight(int16_t height)
{
rect.height = height;
}
/* 此函数可以在父节点上调用,以信号表示其一个或多个子节点的大小或位置已更改
当前仅在ScrollableContainer中使用,以在滚动内容的大小更改时重绘滚动条 */
virtual void childGeometryChanged()
{
}
/* 定义用于处理ClickEvents的事件处理程序接口
只有在Drawable可触摸且可见时,才会收到该事件 */
virtual void handleClickEvent(const ClickEvent& event)
{
(void)event;
}
/* 定义用于处理GestureEvents的事件处理程序接口
只有在Drawable可触摸且可见时,才会收到该事件 */
virtual void handleGestureEvent(const GestureEvent& event)
{
(void)event;
}
/* 设置此Drawable的宽度和高度(不会重绘) */
void setWidthHeight(int16_t width, int16_t height)
{
setWidth(width);
setHeight(height);
}
/* 将Drawable的位置设置为与给定的Drawable相同。这将复制x,y,宽度和高度(不会重绘) */
void setPosition(const Drawable& drawable)
{
setPosition(drawable.getX(), drawable.getY(), drawable.getWidth(), drawable.getHeight());
}
/* 将Drawable的x,y设置为与给定的Drawable相同(不会重绘) */
void setXY(const Drawable& drawable)
{
setXY(drawable.getX(), drawable.getY());
}
/* 将Drawable的宽度和高度设置为与给定的Drawable相同(不会重绘) */
void setWidthHeight(const Drawable& drawable)
{
setWidthHeight(drawable.getWidth(), drawable.getHeight());
}
/* 将bitmap的宽度和高度设置为与给定的Drawable相同(不会重绘) */
void setWidthHeight(const Bitmap& bitmap)
{
setWidthHeight(bitmap.getWidth(), bitmap.getHeight());
}
/* 将矩形的宽度和高度设置为与给定的Drawable相同(不会重绘) */
void setWidthHeight(const Rect& other)
{
setWidthHeight(other.width, other.height);
}
/* 定义处理DragEvent的事件处理器接口
只有当Drawable是可触摸的和可见的时,才会接收到事件 */
virtual void handleDragEvent(const DragEvent& event)
{
(void)event;
}
/* Drawable定时事件处理接口
Application::registerTimerWidget 用于注册计时器小部件的应用程序函数 */
virtual void handleTickEvent()
{
}
/* 设置此Drawable是否可见。只有可见的Drawable才会调用其绘制函数(不会重绘)
另外,不可见的Drawable不会接收输入事件 */
void setVisible(bool vis)
{
visible = vis;
}
/* 设置此Drawable是否接收触摸事件
@param touch 如果为true,它将接收触摸事件;如果为false,则不接收 */
void setTouchable(bool touch)
{
touchable = touch;
}
/* 获取此Drawable是否可见 */
bool isVisible() const
{
return visible;
}
/* 获取此Drawable是否接收触摸事件 */
bool isTouchable() const
{
return touchable;
}
/* 返回父节点。对于根容器,返回值为0 */
Drawable* getParent() const
{
return parent;
}
/**
* 移动Drawable。
*
* @param x 要移动到的相对位置。
* @param y 要移动到的相对位置。
*
* @see moveTo, setXY 用于绝对定位的函数。
*
* @note 将重绘屏幕的适当区域。
*/
virtual void moveRelative(int16_t x, int16_t y);
/**
* 移动Drawable。
*
* @param x 要移动到的绝对位置。
* @param y 要移动到的绝对位置。
*
* @see moveRelative, setXY 另一个用于绝对定位的函数。
*
* @note 将重绘屏幕的适当区域。
*/
virtual void moveTo(int16_t x, int16_t y)
{
moveRelative(x - rect.x, y - rect.y);
}
/* 将Drawable对象渲染到动态位图中 */
void drawToDynamicBitmap(BitmapId id);
protected:
Rect rect; //此Drawable覆盖的矩形区域,坐标相对于其父Drawable
Rect cachedVisibleRect; //当前可见区域的缓存表示。供TouchGFX内部使用
Drawable* parent; //指向此drawable的父级的指针
Drawable* nextSibling; //指向下一个Drawable的指针。由容器维护
Drawable* nextDrawChainElement; //绘制链中的下一个元素。供TouchGFX内部使用
int16_t cachedAbsX; //绝对x坐标的缓存值。供TouchGFX内部使用
int16_t cachedAbsY; //绝对y坐标的缓存值。供TouchGFX内部使用
bool touchable; //如果此drawable应接收触摸事件,则为true
bool visible; //如果此drawable应被绘制,则为true
static const int16_t UNCACHED_INDICATOR = -1; //表示未缓存值的常量。供TouchGFX内部使用
/* 重置缓存的坐标数据。这是TouchGFX内部使用的 */
void resetDrawChainCache()
{
// Resetting the cached indicators
cachedVisibleRect.x = UNCACHED_INDICATOR;
cachedAbsX = UNCACHED_INDICATOR;
cachedAbsY = UNCACHED_INDICATOR;
}
/* 获取缓存的可见矩形版本。只计算一次。这是TouchGFX内部使用的 */
Rect& getCachedVisibleRect()
{
if (cachedVisibleRect.x == UNCACHED_INDICATOR)
{
Rect visibleRect(0, 0, getWidth(), getHeight());
getVisibleRect(visibleRect);
cachedVisibleRect = visibleRect;
}
return cachedVisibleRect;
}
/* 获取缓存的绝对X坐标版本。只计算一次。这是TouchGFX内部使用 */
int16_t getCachedAbsX()
{
if (cachedAbsX == UNCACHED_INDICATOR)
{
Rect absRect = getAbsoluteRect();
cachedAbsX = absRect.x;
cachedAbsY = absRect.y;
}
return cachedAbsX;
}
/* 获取缓存的绝对Y坐标版本。只计算一次。这是TouchGFX内部使用 */
int16_t getCachedAbsY()
{
if (cachedAbsY == UNCACHED_INDICATOR)
{
Rect absRect = getAbsoluteRect();
cachedAbsX = absRect.x;
cachedAbsY = absRect.y;
}
return cachedAbsY;
}
/* 配置绘制链的链表。这是TouchGFX内部使用的 */
virtual void setupDrawChain(const Rect& invalidatedArea, Drawable** nextPreviousElement)
{
(void)invalidatedArea; // Unused variable
resetDrawChainCache();
nextDrawChainElement = *nextPreviousElement;
*nextPreviousElement = this;
}
friend class Container;
friend class Screen;
};
}
#endif