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_actiondrawcircle2p.h"
30 
31 #include "rs_dialogfactory.h"
32 #include "rs_graphicview.h"
33 #include "rs_commandevent.h"
34 #include "rs_circle.h"
35 #include "rs_coordinateevent.h"
36 #include "rs_preview.h"
37 
38 struct RS_ActionDrawCircle2P::Points {
39 	/**
40 	 * 1st point.
41 	 */
42 	RS_Vector point1;
43 	/**
44 	 * 2nd point.
45 	 */
46 	RS_Vector point2;
47 };
48 
RS_ActionDrawCircle2P(RS_EntityContainer & container,RS_GraphicView & graphicView)49 RS_ActionDrawCircle2P::RS_ActionDrawCircle2P(RS_EntityContainer& container,
50         RS_GraphicView& graphicView)
51         :RS_PreviewActionInterface("Draw circles",
52 						   container, graphicView)
53 		, data(new RS_CircleData())
54 		, pPoints(new Points{})
55 {
56 	actionType=RS2::ActionDrawCircle2P;
57     reset();
58 }
59 
60 RS_ActionDrawCircle2P::~RS_ActionDrawCircle2P() = default;
61 
reset()62 void RS_ActionDrawCircle2P::reset() {
63 	data.reset(new RS_CircleData{});
64 	pPoints->point1 = {};
65 	pPoints->point2 = {};
66 }
67 
68 
69 
init(int status)70 void RS_ActionDrawCircle2P::init(int status) {
71     RS_PreviewActionInterface::init(status);
72 
73     reset();
74 }
75 
76 
77 
trigger()78 void RS_ActionDrawCircle2P::trigger() {
79     RS_PreviewActionInterface::trigger();
80 
81     preparePreview();
82 	if (data->isValid()) {
83         RS_Circle* circle = new RS_Circle(container,
84 										  *data);
85         circle->setLayerToActive();
86         circle->setPenToActive();
87         container->addEntity(circle);
88 
89         // upd. undo list:
90         if (document) {
91             document->startUndoCycle();
92             document->addUndoable(circle);
93             document->endUndoCycle();
94         }
95 
96         RS_Vector rz = graphicView->getRelativeZero();
97                 graphicView->redraw(RS2::RedrawDrawing);
98         graphicView->moveRelativeZero(rz);
99 
100         setStatus(SetPoint1);
101         reset();
102 	} else
103 		RS_DIALOGFACTORY->requestWarningDialog(tr("Invalid Circle data."));
104 }
105 
106 
107 
preparePreview()108 void RS_ActionDrawCircle2P::preparePreview() {
109 	data.reset(new RS_CircleData{});
110 	if (pPoints->point1.valid && pPoints->point2.valid) {
111 		RS_Circle circle(nullptr, *data);
112 		bool suc = circle.createFrom2P(pPoints->point1, pPoints->point2);
113         if (suc) {
114 			data.reset(new RS_CircleData(circle.getData()));
115         }
116     }
117 }
118 
119 
mouseMoveEvent(QMouseEvent * e)120 void RS_ActionDrawCircle2P::mouseMoveEvent(QMouseEvent* e) {
121     RS_Vector mouse = snapPoint(e);
122     switch (getStatus()) {
123     case SetPoint1:
124 		pPoints->point1 = mouse;
125         break;
126 
127     case SetPoint2:
128 		pPoints->point2 = mouse;
129         preparePreview();
130 		if (data->isValid()) {
131 			RS_Circle* circle = new RS_Circle(preview.get(), *data);
132             deletePreview();
133             preview->addEntity(circle);
134             drawPreview();
135         }
136         break;
137 
138     default:
139         break;
140     }
141 }
142 
143 
144 
mouseReleaseEvent(QMouseEvent * e)145 void RS_ActionDrawCircle2P::mouseReleaseEvent(QMouseEvent* e) {
146     if (e->button()==Qt::LeftButton) {
147         RS_CoordinateEvent ce(snapPoint(e));
148         coordinateEvent(&ce);
149     } else if (e->button()==Qt::RightButton) {
150         deletePreview();
151         init(getStatus()-1);
152     }
153 }
154 
155 
156 
coordinateEvent(RS_CoordinateEvent * e)157 void RS_ActionDrawCircle2P::coordinateEvent(RS_CoordinateEvent* e) {
158     if (e==NULL) {
159         return;
160     }
161 
162     RS_Vector mouse = e->getCoordinate();
163 
164     switch (getStatus()) {
165     case SetPoint1:
166 		pPoints->point1 = mouse;
167         graphicView->moveRelativeZero(mouse);
168         setStatus(SetPoint2);
169         break;
170 
171     case SetPoint2:
172 		pPoints->point2 = mouse;
173         graphicView->moveRelativeZero(mouse);
174         trigger();
175         break;
176 
177     default:
178         break;
179     }
180 }
181 
182 
183 
commandEvent(RS_CommandEvent * e)184 void RS_ActionDrawCircle2P::commandEvent(RS_CommandEvent* e) {
185     QString c = e->getCommand().toLower();
186 
187     if (checkCommand("help", c)) {
188 		RS_DIALOGFACTORY->commandMessage(msgAvailableCommands()
189 										 + getAvailableCommands().join(", "));
190         return;
191     }
192 
193 }
194 
195 
196 
getAvailableCommands()197 QStringList RS_ActionDrawCircle2P::getAvailableCommands() {
198     QStringList cmd;
199     return cmd;
200 }
201 
202 
203 
updateMouseButtonHints()204 void RS_ActionDrawCircle2P::updateMouseButtonHints() {
205 	switch (getStatus()) {
206 	case SetPoint1:
207 		RS_DIALOGFACTORY->updateMouseWidget(
208 					tr("Specify first point"), tr("Cancel"));
209 		break;
210 	case SetPoint2:
211 		RS_DIALOGFACTORY->updateMouseWidget(
212 					tr("Specify second point"), tr("Back"));
213 		break;
214 	default:
215 		RS_DIALOGFACTORY->updateMouseWidget();
216 		break;
217 	}
218 }
219 
220 
221 
updateMouseCursor()222 void RS_ActionDrawCircle2P::updateMouseCursor() {
223     graphicView->setMouseCursor(RS2::CadCursor);
224 }
225 
226 // EOF
227 
228