1 /****************************************************************************
2 **
3 ** This file is part of the LibreCAD project, a 2D CAD program
4 **
5 ** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
6 ** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
7 **
8 **
9 ** This file may be distributed and/or modified under the terms of the
10 ** GNU General Public License version 2 as published by the Free Software
11 ** Foundation and appearing in the file gpl-2.0.txt included in the
12 ** packaging of this file.
13 **
14 ** This program is distributed in the hope that it will be useful,
15 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ** GNU General Public License for more details.
18 **
19 ** You should have received a copy of the GNU General Public License
20 ** along with this program; if not, write to the Free Software
21 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 **
23 ** This copyright notice MUST APPEAR in all copies of the script!
24 **
25 **********************************************************************/
26 #include<cmath>
27 #include <QAction>
28 #include <QMouseEvent>
29 #include "rs_actiondimlinear.h"
30 #include "rs_dimlinear.h"
31
32 #include "rs_dialogfactory.h"
33 #include "rs_graphicview.h"
34 #include "rs_commandevent.h"
35 #include "rs_constructionline.h"
36 #include "rs_line.h"
37 #include "rs_coordinateevent.h"
38 #include "rs_math.h"
39 #include "rs_preview.h"
40 #include "rs_debug.h"
41
42 /**
43 * Constructor.
44 *
45 * @param angle Initial angle in rad.
46 * @param fixedAngle true: The user can't change the angle.
47 * false: The user can change the angle in a option widget.
48 */
RS_ActionDimLinear(RS_EntityContainer & container,RS_GraphicView & graphicView,double angle,bool _fixedAngle,RS2::ActionType)49 RS_ActionDimLinear::RS_ActionDimLinear(RS_EntityContainer& container,
50 RS_GraphicView& graphicView,
51 double angle,
52 bool _fixedAngle, RS2::ActionType /*type*/)
53 :RS_ActionDimension("Draw linear dimensions",
54 container, graphicView)
55 ,edata(new RS_DimLinearData(RS_Vector(0., 0.), RS_Vector(0., 0.), angle, 0.))
56 ,fixedAngle(_fixedAngle)
57 ,lastStatus(SetExtPoint1)
58 {
59 //TODO: fix dim linear type logic: whether it's for linear only, or should cover horizontal/vertical dim types
60 actionType=RS2::ActionDimLinear;
61 reset();
62 }
63
64
65
66 RS_ActionDimLinear::~RS_ActionDimLinear() = default;
67
reset()68 void RS_ActionDimLinear::reset() {
69 RS_ActionDimension::reset();
70
71 edata.reset(new RS_DimLinearData(RS_Vector(false),
72 RS_Vector(false),
73 (fixedAngle ? edata->angle : 0.0), 0.0)
74 );
75
76 RS_DIALOGFACTORY->requestOptions(this, true, true);
77 }
78
79
80
trigger()81 void RS_ActionDimLinear::trigger() {
82 RS_ActionDimension::trigger();
83
84 preparePreview();
85 RS_DimLinear* dim = new RS_DimLinear(container, *data, *edata);
86 dim->setLayerToActive();
87 dim->setPenToActive();
88 dim->update();
89 container->addEntity(dim);
90
91 // upd. undo list:
92 if (document) {
93 document->startUndoCycle();
94 document->addUndoable(dim);
95 document->endUndoCycle();
96 }
97
98 RS_Vector rz = graphicView->getRelativeZero();
99 graphicView->redraw(RS2::RedrawDrawing);
100 graphicView->moveRelativeZero(rz);
101
102 RS_DEBUG->print("RS_ActionDimLinear::trigger():"
103 " dim added: %d", dim->getId());
104 }
105
106
preparePreview()107 void RS_ActionDimLinear::preparePreview() {
108 RS_Vector dirV = RS_Vector::polar(100., edata->angle+M_PI_2);
109
110 RS_ConstructionLine cl(
111 NULL,
112 RS_ConstructionLineData(
113 edata->extensionPoint2,
114 edata->extensionPoint2+dirV));
115
116 data->definitionPoint =
117 cl.getNearestPointOnEntity(data->definitionPoint);
118
119 }
120
121
122
mouseMoveEvent(QMouseEvent * e)123 void RS_ActionDimLinear::mouseMoveEvent(QMouseEvent* e) {
124 RS_DEBUG->print("RS_ActionDimLinear::mouseMoveEvent begin");
125
126 RS_Vector mouse = snapPoint(e);
127
128 switch (getStatus()) {
129 case SetExtPoint1:
130 break;
131
132 case SetExtPoint2:
133 if (edata->extensionPoint1.valid) {
134 deletePreview();
135 preview->addEntity(new RS_Line{preview.get(),
136 edata->extensionPoint1, mouse});
137 drawPreview();
138 }
139 break;
140
141 case SetDefPoint:
142 if (edata->extensionPoint1.valid && edata->extensionPoint2.valid) {
143 deletePreview();
144 data->definitionPoint = mouse;
145
146 preparePreview();
147
148 RS_DimLinear* dim = new RS_DimLinear(preview.get(), *data, *edata);
149 preview->addEntity(dim);
150 dim->update();
151 drawPreview();
152 }
153 break;
154 }
155
156 RS_DEBUG->print("RS_ActionDimLinear::mouseMoveEvent end");
157 }
158
159
160
mouseReleaseEvent(QMouseEvent * e)161 void RS_ActionDimLinear::mouseReleaseEvent(QMouseEvent* e) {
162 if (e->button()==Qt::LeftButton) {
163 RS_CoordinateEvent ce(snapPoint(e));
164 coordinateEvent(&ce);
165 } else if (e->button()==Qt::RightButton) {
166 deletePreview();
167 init(getStatus()-1);
168 }
169 }
170
171
172
coordinateEvent(RS_CoordinateEvent * e)173 void RS_ActionDimLinear::coordinateEvent(RS_CoordinateEvent* e) {
174 if (e==NULL) {
175 return;
176 }
177
178 RS_Vector pos = e->getCoordinate();
179
180 switch (getStatus()) {
181 case SetExtPoint1:
182 edata->extensionPoint1 = pos;
183 graphicView->moveRelativeZero(pos);
184 setStatus(SetExtPoint2);
185 break;
186
187 case SetExtPoint2:
188 edata->extensionPoint2 = pos;
189 graphicView->moveRelativeZero(pos);
190 setStatus(SetDefPoint);
191 break;
192
193 case SetDefPoint:
194 data->definitionPoint = pos;
195 trigger();
196 reset();
197 setStatus(SetExtPoint1);
198 break;
199
200 default:
201 break;
202 }
203 }
204
getAngle() const205 double RS_ActionDimLinear::getAngle() const{
206 return edata->angle;
207 }
208
setAngle(double a)209 void RS_ActionDimLinear::setAngle(double a) {
210 edata->angle = a;
211 }
212
hasFixedAngle() const213 bool RS_ActionDimLinear::hasFixedAngle() const{
214 return fixedAngle;
215 }
216
commandEvent(RS_CommandEvent * e)217 void RS_ActionDimLinear::commandEvent(RS_CommandEvent* e) {
218 QString c = e->getCommand().toLower();
219
220 if (checkCommand("help", c)) {
221 RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
222 + getAvailableCommands().join(", "));
223 return;
224 }
225
226 switch (getStatus()) {
227 case SetText:
228 setText(c);
229 RS_DIALOGFACTORY->requestOptions(this, true, true);
230 graphicView->enableCoordinateInput();
231 setStatus(lastStatus);
232 break;
233
234 case SetAngle: {
235 bool ok;
236 double a = RS_Math::eval(c, &ok);
237 if (ok) {
238 setAngle(RS_Math::deg2rad(a));
239 } else {
240 RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
241 }
242 RS_DIALOGFACTORY->requestOptions(this, true, true);
243 setStatus(lastStatus);
244 }
245 break;
246
247 default:
248 lastStatus = (Status)getStatus();
249 deletePreview();
250 if (checkCommand("text", c)) {
251 graphicView->disableCoordinateInput();
252 setStatus(SetText);
253 return;
254 } else if (!fixedAngle && (checkCommand("angle", c))) {
255 setStatus(SetAngle);
256 }
257 break;
258 }
259 }
260
261
262
getAvailableCommands()263 QStringList RS_ActionDimLinear::getAvailableCommands() {
264 QStringList cmd;
265
266 switch (getStatus()) {
267 case SetExtPoint1:
268 case SetExtPoint2:
269 case SetDefPoint:
270 cmd += command("text");
271 if (!fixedAngle) {
272 cmd += command("angle");
273 }
274 break;
275
276 default:
277 break;
278 }
279
280 return cmd;
281 }
282
283
updateMouseButtonHints()284 void RS_ActionDimLinear::updateMouseButtonHints() {
285 switch (getStatus()) {
286 case SetExtPoint1:
287 RS_DIALOGFACTORY->updateMouseWidget(
288 tr("Specify first extension line origin"),
289 tr("Cancel"));
290 break;
291 case SetExtPoint2:
292 RS_DIALOGFACTORY->updateMouseWidget(
293 tr("Specify second extension line origin"),
294 tr("Back"));
295 break;
296 case SetDefPoint:
297 RS_DIALOGFACTORY->updateMouseWidget(
298 tr("Specify dimension line location"),
299 tr("Back"));
300 break;
301 case SetText:
302 RS_DIALOGFACTORY->updateMouseWidget(tr("Enter dimension text:"), "");
303 break;
304 case SetAngle:
305 RS_DIALOGFACTORY->updateMouseWidget(
306 tr("Enter dimension line angle:"), "");
307 break;
308 default:
309 RS_DIALOGFACTORY->updateMouseWidget();
310 break;
311 }
312 }
313
314
315
showOptions()316 void RS_ActionDimLinear::showOptions() {
317 RS_ActionInterface::showOptions();
318
319 RS_DIALOGFACTORY->requestOptions(this, true, true);
320 }
321
322
323
hideOptions()324 void RS_ActionDimLinear::hideOptions() {
325 RS_ActionInterface::hideOptions();
326
327 RS_DIALOGFACTORY->requestOptions(this, false);
328 }
329
330
331
332 // EOF
333