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