1 /**********************************************************************************************
2     Copyright (C) 2016 Oliver Eichler <oliver.eichler@gmx.de>
3     Copyright (C) 2018 Norbert Truchsess <norbert.truchsess@t-online.de>
4 
5     This program is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 
18 **********************************************************************************************/
19 
20 #include "gis/CGisDraw.h"
21 #include "mouse/CMouseAdapter.h"
22 #include "mouse/IMouseSelect.h"
23 #include "mouse/IScrOpt.h"
24 
25 #include <QPainterPath>
26 #include <QtWidgets>
27 #include <QPainterPath>
28 
IMouseSelect(CGisDraw * gis,CCanvas * canvas,CMouseAdapter * mouse)29 IMouseSelect::IMouseSelect(CGisDraw* gis, CCanvas* canvas, CMouseAdapter* mouse)
30     : IMouse(gis, canvas, mouse)
31 {
32 }
33 
~IMouseSelect()34 IMouseSelect::~IMouseSelect()
35 {
36     canvas->reportStatus("IMouseSelect", "");
37     delete scrOpt;
38 }
39 
rectRad2Px(const QRectF & rectSrc,QRectF & rectTar) const40 void IMouseSelect::rectRad2Px(const QRectF& rectSrc, QRectF& rectTar) const
41 {
42     QPointF pt1 = rectSrc.topLeft();
43     QPointF pt2 = rectSrc.bottomRight();
44 
45     gis->convertRad2Px(pt1);
46     gis->convertRad2Px(pt2);
47 
48     rectTar = QRectF(pt1, pt2);
49 }
50 
rectRad2Deg(const QRectF & rectSrc,QRectF & rectTar) const51 void IMouseSelect::rectRad2Deg(const QRectF& rectSrc, QRectF& rectTar) const
52 {
53     QPointF pt1 = rectSrc.topLeft();
54     QPointF pt2 = rectSrc.bottomRight();
55 
56     pt1 *= RAD_TO_DEG;
57     pt2 *= RAD_TO_DEG;
58 
59     rectTar = QRectF(pt1, pt2);
60 }
61 
placeScrOpt()62 void IMouseSelect::placeScrOpt()
63 {
64     if(scrOpt.isNull())
65     {
66         return;
67     }
68 
69     if((state == eStateMap) || (state == eStateMapMoving))
70     {
71         QRectF rectSel;
72         rectRad2Px(rectSelection, rectSel);
73         scrOpt->move(rectSel.topRight().toPoint());
74         scrOpt->show();
75     }
76     else
77     {
78         scrOpt->hide();
79     }
80 }
81 
82 
draw(QPainter & p,CCanvas::redraw_e needsRedraw,const QRect & rect)83 void IMouseSelect::draw(QPainter& p, CCanvas::redraw_e needsRedraw, const QRect& rect)
84 {
85     if(rectSelection.isNull())
86     {
87         return;
88     }
89 
90     QRectF rectSel;
91     rectRad2Px(rectSelection, rectSel);
92 
93     QRectF rectScr = canvas->rect();
94 
95     rectTopLeft.moveTopLeft(rectSel.topLeft());
96     rectTopRight.moveTopRight(rectSel.topRight());
97     rectBottomLeft.moveBottomLeft(rectSel.bottomLeft());
98     rectBottomRight.moveBottomRight(rectSel.bottomRight());
99 
100 
101     QPainterPath path;
102     path.addRect(rectScr);
103     path.addRect(rectSel);
104 
105     p.setPen(Qt::black);
106     p.setBrush(QColor(0, 0, 0, 128));
107     p.drawPath(path);
108 
109     p.setBrush(Qt::lightGray);
110     p.drawRect(rectTopLeft);
111     p.drawRect(rectTopRight);
112     p.drawRect(rectBottomLeft);
113     p.drawRect(rectBottomRight);
114 
115     p.setBrush(Qt::red);
116     switch(corner)
117     {
118     case eCornerTopLeft:
119         p.drawRect(rectTopLeft);
120         break;
121 
122     case eCornerTopRight:
123         p.drawRect(rectTopRight);
124         break;
125 
126     case eCornerBottomLeft:
127         p.drawRect(rectBottomLeft);
128         break;
129 
130     case eCornerBottomRight:
131         p.drawRect(rectBottomRight);
132         break;
133     }
134 
135     placeScrOpt();
136 }
137 
leftButtonDown(const QPoint & point)138 void IMouseSelect::leftButtonDown(const QPoint& point)
139 {
140     canvas->reportStatus("IMouseSelect", "");
141     canvas->update();
142 }
143 
mouseDragged(const QPoint & start,const QPoint & last,const QPoint & end)144 void IMouseSelect::mouseDragged(const QPoint& start, const QPoint& last, const QPoint& end)
145 {
146     switch(state)
147     {
148     case eStateIdle:
149     {
150         QPointF pos(start);
151         gis->convertPx2Rad(pos);
152         rectSelection.setTopLeft(pos);
153         rectSelection.setBottomRight(pos);
154         posInitial = pos;
155         state = eStateInitial;
156         break;
157     }
158 
159     case eStateMap:
160     {
161         if(corner != eCornerNone)
162         {
163             state = eStateResize;
164         }
165         else
166         {
167             state = eStateMapMoving;
168         }
169         break;
170     }
171 
172     case eStateInitial:
173     {
174         QPointF pos(end);
175         gis->convertPx2Rad(pos);
176 
177         if(pos.x() < posInitial.x())
178         {
179             rectSelection.setLeft(pos.x());
180         }
181         else
182         {
183             rectSelection.setRight(pos.x());
184         }
185 
186         if(pos.y() < posInitial.y())
187         {
188             rectSelection.setBottom(pos.y());
189         }
190         else
191         {
192             rectSelection.setTop(pos.y());
193         }
194 
195         canvas->update();
196         break;
197     }
198 
199     case eStateResize:
200     {
201         QPointF pos = end - offset;
202         gis->convertPx2Rad(pos);
203         switch(corner)
204         {
205         case eCornerTopLeft:
206             rectSelection.setTopLeft(pos);
207             break;
208 
209         case eCornerTopRight:
210             rectSelection.setTopRight(pos);
211             break;
212 
213         case eCornerBottomLeft:
214             rectSelection.setBottomLeft(pos);
215             break;
216 
217         case eCornerBottomRight:
218             rectSelection.setBottomRight(pos);
219             break;
220         }
221 
222         canvas->update();
223         break;
224     }
225 
226     case eStateMapMoving:
227     {
228         IMouse::mouseDragged(start, last, end);
229         break;
230     }
231 
232     default:
233     {
234         Q_ASSERT(false);
235     }
236     }
237 }
238 
mouseMoved(const QPoint & pos)239 void IMouseSelect::mouseMoved(const QPoint& pos)
240 {
241     switch(state)
242     {
243     case eStateMap:
244     {
245         corner_e _corner = corner;
246         if(rectTopLeft.contains(pos))
247         {
248             offset = pos - rectTopLeft.topLeft();
249             corner = eCornerTopLeft;
250         }
251         else if(rectTopRight.contains(pos))
252         {
253             offset = pos - rectTopRight.topRight();
254             corner = eCornerTopRight;
255         }
256         else if(rectBottomLeft.contains(pos))
257         {
258             offset = pos - rectBottomLeft.bottomLeft();
259             corner = eCornerBottomLeft;
260         }
261         else if(rectBottomRight.contains(pos))
262         {
263             offset = pos - rectBottomRight.bottomRight();
264             corner = eCornerBottomRight;
265         }
266         else
267         {
268             corner = eCornerNone;
269         }
270 
271         if(corner != _corner)
272         {
273             canvas->update();
274         }
275         break;
276     }
277     }
278 }
279 
dragFinished(const QPoint & pos)280 void IMouseSelect::dragFinished(const QPoint& pos)
281 {
282     if(!rectSelection.isNull())
283     {
284         QPointF pt1 = rectSelection.topLeft();
285         QPointF pt2 = rectSelection.bottomRight();
286 
287         gis->convertRad2Px(pt1);
288         gis->convertRad2Px(pt2);
289 
290         QRectF rectSel(pt1, pt2);
291 
292         if(rectSel.width() < 40 || rectSel.height() < 40)
293         {
294             rectSelection = QRectF();
295         }
296     }
297 
298     state = rectSelection.isNull() ? eStateIdle : eStateMap;
299 
300     canvas->update();
301 }
302