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