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