File indexing completed on 2024-04-28 03:51:20
0001 /*. 0002 SPDX-FileCopyrightText: 2007 Vladimir Kuznetsov <ks.vladimir@gmail.com> 0003 SPDX-FileCopyrightText: 2014 Inge Wallin <inge@lysator.liu.se> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #ifndef STEP_STEPGRAPHICSITEM_H 0009 #define STEP_STEPGRAPHICSITEM_H 0010 0011 //#include "worldscene.h" 0012 0013 #include <stepcore/vector.h> 0014 #include <QColor> 0015 #include <QGraphicsItem> 0016 #include <QPointer> 0017 #include <QRectF> 0018 0019 namespace StepCore { 0020 class Object; 0021 class Item; 0022 class MetaProperty; 0023 } 0024 class WorldModel; 0025 //class WorldScene; 0026 class QTimer; 0027 0028 ///////////////////////////////////////////////////////////////////////////////////////// 0029 0030 class OnHoverHandlerGraphicsItem; 0031 0032 /** \brief Base class for all the graphics items on the scene. 0033 * 0034 * This class provides interface for WorldScene and 0035 * some common functionality to simplify subclassing. 0036 */ 0037 class StepGraphicsItem : public QGraphicsItem 0038 { 0039 public: 0040 /** Flags describing movingState when 0041 * moving item with the mouse */ 0042 enum MovingState { Started, Moving, Finished }; 0043 0044 /** Constructs StepGraphicsItem */ 0045 StepGraphicsItem(StepCore::Item* item, WorldModel* worldModel, QGraphicsItem* parent = nullptr); 0046 0047 /** Get StepCore::Item which is represented by this graphicsItem */ 0048 StepCore::Item* item() const { return _item; } 0049 0050 /** Get item bounding rect. Default implementation returns 0051 * value set by setBoundingRect function */ 0052 QRectF boundingRect() const override { return _boundingRect; } 0053 0054 /** Set current bounding rect. Should be called by subclass. */ 0055 void setBoundingRect(const QRectF& rect) { _boundingRect = rect; } 0056 0057 /** Virtual function which is called when view scale is changed */ 0058 virtual void viewScaleChanged(); 0059 0060 /** Virtual function which is called when: 0061 * - item selection state changed 0062 * - item mouse hover state changed 0063 */ 0064 virtual void stateChanged(); 0065 0066 /** Virtual function which is called when something in StepCore::World was changed 0067 * \param dynamicOnly Indicated whether only dynamic variables was changed 0068 * \note Dynamic variables are variables that can change during simulation, 0069 * non-dynamic variables can change only by user action 0070 */ 0071 virtual void worldDataChanged(bool dynamicOnly); 0072 0073 /** Virtual function to paint the item. Default implementation 0074 * draws boundingRect() in grey color */ 0075 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; 0076 0077 /** Get item highlight state */ 0078 bool isItemHighlighted() { return _isHighlighted; } 0079 /** Set item highlight state */ 0080 void setItemHighlighted(bool highlighted) { 0081 _isHighlighted = highlighted; update(); 0082 } 0083 0084 /** Get selection state of the item. This function reflects selection state of 0085 * StepCore::Item and differs from QGraphicsItem::isSelected when selection state 0086 * of QGraphicsItem was not yet updated (for example in stateChanged() function) */ 0087 bool isItemSelected() { return _isSelected; } 0088 /** Return true if item is hovered by the mouse */ 0089 bool isMouseOverItem() { return _isMouseOverItem; } 0090 0091 /** Converts QPointF to StepCore::Vector2d */ 0092 static StepCore::Vector2d pointToVector(const QPointF& point) { 0093 return StepCore::Vector2d(point.x(), point.y()); 0094 } 0095 /** Converts StepCore::Vector2d to QPointF */ 0096 static QPointF vectorToPoint(const StepCore::Vector2d& vector) { 0097 return QPointF(vector[0], vector[1]); 0098 } 0099 0100 protected: 0101 /** Virtual function which is called when item is moved by the mouse. Default implementation 0102 * tries to set "position" property of _item */ 0103 virtual void mouseSetPos(const QPointF& pos, const QPointF& diff, MovingState movingState); 0104 0105 /** Returns current view scale of the scene */ 0106 double currentViewScale() const; 0107 0108 /** Returns highlighted copy of the color */ 0109 QColor highlightColor(const QColor& color); 0110 0111 ///* Draw handler item */ 0112 //void drawHandler(QPainter* painter, const StepCore::Vector2d& v); 0113 0114 /** Draw an arrow starting at r and ending at v */ 0115 void drawArrow(QPainter* painter, const StepCore::Vector2d& r, 0116 const StepCore::Vector2d& v); 0117 /** Draw an arrow starting at (0,0) and ending at v */ 0118 void drawArrow(QPainter* painter, const StepCore::Vector2d& v); 0119 0120 /** Draw circular arrow with the center at r and with given radius and angle */ 0121 void drawCircularArrow(QPainter* painter, const StepCore::Vector2d& r, 0122 double angle, double radius); 0123 /** Draw circular arrow with the center at (0,0) and with given radius and angle */ 0124 void drawCircularArrow(QPainter* painter, double angle, double radius); 0125 0126 /** Set to true if the item should be moved alone (without other selected items) */ 0127 void setExclusiveMoving(bool value) { _exclusiveMoving = value; } 0128 0129 /** Set custom test for undo command for moving item. Works only if exclusiveMoving is true */ 0130 void setExclusiveMovingMessage(const QString& message) { _exclusiveMovingMessage = message; } 0131 0132 /** Called when graphicsitem is changed */ 0133 QVariant itemChange(GraphicsItemChange change, const QVariant& value) override; 0134 0135 /** Get vertex handler enabled status */ 0136 bool isOnHoverHandlerEnabled() const { return _onHoverHandlerEnabled; } 0137 0138 /** Set to true in order to enable on-hover handler. 0139 * \note You should also call setAcceptHoverEvents(true) in order 0140 * for on-hover handler to work */ 0141 void setOnHoverHandlerEnabled(bool enabled); 0142 0143 /** Virtual function which is called to create on-hover handler for given point. 0144 * If the handler is the same as already-existing just return _onHoverHandler. 0145 * If no handler it required for given point just return NULL */ 0146 virtual OnHoverHandlerGraphicsItem* createOnHoverHandler(const QPointF&) { return nullptr; } 0147 0148 protected: 0149 StepCore::Item* _item; 0150 WorldModel* _worldModel; 0151 0152 QRectF _boundingRect; 0153 QString _exclusiveMovingMessage; 0154 bool _exclusiveMoving; 0155 bool _onHoverHandlerEnabled; 0156 0157 bool _isHighlighted; 0158 bool _isMouseOverItem; 0159 bool _isSelected; 0160 bool _isMoving; 0161 0162 QPointer<OnHoverHandlerGraphicsItem> _onHoverHandler; 0163 bool _onHoverHandlerTimer; 0164 0165 void mousePressEvent(QGraphicsSceneMouseEvent* event) override; 0166 void mouseMoveEvent(QGraphicsSceneMouseEvent* event) override; 0167 void mouseReleaseEvent(QGraphicsSceneMouseEvent* event) override; 0168 0169 void hoverEnterEvent(QGraphicsSceneHoverEvent* event) override; 0170 void hoverMoveEvent(QGraphicsSceneHoverEvent* event) override; 0171 void hoverLeaveEvent(QGraphicsSceneHoverEvent* event) override; 0172 0173 void contextMenuEvent(QGraphicsSceneContextMenuEvent* event) override; 0174 0175 protected: 0176 static const QColor SELECTION_COLOR; ///< Default color for selection rectangle 0177 static const int SELECTION_MARGIN = 4; ///< Default distance from object to selection rectangle 0178 static const int ARROW_STROKE = 6; ///< Default size of an arrow stroke 0179 static const int CIRCULAR_ARROW_STROKE = 6; ///< Default size of circular arrow stroke 0180 0181 static const int HANDLER_SIZE = 6; ///< Default size of the handler 0182 static const int HANDLER_SNAP_SIZE = 12; ///< Handler snapping radius 0183 0184 static const int ANGLE_HANDLER_RADIUS = 15; ///< Default radius of the angle handler for RigidBody 0185 static const int ANGULAR_VELOCITY_RADIUS = 30; ///< Default radius of the angularVelocity handler for RigidBody 0186 static const int ANGULAR_ACCELERATION_RADIUS = 34; ///< Default radius of the angularAcceleration handler 0187 0188 static const int REGION_ZVALUE = 100; ///< Default ZValue for regions 0189 static const int BODY_ZVALUE = 200; ///< Default ZValue for bodies 0190 static const int FORCE_ZVALUE = 300; ///< Default ZValue for forces 0191 static const int JOINT_ZVALUE = 400; ///< Default ZValue for joints 0192 static const int HANDLER_ZVALUE = 800; ///< Default ZValue for handlers 0193 0194 static const int COLOR_HIGHLIGHT_AMOUNT = 30; ///< Highlight amount (in percent for value component) 0195 }; 0196 0197 ///////////////////////////////////////////////////////////////////////////////////////// 0198 0199 /** \brief Handler item that controls vector property 0200 */ 0201 class ArrowHandlerGraphicsItem : public StepGraphicsItem 0202 { 0203 public: 0204 /** Construct ArrowHandlerGraphicsItem. 0205 * \param item StepCore::Item to control 0206 * \param worldModel associated worldModel 0207 * \param parent parent StepGraphicsItem 0208 * \param property Property to control 0209 * \param positionProperty Origin of the vector described by property or NULL 0210 */ 0211 ArrowHandlerGraphicsItem(StepCore::Item* item, WorldModel* worldModel, 0212 QGraphicsItem* parent, const StepCore::MetaProperty* property, 0213 const StepCore::MetaProperty* positionProperty = nullptr); 0214 0215 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; 0216 0217 void viewScaleChanged() override; 0218 void worldDataChanged(bool) override; 0219 0220 protected: 0221 /** Virtual function which is called to get current vector value. 0222 * Default implementation returns property + positionProperty */ 0223 virtual StepCore::Vector2d value(); 0224 /** Virtual function which is called to set current new vector value. 0225 * Default implementation sets property = value - positionProperty */ 0226 virtual void setValue(const StepCore::Vector2d& value); 0227 0228 void mouseSetPos(const QPointF& pos, const QPointF& diff, MovingState movingState) override; 0229 QVariant itemChange(GraphicsItemChange change, const QVariant& value) override; 0230 const StepCore::MetaProperty* _property; 0231 const StepCore::MetaProperty* _positionProperty; 0232 }; 0233 0234 ///////////////////////////////////////////////////////////////////////////////////////// 0235 0236 /** \brief Handler item that controls angle property 0237 */ 0238 class CircularArrowHandlerGraphicsItem : public StepGraphicsItem 0239 { 0240 public: 0241 /** Construct CircularArrowHandlerGraphicsItem. 0242 * \param item StepCore::Item to control 0243 * \param worldModel associated worldModel 0244 * \param parent parent StepGraphicsItem 0245 * \param radius radius of the arrow on the screen 0246 * \param property Property to control 0247 * \param positionProperty Position of the center of the circle 0248 */ 0249 CircularArrowHandlerGraphicsItem(StepCore::Item* item, WorldModel* worldModel, 0250 QGraphicsItem* parent, double radius, const StepCore::MetaProperty* property, 0251 const StepCore::MetaProperty* positionProperty = nullptr); 0252 0253 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; 0254 0255 void viewScaleChanged() override; 0256 void worldDataChanged(bool) override; 0257 0258 protected: 0259 /** Virtual function which is called to get current vector value. 0260 * Default implementation reads the value pointed by property */ 0261 virtual double value(); 0262 /** Virtual function which is called to set current new vector value. 0263 * Default implementation sets the value pointed by property */ 0264 virtual void setValue(double value); 0265 0266 QVariant itemChange(GraphicsItemChange change, const QVariant& value) override; 0267 void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; 0268 void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; 0269 const StepCore::MetaProperty* _property; 0270 const StepCore::MetaProperty* _positionProperty; 0271 double _radius; 0272 }; 0273 0274 ///////////////////////////////////////////////////////////////////////////////////////// 0275 0276 /** \brief Base class for handler that exists only on mouse hover */ 0277 class OnHoverHandlerGraphicsItem : public QObject, public ArrowHandlerGraphicsItem 0278 { 0279 Q_OBJECT 0280 0281 public: 0282 OnHoverHandlerGraphicsItem(StepCore::Item* item, WorldModel* worldModel, 0283 QGraphicsItem* parent, const StepCore::MetaProperty* property, 0284 const StepCore::MetaProperty* positionProperty = nullptr, 0285 int vertexNum = 0); 0286 0287 void setDeleteTimerEnabled(bool enabled); 0288 bool isDeleteTimerEnabled() const { return _deleteTimerEnabled; } 0289 0290 int vertexNum() const { return _vertexNum; } 0291 void setVertexNum(int vertexNum) { _vertexNum = vertexNum; } 0292 0293 static const StepCore::Vector2d corners[4]; 0294 static const StepCore::Vector2d scorners[4]; 0295 0296 protected: 0297 void hoverEnterEvent(QGraphicsSceneHoverEvent* event) override; 0298 void hoverLeaveEvent(QGraphicsSceneHoverEvent* event) override; 0299 0300 int _vertexNum; 0301 QTimer* _deleteTimer; 0302 bool _deleteTimerEnabled; 0303 }; 0304 0305 #endif 0306