]> Shamusworld >> Repos - architektonas/blob - src/actions/rs_actiondimlinear.cpp
Last checkin before major refactor...
[architektonas] / src / actions / rs_actiondimlinear.cpp
1 // rs_actiondimlinear.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_actiondimlinear.h"
16
17 #include "rs_commandevent.h"
18 #include "rs_constructionline.h"
19 #include "rs_dialogfactory.h"
20 #include "graphicview.h"
21 #include "rs_preview.h"
22
23 /**
24  * Constructor.
25  *
26  * @param angle Initial angle in rad.
27  * @param fixedAngle true: The user can't change the angle.
28  *                   false: The user can change the angle in a option widget.
29  */
30 RS_ActionDimLinear::RS_ActionDimLinear(RS_EntityContainer & container, GraphicView & graphicView, double angle, bool fixedAngle):
31         RS_ActionDimension("Draw linear dimensions", container, graphicView)
32 {
33         edata.angle = angle;
34         this->fixedAngle = fixedAngle;
35         lastStatus = SetExtPoint1;
36         reset();
37 }
38
39 RS_ActionDimLinear::~RS_ActionDimLinear()
40 {
41 }
42
43 /*virtual*/ RS2::ActionType RS_ActionDimLinear::rtti()
44 {
45         return RS2::ActionDimLinear;
46 }
47
48 void RS_ActionDimLinear::reset()
49 {
50         RS_ActionDimension::reset();
51         edata = RS_DimLinearData(Vector(false), Vector(false), (fixedAngle ? edata.angle : 0.0), 0.0);
52
53         if (RS_DIALOGFACTORY != NULL)
54                 RS_DIALOGFACTORY->requestOptions(this, true, true);
55 }
56
57 void RS_ActionDimLinear::trigger()
58 {
59         RS_ActionDimension::trigger();
60         preparePreview();
61         RS_DimLinear * dim = new RS_DimLinear(container, data, edata);
62         dim->setLayerToActive();
63         dim->setPenToActive();
64         dim->update();
65         container->addEntity(dim);
66
67         // upd. undo list:
68         if (document != NULL)
69         {
70                 document->startUndoCycle();
71                 document->addUndoable(dim);
72                 document->endUndoCycle();
73         }
74
75         deleteSnapper();
76         Vector rz = graphicView->getRelativeZero();
77         graphicView->moveRelativeZero(Vector(0.0, 0.0));
78         graphicView->drawEntity(dim);
79         graphicView->moveRelativeZero(rz);
80         drawSnapper();
81
82         RS_DEBUG->print("RS_ActionDimLinear::trigger(): dim added: %d", dim->getId());
83 }
84
85 void RS_ActionDimLinear::preparePreview()
86 {
87         Vector dirV;
88         dirV.setPolar(100.0, edata.angle + M_PI / 2.0);
89
90         RS_ConstructionLine cl(
91                 NULL, RS_ConstructionLineData(
92                         edata.extensionPoint2,
93                         edata.extensionPoint2 + dirV));
94
95         data.definitionPoint =
96                 cl.getNearestPointOnEntity(data.definitionPoint);
97 }
98
99 void RS_ActionDimLinear::mouseMoveEvent(QMouseEvent * e)
100 {
101         RS_DEBUG->print("RS_ActionDimLinear::mouseMoveEvent begin");
102
103         Vector mouse = snapPoint(e);
104
105         switch (getStatus())
106         {
107         case SetExtPoint1:
108                 break;
109
110         case SetExtPoint2:
111
112                 if (edata.extensionPoint1.valid)
113                 {
114                         deletePreview();
115                         clearPreview();
116                         preview->addEntity(new RS_Line(preview,
117                                         RS_LineData(edata.extensionPoint1,
118                                                 mouse)));
119                         drawPreview();
120                 }
121                 break;
122
123         case SetDefPoint:
124
125                 if (edata.extensionPoint1.valid && edata.extensionPoint2.valid)
126                 {
127                         deletePreview();
128                         clearPreview();
129                         data.definitionPoint = mouse;
130
131                         preparePreview();
132
133                         RS_DimLinear * dim = new RS_DimLinear(preview, data, edata);
134                         dim->update();
135                         preview->addEntity(dim);
136                         drawPreview();
137                 }
138                 break;
139         }
140
141         RS_DEBUG->print("RS_ActionDimLinear::mouseMoveEvent end");
142 }
143
144 void RS_ActionDimLinear::mouseReleaseEvent(QMouseEvent * e)
145 {
146         if (e->button() == Qt::LeftButton)
147         {
148                 Vector ce(snapPoint(e));
149                 coordinateEvent(&ce);
150         }
151         else if (e->button() == Qt::RightButton)
152         {
153                 deletePreview();
154                 deleteSnapper();
155                 init(getStatus() - 1);
156         }
157 }
158
159 void RS_ActionDimLinear::coordinateEvent(Vector * e)
160 {
161         if (e == NULL)
162                 return;
163
164         Vector pos = *e;
165
166         switch (getStatus())
167         {
168         case SetExtPoint1:
169                 edata.extensionPoint1 = pos;
170                 graphicView->moveRelativeZero(pos);
171                 setStatus(SetExtPoint2);
172                 break;
173
174         case SetExtPoint2:
175                 edata.extensionPoint2 = pos;
176                 graphicView->moveRelativeZero(pos);
177                 setStatus(SetDefPoint);
178                 break;
179
180         case SetDefPoint:
181                 data.definitionPoint = pos;
182                 trigger();
183                 reset();
184                 setStatus(SetExtPoint1);
185                 break;
186
187         default:
188                 break;
189         }
190 }
191
192 void RS_ActionDimLinear::commandEvent(RS_CommandEvent * e)
193 {
194         QString c = e->getCommand().toLower();
195
196         if (checkCommand("help", c))
197         {
198                 if (RS_DIALOGFACTORY != NULL)
199                         RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
200                                 + getAvailableCommands().join(", "));
201                 return;
202         }
203
204         switch (getStatus())
205         {
206         case SetText:
207                 setText(c);
208
209                 if (RS_DIALOGFACTORY != NULL)
210                         RS_DIALOGFACTORY->requestOptions(this, true, true);
211                 graphicView->enableCoordinateInput();
212                 setStatus(lastStatus);
213                 break;
214
215         case SetAngle: {
216                 bool ok;
217                 double a = RS_Math::eval(c, &ok);
218
219                 if (ok == true)
220                         setAngle(RS_Math::deg2rad(a));
221                 else if (RS_DIALOGFACTORY != NULL)
222                         RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
223
224                 if (RS_DIALOGFACTORY != NULL)
225                         RS_DIALOGFACTORY->requestOptions(this, true, true);
226                 setStatus(lastStatus);
227         }
228         break;
229
230         default:
231                 lastStatus = (Status)getStatus();
232                 deleteSnapper();
233                 deletePreview();
234                 clearPreview();
235
236                 if (checkCommand("text", c))
237                 {
238                         graphicView->disableCoordinateInput();
239                         setStatus(SetText);
240                         return;
241                 }
242                 else if (!fixedAngle && (checkCommand("angle", c)))
243                         setStatus(SetAngle);
244                 break;
245         }
246 }
247
248 QStringList RS_ActionDimLinear::getAvailableCommands()
249 {
250         QStringList cmd;
251
252         switch (getStatus())
253         {
254         case SetExtPoint1:
255         case SetExtPoint2:
256         case SetDefPoint:
257                 cmd += command("text");
258
259                 if (!fixedAngle)
260                         cmd += command("angle");
261                 break;
262
263         default:
264                 break;
265         }
266
267         return cmd;
268 }
269
270 void RS_ActionDimLinear::updateMouseButtonHints()
271 {
272         if (RS_DIALOGFACTORY != NULL)
273         {
274                 switch (getStatus())
275                 {
276                 case SetExtPoint1:
277                         RS_DIALOGFACTORY->updateMouseWidget(
278                                 tr("Specify first extension line origin"), tr("Cancel"));
279                         break;
280
281                 case SetExtPoint2:
282                         RS_DIALOGFACTORY->updateMouseWidget(
283                                 tr("Specify second extension line origin"), tr("Back"));
284                         break;
285
286                 case SetDefPoint:
287                         RS_DIALOGFACTORY->updateMouseWidget(
288                                 tr("Specify dimension line location"), tr("Back"));
289                         break;
290
291                 case SetText:
292                         RS_DIALOGFACTORY->updateMouseWidget(tr("Enter dimension text:"), "");
293                         break;
294
295                 case SetAngle:
296                         RS_DIALOGFACTORY->updateMouseWidget(tr("Enter dimension line angle:"), "");
297                         break;
298
299                 default:
300                         RS_DIALOGFACTORY->updateMouseWidget("", "");
301                         break;
302                 }
303         }
304 }
305
306 void RS_ActionDimLinear::showOptions()
307 {
308         RS_ActionInterface::showOptions();
309
310         if (RS_DIALOGFACTORY != NULL)
311                 RS_DIALOGFACTORY->requestOptions(this, true, true);
312 }
313
314 void RS_ActionDimLinear::hideOptions()
315 {
316         RS_ActionInterface::hideOptions();
317
318         if (RS_DIALOGFACTORY != NULL)
319                 RS_DIALOGFACTORY->requestOptions(this, false);
320 }
321
322 double RS_ActionDimLinear::getAngle()
323 {
324         return edata.angle;
325 }
326
327 void RS_ActionDimLinear::setAngle(double a)
328 {
329         edata.angle = a;
330 }
331
332 bool RS_ActionDimLinear::hasFixedAngle()
333 {
334         return fixedAngle;
335 }
336