File indexing completed on 2024-12-08 08:10:33
0001 /*************************************************************************** 0002 * Copyright (C) 2004-2005 by David Saxton * 0003 * david@bluehaze.org * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 ***************************************************************************/ 0010 0011 #ifndef MECHANICSITEM_H 0012 #define MECHANICSITEM_H 0013 0014 #include <QList> 0015 #include <item.h> 0016 0017 class LibraryItem; 0018 class MechanicsItem; 0019 // class MechanicsItemOverlayItem; 0020 class MechanicsDocument; 0021 typedef QList<MechanicsItem *> MechanicsItemList; 0022 0023 /** 0024 @short Stores mass, moment of inertia 0025 @author David Saxton 0026 */ 0027 class MechanicsInfo 0028 { 0029 public: 0030 MechanicsInfo(); 0031 0032 double mass; // Mass 0033 double momentOfInertia; // Moment of inertia 0034 }; 0035 0036 class CombinedMechanicsInfo : public MechanicsInfo 0037 { 0038 public: 0039 CombinedMechanicsInfo(); 0040 CombinedMechanicsInfo(const MechanicsInfo &info); 0041 0042 double x; // X coordinate of center of mass 0043 double y; // Y coordinate of center of mass 0044 }; 0045 0046 /** 0047 @short Stores a position and orientation 0048 @author David Saxton 0049 */ 0050 class PositionInfo 0051 { 0052 public: 0053 PositionInfo(); 0054 /** 0055 * Adds together two positions: for this=PARENT +(CHILD), the new position 0056 * is formed by translating this position by that of the CHILDs 0057 * translation, and then rotating everything about the center of this item 0058 */ 0059 const PositionInfo operator+(const PositionInfo &info); 0060 /** 0061 * Not quite the inverse of operator+. Subtracts the given position info 0062 * as if it was applied before this current info. 0063 */ 0064 const PositionInfo operator-(const PositionInfo &info); 0065 /** 0066 * x position (0 is left) 0067 */ 0068 double x() const 0069 { 0070 return m_x; 0071 } 0072 /** 0073 * y position (0 is top) 0074 */ 0075 double y() const 0076 { 0077 return m_y; 0078 } 0079 /** 0080 * Angle in radians, positive direction is anticlockwise 0081 */ 0082 double angle() const 0083 { 0084 return m_angle; 0085 } 0086 /** 0087 * Sets the x-position 0088 */ 0089 void setX(double x) 0090 { 0091 m_x = x; 0092 } 0093 /** 0094 * Sets the y-position 0095 */ 0096 void setY(double y) 0097 { 0098 m_y = y; 0099 } 0100 /** 0101 * Sets the angle 0102 */ 0103 void setAngle(double angle) 0104 { 0105 m_angle = angle; 0106 } 0107 /** 0108 * Adds (x,y) to the current position 0109 */ 0110 void translate(double dx, const double dy) 0111 { 0112 m_x += dx; 0113 m_y += dy; 0114 } 0115 /** 0116 * Rotates anticlockwise by the given amount (in radians) 0117 */ 0118 void rotate(double angle) 0119 { 0120 m_angle += angle; 0121 } 0122 /** 0123 * Resets the position to (0,0), and the orientation to 0 0124 */ 0125 void reset(); 0126 /** 0127 * Rotates the current position about the given point through the given 0128 * angle in radians anticlockwise. This will change the position and 0129 * orientation. 0130 */ 0131 void rotateAboutPoint(double x, double y, double angle); 0132 0133 protected: 0134 double m_x; 0135 double m_y; 0136 double m_angle; 0137 }; 0138 0139 /** 0140 @author David Saxton 0141 */ 0142 class MechanicsItem : public Item 0143 { 0144 Q_OBJECT 0145 public: 0146 MechanicsItem(MechanicsDocument *mechanicsDocument, bool newItem, const QString &id); 0147 ~MechanicsItem() override; 0148 0149 enum SelectionMode { sm_move, sm_resize, sm_rotate }; 0150 /** 0151 * Sets the selection mode (sm_resize or sm_rotate). Note that setSelected 0152 * also needs to be called to select the item. 0153 */ 0154 void setSelectionMode(SelectionMode sm); 0155 void setSelected(bool yes) override; 0156 /** 0157 * @returns the selection mode 0158 */ 0159 SelectionMode selectionMode() const 0160 { 0161 return m_selectionMode; 0162 } 0163 /** 0164 * Move the MechanicsItem by the given amount 0165 */ 0166 void moveBy(double dx, double dy) override; 0167 /** 0168 * Returns the absolute position on the canvas 0169 */ 0170 PositionInfo absolutePosition() const; 0171 /** 0172 * Returns the position relative to the parent item (or the absolute 0173 * position if there is no parent item) 0174 */ 0175 PositionInfo relativePosition() const 0176 { 0177 return m_relativePosition; 0178 } 0179 /** 0180 * Returns the mechanics info for this item (so not taking into account that 0181 * of attached children) 0182 */ 0183 MechanicsInfo *mechanicsInfo() 0184 { 0185 return &m_mechanicsInfo; 0186 } 0187 /** 0188 * Returns the combined mechanics info for this item (which takes into 0189 * account that of attached children). 0190 */ 0191 CombinedMechanicsInfo *mechanicsInfoCombined() 0192 { 0193 return &m_mechanicsInfoCombined; 0194 } 0195 /** 0196 * Returns the rectangle that can legitimately fit inside the given bounding 0197 * rectangle, given this items current rotation. Legitimately means that 0198 * whether this item is allowed to be distorted, inverted, resized, etc. 0199 */ 0200 QRect maxInnerRectangle(const QRect &outerRect) const; 0201 0202 ItemData itemData() const override; 0203 0204 bool mousePressEvent(const EventInfo &eventInfo) override; 0205 bool mouseReleaseEvent(const EventInfo &eventInfo) override; 0206 bool mouseDoubleClickEvent(const EventInfo &eventInfo) override; 0207 bool mouseMoveEvent(const EventInfo &eventInfo) override; 0208 bool wheelEvent(const EventInfo &eventInfo) override; 0209 void enterEvent(QEvent *) override; 0210 void leaveEvent(QEvent *) override; 0211 0212 public slots: 0213 /** 0214 * Rotate the item by the given amount (in radians) 0215 */ 0216 void rotateBy(double dtheta); 0217 void parentMoved(); 0218 0219 signals: 0220 /** 0221 * Emitted when this item moves (translates or rotates) 0222 */ 0223 void moved(); 0224 0225 protected slots: 0226 /** 0227 * Recalculate the combined mechanics info (e.g. when mass is changed, or child added) 0228 */ 0229 void updateMechanicsInfoCombined(); 0230 0231 protected: 0232 void reparented(Item *oldItem, Item *newItem) override; 0233 void childAdded(Item *child) override; 0234 void childRemoved(Item *child) override; 0235 /** 0236 * Called when this item is resized, so that sub classes can do whatever 0237 */ 0238 virtual void itemResized() {}; 0239 /** 0240 * Sets the correct orientation on the painter 0241 */ 0242 void initPainter(QPainter &p); 0243 /** 0244 * *Must* be called after calling initPainter, if initPainter was called 0245 */ 0246 void deinitPainter(QPainter &p); 0247 void dataChanged() override; 0248 void itemPointsChanged() override 0249 { 0250 updateCanvasPoints(); 0251 } 0252 /** 0253 * Calculates the setPoints required from the current m_itemPoints and the 0254 * current position / angle 0255 */ 0256 void updateCanvasPoints(); 0257 0258 MechanicsDocument *p_mechanicsDocument; 0259 PositionInfo m_relativePosition; // Absolution position if not attached to a parent item, or otherwise relative to parent item 0260 MechanicsInfo m_mechanicsInfo; 0261 CombinedMechanicsInfo m_mechanicsInfoCombined; 0262 0263 private: 0264 SelectionMode m_selectionMode; 0265 }; 0266 0267 #endif