]> Shamusworld >> Repos - architektonas/blob - src/actions/rs_actiondrawline.cpp
d911e779c02016f7258631b1c4d6a58075bbdc6b
[architektonas] / src / actions / rs_actiondrawline.cpp
1 // rs_actiondrawline.cpp
2 //
3 // Originally part of QCad Community Edition by Andrew Mustun
4 // Extensively rewritten and refactored by James L. Hammons
5 // (C) 2010 Underground Software
6 //
7 // JLH = James L. Hammons <jlhamm@acm.org>
8 //
9 // Who  When        What
10 // ---  ----------  -----------------------------------------------------------
11 // JLH  05/19/2010  Added this text. :-)
12 //
13
14 #include "rs_actiondrawline.h"
15
16 #include "rs_actioneditundo.h"
17 #include "rs_commandevent.h"
18 #include "commands.h"
19 #include "rs_dialogfactory.h"
20 #include "graphicview.h"
21 #include "rs_preview.h"
22
23 RS_ActionDrawLine::RS_ActionDrawLine(RS_EntityContainer & container, GraphicView & graphicView):
24         RS_PreviewActionInterface("Draw lines", container, graphicView)
25 {
26         RS_DEBUG->print("RS_ActionDrawLine::RS_ActionDrawLine");
27         reset();
28         //hm.
29         graphicView.snapper.SetContainer(&container);
30         graphicView.snapper.SetGraphicView(&graphicView);
31         graphicView.snapper.SetVisible();
32         graphicView.preview.SetVisible();
33         RS_DEBUG->print("RS_ActionDrawLine::RS_ActionDrawLine: OK");
34 }
35
36 RS_ActionDrawLine::~RS_ActionDrawLine()
37 {
38         ClearHistory();
39 }
40
41 /*virtual*/ RS2::ActionType RS_ActionDrawLine::rtti()
42 {
43         return RS2::ActionDrawLine;
44 }
45
46 void RS_ActionDrawLine::reset()
47 {
48         RS_DEBUG->print("RS_ActionDrawLine::reset");
49         data = RS_LineData(Vector(false), Vector(false));
50         start = Vector(false);
51         ClearHistory();
52         RS_DEBUG->print("RS_ActionDrawLine::reset: OK");
53 }
54
55 void RS_ActionDrawLine::init(int status)
56 {
57         RS_DEBUG->print("RS_ActionDrawLine::init");
58         RS_PreviewActionInterface::init(status);
59         reset();
60         RS_DEBUG->print("RS_ActionDrawLine::init: OK");
61 }
62
63 void RS_ActionDrawLine::trigger()
64 {
65 #if 0
66         RS_PreviewActionInterface::trigger();   // XOR off screen, delete entities in container
67 #else
68         graphicView->preview.clear();
69 //      graphicView->redraw();
70 #endif
71
72         RS_Line * line = new RS_Line(container, data);
73         line->setLayerToActive();
74         line->setPenToActive();
75         container->addEntity(line);
76 //std::cout << container;
77 //printf("RS_ActionDrawLine::trigger(): new line is %f,%f to %f,%f\n", data.startpoint.x, data.startpoint.y, data.endpoint.x, data.endpoint.y);
78 //This makes it come back as "Unknown Entity"
79 //std::cout << *((RS_Entity *)container);
80 //std::cout << *container;
81
82         // Update undo list:
83         if (document)
84         {
85                 document->startUndoCycle();
86                 document->addUndoable(line);
87                 document->endUndoCycle();
88         }
89
90         graphicView->moveRelativeZero(line->getEndpoint());
91         //hm. [OK, it just moves the relative zero tho. Overkill. And remove preview, so OK.]
92         graphicView->redraw();
93         RS_DEBUG->print("RS_ActionDrawLine::trigger(): line added: %d", line->getId());
94 }
95
96 void RS_ActionDrawLine::mouseMoveEvent(QMouseEvent * e)
97 {
98         RS_DEBUG->print("RS_ActionDrawLine::mouseMoveEvent begin");
99
100         RS_DEBUG->print("RS_ActionDrawLine::mouseMoveEvent: snap point");
101         Vector mouse = graphicView->snapper.snapPoint(e);
102         RS_DEBUG->print("RS_ActionDrawLine::mouseMoveEvent: snap point: OK");
103
104         if (getStatus() == SetEndpoint && data.startpoint.valid)
105         {
106                 RS_DEBUG->print("RS_ActionDrawLine::mouseMoveEvent: update preview");
107 #if 0
108 //not needed, but without this, it doesn't draw... strange...
109 //obviously we haven't gotten our rendering path correct...
110 //              deletePreview();                // XOR off of screen
111                 clearPreview();                 // Remove entities from the container
112                 preview->addEntity(new RS_Line(preview, RS_LineData(data.startpoint, mouse)));
113                 RS_DEBUG->print("RS_ActionDrawLine::mouseMoveEvent: draw preview");
114 //              drawPreview();                  // XOR on screen
115                 xorPreview();                   // XOR on screen
116 #else
117                 // This is lame. Creating a new Line every time the endpoint moves.
118                 // Surely we can alter the line entity inside the preview, no?
119                 graphicView->preview.clear();                   // Remove entities from the container
120                 RS_Line * line = new RS_Line(&(graphicView->preview), RS_LineData(data.startpoint, mouse));
121 //wha? Even THIS doesn't work!!! It was the container...
122 //              line->setPen(RS_Pen(RS_Color(60, 255, 60), RS2::Width00, RS2::SolidLine));
123                 graphicView->preview.addEntity(line);
124 #endif
125         }
126
127         //hm. [ok, this works. :-D]
128         graphicView->redraw();
129         RS_DEBUG->print("RS_ActionDrawLine::mouseMoveEvent end");
130 }
131
132 void RS_ActionDrawLine::mouseReleaseEvent(QMouseEvent * e)
133 {
134         if (e->button() == Qt::LeftButton)
135         {
136                 Vector ce(snapPoint(e));
137                 coordinateEvent(&ce);
138         }
139         else if (e->button() == Qt::RightButton)
140         {
141                 if (getStatus() == 0)
142                 {
143                         graphicView->snapper.SetVisible(false);
144                         graphicView->preview.SetVisible(false);
145                 }
146
147 #if 0
148                 deletePreview();                // XOR off of screen
149                 clearPreview();                 // Remove entities from the container
150 #else
151 #endif
152                 init(getStatus() - 1);
153         }
154
155         //hm. [Seems to work OK.]
156         graphicView->preview.clear();                           // Remove entities from container
157         graphicView->redraw();
158 }
159
160 void RS_ActionDrawLine::coordinateEvent(Vector * e)
161 {
162         RS_DEBUG->print("RS_ActionDrawLine::coordinateEvent");
163
164         if (!e)
165         {
166                 RS_DEBUG->print("RS_ActionDrawLine::coordinateEvent: event was NULL");
167                 return;
168         }
169
170         Vector mouse = *e;
171
172         switch (getStatus())
173         {
174         case SetStartpoint:
175                 data.startpoint = mouse;
176                 ClearHistory();
177                 history.append(new Vector(mouse));
178                 start = data.startpoint;
179                 setStatus(SetEndpoint);
180                 graphicView->moveRelativeZero(mouse);
181                 updateMouseButtonHints();
182                 break;
183
184         case SetEndpoint:
185                 data.endpoint = mouse;
186                 history.append(new Vector(mouse));
187                 trigger();
188                 data.startpoint = data.endpoint;
189                 updateMouseButtonHints();
190                 break;
191
192         default:
193                 break;
194         }
195
196         RS_DEBUG->print("RS_ActionDrawLine::coordinateEvent: OK");
197 }
198
199 void RS_ActionDrawLine::commandEvent(RS_CommandEvent * e)
200 {
201         RS_DEBUG->print("RS_ActionDrawLine::commandEvent");
202         QString c = e->getCommand().toLower();
203
204         switch (getStatus())
205         {
206         case SetStartpoint:
207
208                 if (checkCommand("help", c))
209                 {
210                         RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
211                                 + getAvailableCommands().join(", "));
212                         return;
213                 }
214                 break;
215
216         case SetEndpoint:
217
218                 if (checkCommand("close", c))
219                 {
220                         close();
221                         updateMouseButtonHints();
222                         return;
223                 }
224
225                 if (checkCommand("undo", c))
226                 {
227                         undo();
228                         updateMouseButtonHints();
229                         return;
230                 }
231                 break;
232
233         default:
234                 break;
235         }
236
237         RS_DEBUG->print("RS_ActionDrawLine::commandEvent: OK");
238 }
239
240 QStringList RS_ActionDrawLine::getAvailableCommands()
241 {
242         QStringList cmd;
243
244         switch (getStatus())
245         {
246         case SetStartpoint:
247                 break;
248
249         case SetEndpoint:
250
251                 if (history.count() >= 2)
252                         cmd += command("undo");
253
254                 if (history.count() >= 3)
255                         cmd += command("close");
256
257                 break;
258
259         default:
260                 break;
261         }
262
263         return cmd;
264 }
265
266 void RS_ActionDrawLine::updateMouseButtonHints()
267 {
268         switch (getStatus())
269         {
270         case SetStartpoint:
271                 RS_DIALOGFACTORY->updateMouseWidget(tr("Specify first point"), tr("Cancel"));
272                 break;
273
274         case SetEndpoint:
275         {
276                 QString msg = "";
277
278                 if (history.count() >= 3)
279                 {
280                         msg += RS_COMMANDS->command("close");
281                         msg += "/";
282                 }
283
284                 if (history.count() >= 2)
285                         msg += RS_COMMANDS->command("undo");
286
287                 if (history.count() >= 2)
288                         RS_DIALOGFACTORY->updateMouseWidget(tr("Specify next point or [%1]").arg(msg), tr("Back"));
289                 else
290                         RS_DIALOGFACTORY->updateMouseWidget(tr("Specify next point"), tr("Back"));
291         }
292         break;
293
294         default:
295                 RS_DIALOGFACTORY->updateMouseWidget("", "");
296                 break;
297         }
298 }
299
300 void RS_ActionDrawLine::showOptions()
301 {
302         RS_DEBUG->print("RS_ActionDrawLine::showOptions");
303         RS_ActionInterface::showOptions();
304         RS_DIALOGFACTORY->requestOptions(this, true);
305         RS_DEBUG->print("RS_ActionDrawLine::showOptions: OK");
306 }
307
308 void RS_ActionDrawLine::hideOptions()
309 {
310         RS_ActionInterface::hideOptions();
311         RS_DIALOGFACTORY->requestOptions(this, false);
312 }
313
314 void RS_ActionDrawLine::updateMouseCursor()
315 {
316         graphicView->setMouseCursor(RS2::CadCursor);
317 }
318
319 void RS_ActionDrawLine::updateToolBar()
320 {
321         if (!isFinished())
322                 RS_DIALOGFACTORY->requestToolBar(RS2::ToolBarSnap);
323         else
324                 RS_DIALOGFACTORY->requestToolBar(RS2::ToolBarLines);
325 }
326
327 void RS_ActionDrawLine::close()
328 {
329 //NOTE: We should grey out the "close" button until the conditions for its use are satisfied.
330 //      Though I can see how this would be called via cmd line... So I guess it's OK
331         if (history.count() > 2 && start.valid)
332         {
333                 data.endpoint = start;
334                 trigger();
335                 setStatus(SetStartpoint);
336                 graphicView->moveRelativeZero(start);
337         }
338         else
339                 RS_DIALOGFACTORY->commandMessage(tr("Cannot close sequence of lines: Not enough entities defined yet."));
340 }
341
342 void RS_ActionDrawLine::undo()
343 {
344 //NOTE: We should grey out the "undo" button until the conditions for its use are satisfied.
345         if (history.count() > 1)
346         {
347                 history.removeLast();
348 //              deletePreview();                // XOR off of screen
349 //              clearPreview();                 // Delete entities in container
350                 graphicView->setCurrentAction(new RS_ActionEditUndo(true, *container, *graphicView));
351                 data.startpoint = *history.last();
352                 graphicView->moveRelativeZero(data.startpoint);
353 graphicView->preview.clear();
354 graphicView->redraw();
355         }
356         else
357                 RS_DIALOGFACTORY->commandMessage(tr("Cannot undo: Not enough entities defined yet."));
358 }
359
360 void RS_ActionDrawLine::ClearHistory(void)
361 {
362         while (!history.isEmpty())
363                 delete history.takeFirst();
364 }