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