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