Logo Search packages:      
Sourcecode: ktechlab version File versions  Download package

canvasmanipulator.h

/***************************************************************************
 *   Copyright (C) 2004-2005 by David Saxton                               *
 *   david@bluehaze.org                                                    *
 *                                                                         *
 *   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
*/
00069 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
*/
00171 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
       */
00195       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
       */
00201       virtual bool mousePressedRepeat( const EventInfo &/*info*/ ) { return false; };
      /**
       * Called when the user moves the mouse
       * @returns true if the manipulation operation has finished
       */
00206       virtual bool mouseMoved( const EventInfo &/*info*/ ) { return false; };
      /**
       * Called when the user releases the mouse
       * @returns true if the manipulation operation has finished
       */
00211       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
*/
00233 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
*/
00257 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
*/
00279 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
*/
00322 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
*/
00345 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
*/
00370 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
*/
00395 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
*/
00420 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
*/
00443 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
*/
00470 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
*/
00493 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
*/
00518 class CanvasEllipseDraw : public QCanvasEllipse
{
      public:
            CanvasEllipseDraw( int x, int y, QCanvas * canvas );
            
      protected:
            virtual void drawShape( QPainter & p );
};


/**
@author David Saxton
*/
00531 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
*/
00556 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

Generated by  Doxygen 1.6.0   Back to index