You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWATI/Include/iPlot/iPlotBase/ZxRenderView.h

554 lines
16 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#pragma once
#include <QAbstractScrollArea>
#include <QVector>
#include <QPoint>
#include <QPixmap>
#include "ZxRenderItem.h"
#include "ZxSceneItem.h"
#include "ZxRenderItemIterator.h"
#include "IxRedoUndo.h"
#include "iPlotBase_global.h"
class QActionGroup;
class QUndoCommand;
class ZxToolState;
class ZxTool;
class QMenu;
class QComboBox;
class QPixmap;
class QPushButton;
class QPrinter;
class ZxSelectionOutline
{
public:
QPixmap pixmap;
int xc;
int yc;
};
// 图形视图(图元显示和操作)
class I_PLOTBASE_EXPORT ZxRenderView
: public QAbstractScrollArea
, virtual public IxDynObj
, virtual public IxRedoUndo
{
Q_OBJECT
ZX_DECLARE_DYNAMIC
public:
ZxRenderView(QWidget* parent = 0);
virtual ~ZxRenderView();
enum ZoomMode
{
eZoomFree,
eZoomFitWidth,
eZoomFitHeight,
eZoomFitWindow
};
public:
// 强制显示隐藏滚动条
void forceShowScrollBar(bool bHori, bool bVisible);
// 获取图元树迭代器
ZxRenderItemIterator getRenderTree() const;
// 堆栈相关
virtual QUndoStack* getUndoStack();
virtual void pushCommand(QUndoCommand* cmd);
// 场景
virtual void setScene(ZxSceneItem* p, bool bOwnScene = false);
virtual ZxSceneItem* getScene() const;
// 获取当前工具正在操作视图
static ZxRenderView* getCurrentToolView();
// 获取(建议的)控制点尺寸
float getHandleSize(); // mm
// 获取(建议的)控制点尺寸, 并转到文档坐标(随着缩放率变化)
float getHandleSizeSceneCoord(); // mm
// 快照模式开关,快照模式下重绘速度快, 但只在显示区域发生变化时才刷新快照.
virtual void setSnapshotMode(bool b);
virtual bool isSnapshotMode() const;
QPixmap getSnapshot(); //获取快照
virtual void repaintSnapshot();//立即刷新快照, 在非快照模式下无效果.
virtual void updateSnapshot();//刷新快照, 但不是立即刷新, 在非快照模式下无效果.
// 是否显示纸张页面及边框
void setPaperMode(bool b);
public:
// 准备右键菜单
virtual void onPrepareContextMenu(QMenu* pMenu, const QPointF& pos);
// 获取选择区域的轮廓(实际上可能是详图, 不一定就是线框轮廓)
virtual ZxSelectionOutline getSelectionOutline(int nMouseX, int nMouseY, \
const QColor overlapColor = QColor(0, 127, 255, 63), \
ZxFilterFun filter = 0);
// 从本视图坐标系转到文档坐标系
QPointF mapToScene(const QPointF& pos) const;
QRectF mapToScene(const QRectF& rect) const;
QSizeF mapToScene(const QSizeF & sz) const;
// 从文档坐标系转到本视图坐标系
QPointF mapFromScene(const QPointF& pos) const;
QRectF mapFromScene(const QRectF& rect) const;
QSizeF mapFromScene(const QSizeF & sz) const;
// 从本视图坐标系转到全局坐标系
QPointF mapToGlobal(const QPointF& pos) const;
QPoint mapToGlobal(const QPoint& pos) const;
// 从全局坐标系转到本视图坐标系
QPointF mapFromGlobal(const QPointF& pos) const;
QPoint mapFromGlobal(const QPoint& pos) const;
// 缩放模式
virtual void setZoomMode(ZoomMode mode, bool reLayout = true);
ZoomMode getZoomMode() const;
// 获取缩放倍数
float getZoomRatioX() const;
float getZoomRatioY() const;
float getZoomRatio() const;
// 获取缩放模式或百分比, 以便用来显示给用户.
QString getZoomString() const;
// 缩放到指定区域
virtual void zoomTo(const QRectF& rectSceneCoord);
// 把场景的某点对应到视图的某点
virtual void scrollScenePosToViewPos(const QPointF& ptScene, const QPointF& ptView);
// 把场景的某点显示到视图中心
virtual void scrollScenePosToViewCenter(const QPointF& ptScene);
// 把矩形变为和视图一样的长宽比例
virtual QRectF adjustRectFitViewAspect(const QRectF& rect);
// 获取屏幕DPI
static int getDpiX();
static int getDpiY();
// 获取屏幕每毫米的像素数
static float getPpmmX();
static float getPpmmY();
// 还原鼠标光标.
// 一般是箭头, 但也可能是其它, 所以不能用 setCursor(Qt::ArrowCursor);
virtual void restoreCursor();
signals:
// 信号: 有图元被移出图件树
void sigItemDetached(ZxRenderItem* pItem);
// 信号:双击
void sigLeftDoubleClick(const QPointF& pt);
// 信号为了PF同步新增的信号
void sigZoomedX(float r, bool reLayout);
void sigZoomedY(float r, bool reLayout);
void sigMouseWheel(const QPointF& pt, int delta);
void sigZoomStrChanged(const QString& s, bool reLayout = true);
// 信号:缩放
void sigZoomedIn();
void sigZoomedOut();
void sigZoomedRaw();
public slots:
// 设置缩放倍数(例如2.5倍)
virtual void setZoomRatioX(float r, bool reLayout);
virtual void setZoomRatioY(float r, bool reLayout);
virtual void slotMouseWheel(const QPointF& pt, int delta);
// 设置缩放模式或百分比.
// @param s 输入"120"或"120%"均表示放大到1.2倍
// @param reLayout 是否立即重新布局
virtual void slotZoomStrChanged(const QString& s, bool reLayout);
// 放大/缩小/初始
virtual void zoomIn();
virtual void zoomOut();
virtual void zoomRaw();
virtual void zoomInOnly();
virtual void zoomOutOnly();
// 处理保存
virtual void slotSaveAsImg();
// 处理打印动作
virtual void slotPrint();
virtual void slotPrintPreview();
virtual void print(QPrinter *printer);
virtual void printPreview(QPrinter *printer);
// 相当于 viewport()->update(...)
virtual void updateViewport();
// 相当于 viewport()->update(...)
virtual void slotUpdateViewport(const QRect&);
// 相当于 viewport()->repaint(...)
virtual void repaintViewport();
private:
void notifyItemDetached(ZxRenderItem* pItem);
protected slots:
virtual void slotZoomEditingFinished();
virtual void slotZoomComboIndexChanged(const QString& text);
void slotTheOwnedSceneDestroyed(QObject* p);
public:
// 画背景及纸张
virtual void paintPaper(QPainter* painter);
// 画工具、Policy、控制点、辅助线等前景
// @note 打印和输出图片时不画这一层
virtual void paintOverlay(QPainter* painter);
// 画文档内容
virtual void paintScene(QPainter* painter, const ZxPaintParam& param);
// 用默认的ZxPaintParam来绘图
virtual void paintScene(QPainter* painter);
// 在指定画布上绘制图形(无前景和背景)
// deviceRect: 设备坐标范围,坐标单位为像素,如果为空,则表示按照图形实际大小输出
// expose: 文档坐标范围,如果为空表示输出完整图形
virtual void paint(QPainter* painter, QRect deviceRect = QRect(), QRectF expose = QRectF(), bool isPreview = false);
protected:
virtual void paintEvent(QPaintEvent *);
virtual void resizeEvent(QResizeEvent *);
virtual void mousePressEvent(QMouseEvent *);
virtual void mouseMoveEvent(QMouseEvent *);
virtual void mouseReleaseEvent(QMouseEvent *);
virtual void mouseDoubleClickEvent(QMouseEvent *);
virtual void wheelEvent(QWheelEvent *);
virtual void keyPressEvent(QKeyEvent *);
virtual void keyReleaseEvent(QKeyEvent *);
virtual void customContextMenuRequested(const QPoint &pos);
virtual void enterEvent(QEvent *);
virtual void leaveEvent(QEvent *);
virtual void hideEvent(QHideEvent *);
virtual void focusInEvent(QFocusEvent *);
virtual void focusOutEvent(QFocusEvent *);
virtual void closeEvent(QCloseEvent *);
protected:
virtual QSizeF getViewportSizePixel() const;
// 见Qt文档, 滚动位置发生变化
virtual void scrollContentsBy ( int dx, int dy );
// 根据缩放模式计算出缩放率
virtual void calcZoomRatio();
// 计算转换矩阵
static void calcMatrix(QMatrix & m, float scaleX, float scaleY, float x0, float y0);
// 计算转换矩阵
void calcMatrix(QMatrix & m, float x0, float y0);
// 更新转换矩阵
virtual void calcMatrix();
private:
void _setZoomRatio(float f, bool reLayout, bool sync, bool bX);
// 以下函数在QWdiget里是非虚的, 不能重写.
// 但他们又很容易和viewport里的混淆, 所以设为private的, 避免误用
// 如果确实要用, 可使用限定符调用基类的: QAbstractScrollArea::update()
// (已封闭) use viewport()->update(...) instead.
void update();
// (已封闭) use viewport()->repaint(...) instead.
void repaint();
// (已封闭) use viewport()->update(...) instead.
void update(int x, int y, int w, int h);
// (已封闭) use viewport()->update(...) instead.
void update(const QRect&);
// (已封闭) use viewport()->update(...) instead.
void update(const QRegion&);
// (已封闭) use viewport()->repaint(...) instead.
void repaint(int x, int y, int w, int h);
// (已封闭) use viewport()->repaint(...) instead.
void repaint(const QRect &);
// (已封闭) use viewport()->repaint(...) instead.
void repaint(const QRegion &);
// (已封闭) use paint(...) instead
void render(QPaintDevice *target, const QPoint &targetOffset = QPoint(),
const QRegion &sourceRegion = QRegion(),
RenderFlags renderFlags = RenderFlags(DrawWindowBackground | DrawChildren));
// (已封闭) use paint(...) instead
void render(QPainter* painter, const QPoint &targetOffset = QPoint(),
const QRegion &sourceRegion = QRegion(),
RenderFlags renderFlags = RenderFlags(DrawWindowBackground | DrawChildren));
// 打印或者打印预览
virtual void print(QPrinter *printer, bool isPreview);
public:
// 相当于 viewport()->update(...)
virtual void updateViewport(int x, int y, int w, int h);
// 相当于 viewport()->update(...)
virtual void updateViewport(const QRect&);
// @see void updateViewport(const QRect&)
virtual void updateViewport(const QRectF&);
// 相当于 viewport()->update(...)
virtual void updateViewport(const QRegion&);
// 相当于 viewport()->repaint(...)
virtual void repaintViewport(int x, int y, int w, int h);
// 相当于 viewport()->repaint(...)
virtual void repaintViewport(const QRect &);
// 相当于 viewport()->repaint(...)
virtual void repaintViewport(const QRegion &);
// 文档发生改变
virtual void onDocUpdate(const QRectF * pSceneRect);
// 布局. 包括更新滚动条范围, 做页面布局, 计算矩阵等
virtual void layoutViewport(QRectF * pSceneBounds = 0);
// 获取窗口边距
virtual void getMargins(float * top, float * left, float * bottom, float * right) const;
// 设置窗口边距
virtual void setMargins(float top, float left, float bottom, float right);
// 获取文档坐标系下的窗口边距
virtual void getMarginsSceneCoord(float * top, float * left, float * bottom, float * right) const;
// 获取文档范围
virtual QRectF getSceneBounds() const;
// 获取加上缩进后的文档范围
virtual QRectF getSceneBoundsWithMargins() const;
// 获取当前缩放率下视口能显示的最大文档尺寸
virtual QSizeF getViewportSizeMillimeter() const;
// 获取当前可见的场景区域
virtual QRectF getViewportRectSceneCoord() const;
// 滚动位置
virtual QPointF getScrollPos() const;
virtual void setScrollPos(const QPointF& pos);
virtual void setScrollPos(float x, float y);
// 水平滚动位置
virtual void setHorizontalScrollPos(float pos);
virtual void setVerticalScrollPos(float pos);
// 设置缩放下拉栏是否可见
void setZoomComboVisible(bool b);
// 不变性检测
virtual void invariant() const;
// 对齐方式.
// 暂时只支持居中和不居中
virtual void setAlignment(Qt::Alignment alignment);
virtual Qt::Alignment getAlignment() const;
#ifdef _SCAN_OLD_CODE_
virtual void setSmartHorizontalScrollPos(bool b);
bool isSmartHorizontalScrollPos() const;
virtual void setSmartVerticalScrollPos(bool b);
bool isSmartVerticalScrollPos() const;
#endif
public:
// 获取视图中所有工具
QVector<ZxTool*> getTools() const;
// 活动工具
virtual ZxTool* getActiveTool() const;
virtual void setActiveTool(int index);
virtual void setActiveTool(ZxTool* p);
virtual void setActiveTool(const QString& sToolText);
// 默认工具
virtual ZxTool* getDefaultTool() const;
virtual void setDefaultTool(int index);
virtual void setDefaultTool(ZxTool* p);
// 把工具加到视图中.
// @ pTool 要添加的工具. 可以为0, 0将显示为分隔线.
// 注: 视图将负责销毁工具
int addTool(ZxTool* pTool);
// 获取指定action, 触发action可激活工具
QAction* getToolAction(int index) const;
QAction* getToolAction(ZxTool* p) const;
// 删除全部工具
virtual void clearTools();
// 活动视图
bool isActiveView() const;
bool activateView();
// 当前视图被激活/被取消激活
virtual void onActivated(QWidget* pOldActiveView);
virtual void onDeactivated(QWidget* pNewActiveView);
// 工具的状态和另一个视图同步(单次同步)
void syncActiveToolWith(const ZxRenderView* pOther);
// 从另一个视图中复制工具
void copyToolsFrom(const ZxRenderView* pOther);
protected:
// void onSerialize(ZxSerializer* ser);
// void onDeserialize(ZxSerializer* ser);
bool checkAndDoLayout();
virtual void onViewportParamChanged();
virtual void onSelectionChanged(ZxSelection& selection);
// 转换矩阵, 用作painter的 matrix
QMatrix getMatrixDocToView() const;
// 转换矩阵
QMatrix getMatrixViewToDoc() const;
virtual void onIdle();
public:
void setCursorKeeping(bool bKeeping);
private:
// scene
// |<----------------------------------------->|
// |==============================|<---------->|
// min page
void setHorizontalScrollInfo(float fMin, float fScene, float fView);
void setVerticalScrollInfo(float fMin, float fScene, float fView);
void prepareBackBuffer();
private slots:
void slotActivateTool();
private:
// 场景指针
ZxSceneItem* m_pScene;
// Action & Tool
QVector<QAction*> m_vecToolActions;
QVector<ZxTool*> m_vecTools;
QActionGroup* m_pToolActionGroup;
int m_nDefaultTool;
int m_nActiveTool;
// 用作painter的world matrix
QMatrix* m_pMatrixDocToView;
QMatrix* m_pMatrixViewToDoc;
static float m_fCachedPpmmX;
static float m_fCachedPpmmY;
// 工具的状态, 同时只有一个工具激活, 所以没必要每个工具都记一份
ZxToolState* m_pToolState;
// 缩放
QComboBox* m_pComboZoom;
ZoomMode m_nZoomMode;
float m_fZoomX;
float m_fZoomY;
float m_fMarginLeft;
float m_fMarginTop;
float m_fMarginRight;
float m_fMarginBottom;
float m_fScrollOriginX;
float m_fScrollOriginY;
QRectF m_rectLastBounds; // 用来检测是否需要重新布局
QSizeF m_sizeLastViewport;
QPixmap m_snapshot;
QPixmap m_backBuffer;
Qt::Alignment m_nAlignment;
bool m_bSnapshotMode;
bool m_bPaperMode;
bool m_bNeedRepaintSnapshot;
bool m_bInLayoutViewport;
#ifdef _SCAN_OLD_CODE_
bool m_bSmartHorizontalScrollPos : 1;
bool m_bSmartVerticalScrollPos : 1;
#endif
bool m_bOwnScene;
bool m_bPainting;
bool m_bHover;
bool m_bNoBackBuffer; // 不使用后台缓存 (此变量不影响Qt自带的防闪烁机制)
private:
// 临时变量
bool m_bKeepingCursor; //对于Polygon生成过程中不能恢复为箭头
bool m_bActive;//临时
friend class ZxTool;
friend class ZxSceneItem;
friend class ZxCompoundTool;
};