]> Shamusworld >> Repos - architektonas/blob - src/actions/actiondrawarc.cpp
GPL compliance check...
[architektonas] / src / actions / actiondrawarc.cpp
1 // actiondrawarc.cpp
2 //
3 // Part of the Architektonas Project
4 // Originally part of QCad Community Edition by Andrew Mustun
5 // Extensively rewritten and refactored by James L. Hammons
6 // Portions copyright (C) 2001-2003 RibbonSoft
7 // Copyright (C) 2010 Underground Software
8 // See the README and GPLv2 files for licensing and warranty information
9 //
10 // JLH = James L. Hammons <jlhamm@acm.org>
11 //
12 // Who  When        What
13 // ---  ----------  -----------------------------------------------------------
14 // JLH  06/03/2010  Added this text. :-)
15 //
16
17 #include "actiondrawarc.h"
18
19 #include "rs_commandevent.h"
20 #include "commands.h"
21 #include "rs_dialogfactory.h"
22 #include "graphicview.h"
23 #include "rs_preview.h"
24
25 ActionDrawArc::ActionDrawArc(RS_EntityContainer & container, GraphicView & graphicView):
26         ActionInterface("Draw arcs", container, graphicView)
27 {
28         reset();
29 }
30
31 ActionDrawArc::~ActionDrawArc()
32 {
33 }
34
35 RS2::ActionType ActionDrawArc::rtti()
36 {
37         return RS2::ActionDrawArc;
38 }
39
40 void ActionDrawArc::reset()
41 {
42         if (data.reversed)
43                 data = RS_ArcData(Vector(false), 0.0, 2 * M_PI, 0.0, true);
44         else
45                 data = RS_ArcData(Vector(false), 0.0, 0.0, 2 * M_PI, false);
46 }
47
48 void ActionDrawArc::init(int status)
49 {
50         ActionInterface::init(status);
51         reset();
52 }
53
54 void ActionDrawArc::trigger()
55 {
56         ActionInterface::trigger();
57
58         RS_Arc * arc = new RS_Arc(container, data);
59         arc->setLayerToActive();
60         arc->setPenToActive();
61         container->addEntity(arc);
62
63         // upd. undo list:
64         if (document != NULL)
65         {
66                 document->startUndoCycle();
67                 document->addUndoable(arc);
68                 document->endUndoCycle();
69         }
70
71         deleteSnapper();
72         graphicView->moveRelativeZero(Vector(0.0, 0.0));
73         graphicView->drawEntity(arc);
74         graphicView->moveRelativeZero(arc->getCenter());
75         drawSnapper();
76
77         setStatus(SetCenter);
78         reset();
79
80         RS_DEBUG->print("ActionDrawArc::trigger(): arc added: %d", arc->getId());
81 }
82
83 void ActionDrawArc::mouseMoveEvent(QMouseEvent * e)
84 {
85         RS_DEBUG->print("ActionDrawArc::mouseMoveEvent begin");
86         Vector mouse = snapPoint(e);
87
88         switch (getStatus())
89         {
90         case SetCenter:
91                 data.center = mouse;
92                 break;
93
94         case SetRadius:
95
96                 if (data.center.valid)
97                 {
98                         data.radius = data.center.distanceTo(mouse);
99                         deletePreview();
100                         clearPreview();
101 //                      preview->addEntity(new RS_Circle(preview, RS_CircleData(data.center, data.radius)));
102                         drawPreview();
103                 }
104                 break;
105
106         case SetAngle1:
107                 data.angle1 = data.center.angleTo(mouse);
108
109                 if (data.reversed)
110                         data.angle2 = RS_Math::correctAngle(data.angle1 - M_PI / 3);
111                 else
112                         data.angle2 = RS_Math::correctAngle(data.angle1 + M_PI / 3);
113
114                 deletePreview();
115                 clearPreview();
116 //              preview->addEntity(new RS_Arc(preview, data));
117                 drawPreview();
118                 break;
119
120         case SetAngle2:
121                 data.angle2 = data.center.angleTo(mouse);
122                 deletePreview();
123                 clearPreview();
124 //              preview->addEntity(new RS_Arc(preview, data));
125                 drawPreview();
126                 break;
127
128         case SetIncAngle:
129                 data.angle2 = data.angle1 + data.center.angleTo(mouse);
130                 deletePreview();
131                 clearPreview();
132 //              preview->addEntity(new RS_Arc(preview, data));
133                 drawPreview();
134                 break;
135
136         case SetChordLength:
137         {
138                 double x = data.center.distanceTo(mouse);
139
140                 if (fabs(x / (2 * data.radius)) <= 1.0)
141                 {
142                         data.angle2 = data.angle1 + asin(x / (2 * data.radius)) * 2;
143                         deletePreview();
144                         clearPreview();
145 //                      preview->addEntity(new RS_Arc(preview, data));
146                         drawPreview();
147                 }
148         }
149         break;
150
151         default:
152                 break;
153         }
154
155         RS_DEBUG->print("ActionDrawArc::mouseMoveEvent end");
156 }
157
158 void ActionDrawArc::mouseReleaseEvent(QMouseEvent * e)
159 {
160         if (e->button() == Qt::LeftButton)
161         {
162                 Vector ce(snapPoint(e));
163                 coordinateEvent(&ce);
164         }
165         else if (e->button() == Qt::RightButton)
166         {
167                 deletePreview();
168                 deleteSnapper();
169                 init(getStatus() - 1);
170         }
171 }
172
173 void ActionDrawArc::coordinateEvent(Vector * e)
174 {
175         if (e == NULL)
176                 return;
177
178         Vector mouse = *e;
179
180         switch (getStatus())
181         {
182         case SetCenter:
183                 data.center = mouse;
184                 graphicView->moveRelativeZero(mouse);
185                 //deleteSnapper();
186                 setStatus(SetRadius);
187                 break;
188
189         case SetRadius:
190
191                 if (data.center.valid)
192                         data.radius = data.center.distanceTo(mouse);
193
194                 setStatus(SetAngle1);
195                 break;
196
197         case SetAngle1:
198                 data.angle1 = data.center.angleTo(mouse);
199                 setStatus(SetAngle2);
200                 break;
201
202         case SetAngle2:
203                 data.angle2 = data.center.angleTo(mouse);
204                 trigger();
205                 break;
206
207         case SetIncAngle:
208                 data.angle2 = data.angle1 + data.center.angleTo(mouse);
209                 trigger();
210                 break;
211
212         case SetChordLength:
213         {
214                 double x = data.center.distanceTo(mouse);
215
216                 if (fabs(x / (2 * data.radius)) <= 1.0)
217                 {
218                         data.angle2 = data.angle1 + asin(x / (2 * data.radius)) * 2;
219                         trigger();
220                 }
221         }
222         break;
223
224         default:
225                 break;
226         }
227 }
228
229 void ActionDrawArc::commandEvent(RS_CommandEvent * e)
230 {
231         QString c = e->getCommand().toLower();
232
233         if (RS_COMMANDS->checkCommand("help", c))
234         {
235                 if (RS_DIALOGFACTORY != NULL)
236                         RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
237                                 + getAvailableCommands().join(", "));
238                 return;
239         }
240
241         if (RS_COMMANDS->checkCommand("reversed", c))
242         {
243                 e->accept();
244                 setReversed(!isReversed());
245
246                 if (RS_DIALOGFACTORY != NULL)
247                         RS_DIALOGFACTORY->requestOptions(this, true, true);
248                 return;
249         }
250
251         switch (getStatus())
252         {
253         case SetRadius: {
254                 bool ok;
255                 double r = RS_Math::eval(c, &ok);
256
257                 if (ok == true)
258                 {
259                         data.radius = r;
260                         setStatus(SetAngle1);
261                 }
262                 else if (RS_DIALOGFACTORY != NULL)
263                         RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
264
265         }
266         break;
267
268         case SetAngle1: {
269                 bool ok;
270                 double a = RS_Math::eval(c, &ok);
271
272                 if (ok == true)
273                 {
274                         data.angle1 = RS_Math::deg2rad(a);
275                         setStatus(SetAngle2);
276                 }
277                 else if (RS_DIALOGFACTORY != NULL)
278                         RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
279
280         }
281         break;
282
283         case SetAngle2:
284
285                 if (RS_COMMANDS->checkCommand("angle", c))
286                         setStatus(SetIncAngle);
287                 else if (RS_COMMANDS->checkCommand("chord length", c))
288                         setStatus(SetChordLength);
289                 else
290                 {
291                         bool ok;
292                         double a = RS_Math::eval(c, &ok);
293
294                         if (ok == true)
295                         {
296                                 data.angle2 = RS_Math::deg2rad(a);
297                                 trigger();
298                         }
299                         else if (RS_DIALOGFACTORY != NULL)
300                                 RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
301
302                 }
303                 break;
304
305         case SetIncAngle: {
306                 bool ok;
307                 double a = RS_Math::eval(c, &ok);
308
309                 if (ok == true)
310                 {
311                         data.angle2 = data.angle1 + RS_Math::deg2rad(a);
312                         trigger();
313                 }
314                 else if (RS_DIALOGFACTORY != NULL)
315                         RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
316
317         }
318         break;
319
320         case SetChordLength: {
321                 bool ok;
322                 double l = RS_Math::eval(c, &ok);
323
324                 if (ok == true)
325                 {
326                         if (fabs(l / (2 * data.radius)) <= 1.0)
327                         {
328                                 data.angle2 = data.angle1 + asin(l / (2 * data.radius)) * 2;
329                                 trigger();
330                         }
331                         else if (RS_DIALOGFACTORY != NULL)
332                                 RS_DIALOGFACTORY->commandMessage(
333                                         tr("Not a valid chord length"));
334
335                 }
336                 else if (RS_DIALOGFACTORY != NULL)
337                         RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
338
339         }
340         break;
341
342         default:
343                 break;
344         }
345 }
346
347 QStringList ActionDrawArc::getAvailableCommands()
348 {
349         QStringList cmd;
350         cmd += RS_COMMANDS->command("reversed");
351         return cmd;
352 }
353
354 void ActionDrawArc::updateMouseButtonHints()
355 {
356         if (RS_DIALOGFACTORY != NULL)
357         {
358                 switch (getStatus())
359                 {
360                 case SetCenter:
361                         RS_DIALOGFACTORY->updateMouseWidget(tr("Specify center"), tr("Cancel"));
362                         break;
363
364                 case SetRadius:
365                         RS_DIALOGFACTORY->updateMouseWidget(tr("Specify radius"), tr("Back"));
366                         break;
367
368                 case SetAngle1:
369                         RS_DIALOGFACTORY->updateMouseWidget(
370                                 tr("Specify start angle:"), tr("Back"));
371                         break;
372
373                 case SetAngle2:
374                         RS_DIALOGFACTORY->updateMouseWidget(
375                                 tr("Specify end angle or [Angle/chord Length]"),
376                                 tr("Back"));
377                         break;
378
379                 case SetIncAngle:
380                         RS_DIALOGFACTORY->updateMouseWidget(tr("Specify included angle:"),
381                                 tr("Back"));
382                         break;
383
384                 case SetChordLength:
385                         RS_DIALOGFACTORY->updateMouseWidget(tr("Specify chord length:"),
386                                 tr("Back"));
387                         break;
388
389                 default:
390                         RS_DIALOGFACTORY->updateMouseWidget("", "");
391                         break;
392                 }
393         }
394 }
395
396 void ActionDrawArc::showOptions()
397 {
398         ActionInterface::showOptions();
399
400         if (RS_DIALOGFACTORY)
401                 RS_DIALOGFACTORY->requestOptions(this, true);
402 }
403
404 void ActionDrawArc::hideOptions()
405 {
406         ActionInterface::hideOptions();
407
408         if (RS_DIALOGFACTORY)
409                 RS_DIALOGFACTORY->requestOptions(this, false);
410 }
411
412 void ActionDrawArc::updateMouseCursor()
413 {
414         graphicView->setMouseCursor(RS2::CadCursor);
415 }
416
417 void ActionDrawArc::updateToolBar()
418 {
419         if (!RS_DIALOGFACTORY)
420                 return;
421
422         if (!isFinished())
423                 RS_DIALOGFACTORY->requestToolBar(RS2::ToolBarSnap);
424         else
425                 RS_DIALOGFACTORY->requestToolBar(RS2::ToolBarArcs);
426 }
427
428 bool ActionDrawArc::isReversed()
429 {
430         return data.reversed;
431 }
432
433 void ActionDrawArc::setReversed(bool r)
434 {
435         data.reversed = r;
436 }