1 /****************************************************************************
2 **
3  * This action class can handle user events to draw tangents normal to lines
4 
5 Copyright (C) 2011-2012 Dongxu Li (dongxuli2011@gmail.com)
6 Copyright (C) 2011 R. van Twisk (librecad@rvt.dds.nl)
7 
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 **********************************************************************/
22 
23 #include<QAction>
24 #include <QMouseEvent>
25 #include "rs_actiondrawlineorthtan.h"
26 
27 #include "rs_dialogfactory.h"
28 #include "rs_graphicview.h"
29 #include "rs_creation.h"
30 #include "rs_selection.h"
31 #include "rs_line.h"
32 #include "rs_preview.h"
33 #include "rs_debug.h"
34 
35 namespace{
36 auto circleList={RS2::EntityArc, RS2::EntityCircle, RS2::EntityEllipse}; //this holds a list of entity types which supports tangent
37 }
38 
39 /**
40  * This action class can handle user events to draw tangents normal to lines
41  *
42  * @author Dongxu Li
43  */
RS_ActionDrawLineOrthTan(RS_EntityContainer & container,RS_GraphicView & graphicView)44 RS_ActionDrawLineOrthTan::RS_ActionDrawLineOrthTan(
45         RS_EntityContainer& container,
46         RS_GraphicView& graphicView)
47     :RS_PreviewActionInterface("Draw Tangent Orthogonal", container, graphicView)
48 	,normal(nullptr)
49 	,tangent(nullptr)
50 	,circle(nullptr)
51 {
52 	actionType=RS2::ActionDrawLineOrthTan;
53 }
54 
55 
finish(bool updateTB)56 void RS_ActionDrawLineOrthTan::finish(bool updateTB){
57 	clearLines();
58     RS_PreviewActionInterface::finish(updateTB);
59 }
60 
trigger()61 void RS_ActionDrawLineOrthTan::trigger() {
62 	if(!tangent) return;
63     RS_PreviewActionInterface::trigger();
64 
65 	deletePreview();
66 	if(circle)
67 		circle->setHighlighted(false);
68 	circle=nullptr;
69 	graphicView->redraw(RS2::RedrawDrawing);
70 	RS_Entity* newEntity = new RS_Line(container,
71 									   tangent->getData());
72 	newEntity->setLayerToActive();
73 	newEntity->setPenToActive();
74 	container->addEntity(newEntity);
75 
76 	// upd. undo list:
77 	if (document) {
78 		document->startUndoCycle();
79 		document->addUndoable(newEntity);
80 		document->endUndoCycle();
81 	}
82 
83 	graphicView->redraw(RS2::RedrawDrawing);
84 
85 	setStatus(SetCircle);
86 
87 }
88 
89 
90 
mouseMoveEvent(QMouseEvent * e)91 void RS_ActionDrawLineOrthTan::mouseMoveEvent(QMouseEvent* e) {
92     RS_DEBUG->print("RS_ActionDrawLineOrthTan::mouseMoveEvent begin");
93 	e->accept();
94 	RS_Vector mouse(graphicView->toGraphX(e->x()),
95 					graphicView->toGraphY(e->y()));
96 
97 	switch(getStatus()){
98 	case SetLine:
99 		return;
100 	case SetCircle:{
101 
102 		RS_Entity* en = catchEntity(e, circleList, RS2::ResolveAll);
103 		if(!en) return;
104 		deletePreview();
105 		if(circle)
106 			circle->setHighlighted(false);
107 		circle = en;
108 		circle->setHighlighted(true);
109 		graphicView->redraw(RS2::RedrawDrawing);
110 		deletePreview();
111 		RS_Creation creation(preview.get(), graphicView, false);
112 		tangent = creation.createLineOrthTan(mouse,
113 											 normal,
114 											 circle);
115 		preview->addEntity(tangent);
116 		drawPreview();
117 
118 	}
119 	default:
120 		break;
121 	}
122 	RS_DEBUG->print("RS_ActionDrawLineOrthTan::mouseMoveEvent end");
123 }
124 
125 
clearLines()126 void RS_ActionDrawLineOrthTan::clearLines()
127 {
128 	for(RS_Entity* p: {(RS_Entity*) normal, circle}){
129 		if(p){
130 			p->setHighlighted(false);
131 			graphicView->drawEntity(p);
132 		}
133 	}
134 	if(circle) circle=nullptr;
135 	deletePreview();
136 }
137 
mouseReleaseEvent(QMouseEvent * e)138 void RS_ActionDrawLineOrthTan::mouseReleaseEvent(QMouseEvent* e) {
139     if (e->button()==Qt::RightButton) {
140 		clearLines();
141         if (getStatus() == SetLine) {
142 				finish(true);
143         }else{
144                 init(getStatus()-1);
145         }
146     } else {
147         switch (getStatus()) {
148         case SetLine: {
149             RS_Entity* en=catchEntity(e,RS2::EntityLine);
150 			if(en){
151                 if (en->getLength() < RS_TOLERANCE) {
152                     //ignore lines not long enough
153                     break;
154                 }
155 				if(normal) {
156                     normal->setHighlighted(false);
157                     graphicView->drawEntity(normal);
158                 }
159                 normal=static_cast<RS_Line*>(en);
160                 normal->setHighlighted(true);
161                 graphicView->drawEntity(normal);
162                 setStatus(SetCircle);
163             }
164         }
165             break;
166 
167         case SetCircle:
168 			if(tangent){
169 				trigger();
170 			}
171 			break;
172 
173         default:
174             break;
175         }
176     }
177 
178 }
179 
180 
181 
updateMouseButtonHints()182 void RS_ActionDrawLineOrthTan::updateMouseButtonHints() {
183 	switch (getStatus()) {
184 	case SetLine:
185 		RS_DIALOGFACTORY->updateMouseWidget(tr("Select a line"),
186 											tr("Cancel"));
187 		break;
188 	case SetCircle:
189 		RS_DIALOGFACTORY->updateMouseWidget(tr("Select circle, arc or ellipse"),
190 											tr("Back"));
191 		break;
192 	default:
193 		RS_DIALOGFACTORY->updateMouseWidget();
194 		break;
195 	}
196 }
197 
198 
199 
updateMouseCursor()200 void RS_ActionDrawLineOrthTan::updateMouseCursor() {
201         if(isFinished()) {
202     graphicView->setMouseCursor(RS2::ArrowCursor);
203         }else{
204     graphicView->setMouseCursor(RS2::SelectCursor);
205         }
206 }
207 
208 // EOF
209