1 /*
2 For general Scribus (>=1.3.2) copyright and licensing information please refer
3 to the COPYING file provided with the program. Following this notice may exist
4 a copyright and/or license notice that predates the release of Scribus 1.3.2
5 for which a new license (GPL+exception) is in place.
6 */
7 /***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16 #include "canvasgesture_linemove.h"
17
18 //#include <QDebug>
19 #include <QMouseEvent>
20 #include <QPainter>
21 #include <QPen>
22
23 #include "canvas.h"
24 #include "pageitem_line.h"
25 #include "scribusview.h"
26 #include "selection.h"
27 #include "undomanager.h"
28 #include "util_math.h"
29
clear()30 void LineMove::clear()
31 {
32 m_haveLineItem = false;
33 if (m_transaction.isStarted())
34 {
35 m_transaction.cancel();
36 m_transaction.reset();
37 }
38 }
39
40
prepare(QPointF start,QPointF end)41 void LineMove::prepare(QPointF start, QPointF end)
42 {
43 m_haveLineItem = false;
44 setStartPoint(start);
45 setStartPoint(end);
46 }
47
48
prepare(PageItem_Line * line,bool useOriginAsEndpoint)49 void LineMove::prepare(PageItem_Line* line, bool useOriginAsEndpoint)
50 {
51 m_haveLineItem = (line != nullptr);
52 if (!m_haveLineItem)
53 return;
54 m_useOriginAsEndpoint = useOriginAsEndpoint;
55 m_line = line;
56 setStartPoint(QPointF(m_line->xPos(), m_line->yPos()));
57 setEndPoint(QPointF(m_line->xPos() + m_line->width(), m_line->yPos()));
58 setRotation(m_line->rotation());
59 if (m_useOriginAsEndpoint)
60 {
61 QPointF tmp = startPoint();
62 setStartPoint(endPoint());
63 setEndPoint(tmp);
64 }
65 }
66
67
rotation() const68 double LineMove::rotation() const
69 {
70 double rot = xy2Deg(m_bounds.width(), m_bounds.height());
71 if (rot < 0.0)
72 return 360 + rot;
73 return rot;
74 }
75
76
setRotation(double rot)77 void LineMove::setRotation(double rot)
78 {
79 m_bounds.setSize(length() * QSizeF(cosd(rot), sind(rot)));
80 }
81
82
length() const83 double LineMove::length() const
84 {
85 return qMax(0.01, distance(m_bounds.width(), m_bounds.height()));
86 }
87
88
setStartPoint(QPointF p)89 void LineMove::setStartPoint(QPointF p)
90 {
91 m_bounds.setTopLeft(p);
92 }
93
94
setEndPoint(QPointF p)95 void LineMove::setEndPoint(QPointF p)
96 {
97 m_bounds.setBottomRight(p);
98 }
99
100
activate(bool forGesture)101 void LineMove::activate(bool forGesture)
102 {
103 CanvasGesture::activate(forGesture);
104 }
105
106
107
deactivate(bool forGesture)108 void LineMove::deactivate(bool forGesture)
109 {
110 // qDebug() << "LineMove::deactivate" << flag;
111 if (!forGesture)
112 clear();
113 CanvasGesture::deactivate(forGesture);
114 }
115
116
117
drawControls(QPainter * p)118 void LineMove::drawControls(QPainter* p)
119 {
120 p->save();
121 p->scale(m_canvas->scale(), m_canvas->scale());
122 p->translate(-m_doc->minCanvasCoordinate.x(), -m_doc->minCanvasCoordinate.y());
123 p->setBrush(Qt::NoBrush);
124 p->setPen(QPen(Qt::black, 1.0 / m_canvas->scale(), Qt::DotLine, Qt::FlatCap, Qt::MiterJoin));
125 p->drawLine(m_bounds.topLeft(), m_bounds.bottomRight());
126 p->restore();
127 }
128
mousePressEvent(QMouseEvent * m)129 void LineMove::mousePressEvent(QMouseEvent *m)
130 {
131 PageItem_Line* line = m_doc->m_Selection->count() == 1 ? m_doc->m_Selection->itemAt(0)->asLine() : nullptr;
132 if (line)
133 {
134 bool hitsOrigin = m_canvas->hitsCanvasPoint(m->globalPos(), line->xyPos());
135 prepare(line, hitsOrigin);
136 // now we also know the line's endpoint:
137 bool hitsEnd = m_canvas->hitsCanvasPoint(m->globalPos(), endPoint());
138 m_haveLineItem = hitsOrigin || hitsEnd;
139 }
140 else
141 {
142 FPoint point = m_canvas->globalToCanvas(m->globalPos());
143 setStartPoint(QPointF(point.x(), point.y()));
144 setEndPoint(QPointF(point.x(), point.y()));
145 m_haveLineItem = false;
146 }
147 if (m_haveLineItem)
148 {
149 if (!m_transaction)
150 {
151 QString targetName = line->getUName();
152 QPixmap* targetIcon = line->getUPixmap();
153 m_transaction = Um::instance()->beginTransaction(targetName, targetIcon, Um::Resize, "", Um::IResize);
154 }
155 adjustBounds(m, false);
156 m_initialBounds = m_bounds;
157 m->accept();
158 }
159 }
160
mouseMoveEvent(QMouseEvent * m)161 void LineMove::mouseMoveEvent(QMouseEvent *m)
162 {
163 adjustBounds(m);
164 if (m_haveLineItem)
165 {
166 doResize();
167 double angle = rotation();
168 if (angle > 0)
169 angle = 360 - angle;
170 m_canvas->displaySizeHUD(m->globalPos(), length(), fabs(angle), true);
171 }
172 m->accept();
173 m_canvas->repaint();
174 }
175
mouseReleaseEvent(QMouseEvent * m)176 void LineMove::mouseReleaseEvent(QMouseEvent *m)
177 {
178 adjustBounds(m);
179 if (m_haveLineItem)
180 {
181 if (m_bounds != m_initialBounds)
182 doResize();
183 m_doc->setRedrawBounding(m_line);
184 m_view->resetMousePressed();
185 m_line->checkChanges();
186 m_line->update();
187 }
188 if (m_transaction.isStarted())
189 {
190 m_transaction.commit();
191 m_transaction.reset();
192 }
193 m->accept();
194 m_canvas->update();
195 // qDebug() << "LineMove::mouseRelease" << m_line->xPos() << "," << m_line->yPos() << "@" << m_line->rotation() << m_line->width() << "x" << m_line->height();
196 m_view->stopGesture();
197 }
198
199
doResize()200 void LineMove::doResize()
201 {
202 if (m_useOriginAsEndpoint)
203 {
204 m_line->setXYPos(m_bounds.right(), m_bounds.bottom());
205 double rot = rotation();
206 m_line->setRotation(rot < 180? rot + 180 : rot - 180);
207 }
208 else
209 {
210 m_line->setXYPos(m_bounds.x(), m_bounds.y());
211 m_line->setRotation(rotation());
212 }
213 m_line->setWidth(length());
214 m_line->setHeight(1.0);
215 m_line->updateClip();
216 // qDebug() << "LineMove::doresize" << m_line->xPos() << "," << m_line->yPos() << "@" << m_line->rotation() << m_line->width() << "x" << m_line->height();
217 }
218
adjustBounds(QMouseEvent * m,bool updateCanvas)219 void LineMove::adjustBounds(QMouseEvent *m, bool updateCanvas)
220 {
221 FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
222 bool constrainRatio = ((m->modifiers() & Qt::ControlModifier) != Qt::NoModifier);
223
224 double newX = mousePointDoc.x();
225 double newY = mousePointDoc.y();
226
227 if (m_doc->SnapGrid)
228 {
229 newX = qRound(newX / m_doc->guidesPrefs().minorGridSpacing) * m_doc->guidesPrefs().minorGridSpacing;
230 newY = qRound(newY / m_doc->guidesPrefs().minorGridSpacing) * m_doc->guidesPrefs().minorGridSpacing;
231 }
232 //<<#8099
233 FPoint np2 = m_doc->ApplyGridF(FPoint(newX, newY));
234 double nx = np2.x();
235 double ny = np2.y();
236 m_doc->ApplyGuides(&nx, &ny);
237 m_doc->ApplyGuides(&nx, &ny,true);
238 newX = nx;
239 newY = ny;
240 //>>#8099
241
242 m_bounds.setBottomRight(QPointF(newX, newY));
243 //Constrain rotation angle, when the mouse is being dragged around for a new line
244 if (constrainRatio)
245 {
246 double newRot = rotation();
247 newRot = constrainAngle(newRot, m_doc->opToolPrefs().constrain);
248 setRotation(newRot);
249 }
250 if (updateCanvas)
251 {
252 m_view->updateCanvas(m_bounds.normalized().adjusted(-10, -10, 20, 20));
253 }
254 }
255