]> Shamusworld >> Repos - architektonas/blob - src/actions/actiondrawellipseaxis.cpp
Last checkin before major refactor...
[architektonas] / src / actions / actiondrawellipseaxis.cpp
1 // actiondrawellipseaxis.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  05/22/2010  Added this text. :-)
13 //
14
15 #include "actiondrawellipseaxis.h"
16
17 #include "rs_commandevent.h"
18 #include "rs_dialogfactory.h"
19 #include "graphicview.h"
20 #include "rs_preview.h"
21
22 /**
23  * Constructor.
24  *
25  * @param isArc true if this action will produce an ellipse arc.
26  *              false if it will produce a full ellipse.
27  */
28 ActionDrawEllipseAxis::ActionDrawEllipseAxis(RS_EntityContainer & container, GraphicView & graphicView, bool isArc): ActionInterface("Draw ellipse with axis",
29                 container, graphicView)
30 {
31         this->isArc = isArc;
32         center = Vector(false);
33         major = Vector(false);
34         ratio = 0.5;
35         angle1 = 0.0;
36         angle2 = 2 * M_PI;
37 }
38
39 ActionDrawEllipseAxis::~ActionDrawEllipseAxis()
40 {
41 }
42
43 void ActionDrawEllipseAxis::init(int status)
44 {
45         ActionInterface::init(status);
46
47         if (status == SetCenter)
48                 center = Vector(false);
49
50         if (status <= SetMajor)
51                 major = Vector(false);
52
53         if (status <= SetMinor)
54                 ratio = 0.5;
55
56         if (status <= SetAngle1)
57                 angle1 = 0.0;
58
59         if (status <= SetAngle2)
60                 angle2 = 2 * M_PI;
61 }
62
63 void ActionDrawEllipseAxis::trigger()
64 {
65         ActionInterface::trigger();
66
67         RS_EllipseData ellipseData(center, major, ratio, angle1, angle2, false);
68         RS_Ellipse * ellipse = new RS_Ellipse(container, ellipseData);
69         ellipse->setLayerToActive();
70         ellipse->setPenToActive();
71
72         container->addEntity(ellipse);
73
74         // upd. undo list:
75         if (document != NULL)
76         {
77                 document->startUndoCycle();
78                 document->addUndoable(ellipse);
79                 document->endUndoCycle();
80         }
81
82         deleteSnapper();
83         Vector rz = graphicView->getRelativeZero();
84         graphicView->moveRelativeZero(Vector(0.0, 0.0));
85         graphicView->drawEntity(ellipse);
86         graphicView->moveRelativeZero(rz);
87         drawSnapper();
88
89         setStatus(SetCenter);
90
91         RS_DEBUG->print("ActionDrawEllipseAxis::trigger():"
92                 " entity added: %d", ellipse->getId());
93 }
94
95 void ActionDrawEllipseAxis::mouseMoveEvent(QMouseEvent * e)
96 {
97         RS_DEBUG->print("ActionDrawEllipseAxis::mouseMoveEvent begin");
98
99         Vector mouse = snapPoint(e);
100
101         switch (getStatus())
102         {
103         case SetCenter:
104                 break;
105
106         case SetMajor:
107
108                 if (center.valid)
109                 {
110                         deletePreview();
111                         clearPreview();
112                         RS_EllipseData ed(center, mouse - center, 0.5, 0.0, 2 * M_PI, false);
113 //                      preview->addEntity(new RS_Ellipse(preview, ed));
114                         drawPreview();
115                 }
116                 break;
117
118         case SetMinor:
119
120                 if (center.valid && major.valid)
121                 {
122                         deletePreview();
123                         clearPreview();
124                         RS_Line line(NULL, RS_LineData(center - major, center + major));
125                         double d = line.getDistanceToPoint(mouse);
126                         ratio = d / (line.getLength() / 2);
127                         RS_EllipseData ed(center, major, ratio, 0.0, 2 * M_PI, false);
128 //                      preview->addEntity(new RS_Ellipse(preview, ed));
129                         drawPreview();
130                 }
131                 break;
132
133         case SetAngle1:
134
135                 if (center.valid && major.valid)
136                 {
137                         deletePreview();
138                         clearPreview();
139
140                         //angle1 = center.angleTo(mouse);
141
142                         Vector m = mouse;
143                         m.rotate(center, -major.angle());
144                         Vector v = m - center;
145                         v.scale(Vector(1.0, 1.0 / ratio));
146                         angle1 = v.angle(); // + major.angle();
147
148 //                      preview->addEntity(new RS_Line(preview, RS_LineData(center, mouse)));
149
150                         RS_EllipseData ed(center, major, ratio, angle1, angle1 + 1.0, false);
151 //                      preview->addEntity(new RS_Ellipse(preview, ed));
152                         drawPreview();
153                 }
154                 break;
155
156         case SetAngle2:
157
158                 if (center.valid && major.valid)
159                 {
160                         deletePreview();
161                         clearPreview();
162                         //angle2 = center.angleTo(mouse);
163
164                         Vector m = mouse;
165                         m.rotate(center, -major.angle());
166                         Vector v = m - center;
167                         v.scale(Vector(1.0, 1.0 / ratio));
168                         angle2 = v.angle(); // + major.angle();
169
170 //                      preview->addEntity(new RS_Line(preview, RS_LineData(center, mouse)));
171
172                         RS_EllipseData ed(center, major, ratio, angle1, angle2, false);
173 //                      preview->addEntity(new RS_Ellipse(preview, ed));
174                         drawPreview();
175                 }
176
177         default:
178                 break;
179         }
180
181         RS_DEBUG->print("ActionDrawEllipseAxis::mouseMoveEvent end");
182 }
183
184 void ActionDrawEllipseAxis::mouseReleaseEvent(QMouseEvent * e)
185 {
186         // Proceed to next status
187         if (e->button() == Qt::LeftButton)
188         {
189                 Vector ce(snapPoint(e));
190                 coordinateEvent(&ce);
191         }
192         // Return to last status:
193         else if (e->button() == Qt::RightButton)
194         {
195                 deletePreview();
196                 deleteSnapper();
197                 init(getStatus() - 1);
198         }
199 }
200
201 void ActionDrawEllipseAxis::coordinateEvent(Vector * e)
202 {
203         if (e == NULL)
204                 return;
205
206         Vector mouse = *e;
207
208         switch (getStatus())
209         {
210         case SetCenter:
211                 center = mouse;
212                 graphicView->moveRelativeZero(mouse);
213                 setStatus(SetMajor);
214                 break;
215
216         case SetMajor:
217                 major = mouse - center;
218                 setStatus(SetMinor);
219                 break;
220
221         case SetMinor:
222         {
223                 RS_Line line(NULL, RS_LineData(center - major, center + major));
224                 double d = line.getDistanceToPoint(mouse);
225                 ratio = d / (line.getLength() / 2);
226
227                 if (!isArc)
228                 {
229                         trigger();
230                         setStatus(SetCenter);
231                 }
232                 else
233                         setStatus(SetAngle1);
234         }
235         break;
236
237         case SetAngle1:
238         {
239                 //angle1 = center.angleTo(mouse);
240                 Vector m = mouse;
241                 m.rotate(center, -major.angle());
242                 Vector v = m - center;
243                 v.scale(Vector(1.0, 1.0 / ratio));
244                 angle1 = v.angle();
245                 setStatus(SetAngle2);
246         }
247         break;
248
249         case SetAngle2:
250         {
251                 //angle2 = center.angleTo(mouse);
252                 Vector m = mouse;
253                 m.rotate(center, -major.angle());
254                 Vector v = m - center;
255                 v.scale(Vector(1.0, 1.0 / ratio));
256                 angle2 = v.angle();
257                 trigger();
258         }
259         break;
260
261         default:
262                 break;
263         }
264 }
265
266 void ActionDrawEllipseAxis::commandEvent(RS_CommandEvent * e)
267 {
268         QString c = e->getCommand().toLower();
269
270         if (checkCommand("help", c))
271         {
272                 if (RS_DIALOGFACTORY != NULL)
273                         RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
274                                 + getAvailableCommands().join(", "));
275                 return;
276         }
277
278         switch (getStatus())
279         {
280         case SetMinor: {
281                 bool ok;
282                 double m = RS_Math::eval(c, &ok);
283
284                 if (ok == true)
285                 {
286                         ratio = m / major.magnitude();
287
288                         if (!isArc)
289                                 trigger();
290                         else
291                                 setStatus(SetAngle1);
292                 }
293                 else if (RS_DIALOGFACTORY != NULL)
294                         RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
295
296         }
297         break;
298
299         case SetAngle1: {
300                 bool ok;
301                 double a = RS_Math::eval(c, &ok);
302
303                 if (ok == true)
304                 {
305                         angle1 = RS_Math::deg2rad(a);
306                         setStatus(SetAngle2);
307                 }
308                 else if (RS_DIALOGFACTORY != NULL)
309                         RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
310
311         }
312         break;
313
314         case SetAngle2: {
315                 bool ok;
316                 double a = RS_Math::eval(c, &ok);
317
318                 if (ok == true)
319                 {
320                         angle2 = RS_Math::deg2rad(a);
321                         trigger();
322                 }
323                 else if (RS_DIALOGFACTORY != NULL)
324                         RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
325
326         }
327         break;
328
329         default:
330                 break;
331         }
332 }
333
334 QStringList ActionDrawEllipseAxis::getAvailableCommands()
335 {
336         QStringList cmd;
337         return cmd;
338 }
339
340 void ActionDrawEllipseAxis::updateMouseButtonHints()
341 {
342         if (RS_DIALOGFACTORY != NULL)
343         {
344                 switch (getStatus())
345                 {
346                 case SetCenter:
347                         RS_DIALOGFACTORY->updateMouseWidget(tr("Specify ellipse center"),
348                                 tr("Cancel"));
349                         break;
350
351                 case SetMajor:
352                         RS_DIALOGFACTORY->updateMouseWidget(tr("Specify endpoint of major axis"),
353                                 tr("Back"));
354                         break;
355
356                 case SetMinor:
357                         RS_DIALOGFACTORY->updateMouseWidget(
358                                 tr("Specify endpoint or length of minor axis:"),
359                                 tr("Back"));
360                         break;
361
362                 case SetAngle1:
363                         RS_DIALOGFACTORY->updateMouseWidget(tr("Specify start angle"),
364                                 tr("Back"));
365                         break;
366
367                 case SetAngle2:
368                         RS_DIALOGFACTORY->updateMouseWidget(tr("Specify end angle"),
369                                 tr("Back"));
370                         break;
371
372                 default:
373                         RS_DIALOGFACTORY->updateMouseWidget("", "");
374                         break;
375                 }
376         }
377 }
378
379 void ActionDrawEllipseAxis::updateMouseCursor()
380 {
381         graphicView->setMouseCursor(RS2::CadCursor);
382 }
383
384 void ActionDrawEllipseAxis::updateToolBar()
385 {
386         if (RS_DIALOGFACTORY)
387         {
388                 if (!isFinished())
389                         RS_DIALOGFACTORY->requestToolBar(RS2::ToolBarSnap);
390                 else
391                         RS_DIALOGFACTORY->requestToolBar(RS2::ToolBarEllipses);
392         }
393 }