File indexing completed on 2024-05-12 05:40:25
0001 /*************************************************************************** 0002 * Copyright (C) 2022 by Renaud Guezennec * 0003 * http://www.rolisteam.org/contact * 0004 * * 0005 * This software 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 * This program is distributed in the hope that it will be useful, * 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0013 * GNU General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU General Public License * 0016 * along with this program; if not, write to the * 0017 * Free Software Foundation, Inc., * 0018 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 0019 ***************************************************************************/ 0020 #include "positioneditem.h" 0021 0022 #include <QDebug> 0023 0024 #include "mindmap/data/linkcontroller.h" 0025 0026 namespace mindmap 0027 { 0028 constexpr int velocityMaxLimit{20}; 0029 PositionedItem::PositionedItem(Type type, QObject* parent) : MindItem(type, parent) 0030 { 0031 if(type == MindItem::NodeType) 0032 { 0033 setWidth(100); 0034 setHeight(20); 0035 } 0036 else if(type == MindItem::PackageType) 0037 { 0038 setWidth(100); 0039 setHeight(100); 0040 } 0041 // comment 0042 connect(this, &PositionedItem::visibleChanged, this, &PositionedItem::setLinkVisibility); 0043 } 0044 0045 QPointF PositionedItem::position() const 0046 { 0047 return m_position; 0048 } 0049 0050 QPointF PositionedItem::centerPoint() const 0051 { 0052 return boundingRect().center(); 0053 } 0054 0055 qreal PositionedItem::width() const 0056 { 0057 return m_w; 0058 } 0059 0060 qreal PositionedItem::height() const 0061 { 0062 return m_h; 0063 } 0064 0065 void PositionedItem::setWidth(qreal w) 0066 { 0067 if(qFuzzyCompare(w, m_w)) 0068 return; 0069 m_w= w; 0070 emit widthChanged(); 0071 } 0072 0073 void PositionedItem::setHeight(qreal h) 0074 { 0075 if(qFuzzyCompare(h, m_h)) 0076 return; 0077 m_h= h; 0078 emit heightChanged(); 0079 } 0080 0081 void PositionedItem::setDragged(bool isdragged) 0082 { 0083 if(m_isDragged == isdragged) 0084 return; 0085 m_isDragged= isdragged; 0086 emit isDraggedChanged(); 0087 } 0088 void PositionedItem::setOpen(bool op) 0089 { 0090 if(op == m_open) 0091 return; 0092 m_open= op; 0093 emit openChanged(); 0094 setLinkVisibility(); 0095 } 0096 void PositionedItem::setPosition(const QPointF& p) 0097 { 0098 if(m_position == p || p.x() < 0 || p.y() < 0) 0099 return; 0100 auto motion= m_position - p; 0101 m_position= p; 0102 emit positionChanged(m_position); 0103 if(isDragged()) 0104 emit itemDragged(motion); 0105 } 0106 0107 bool PositionedItem::isDragged() const 0108 { 0109 return m_isDragged; 0110 } 0111 0112 int PositionedItem::mass() const 0113 { 0114 return m_mass; 0115 } 0116 void PositionedItem::setMass(int m) 0117 { 0118 if(m_mass == m) 0119 return; 0120 m_mass= m; 0121 emit massChanged(); 0122 } 0123 0124 QRectF PositionedItem::boundingRect() const 0125 { 0126 return QRectF(m_position, QSizeF(m_w, m_h)); 0127 } 0128 0129 QVector2D PositionedItem::getVelocity() const 0130 { 0131 return m_velocity; 0132 } 0133 0134 void PositionedItem::setVelocity(const QVector2D& velocity) 0135 { 0136 if(qIsNaN(velocity.x()) && qIsNaN(velocity.y())) 0137 return; 0138 0139 if(velocity.x() > velocityMaxLimit) 0140 m_velocity.setX(velocityMaxLimit); 0141 0142 if(velocity.y() > velocityMaxLimit) 0143 m_velocity.setY(velocityMaxLimit); 0144 0145 if(velocity.y() < velocityMaxLimit && velocity.x() < velocityMaxLimit) 0146 m_velocity= velocity; 0147 } 0148 0149 QVector2D PositionedItem::getAcceleration() const 0150 { 0151 return m_acceleration; 0152 } 0153 0154 void PositionedItem::setAcceleration(const QVector2D& acceleration) 0155 { 0156 m_acceleration= acceleration; 0157 } 0158 0159 void PositionedItem::applyForce(const QVector2D& force) 0160 { 0161 m_acceleration+= force / m_mass; 0162 } 0163 0164 void PositionedItem::setNextPosition(const QPointF& pos, LinkController* emiter) 0165 { 0166 m_nextPositions.erase(emiter); 0167 m_nextPositions.insert(std::pair<LinkController*, QPointF>(emiter, pos)); 0168 updatePosition(); 0169 } 0170 void PositionedItem::addLink(LinkController* link) 0171 { 0172 auto h= hasLink(); 0173 m_subNodelinks.push_back(link); 0174 if(h != hasLink()) 0175 emit hasLinkChanged(); 0176 } 0177 void PositionedItem::updatePosition() 0178 { 0179 if(m_nextPositions.size() == 0) 0180 return; 0181 0182 if(m_nextPositions.size() == 1) 0183 setPosition(m_nextPositions.begin()->second); 0184 0185 qreal x= 0; 0186 qreal y= 0; 0187 for(auto it= m_nextPositions.begin(); it != m_nextPositions.end(); ++it) 0188 { 0189 x+= it->second.x(); 0190 y+= it->second.y(); 0191 } 0192 x/= m_nextPositions.size(); 0193 y/= m_nextPositions.size(); 0194 0195 setPosition(QPointF(x, y)); 0196 } 0197 0198 void PositionedItem::setParentNode(PositionedItem* parent) 0199 { 0200 m_parent= parent; 0201 } 0202 0203 PositionedItem* PositionedItem::parentNode() const 0204 { 0205 return m_parent; 0206 } 0207 0208 bool PositionedItem::hasLink() const 0209 { 0210 return !m_subNodelinks.empty(); 0211 } 0212 0213 bool PositionedItem::open() const 0214 { 0215 return m_open; 0216 } 0217 0218 QString PositionedItem::parentId() const 0219 { 0220 return parentNode() ? parentNode()->id() : QString(); 0221 } 0222 0223 const std::vector<QPointer<LinkController>>& PositionedItem::subLinks() const 0224 { 0225 return m_subNodelinks; 0226 } 0227 0228 int PositionedItem::subNodeCount(QSet<LinkController*>& alreadySeen) const 0229 { 0230 int sum= std::accumulate(m_subNodelinks.begin(), m_subNodelinks.end(), 0, 0231 [&alreadySeen](int& a, LinkController* link) 0232 { 0233 if(nullptr == link) 0234 return 0; 0235 auto end= link->end(); 0236 if(nullptr == end) 0237 return 0; 0238 0239 int res= 0; 0240 if(!alreadySeen.contains(link)) 0241 res= a + 1 + end->subNodeCount(alreadySeen); 0242 else 0243 res= a + end->subNodeCount(alreadySeen); 0244 0245 alreadySeen.insert(link); 0246 return res; 0247 }); 0248 return sum; 0249 } 0250 0251 void PositionedItem::removeLink(LinkController* link) 0252 { 0253 auto it= std::find(m_subNodelinks.begin(), m_subNodelinks.end(), link); 0254 0255 if(it == m_subNodelinks.end()) 0256 return; 0257 0258 m_subNodelinks.erase(it); 0259 } 0260 0261 void PositionedItem::setLinkVisibility() 0262 { 0263 bool visiblility= isVisible() & m_open; 0264 std::for_each(m_subNodelinks.begin(), m_subNodelinks.end(), 0265 [visiblility](LinkController* link) 0266 { 0267 if(nullptr == link) 0268 return; 0269 link->setVisible(visiblility); 0270 }); 0271 } 0272 0273 void PositionedItem::translate(const QPointF& motion) 0274 { 0275 setPosition(m_position + motion); 0276 } 0277 0278 bool PositionedItem::isLocked() const 0279 { 0280 return m_locked; 0281 } 0282 0283 void PositionedItem::setLocked(bool newLocked) 0284 { 0285 if(m_locked == newLocked) 0286 return; 0287 m_locked= newLocked; 0288 emit lockedChanged(); 0289 } 0290 } // namespace mindmap