#pragma once #include #include #include #include #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 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 m_vecToolActions; QVector 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; };