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