# pragma once
# include <QVector>
# include <QList>
# include <QCursor>
# include <QObject>
# include <QRectF>
# include <QPen>
# include <QBrush>
# include <IxPtySource.h>
# include <IxRenderItem.h>
# include "ZxPaintParam.h"
# include "ZxRenderItemIterator.h"
# include "ZxHandleRef.h"
# include "iPlotBase_global.h"
class ZxRenderView ;
class ZxSceneItem ;
class ZxPaintParam ;
//class QPainter;
class _ZxRenderChildIndex ;
class ZxHandlePolicy ;
class ZxEdit ;
class ZxRenderItem ;
class QSizeF ;
class QPointF ;
class ZxLayout ;
class QFile ;
class QDataStream ;
class QAction ;
class IxPtyItem ;
class QMimeData ;
class ZxSceneItem ;
class QMenu ;
class ZxTool ;
/// 图元的根类
class I_PLOTBASE_EXPORT ZxRenderItem
: public QObject
, virtual public IxRenderItem
, virtual public IxPtySource
{
Q_OBJECT
ZX_DECLARE_DYNAMIC
public :
ZxRenderItem ( ) ;
virtual ~ ZxRenderItem ( ) ;
void init ( ) ;
virtual void onSerialize ( ZxSerializer * ser ) ;
virtual void onDeserialize ( ZxSerializer * ser ) ;
virtual void onLoadTempl ( ZxSerializer * ser ) ;
virtual void onSaveTempl ( ZxSerializer * ser ) ;
// 这是从外界调用的统一封装,模板
// bLoad 加载 or 保存
// bSelf 是否仅仅某类名称的,比如 TheorySource
void dealwithTempl ( bool bLoad , bool bSelf ) ;
virtual QString getTemplPath ( bool bSelf ) ;
bool loadTempl ( QString s = " " ) ; //模板的处理
bool saveTempl ( QString s ) ;
/// 指定父节点, 并加自动入父节点的子图元列表中
virtual void setParent ( IxRenderItem * pParent ) ;
/// 重新实现 QObject::setParent()
virtual void setParentObject ( QObject * pParent ) ;
/// 获取父节点的指针. 对于根结点, 这个函数返回NULL.
ZxRenderItem * getParent ( ) const ;
/// 获取根结点
ZxRenderItem * getRootItem ( ) const ;
/// 获取所在的场景
ZxSceneItem * getScene ( ) const ;
/// 获取当前工具
ZxTool * getCurrentTool ( ) const ;
/// 获取当前视图
ZxRenderView * getCurrentToolView ( ) const ;
/// 获取图元的显示名
virtual QString getTitle ( ) const ;
/// 获取图元的图标
virtual QIcon getIcon ( ) const ;
/// 递归绘图, 含自身和子图元
virtual void paint ( QPainter * painter , const ZxPaintParam & param ) ;
/// 绘制背景(位于子图元下方), 如无特殊情况, 普通内容应在此绘制
virtual void paintBack ( QPainter * painter , const ZxPaintParam & param ) ;
/// 绘制前景(位于子图元上方)
virtual void paintFront ( QPainter * painter , const ZxPaintParam & param ) ;
/// 画子图元(一般不需要重写)
virtual void paintChildren ( QPainter * painter , const ZxPaintParam & param ) ;
/// 绘制Edit和Policy
/// @note 此方法是独立的, 和绘制图元完全是不同的系统
virtual void paintEdit ( QPainter * painter , const ZxPaintParam & param ) ;
/// 获取子图元列表
const QVector < ZxRenderItem * > & getChildren ( ) const ;
/// 子图元数量, 等同于 size()
int count ( ) const ;
/// 子图元数量, 等同于 count()
int size ( ) const ;
/// 子图元数量是否为0, 等同于 empty()
bool isEmpty ( ) const ;
/// 子图元数量是否为0, 等同于 isEmpty()
bool empty ( ) const ;
/// 在指定位置插入子图元, 并自动把子图元的parent指向当前图元.
/// index 为 0 时插到前面, index为-1或等于size()时追加到最后.
void insert ( int index , ZxRenderItem * pItem ) ;
/// 替换子图元.
/// @param index 替换的位置
/// @param pItem 用来替换旧图元的新图元
/// @param bDelete 是否删除旧图元
/// @return bDelete为FALSE时返回旧图元, 否则返回NULL
ZxRenderItem * replace ( int index , ZxRenderItem * pItem , bool bDelete ) ;
/// 追加子图元
void append ( ZxRenderItem * p ) ;
/// 移除指定的子图元(不销毁)
void remove ( ZxRenderItem * p ) ;
/// 返回指定位置的子图元
ZxRenderItem * at ( int i ) const ;
/// 返回指定子图元的位置索引, 如果没找到则返回-1. 对于空指针, 此方法总是返回-1.
int indexOf ( const ZxRenderItem * p ) const ;
/// 从图元树上移除
ZxRenderItem * detach ( ) ;
/// 删除所有子节点
virtual void clear ( ) ;
// 在手动操作时, 判断此图元是否能容纳指定的子图元.
// 例如在曲线道里, 就可以对曲线以外的类型返回false.
//virtual bool canManualAdd(const ZxRenderItem* p) const;
/// 获取图元基础边框(位置)
virtual QRectF getBounds ( ) const ;
/// 获取图元的扩展边框. 默认是基础边框+外檐
QRectF getExtendedBounds ( ) const ;
/// 获取图元的外檐尺寸
virtual double getEavesSize ( ) const ;
/// 获取子图元坐标系下的边框(位置), 类似于Windows的Client Rect
QRectF getBoundsChildCoord ( ) const ;
/// 获取场景坐标系下的图元基础边框(位置)
QRectF getBoundsSceneCoord ( ) const ;
/// 获取场景坐标系下的图元扩展边框(位置)
QRectF getExtendedBoundsSceneCoord ( ) const ;
/// 获取图元x坐标, short for getX()
double x ( ) const ;
/// 获取图元y坐标, short for getY()
double y ( ) const ;
/// 获取图元左上角坐标, short for getPos()
QPointF pos ( ) const ;
/// 获取图元宽度, short for getWidth()
double width ( ) const ;
/// 获取图元高度, short for getHeight()
double height ( ) const ;
/// 获取图元x坐标
double getX ( ) const ;
/// 获取图元y坐标
double getY ( ) const ;
/// 获取图元左上角坐标
QPointF getPos ( ) const ;
/// 获取图元宽度
double getWidth ( ) const ;
/// 获取图元高度
double getHeight ( ) const ;
/// 设置图元边框
/// @param rect 边框
/// @param bSendEvent 是否发出 resize 和 move 事件, 默认为true.
/// @see onMove onResize
/// @note 普通情况都应该发事件, 但有一类逻辑问题可以用不发事件来解决, 见代码:
/// @code
/// void ZxPolyItem::setPoints(const QPolygonF & val)
/// {
/// m_points = val;
/// setBounds(m_points.boundingRect(), false);
/// }
///
/// void ZxPolyItem::onMove(const QPointF& ptOld, const QPointF& ptNew)
/// {
/// m_points.translate(ptNew - ptOld);
/// }
/// @endcode
virtual void setBounds ( const QRectF & rect , bool bSendEvent = true ) ;
/// 设置图元边框
/// @see setBounds(const QRectF &, bool)
virtual void setBounds ( double x , double y , double width , double height , bool bSendEvent = true ) ;
/// 移动图元
/// @param x X坐标
/// @param y Y坐标
/// @note 此方法会发出move事件, 如果不想发出事件, 请用 setBounds 方法
/// @see onMove
void move ( double x , double y ) ;
/// 移动图元
/// @param pos 坐标
/// @note 此方法会发出move事件, 如果不想发出事件, 请用 setBounds 方法
/// @see onMove
void move ( const QPointF & pos ) ;
/// 改变图元尺寸
/// @param width 宽度
/// @param height 高度
/// @note 此方法会发出resize事件, 如果不想发出事件, 请用 setBounds 方法.
/// @see onResize
void resize ( double width , double height ) ;
/// 改变图元尺寸
/// @param sz 尺寸
/// @note 此方法会发出resize事件, 如果不想发出事件, 请用 setBounds 方法.
/// @see onResize
void resize ( const QSizeF & sz ) ;
/// 移动图元
/// @param x X坐标
/// @note 此方法会发出move事件, 如果不想发出事件, 请用 setBounds 方法
/// @see onMove
void setX ( double x ) ;
/// 移动图元
/// @param y Y坐标
/// @note 此方法会发出move事件, 如果不想发出事件, 请用 setBounds 方法
/// @see onMove
void setY ( double y ) ;
/// 改变图元宽度
/// @param width 宽度
/// @note 此方法会发出resize事件, 如果不想发出事件, 请用 setBounds 方法.
/// @see onResize
void setWidth ( double width ) ;
/// 改变图元高度
/// @param height 高度
/// @note 此方法会发出resize事件, 如果不想发出事件, 请用 setBounds 方法.
/// @see onResize
void setHeight ( double height ) ;
// 位置改变
virtual void onMove ( const QPointF & ptOld , const QPointF & ptNew ) ;
// 尺寸改变
virtual void onResize ( const QSizeF & szOld , const QSizeF & szNew ) ;
/// 查找指定位置处的控制点
ZxHandleRef findHandle ( const QPointF & pos , double fHandleSize , bool bSelectedOnly ) ;
/// 查找指定位置处的控制点
ZxHandleRef findHandle ( double x , double y , double fHandleSize , bool bSelectedOnly ) ;
/// 查找指定位置处的单个图元
/// @param pos 查找的坐标
/// @param bRecursive true表示查找所有子孙节点, false表示只查找直接子节点. 默认为true.
/// @param filter 查找条件, 这是一个过滤函数. 默认为NULL, 匹配所有图元.
/// @return 第一个匹配的图元
ZxRenderItem * findItem ( const QPointF & pos , ZxFilterFun filter = NULL , bool bRecursive = true ) ;
/// 查找指定位置处的单个图元
/// @param x 查找的X坐标
/// @param y 查找的Y坐标
/// @param bRecursive true表示查找所有子孙节点, false表示只查找直接子节点. 默认为true.
/// @param filter 查找条件, 这是一个过滤函数. 默认为NULL, 匹配所有图元.
/// @return 第一个匹配的图元
virtual ZxRenderItem * findItem ( double x , double y , ZxFilterFun filter = NULL , bool bRecursive = true ) ;
/// 查找指定位置处的多个图元
/// @param pos 查找的坐标
/// @param bRecursive true表示查找所有子孙节点, false表示只查找直接子节点. 默认为true.
/// @param filter 查找条件, 这是一个过滤函数. 默认为NULL, 匹配所有图元.
/// @return 所有匹配的图元
QList < ZxRenderItem * > findItems ( const QPointF & pos , ZxFilterFun filter = NULL , bool bRecursive = true ) ;
/// 查找指定位置处的多个图元
/// @param x 查找的X坐标
/// @param y 查找的Y坐标
/// @param bRecursive true表示查找所有子孙节点, false表示只查找直接子节点. 默认为true.
/// @param filter 查找条件, 这是一个过滤函数. 默认为NULL, 匹配所有图元.
/// @return 所有匹配的图元
virtual QList < ZxRenderItem * > findItems ( double x , double y , ZxFilterFun filter = NULL , bool bRecursive = true ) ;
/// 查找指定类型的子(孙)图元
template < typename T >
T findChildItem ( bool recursive = true )
{
int n = this - > count ( ) ;
for ( int i = n - 1 ; i > = 0 ; i - - )
{
ZxRenderItem * c = at ( i ) ;
T p = 0 ;
if ( recursive )
{
p = c - > findChildItem < T > ( true ) ;
}
if ( p = = 0 )
{
p = dynamic_cast < T > ( c ) ;
}
if ( p )
{
return p ;
}
}
return 0 ;
}
/// 检测指定点处是否位于图元内部
virtual bool isItemBody ( double x , double y ) ;
/// 图元标志集
Flags getFlags ( ) const ;
void setFlags ( Flags flags ) ;
/// 是否选中
bool isSelected ( ) const ;
virtual bool isEqual ( const IxRenderItem * pAnother ) const ;
/// 设置选中标志
void setSelected ( bool b ) ;
public :
/// 选中状态改变
virtual void onSelectedChanged ( ) ;
/// 选择本图元
/// @note 此方法不但设置图元选中状态, 而且把图元加入场景的选中列表中.
/// @see setSelected(bool)
virtual void select ( bool bClearOldSelect = true ) ;
/// 取消选择本图元.
/// @note 此方法不但取消图元选中状态, 而且从场景的选中列表中删除图元.
/// @see setSelected(bool)
virtual void deselect ( bool bRecursive = false ) ;
/// 是否可见
bool isVisible ( ) const ;
void setVisible ( bool b ) ;
/// 可见状态改变
virtual void onVisibleChanged ( ) ;
/// 显示, 相当于setVisible(true)
void show ( ) ;
/// 隐藏, 相当于setVisible(false)
void hide ( ) ;
/// 是否隐藏, 等于 !isVisible()
bool isHidden ( ) const ;
/// 是否可选
bool isSelectable ( ) const ;
void setSelectable ( bool b ) ;
/// 可选状态改变
virtual void onSelectableChanged ( ) ;
/// 是否锁定位置
bool isLockPos ( ) const ;
void setLockPos ( bool b ) ;
/// 锁定位置状态改变
virtual void onLockPosChanged ( ) ;
/// 是否锁定尺寸
bool isLockSize ( ) const ;
void setLockSize ( bool b ) ;
/// 锁定尺寸状态改变
virtual void onLockSizeChanged ( ) ;
/// 是否只读
bool isReadOnly ( ) const ;
void setReadOnly ( bool b ) ;
/// 只读状态改变
virtual void onReadOnlyChanged ( ) ;
/// 是否剪裁
bool isClipping ( ) const ;
void setClipping ( bool b ) ;
/// 剪裁状态改变
virtual void onClippingChanged ( ) ;
/// 是否偏移坐标
bool hasLocalCoord ( ) const ;
void setLocalCoord ( bool b ) ;
/// 偏移坐标状态改变
virtual void onLocalCoordChanged ( ) ;
/// 获取坐标系所属的图元.
/// @return 往祖先结点找, 返回最近一个hasLocalCoord()的图元. 没找到则返回图元树的根结点.
virtual ZxRenderItem * getCoordItem ( ) const ;
/// 是否自动尺寸
bool isAutoSize ( ) const ;
void setAutoSize ( bool b ) ;
/// 自动尺寸标志改变
virtual void onAutoSizeChanged ( ) ;
/// 是否自动布局
bool isAutoLayout ( ) const ;
void setAutoLayout ( bool b ) ;
/// 自动布局标志改变
virtual void onAutoLayoutChanged ( ) ;
/// 绘图时是否反走样
bool isAntiAlias ( ) const ;
void setAntiAlias ( bool b ) ;
/// 反走样标志改变
virtual void onAntiAliasChanged ( ) ;
/// 是否紧缩
bool isShrink ( ) const ;
void setShrink ( bool b ) ;
/// 紧缩标志改变
virtual void onShrinkChanged ( ) ;
/// 是否需要重新布局
bool needLayout ( ) const ;
/// 是否强制重新布局
bool isForceLayout ( ) const ;
/// 刷新布局
void updateLayout ( bool bForce = false ) ;
/// 可否手动删除
bool canManualDelete ( ) const ;
void setManualDelete ( bool b = true ) ;
/// 是否静态Policy
bool isStaticPolicy ( ) const ;
void setStaticPolicy ( bool b ) ;
/// 是否平凡Policy
bool isOrdinaryPolicy ( ) const ;
void setOrdinaryPolicy ( bool b ) ;
/// 实际上是否锁定位置
bool isActuallyLockPos ( ) const ;
bool isActuallyLockSize ( ) const ;
/// 刷新
/// @note 刷新图元所占的区域, 包括附着在图元上的Policy等所占的区域
virtual void update ( ) ;
/// 刷新指定区域(图元的当前坐标系)
virtual void update ( const QRectF & rect ) ;
/// 准备右键菜单
virtual void onPrepareContextMenu ( QMenu * pMenu , const QPointF & pos ) ;
/// 从本图元坐标系转到子图元坐标系
QPointF mapToChild ( const QPointF & pos ) const ;
/// 从子图元坐标系转到本图元坐标系
QPointF mapFromChild ( const QPointF & pos ) const ;
/// 从本图元坐标系转到子图元坐标系
QRectF mapToChild ( const QRectF & rect ) const ;
/// 从子图元坐标系转到本图元坐标系
QRectF mapFromChild ( const QRectF & rect ) const ;
/// 从其他图元坐标系转到本图元坐标系
QPointF mapFrom ( ZxRenderItem * item , const QPointF & pt ) const ;
/// 从本图元坐标系转到其他图元坐标系
QPointF mapTo ( ZxRenderItem * item , const QPointF & pt ) const ;
/// 从本图元坐标系转到文档坐标系
QPointF mapToScene ( const QPointF & pos ) const ;
/// 从文档图元坐标系转到本坐标系
QPointF mapFromScene ( const QPointF & pos ) const ;
/// 从本图元坐标系转到文档坐标系
QRectF mapToScene ( const QRectF & rect ) const ;
/// 从文档图元坐标系转到本坐标系
QRectF mapFromScene ( const QRectF & rect ) const ;
/// 填属性表
virtual void fillPtyPano ( IxPtyPano * sheet ) ;
/// 获取标志集的字符串, 用来显示和调试
virtual QString getFlagsString ( ) const ;
/// 是否有祖先图元被选中
/// @note 在某些操作中, 选中某个图元时相当于把整棵子树全选中了. 这个函数提了供一种快速检测这种状态的方法.
virtual bool isAncestorSelected ( ) const ;
/// 判断本图元是否指定图元的祖先
/// @note 这的祖先指图元树上的关系, 不是类的继承关系. 任何图元都不是它自己的祖先
bool isAncestorOf ( const ZxRenderItem * p ) const ;
/// 判断本图元是否指定图元的子孙
/// @note 这的子孙指图元树的上的关系, 不是类的继承关系. 任何图元都不是它自己的子孙
bool isDescendantOf ( const ZxRenderItem * p ) const ;
// 左键双击
virtual void onLeftDoubleClick ( const QPointF & pt ) ;
// 左键单击
virtual void onLeftClick ( const QPointF & pt ) ;
// parent指针被改变
/// @note 不是parent的内容被改变
virtual void onParentChanged ( ) ;
/// 不变性(完整性)验证. 这个函数里有一堆ASSERT, 验证图元未损坏.
/// @note ZxSceneItem 要求子图元必须是几个特定图层, 在ZxSceneItem::invariant() 中就可以加上这些验证.
/// @note 此为契约编程的概念, C++无法自动调用此方法, 但底层会在paint等使用频繁使用的函数里调用. 必要时模块层也可以显示调用.
virtual void invariant ( ) const ;
/// 加载文件
template < typename T >
static T load ( const QString & filePath )
{
ZxRenderItem * p = load ( filePath ) ;
T p1 = dynamic_cast < T > ( p ) ;
if ( p1 = = 0 & & p ! = 0 )
{
Q_ASSERT ( false ) ;
delete p ;
}
return p1 ;
}
/// 加载
static ZxRenderItem * load ( const QString & filePath ) ;
static ZxRenderItem * load ( QFile & file ) ;
static ZxRenderItem * load ( QDataStream & stream ) ;
/// 保存
virtual bool save ( const QString & filePath ) const ;
virtual bool save ( QFile & file ) const ;
virtual bool save ( QDataStream & stream ) const ;
/// 克隆图元
/// @note 此函数自动使用序列化来克隆图元, 一般情况下无需重写.
virtual IxRenderItem * clone ( ) const ;
/// 克隆图元
/// @note 此函数自动使用序列化来克隆图元, 一般情况下无需重写.
template < typename T >
T clone ( ) const
{
ZxRenderItem * p = this - > clone ( ) ;
T ret = dynamic_cast < T > ( p ) ;
if ( ret = = 0 )
{
delete p ;
}
return ret ;
}
/// 图元导出为图片文件
/// @param fileName 文件路径.
/// @param format 图片格式, 支持Qt所支持的格式和"SVG".
/// @param quality 暂未使用, 请设为-1
/// @return 导出成功返回true, 失败返回false.
virtual bool exportImage ( const QString & fileName , const char * format = 0 , int quality = - 1 ) const ;
/// 获取图元树迭代器
virtual ZxRenderItemIterator getRenderTree ( ) ;
/// 设置布局器
virtual void setLayout ( ZxLayout * p ) ;
/// 查找多个图元的最近公共祖先节点
static ZxRenderItem * findCommonAncestor ( const QList < ZxRenderItem * > & items ) ;
/// 获取当前活动的属性表条目.
/// @note 用户在属性表里修改属性后, 通常会有一个回调, 例如调用对象的setXXXX()函数.
/// 在这些回调函数里, 我们就可以用getPropertyItem(bool)来获取当前所修改的属性表条目.
/// @param bOnlyWhenIsFirst 是否仅在当前图元是第一个图元时才返回.
/// @return 当前活动的(用户正在修改的)属性条目. 如果当前没有活动条目, 此函数返回NULL.
/// @see findPropertyItem(const QString &, bool)
static IxPtyItem * getPropertyItem ( bool bOnlyWhenIsFirst = true ) ;
/// 从当前活动的属性表里查找指定条目.
/// @note 用户在属性表里修改属性后, 通常会有一个回调, 例如调用对象的setXXXX()函数.
/// 在这些回调函数里, findPropertyItem()来查找当前所修改的属性表中的指定条目.
/// @param key 指定条目的名称(路径), 如 "井头.井名.字体"
/// @param bOnlyWhenIsFirst 是否仅在当前图元是第一个图元时才返回.
/// @return 找到的条目, 当前没有活动条目或者查找失败时返回NULL.
/// @see getPropertyItem(bool)
static IxPtyItem * findPropertyItem ( const QString & key , bool bOnlyWhenIsFirst = true ) ;
protected :
/// 布局操作, 可重写, 默认操作是使用布局器布局.
/// \li 无论needLayout()的值是什么, 都要做布局.
/// \li 布局完了以后一定要setNeedLaout(false)
/// \li 此方法内要递归调用子图元的 doLayout()
virtual void onLayout ( ) ;
public :
/// 在需要布局的时候调用 onLayout() 重新布局
void doLayout ( ) ;
/// 获取属性窗口
virtual IxPtyPano * getPtyPano ( bool tryOuter = true ) const ;
/// 获取图元的编辑器
/// @param bCreate 是否创建
/// @return 图元的编辑器, bCreate为true时保证返回可用的编辑器, 否则可能为NULL.
/// @note 每个图元都关联着一个编辑器
/// @see emitSigInstallPolicies() sigInstallPolicies() onInstallPolicies()
virtual ZxEdit * getEdit ( bool bCreate = true ) const ;
// short for getEdit()->getHandlePolicy()
ZxHandlePolicy * getHandlePolicy ( ) const ;
/// The recommended size for the widget.
/// If the value is an invalid size, no size is recommended.
/// The default implementation of sizeHint() returns an invalid size if there is no layout for this item, and returns the layout's preferred size otherwise.
virtual QSizeF getSizeHint ( ) const ;
/// 调用 onInstallPolicies(), 然后发出信号 sigInstallPolicies()
void emitSigInstallPolicies ( ) ;
/// (内部使用)
/// \internal
ZxRenderItem * getClippedBy ( ) ;
static void saveMulti ( QDataStream & stream , const QList < ZxRenderItem * > & list ) ;
static QList < ZxRenderItem * > loadMulti ( QDataStream & stream ) ;
public slots :
protected :
/// 在此函数内安装编辑策略
virtual void onInstallPolicies ( ) ;
virtual bool needPaintSelf ( QPainter * painter , const ZxPaintParam & param ) const ;
virtual bool needPaintDescendants ( QPainter * painter , const ZxPaintParam & param ) const ;
virtual void onApplyAutoSize ( ) ;
virtual void onChildItemAdded ( ZxRenderItem * p ) ;
virtual void onChildItemRemoved ( ZxRenderItem * p ) ;
private :
void checkNeedLayoutFlagConsistency ( ) ;
bool _findItems ( QList < ZxRenderItem * > & list , double x , double y , \
ZxFilterFun filter , bool bRecursive ) ;
void _insert ( int index , ZxRenderItem * p ) ;
void _setNeedLayout ( bool bNeed ) ;
void _setForceLayout ( bool bForce ) ;
_ZxRenderChildIndex * get_item_index_map ( ) ;
private :
// QList内部用的是指针数组, 我们直接用指针数据效率可能更高
QVector < ZxRenderItem * > m_vecChildren ;
// 父节点
ZxRenderItem * m_pParent ;
// 外接矩形
QRectF m_rectBounds ;
// 标志集
Flags m_nFlags ;
// 当前的编辑器, 如内嵌文本输入框
mutable ZxEdit * m_pEdit ;
// 布局器
ZxLayout * m_pLayout ;
// 子图元位置索引, 加快indexOf等操作
_ZxRenderChildIndex * m_pChildIndex ;
bool m_bInDoLayout : 1 ; // for debug
bool m_bHasOldOnLayout : 1 ; // for debug
bool m_bInPainting : 1 ; // for debug
friend class ZxRenderView ;
friend class ZxSceneItem ;
friend class ZxSelectionPrivate ;
friend class ZxLayout ;
} ;
I_PLOTBASE_EXPORT QString zxSplitTagName ( const QString & s ) ;