TouchGFX框架中的所有控件均为Drawable类的子类。 该类别包含控制大小和位置的一般方法。

TouchGFX之Drawable-LMLPHP

#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

 

03-26 22:49