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 
27 #include <QAction>
28 #include <QMouseEvent>
29 #include "rs_actionblocksinsert.h"
30 #include "rs_insert.h"
31 #include "rs_block.h"
32 
33 #include "rs_graphic.h"
34 #include "rs_graphicview.h"
35 #include "rs_dialogfactory.h"
36 #include "rs_commandevent.h"
37 #include "rs_coordinateevent.h"
38 #include "rs_creation.h"
39 #include "rs_math.h"
40 #include "rs_preview.h"
41 
42 /**
43  * Constructor.
44  */
RS_ActionBlocksInsert(RS_EntityContainer & container,RS_GraphicView & graphicView)45 RS_ActionBlocksInsert::RS_ActionBlocksInsert(RS_EntityContainer& container,
46 											 RS_GraphicView& graphicView)
47 	:RS_PreviewActionInterface("Blocks Insert",
48 							   container, graphicView)
49 	,block(nullptr)
50 	,lastStatus(SetUndefined)
51 {
52 	actionType = RS2::ActionBlocksInsert;
53 	reset();    // init data Member
54 }
55 
56 
57 
58 RS_ActionBlocksInsert::~RS_ActionBlocksInsert()  = default;
59 
60 
init(int status)61 void RS_ActionBlocksInsert::init(int status) {
62     RS_PreviewActionInterface::init(status);
63 
64     reset();
65 
66     if (graphic) {
67         block = graphic->getActiveBlock();
68         if (block) {
69             QString blockName = block->getName();
70             data->name = blockName;
71             if (document->rtti() == RS2::EntityBlock) {
72                 QString parentBlockName = ((RS_Block*)(document))->getName();
73                 if (parentBlockName == blockName) {
74                     RS_DIALOGFACTORY->commandMessage(tr("Block cannot contain an insert of itself."));
75                     finish(false);
76                 } else {
77                     QStringList bnChain = block->findNestedInsert(parentBlockName);
78                     if (!bnChain.empty()) {
79                         RS_DIALOGFACTORY->commandMessage(blockName
80                             + tr(" has nested insert of current block in:\n")
81                             + bnChain.join("->")
82                             + tr("\nThis block cannot be inserted."));
83                         finish(false);
84                     }
85                 }
86             }
87         } else {
88             finish(false);
89         }
90     }
91 }
92 
93 
94 
reset()95 void RS_ActionBlocksInsert::reset() {
96 	data.reset(new RS_InsertData("",
97                          RS_Vector(0.0,0.0),
98                          RS_Vector(1.0,1.0),
99                          0.0,
100                          1, 1,
101                          RS_Vector(1.0,1.0),
102                          NULL,
103 						 RS2::Update));
104 }
105 
106 
107 
trigger()108 void RS_ActionBlocksInsert::trigger() {
109     deletePreview();
110 
111     //RS_Modification m(*container, graphicView);
112 	//m.paste(img->insertionPoint);
113     //std::cout << *RS_Clipboard::instance();
114 
115 	if (block) {
116         RS_Creation creation(container, graphicView);
117 		data->updateMode = RS2::Update;
118 		creation.createInsert(data.get());
119     }
120 
121 	graphicView->redraw(RS2::RedrawDrawing);
122 
123     //finish();
124 }
125 
126 
mouseMoveEvent(QMouseEvent * e)127 void RS_ActionBlocksInsert::mouseMoveEvent(QMouseEvent* e) {
128     switch (getStatus()) {
129     case SetTargetPoint:
130 		data->insertionPoint = snapPoint(e);
131 
132 		if (block) {
133             deletePreview();
134             //preview->addAllFrom(*block);
135 			//preview->move(data->insertionPoint);
136 			RS_Creation creation(preview.get(), nullptr, false);
137 			// Create insert as preview only
138 			data->updateMode = RS2::PreviewUpdate;
139 			creation.createInsert(data.get());
140             drawPreview();
141         }
142         break;
143 
144     default:
145         break;
146     }
147 }
148 
149 
150 
mouseReleaseEvent(QMouseEvent * e)151 void RS_ActionBlocksInsert::mouseReleaseEvent(QMouseEvent* e) {
152     if (e->button()==Qt::LeftButton) {
153         RS_CoordinateEvent ce(snapPoint(e));
154         coordinateEvent(&ce);
155     } else if (e->button()==Qt::RightButton) {
156         init(getStatus()-1);
157     }
158 }
159 
160 
161 
coordinateEvent(RS_CoordinateEvent * e)162 void RS_ActionBlocksInsert::coordinateEvent(RS_CoordinateEvent* e) {
163     if (e==NULL) {
164         return;
165     }
166 
167 	data->insertionPoint = e->getCoordinate();
168     trigger();
169 }
170 
171 
172 
commandEvent(RS_CommandEvent * e)173 void RS_ActionBlocksInsert::commandEvent(RS_CommandEvent* e) {
174     QString c = e->getCommand().toLower();
175 
176     if (checkCommand("help", c)) {
177         RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
178                                          + getAvailableCommands().join(", "));
179         return;
180     }
181 
182     switch (getStatus()) {
183     case SetTargetPoint:
184         if (checkCommand("angle", c)) {
185             deletePreview();
186             lastStatus = (Status)getStatus();
187             setStatus(SetAngle);
188         } else if (checkCommand("factor", c)) {
189             deletePreview();
190             lastStatus = (Status)getStatus();
191             setStatus(SetFactor);
192         } else if (checkCommand("columns", c)) {
193             deletePreview();
194             lastStatus = (Status)getStatus();
195             setStatus(SetColumns);
196         } else if (checkCommand("rows", c)) {
197             deletePreview();
198             lastStatus = (Status)getStatus();
199             setStatus(SetRows);
200         } else if (checkCommand("columnspacing", c)) {
201             deletePreview();
202             lastStatus = (Status)getStatus();
203             setStatus(SetColumnSpacing);
204         } else if (checkCommand("rowspacing", c)) {
205             deletePreview();
206             lastStatus = (Status)getStatus();
207             setStatus(SetRowSpacing);
208         }
209         break;
210 
211     case SetAngle: {
212             bool ok;
213             double a = RS_Math::eval(c, &ok);
214             if (ok) {
215 				data->angle = RS_Math::deg2rad(a);
216             } else {
217                 RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
218             }
219             RS_DIALOGFACTORY->requestOptions(this, true, true);
220             setStatus(lastStatus);
221         }
222         break;
223 
224     case SetFactor: {
225             bool ok;
226             double f = RS_Math::eval(c, &ok);
227             if (ok) {
228                 setFactor(f);
229             } else {
230                 RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
231             }
232             RS_DIALOGFACTORY->requestOptions(this, true, true);
233             setStatus(lastStatus);
234         }
235         break;
236 
237     case SetColumns: {
238             bool ok;
239             int cols = (int)RS_Math::eval(c, &ok);
240             if (ok) {
241 				data->cols = cols;
242             } else {
243                 RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
244             }
245             RS_DIALOGFACTORY->requestOptions(this, true, true);
246             setStatus(lastStatus);
247         }
248         break;
249 
250     case SetRows: {
251             bool ok;
252             int rows = (int)RS_Math::eval(c, &ok);
253             if (ok) {
254 				data->rows = rows;
255             } else {
256                 RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
257             }
258             RS_DIALOGFACTORY->requestOptions(this, true, true);
259             setStatus(lastStatus);
260         }
261         break;
262 
263     case SetColumnSpacing: {
264             bool ok;
265             double cs = (int)RS_Math::eval(c, &ok);
266             if (ok) {
267 				data->spacing.x = cs;
268             } else {
269                 RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
270             }
271             RS_DIALOGFACTORY->requestOptions(this, true, true);
272             setStatus(lastStatus);
273         }
274         break;
275 
276     case SetRowSpacing: {
277             bool ok;
278             int rs = (int)RS_Math::eval(c, &ok);
279             if (ok) {
280 				data->spacing.y = rs;
281             } else {
282                 RS_DIALOGFACTORY->commandMessage(tr("Not a valid expression"));
283             }
284             RS_DIALOGFACTORY->requestOptions(this, true, true);
285             setStatus(lastStatus);
286         }
287         break;
288 
289     default:
290         break;
291     }
292 }
293 
getAngle() const294 double RS_ActionBlocksInsert::getAngle() const {
295 	return data->angle;
296 }
297 
setAngle(double a)298 void RS_ActionBlocksInsert::setAngle(double a) {
299 	data->angle = a;
300 }
301 
getFactor() const302 double RS_ActionBlocksInsert::getFactor() const {
303 	return data->scaleFactor.x;
304 }
305 
setFactor(double f)306 void RS_ActionBlocksInsert::setFactor(double f) {
307 	data->scaleFactor = RS_Vector(f, f);
308 }
309 
getColumns() const310 int RS_ActionBlocksInsert::getColumns() const {
311 	return data->cols;
312 }
313 
setColumns(int c)314 void RS_ActionBlocksInsert::setColumns(int c) {
315 	data->cols = c;
316 }
317 
getRows() const318 int RS_ActionBlocksInsert::getRows() const {
319 	return data->rows;
320 }
321 
setRows(int r)322 void RS_ActionBlocksInsert::setRows(int r) {
323 	data->rows = r;
324 }
325 
getColumnSpacing() const326 double RS_ActionBlocksInsert::getColumnSpacing() const {
327 	return data->spacing.x;
328 }
329 
setColumnSpacing(double cs)330 void RS_ActionBlocksInsert::setColumnSpacing(double cs) {
331 	data->spacing.x = cs;
332 }
333 
getRowSpacing() const334 double RS_ActionBlocksInsert::getRowSpacing() const {
335 	return data->spacing.y;
336 }
337 
setRowSpacing(double rs)338 void RS_ActionBlocksInsert::setRowSpacing(double rs) {
339 	data->spacing.y = rs;
340 }
341 
getAvailableCommands()342 QStringList RS_ActionBlocksInsert::getAvailableCommands() {
343     QStringList cmd;
344 
345     switch (getStatus()) {
346     case SetTargetPoint:
347         cmd += command("angle");
348         cmd += command("factor");
349         ;
350         cmd += command("columns");
351         cmd += command("rows");
352         cmd += command("columnspacing");
353         cmd += command("rowspacing");
354         break;
355     default:
356         break;
357     }
358 
359     return cmd;
360 }
361 
362 
showOptions()363 void RS_ActionBlocksInsert::showOptions() {
364     RS_ActionInterface::showOptions();
365 
366     RS_DIALOGFACTORY->requestOptions(this, true);
367 }
368 
369 
370 
hideOptions()371 void RS_ActionBlocksInsert::hideOptions() {
372     RS_ActionInterface::hideOptions();
373 
374     RS_DIALOGFACTORY->requestOptions(this, false);
375 }
376 
377 
updateMouseButtonHints()378 void RS_ActionBlocksInsert::updateMouseButtonHints() {
379     switch (getStatus()) {
380     case SetTargetPoint:
381         RS_DIALOGFACTORY->updateMouseWidget(tr("Specify reference point"),
382                                             tr("Cancel"));
383         break;
384     case SetAngle:
385         RS_DIALOGFACTORY->updateMouseWidget(tr("Enter angle:"),
386                                             "");
387         break;
388     case SetFactor:
389         RS_DIALOGFACTORY->updateMouseWidget(tr("Enter factor:"),
390                                             "");
391         break;
392     case SetColumns:
393         RS_DIALOGFACTORY->updateMouseWidget(tr("Enter columns:"),
394                                             "");
395         break;
396     case SetRows:
397         RS_DIALOGFACTORY->updateMouseWidget(tr("Enter rows:"),
398                                             "");
399         break;
400     case SetColumnSpacing:
401         RS_DIALOGFACTORY->updateMouseWidget(tr("Enter column spacing:"),
402                                             "");
403         break;
404     case SetRowSpacing:
405         RS_DIALOGFACTORY->updateMouseWidget(tr("Enter row spacing:"),
406                                             "");
407         break;
408     default:
409 		RS_DIALOGFACTORY->updateMouseWidget();
410         break;
411     }
412 }
413 
414 
415 
updateMouseCursor()416 void RS_ActionBlocksInsert::updateMouseCursor() {
417     graphicView->setMouseCursor(RS2::CadCursor);
418 }
419 
420 // EOF
421