diff options
Diffstat (limited to 'src/canvasmanipulator.h')
-rw-r--r-- | src/canvasmanipulator.h | 605 |
1 files changed, 605 insertions, 0 deletions
diff --git a/src/canvasmanipulator.h b/src/canvasmanipulator.h new file mode 100644 index 0000000..06d463c --- /dev/null +++ b/src/canvasmanipulator.h @@ -0,0 +1,605 @@ +/*************************************************************************** + * Copyright (C) 2004-2005 by David Saxton * + * [email protected] * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifndef CANVAsmANIPULATOR_H +#define CANVAsmANIPULATOR_H + +#include "eventinfo.h" + +#include <qcanvas.h> +#include <qguardedptr.h> + +class CanvasManipulator; +class Connector; +class CMManager; +class CNItem; +class CNItemGroup; +class EventInfo; +class FlowContainer; +class ICNDocument; +class Item; +class ItemDocument; +class ItemGroup; +class ItemView; +class ManipulatorInfo; +class ManualConnectorDraw; +class MechanicsItem; +class MechanicsGroup; +class MechanicsDocument; +class Node; +class NodeGroup; +class ResizeHandle; + +class QCanvas; +class QCanvasItem; +class QCanvasLine; +class QCanvasRectangle; +class QMouseEvent; +class QTimer; +class QWheelEvent; + +typedef CanvasManipulator*(*CreateManipulatorPtr)( ItemDocument *, CMManager * ); +typedef bool(*AcceptManipulationPtr)( uint eventState, uint cmState, uint itemType, uint cnItemType ); +typedef QValueList<NodeGroup*> NodeGroupList; +typedef QValueList<QGuardedPtr<Connector> > ConnectorList; +typedef QValueList<QPoint> QPointList; + + +class ManipulatorInfo +{ +public: + ManipulatorInfo(); + AcceptManipulationPtr m_acceptManipulationPtr; + CreateManipulatorPtr m_createManipulatorPtr; +}; +typedef QValueList<ManipulatorInfo*> ManipulatorInfoList; + + +/** +Handles canvas manipulation, such as moving an item or resizing the canvas +@author David Saxton +*/ +class CMManager : public QObject +{ +Q_OBJECT +public: + enum EventState + { + es_right_click = 1 << 0, + es_ctrl_pressed = 1 << 1 + }; + enum CMState + { + cms_repeated_add = 1 << 0, + cms_manual_route = 1 << 1, + cms_draw = 1 << 2 + }; + enum ItemType + { + it_none = 1 << 0, + it_node = 1 << 1, + it_connector = 1 << 2, + it_pin = 1 << 3, + it_canvas_item = 1 << 4, + it_mechanics_item = 1 << 5, + it_resize_handle = 1 << 6, + it_drawpart = 1 << 7 + }; + enum ItemStateInfo + { + isi_isMovable = 0x2, + }; + CMManager( ItemDocument *itemDocument ); + ~CMManager(); + /** + * Called when the user single-clicks the mouse + */ + void mousePressEvent( EventInfo eventInfo ); + /** + * Called when the user releases the mouse + */ + void mouseReleaseEvent( const EventInfo &eventInfo ); + /** + * Called when the user double clicks the mouse + */ + void mouseDoubleClickEvent( const EventInfo &eventInfo ); + /** + * Called when the user moves the mouse + */ + void mouseMoveEvent( const EventInfo &eventInfo ); + /** + * Called when the user scrolls the mouse + */ + void wheelEvent( const EventInfo &eventInfo ); + /** + * Set a current CMState to true or false + */ + void setCMState( CMState type, bool state ); + /** + * Cancels the current manipulation (if there is one) + */ + void cancelCurrentManipulation(); + CanvasManipulator * currentManipulator() const { return m_canvasManipulator; } + void setRepeatedAddId( const QString & repeatedId = QString::null ); + uint cmState() const { return m_cmState; } + void addManipulatorInfo( ManipulatorInfo *info ); + QString repeatedItemId() const { return m_repeatedItemId; } + void setDrawAction( int drawAction ); + int drawAction() const { return m_drawAction; } + +public slots: + void slotSetManualRoute( bool manualRoute ); + +signals: + void manualRoutingChanged( bool manualRouting ); + +protected: + /** + * Called when the mouse is moved or released, with the ResizeHandle that + * the mouse is currently over (which can be null). Updates which handle is + * selected, etc. + */ + void updateCurrentResizeHandle( ResizeHandle * mouseOver ); + CanvasManipulator *m_canvasManipulator; + uint m_cmState; + QString m_repeatedItemId; + ItemDocument *p_itemDocument; + ManipulatorInfoList m_manipulatorInfoList; + QGuardedPtr<Item> p_lastMouseOverItem; // Pointer to the item where the mouse was last over - this is used to determine when mouse + QGuardedPtr<ResizeHandle> p_lastMouseOverResizeHandle; + QGuardedPtr<Item> p_lastItemClicked; + QTimer *m_allowItemScrollTmr; // When a user scrolls on the canvas, we don't want to stop scrolling when the user gets to (e.g.) a scrollable widget. So this timer prevents scrolling a widget for a few hundred milliseconds after a scroll event if it was initiated over the canvas + bool b_allowItemScroll; // See above. + int m_drawAction; + +private slots: + void slotAllowItemScroll() { b_allowItemScroll = true; } +}; + + +/** +Abstract class for a "editing operation" on the ICNDocument, such as moving an item or resizing the canvas +@author David Saxton +*/ +class CanvasManipulator +{ +public: + CanvasManipulator( ItemDocument *itemDocument, CMManager *cmManager ); + virtual ~CanvasManipulator(); + enum Type + { + RepeatedItemAdd, + RightClick, + AutoConnector, + ManualConnector, + ItemMove, + ItemResize, + MechItemMove, + Select, + CanvasResize, + ItemDrag, + Draw + }; + virtual Type type() const = 0; + /** + * Called when the user single-clicks the mouse + * @returns true if the manipulation operation has finished + */ + virtual bool mousePressedInitial( const EventInfo &/*info*/ ) { return false; } + /** + * Called when the user single-clicks the mouse after the first time (only + * applicable for those operations who are not oneClick + * @returns true if the manipulation operation has finished + */ + virtual bool mousePressedRepeat( const EventInfo &/*info*/ ) { return false; }; + /** + * Called when the user moves the mouse + * @returns true if the manipulation operation has finished + */ + virtual bool mouseMoved( const EventInfo &/*info*/ ) { return false; }; + /** + * Called when the user releases the mouse + * @returns true if the manipulation operation has finished + */ + virtual bool mouseReleased( const EventInfo &/*info*/ ) { return true; } + +protected: + Type m_type; + EventInfo m_eventInfo; + QPoint m_prevPos; + ItemDocument *p_itemDocument; + ICNDocument *p_icnDocument; + MechanicsDocument *p_mechanicsDocument; + QCanvas *p_canvas; + ItemGroup *p_selectList; + CNItemGroup *p_cnItemSelectList; + MechanicsGroup *p_mechItemSelectList; + CNItem *p_cnItemClickedOn; + MechanicsItem *p_mechanicsItemClickedOn; + CMManager *p_cmManager; +}; + + +/** +@author David Saxton +*/ +class CMRepeatedItemAdd : public CanvasManipulator +{ +public: + CMRepeatedItemAdd( ItemDocument *itemDocument, CMManager *cmManager ); + virtual ~CMRepeatedItemAdd(); + virtual Type type() const { return RepeatedItemAdd; } + + static CanvasManipulator* construct( ItemDocument *itemDocument, CMManager *cmManager ); + static ManipulatorInfo *manipulatorInfo(); + static bool acceptManipulation( uint eventState, uint cmState, uint itemType, uint cnItemType ); + + virtual bool mousePressedInitial( const EventInfo &info ); + virtual bool mousePressedRepeat( const EventInfo &info ); + virtual bool mouseMoved( const EventInfo &info ); + virtual bool mouseReleased( const EventInfo &info ); + +protected: +}; + + + +/** +@author David Saxton +*/ +class CMRightClick : public CanvasManipulator +{ +public: + CMRightClick( ItemDocument *itemDocument, CMManager *cmManager ); + virtual ~CMRightClick(); + virtual Type type() const { return RightClick; } + + static CanvasManipulator* construct( ItemDocument *itemDocument, CMManager *cmManager ); + static ManipulatorInfo *manipulatorInfo(); + static bool acceptManipulation( uint eventState, uint cmState, uint itemType, uint cnItemType ); + + virtual bool mousePressedInitial( const EventInfo &info ); + virtual bool mouseMoved( const EventInfo &info ); + virtual bool mouseReleased( const EventInfo &info ); + +protected: +}; + + +/** +@author David Saxton +*/ +class ConnectorDraw : public CanvasManipulator +{ + public: + ConnectorDraw( ItemDocument *itemDocument, CMManager *cmManager ); + virtual ~ConnectorDraw(); + + /** + * Returns the colour used to indicate that the current connection + * being drawn is valid. Invalid colour is black. + */ + static QColor validConnectionColor(); + + protected: + /** + * If the node has more than 2 connections, return one of the + * connectors + */ + Connector * toConnector( Node * node ); + /** + * Converts the given qcanvasitem to an appropriate node or connector. + * @param posIsExact if true, then only gets an appropriate node or + * connector when the to-be end-point of the new connector will coincide + * with pos (i.e. auto-connector will call this with posIsExact = false, + * and manual-connector will call this with posIsExact = true). + */ + void grabEndStuff( QCanvasItem * endItem, const QPoint & pos, bool posIsExact ); + /** + * Returns the closest point to the clickPos that is on the given + * connector. + */ + QPoint toValidPos( const QPoint & clickPos, Connector * clickedConnector ) const; + + QGuardedPtr<Node> p_startNode; + QGuardedPtr<Connector> p_startConnector; + Node * p_endNode; + Connector * p_endConnector; + QPoint startConnectorPoint; +}; + + +/** +@author David Saxton +*/ +class CMAutoConnector : public ConnectorDraw +{ +public: + CMAutoConnector( ItemDocument *itemDocument, CMManager *cmManager ); + virtual ~CMAutoConnector(); + virtual Type type() const { return AutoConnector; } + + static CanvasManipulator* construct( ItemDocument *itemDocument, CMManager *cmManager ); + static ManipulatorInfo *manipulatorInfo(); + static bool acceptManipulation( uint eventState, uint cmState, uint itemType, uint cnItemType ); + + virtual bool mousePressedInitial( const EventInfo &info ); + virtual bool mouseMoved( const EventInfo &info ); + virtual bool mouseReleased( const EventInfo &info ); + +protected: + QCanvasLine *m_connectorLine; +}; + + +/** +@author David Saxton +*/ +class CMManualConnector : public ConnectorDraw +{ +public: + CMManualConnector( ItemDocument *itemDocument, CMManager *cmManager ); + virtual ~CMManualConnector(); + virtual Type type() const { return ManualConnector; } + + static CanvasManipulator* construct( ItemDocument *itemDocument, CMManager *cmManager ); + static ManipulatorInfo *manipulatorInfo(); + static bool acceptManipulation( uint eventState, uint cmState, uint itemType, uint cnItemType ); + + virtual bool mousePressedInitial( const EventInfo &info ); + virtual bool mousePressedRepeat( const EventInfo &info ); + virtual bool mouseMoved( const EventInfo &info ); + virtual bool mouseReleased( const EventInfo &info ); + +protected: + ConnectorList m_fixedRouteConnectors; + ManualConnectorDraw *m_manualConnectorDraw; +}; + + +/** +@author David Saxton +*/ +class CMItemMove : public CanvasManipulator +{ +public: + CMItemMove( ItemDocument *itemDocument, CMManager *cmManager ); + virtual ~CMItemMove(); + virtual Type type() const { return ItemMove; } + + static CanvasManipulator* construct( ItemDocument *itemDocument, CMManager *cmManager ); + static ManipulatorInfo *manipulatorInfo(); + static bool acceptManipulation( uint eventState, uint cmState, uint itemType, uint cnItemType ); + + virtual bool mousePressedInitial( const EventInfo &info ); + virtual bool mouseMoved( const EventInfo &info ); + virtual bool mouseReleased( const EventInfo &info ); + +protected: + ConnectorList m_translatableConnectors; + NodeGroupList m_translatableNodeGroups; + FlowContainer *p_flowContainerCandidate; +}; + + +/** +@author David Saxton +*/ +class CMItemResize : public CanvasManipulator +{ +public: + CMItemResize( ItemDocument *itemDocument, CMManager *cmManager ); + virtual ~CMItemResize(); + virtual Type type() const { return ItemResize; } + + static CanvasManipulator* construct( ItemDocument *itemDocument, CMManager *cmManager ); + static ManipulatorInfo *manipulatorInfo(); + static bool acceptManipulation( uint eventState, uint cmState, uint itemType, uint cnItemType ); + + virtual bool mousePressedInitial( const EventInfo &info ); + virtual bool mouseMoved( const EventInfo &info ); + virtual bool mouseReleased( const EventInfo &info ); + +protected: + ResizeHandle *p_resizeHandle; + double m_rh_dx; + double m_rh_dy; +}; + + +/** +@author David Saxton +*/ +class CMMechItemMove : public CanvasManipulator +{ +public: + CMMechItemMove( ItemDocument *itemDocument, CMManager *cmManager ); + virtual ~CMMechItemMove(); + virtual Type type() const { return MechItemMove; } + + static CanvasManipulator* construct( ItemDocument *itemDocument, CMManager *cmManager ); + static ManipulatorInfo *manipulatorInfo(); + static bool acceptManipulation( uint eventState, uint cmState, uint itemType, uint cnItemType ); + + virtual bool mousePressedInitial( const EventInfo &info ); + virtual bool mouseMoved( const EventInfo &info ); + virtual bool mouseReleased( const EventInfo &info ); + +protected: + uint m_prevClickedOnSM; // Previous select mode of the item that was clicked on +}; + + +/** +@author David Saxton +*/ +class SelectRectangle +{ + public: + SelectRectangle( int x, int y, int w, int h, QCanvas *qcanvas ); + ~SelectRectangle(); + + void setSize( int w, int h ); + QCanvasItemList collisions(); + + protected: + QCanvasLine *m_topLine; + QCanvasLine *m_rightLine; + QCanvasLine *m_bottomLine; + QCanvasLine *m_leftLine; + const int m_x; + const int m_y; + int m_w; + int m_h; + int m_prevCollisions_w; + int m_prevCollisions_h; + QCanvasItemList m_prevCollisions; +}; + + +/** +@author David Saxton +*/ +class CMSelect : public CanvasManipulator +{ +public: + CMSelect( ItemDocument *itemDocument, CMManager *cmManager ); + virtual ~CMSelect(); + virtual Type type() const { return Select; } + + static CanvasManipulator* construct( ItemDocument *itemDocument, CMManager *cmManager ); + static ManipulatorInfo *manipulatorInfo(); + static bool acceptManipulation( uint eventState, uint cmState, uint itemType, uint cnItemType ); + + virtual bool mousePressedInitial( const EventInfo &info ); + virtual bool mouseMoved( const EventInfo &info ); + virtual bool mouseReleased( const EventInfo &info ); + +protected: + SelectRectangle *m_selectRectangle; +}; + + +/** +@author David Saxton +*/ +class CMItemDrag : public CanvasManipulator +{ +public: + CMItemDrag( ItemDocument *itemDocument, CMManager *cmManager ); + virtual ~CMItemDrag(); + virtual Type type() const { return ItemDrag; } + + static CanvasManipulator* construct( ItemDocument *itemDocument, CMManager *cmManager ); + static ManipulatorInfo *manipulatorInfo(); + static bool acceptManipulation( uint eventState, uint cmState, uint itemType, uint cnItemType ); + + virtual bool mousePressedInitial( const EventInfo &info ); + virtual bool mouseMoved( const EventInfo &info ); + virtual bool mouseReleased( const EventInfo &info ); + +protected: + bool b_dragged; +}; + + + +/** +@author David Saxton +A QCanvasEllipse that uses a pen (not a brush) to paint +*/ +class CanvasEllipseDraw : public QCanvasEllipse +{ + public: + CanvasEllipseDraw( int x, int y, QCanvas * canvas ); + + protected: + virtual void drawShape( QPainter & p ); +}; + + +/** +@author David Saxton +*/ +class CMDraw : public CanvasManipulator +{ + public: + CMDraw( ItemDocument *itemDocument, CMManager *cmManager ); + virtual ~CMDraw(); + virtual Type type() const { return Draw; } + + static CanvasManipulator* construct( ItemDocument *itemDocument, CMManager *cmManager ); + static ManipulatorInfo *manipulatorInfo(); + static bool acceptManipulation( uint eventState, uint cmState, uint itemType, uint cnItemType ); + + virtual bool mousePressedInitial( const EventInfo &info ); + virtual bool mouseMoved( const EventInfo &info ); + virtual bool mouseReleased( const EventInfo &info ); + + protected: + QCanvasRectangle * m_pDrawRectangle; + CanvasEllipseDraw * m_pDrawEllipse; + QCanvasLine * m_pDrawLine; +}; + + +/** +@author David Saxton +*/ +class ManualConnectorDraw +{ + public: + ManualConnectorDraw( ICNDocument *_icnDocument, const QPoint &initialPos ); + virtual ~ManualConnectorDraw(); + + /** + * Called when the mouse is moved. + * Normally will do something like updating the connector route + */ + void mouseMoved( const QPoint &pos ); + /** + * Called when the user clicks the mouse. If the connector finishes on a + * valid QCanvasItem (Node or Connetor), then this is returned. Otherwise, + * null is returned. + */ + QCanvasItem * mouseClicked( const QPoint &pos ); + /** + * Returns the list of points that define the manual connection route + */ + QPointList pointList(); + /** + * Sets the colour used to draw the connection lines. + */ + void setColor( const QColor & color ); + + protected: + void updateConnectorEnds(); + + QValueList<QCanvasLine*> m_connectorLines; + ICNDocument *icnDocument; + + bool b_currentVertical; + bool b_orientationDefined; + + QPoint m_initialPos; + QPoint m_previousPos; + QPoint m_currentPos; + + QCanvasLine *m_currentCon; + QCanvasLine *m_previousCon; + + // The first item that we clicked on + QCanvasItem *p_initialItem; + + QColor m_color; +}; + + +#endif |