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