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