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 canvasmode_editspiral.cpp - description
17 -------------------
18 begin : Wed Jan 27 2011
19 copyright : (C) 2011 by Franz Schmid
20 email : Franz.Schmid@altmuehlnet.de
21 ***************************************************************************/
22
23
24 #include "canvasmode_editspiral.h"
25
26 #include <QApplication>
27 #include <QCursor>
28 #include <QEvent>
29 #include <QMouseEvent>
30 #include <QPainterPath>
31 #include <QPoint>
32 #include <QRect>
33 #include <QTimer>
34 #include <QWidgetAction>
35
36 #include "appmodes.h"
37 #include "canvas.h"
38 #include "fpoint.h"
39 #include "pageitem_spiral.h"
40 #include "scribus.h"
41 #include "scribusdoc.h"
42 #include "scribusview.h"
43 #include "selection.h"
44 #include "ui/propertiespalette.h"
45 #include "undomanager.h"
46 #include "util.h"
47 #include "util_math.h"
48
49
CanvasMode_EditSpiral(ScribusView * view)50 CanvasMode_EditSpiral::CanvasMode_EditSpiral(ScribusView* view) : CanvasMode(view), m_ScMW(view->m_ScMW)
51 {
52 }
53
GetItem(PageItem ** pi)54 inline bool CanvasMode_EditSpiral::GetItem(PageItem** pi)
55 {
56 *pi = m_doc->m_Selection->itemAt(0);
57 return (*pi) != nullptr;
58 }
59
drawControls(QPainter * p)60 void CanvasMode_EditSpiral::drawControls(QPainter* p)
61 {
62 p->save();
63 if (m_canvas->m_viewMode.operItemMoving)
64 {
65 drawOutline(p);
66 }
67 else
68 {
69 drawSelection(p, false);
70 }
71 if (m_doc->appMode == modeEditSpiral)
72 {
73 drawControlsSpiral(p, m_doc->m_Selection->itemAt(0));
74 }
75 p->restore();
76 }
77
drawControlsSpiral(QPainter * psx,PageItem * currItem)78 void CanvasMode_EditSpiral::drawControlsSpiral(QPainter* psx, PageItem* currItem)
79 {
80 QPen p8b = QPen(Qt::blue, 8.0 / m_canvas->m_viewMode.scale, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin);
81 QPen p8r = QPen(Qt::red, 8.0 / m_canvas->m_viewMode.scale, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin);
82 psx->setTransform(currItem->getTransform(), true);
83 psx->setBrush(Qt::NoBrush);
84 psx->setPen(p8b);
85 if (m_arcPoint == useControlStart)
86 psx->setPen(p8r);
87 else
88 psx->setPen(p8b);
89 psx->drawPoint(m_startPoint);
90 if (m_arcPoint == useControlEnd)
91 psx->setPen(p8r);
92 else
93 psx->setPen(p8b);
94 psx->drawPoint(m_endPoint);
95 }
96
enterEvent(QEvent * e)97 void CanvasMode_EditSpiral::enterEvent(QEvent *e)
98 {
99 if (!m_canvas->m_viewMode.m_MouseButtonPressed)
100 {
101 setModeCursor();
102 }
103 }
104
leaveEvent(QEvent * e)105 void CanvasMode_EditSpiral::leaveEvent(QEvent *e)
106 {
107 }
108
109
activate(bool fromGesture)110 void CanvasMode_EditSpiral::activate(bool fromGesture)
111 {
112 CanvasMode::activate(fromGesture);
113
114 m_VectorDialog = new SpiralVectorDialog(m_ScMW);
115 m_canvas->m_viewMode.m_MouseButtonPressed = false;
116 m_canvas->resetRenderMode();
117 m_doc->DragP = false;
118 m_doc->leaveDrag = false;
119 m_canvas->m_viewMode.operItemMoving = false;
120 m_canvas->m_viewMode.operItemResizing = false;
121 m_view->MidButt = false;
122 m_Mxp = m_Myp = -1;
123 PageItem *currItem = m_doc->m_Selection->itemAt(0);
124 PageItem_Spiral* item = currItem->asSpiral();
125 m_startPoint = currItem->PoLine.pointQF(0);
126 m_endPoint = currItem->PoLine.pointQF(currItem->PoLine.size() - 2);
127 m_startAngle = item->spiralStartAngle;
128 m_endAngle = item->spiralEndAngle;
129 m_VectorDialog->setValues(computeRealAngle(m_startAngle, false), computeRealAngle(m_endAngle, false), item->spiralFactor);
130 m_VectorDialog->show();
131 setModeCursor();
132 if (fromGesture)
133 {
134 m_view->update();
135 }
136 connect(m_VectorDialog, SIGNAL(NewVectors(double, double, double)), this, SLOT(applyValues(double, double, double)));
137 connect(m_VectorDialog, SIGNAL(endEdit()), this, SLOT(endEditing()));
138 connect(m_VectorDialog, SIGNAL(paletteShown(bool)), this, SLOT(endEditing(bool)));
139 connect(m_doc, SIGNAL(docChanged()), this, SLOT(updateFromItem()));
140 }
141
deactivate(bool forGesture)142 void CanvasMode_EditSpiral::deactivate(bool forGesture)
143 {
144 disconnect(m_VectorDialog, SIGNAL(paletteShown(bool)), this, SLOT(endEditing(bool)));
145 m_VectorDialog->close();
146 m_VectorDialog->deleteLater();
147 m_view->setRedrawMarkerShown(false);
148 m_arcPoint = noPointDefined;
149 disconnect(m_doc, SIGNAL(docChanged()), this, SLOT(updateFromItem()));
150
151 CanvasMode::deactivate(forGesture);
152 }
153
updateFromItem()154 void CanvasMode_EditSpiral::updateFromItem()
155 {
156 if (updateFromItemBlocked())
157 return;
158 PageItem *currItem = m_doc->m_Selection->itemAt(0);
159 PageItem_Spiral* item = currItem->asSpiral();
160 m_startPoint = currItem->PoLine.pointQF(0);
161 m_endPoint = currItem->PoLine.pointQF(currItem->PoLine.size() - 2);
162 m_startAngle = item->spiralStartAngle;
163 m_endAngle = item->spiralEndAngle;
164 m_VectorDialog->setValues(computeRealAngle(m_startAngle, false), computeRealAngle(m_endAngle, false), item->spiralFactor);
165 m_view->update();
166 }
167
endEditing(bool active)168 void CanvasMode_EditSpiral::endEditing(bool active)
169 {
170 if (!active)
171 endEditing();
172 }
173
endEditing()174 void CanvasMode_EditSpiral::endEditing()
175 {
176 m_view->requestMode(modeNormal);
177 }
178
getSegment(double angle)179 QPointF CanvasMode_EditSpiral::getSegment(double angle)
180 {
181 PageItem *currItem = m_doc->m_Selection->itemAt(0);
182 PageItem_Spiral *item = currItem->asSpiral();
183 double ww = item->width();
184 double wws = 0.0;
185 double wwn = ww;
186 double hh = item->height() - (item->height() / (item->spiralFactor + 1.0));
187 double segStart = 0.0;
188 double segEnd = 180;
189 bool segPart = true;
190 QPointF ret = QPointF(item->width() / 2.0, item->height() / 2.0);
191 if (angle < 0)
192 return ret;
193 while (true)
194 {
195 QLineF lin = QLineF(QPointF(wws, hh), QPointF(wwn, hh));
196 if ((angle <= segEnd) && (angle >= segStart))
197 {
198 ret = lin.pointAt(0.5);
199 break;
200 }
201 ww /= item->spiralFactor;
202 wws = wwn;
203 if (segPart)
204 wwn -= ww;
205 else
206 wwn += ww;
207 segPart = !segPart;
208 segStart += 180.0;
209 segEnd += 180.0;
210 }
211 return ret;
212 }
213
computeRealAngle(double angle,bool fromDia)214 double CanvasMode_EditSpiral::computeRealAngle(double angle, bool fromDia)
215 {
216 PageItem *currItem = m_doc->m_Selection->itemAt(0);
217 double ret = angle;
218 int rev = static_cast<int>(angle / 360.0);
219 double part = angle - (rev * 360);
220 QTransform bb;
221 bb.scale(currItem->width() / currItem->height(), 1.0);
222 QLineF inp = QLineF(QPointF(currItem->width() / 2.0, currItem->height() / 2.0), QPointF(currItem->width(), currItem->height() / 2.0));
223 inp.setAngle(part);
224 if (fromDia)
225 {
226 QLineF res = bb.map(inp);
227 ret = res.angle();
228 }
229 else
230 {
231 QTransform bt = bb.inverted();
232 QLineF res = bt.map(inp);
233 ret = res.angle();
234 }
235 ret += rev * 360;
236 return ret;
237 }
238
applyValues(double start,double end,double factor)239 void CanvasMode_EditSpiral::applyValues(double start, double end, double factor)
240 {
241 PageItem *currItem = m_doc->m_Selection->itemAt(0);
242 PageItem_Spiral *item = currItem->asSpiral();
243 SimpleState *ss = new SimpleState(Um::EditSpiral, "", Um::IPolygon);
244 ss->set("SPIRAL");
245 ss->set("OLD_START",item->spiralStartAngle);
246 ss->set("OLD_END",item->spiralEndAngle);
247 ss->set("OLD_FACTOR",item->spiralFactor);
248 item->spiralStartAngle = computeRealAngle(start, true);
249 item->spiralEndAngle = computeRealAngle(end, true);
250 item->spiralFactor = factor;
251 ss->set("NEW_START",item->spiralStartAngle);
252 ss->set("NEW_END",item->spiralEndAngle);
253 ss->set("NEW_FACTOR",item->spiralFactor);
254 undoManager->action(item,ss);
255 item->recalcPath();
256 m_startPoint = currItem->PoLine.pointQF(0);
257 m_endPoint = currItem->PoLine.pointQF(currItem->PoLine.size() - 2);
258 m_startAngle = item->spiralStartAngle;
259 m_endAngle = item->spiralEndAngle;
260 QTransform itemMatrix = currItem->getTransform();
261 m_doc->regionsChanged()->update(itemMatrix.mapRect(QRectF(0, 0, currItem->width(), currItem->height())).adjusted(-5, -5, 10, 10));
262 }
263
keyPressEvent(QKeyEvent * e)264 void CanvasMode_EditSpiral::keyPressEvent(QKeyEvent *e)
265 {
266 commonkeyPressEvent_Default(e);
267 }
268
keyReleaseEvent(QKeyEvent * e)269 void CanvasMode_EditSpiral::keyReleaseEvent(QKeyEvent *e)
270 {
271 commonkeyReleaseEvent(e);
272 }
273
mouseDoubleClickEvent(QMouseEvent * m)274 void CanvasMode_EditSpiral::mouseDoubleClickEvent(QMouseEvent *m)
275 {
276 m->accept();
277 m_canvas->m_viewMode.m_MouseButtonPressed = false;
278 m_canvas->resetRenderMode();
279 m_view->requestMode(modeNormal);
280 }
281
mouseMoveEvent(QMouseEvent * m)282 void CanvasMode_EditSpiral::mouseMoveEvent(QMouseEvent *m)
283 {
284 const FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
285 m->accept();
286 double newX = mousePointDoc.x();
287 double newY = mousePointDoc.y();
288 if (m_canvas->m_viewMode.m_MouseButtonPressed && m_view->moveTimerElapsed() && (m_arcPoint != noPointDefined))
289 {
290 PageItem *currItem = m_doc->m_Selection->itemAt(0);
291 QTransform itemMatrix = currItem->getTransform();
292 PageItem_Spiral *item = currItem->asSpiral();
293 QPointF sPoint;
294 if (m_arcPoint == useControlStart)
295 sPoint = getSegment(m_startAngle);
296 else if (m_arcPoint == useControlEnd)
297 sPoint = getSegment(m_endAngle);
298 QPointF smPoint = itemMatrix.map(sPoint);
299 QLineF stLinA = QLineF(smPoint, QPointF(m_Mxp, m_Myp));
300 QLineF stLinM = QLineF(smPoint, QPointF(newX, newY));
301 double deltaAngle = stLinM.angle() - stLinA.angle();
302 if (deltaAngle < -180)
303 deltaAngle = deltaAngle + 360;
304 else if (deltaAngle > 180)
305 deltaAngle = deltaAngle - 360;
306 if (currItem->imageFlippedV())
307 deltaAngle *= -1.0;
308 if (currItem->imageFlippedH())
309 deltaAngle *= -1.0;
310 if (m_arcPoint == useControlStart)
311 {
312 if (m_startAngle + deltaAngle >= 0)
313 {
314 m_startAngle += deltaAngle;
315 applyValues(m_startAngle,m_endAngle,item->spiralFactor);
316 item->recalcPath();
317 m_startPoint = currItem->PoLine.pointQF(0);
318 m_canvas->displayRealRotHUD(m->globalPos(), m_startAngle);
319 }
320 m_VectorDialog->setValues(computeRealAngle(m_startAngle, false), computeRealAngle(m_endAngle, false), item->spiralFactor);
321 }
322 else if (m_arcPoint == useControlEnd)
323 {
324 if (m_endAngle + deltaAngle > m_startAngle)
325 {
326 m_endAngle += deltaAngle;
327 applyValues(m_startAngle,m_endAngle,item->spiralFactor);
328 item->recalcPath();
329 m_endPoint = currItem->PoLine.pointQF(currItem->PoLine.size() - 2);
330 m_canvas->displayRealRotHUD(m->globalPos(), m_endAngle);
331 }
332 m_VectorDialog->setValues(computeRealAngle(m_startAngle, false), computeRealAngle(m_endAngle, false), item->spiralFactor);
333 }
334 currItem->update();
335 m_doc->regionsChanged()->update(itemMatrix.mapRect(QRectF(0, 0, currItem->width(), currItem->height())).adjusted(-5, -5, 10, 10));
336 }
337 m_Mxp = newX;
338 m_Myp = newY;
339 }
340
mousePressEvent(QMouseEvent * m)341 void CanvasMode_EditSpiral::mousePressEvent(QMouseEvent *m)
342 {
343 const FPoint mousePointDoc = m_canvas->globalToCanvas(m->globalPos());
344 m_canvas->PaintSizeRect(QRect());
345 m_canvas->m_viewMode.m_MouseButtonPressed = true;
346 m_canvas->m_viewMode.operItemMoving = false;
347 m_view->HaveSelRect = false;
348 m_doc->DragP = false;
349 m_doc->leaveDrag = false;
350 m->accept();
351 m_view->registerMousePress(m->globalPos());
352 m_Mxp = mousePointDoc.x(); //m->x();
353 m_Myp = mousePointDoc.y(); //m->y();
354 if (m->button() == Qt::MidButton)
355 {
356 m_view->MidButt = true;
357 if (m->modifiers() & Qt::ControlModifier)
358 m_view->DrawNew();
359 return;
360 }
361 PageItem *currItem = m_doc->m_Selection->itemAt(0);
362 QTransform itemMatrix = currItem->getTransform();
363 QPointF stPoint = m_startPoint;
364 stPoint = itemMatrix.map(stPoint);
365 QPointF swPoint = m_endPoint;
366 swPoint = itemMatrix.map(swPoint);
367 if (m_canvas->hitsCanvasPoint(m->globalPos(), stPoint))
368 m_arcPoint = useControlStart;
369 else if (m_canvas->hitsCanvasPoint(m->globalPos(), swPoint))
370 m_arcPoint = useControlEnd;
371 else
372 m_arcPoint = noPointDefined;
373 if (m_arcPoint != noPointDefined)
374 m_transaction = undoManager->beginTransaction(Um::Polygon, Um::IPolygon, Um::EditSpiral, "", Um::IPolygon);
375 m_canvas->m_viewMode.m_MouseButtonPressed = true;
376 m_view->setCursor(QCursor(Qt::CrossCursor));
377 m_doc->regionsChanged()->update(itemMatrix.mapRect(QRectF(0, 0, currItem->width(), currItem->height())).adjusted(-5, -5, 10, 10));
378 }
379
mouseReleaseEvent(QMouseEvent * m)380 void CanvasMode_EditSpiral::mouseReleaseEvent(QMouseEvent *m)
381 {
382 m_canvas->m_viewMode.m_MouseButtonPressed = false;
383 m_canvas->resetRenderMode();
384 m->accept();
385 PageItem *currItem = m_doc->m_Selection->itemAt(0);
386 if (m_transaction)
387 {
388 m_transaction.commit();
389 m_transaction.reset();
390 }
391 QTransform itemMatrix = currItem->getTransform();
392 m_doc->regionsChanged()->update(itemMatrix.mapRect(QRectF(0, 0, currItem->width(), currItem->height())).adjusted(-5, -5, 10, 10));
393 }
394