placeable_window_proxy.cpp
Go to the documentation of this file.
1 // *****************************************************************************
2 //
3 // Copyright (c) 2014, Southwest Research Institute® (SwRI®)
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of Southwest Research Institute® (SwRI®) nor the
14 // names of its contributors may be used to endorse or promote products
15 // derived from this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 //
28 // *****************************************************************************
29 
31 
32 #include <math.h>
33 #include <cmath>
34 
35 #include <QApplication>
36 #include <QCursor>
37 #include <QLine>
38 #include <QMouseEvent>
39 #include <QResizeEvent>
40 #include <QTimerEvent>
41 #include <QWidget>
42 
43 #include <QDebug>
44 
45 namespace mapviz_plugins
46 {
48  :
49  target_(NULL),
50  visible_(true),
51  has_cursor_(false),
52  state_(INACTIVE),
53  win_resize_timer_(-1)
54 {
55 }
56 
58 {
59  if (target_)
60  {
61  target_->removeEventFilter(this);
62  }
63 }
64 
66 {
67  if (target_)
68  {
69  target_->removeEventFilter(this);
70  }
71 
72  target_ = target;
73 
74  if (target_)
75  {
76  target_->installEventFilter(this);
77  }
78 }
79 
81 {
82  return rect_.toRect();
83 }
84 
86 {
87  rect_ = QRectF(rect);
88  state_ = INACTIVE;
89 }
90 
92 {
93  if (visible == visible_)
94  {
95  return;
96  }
97 
98  visible_ = visible;
99 
100  if (!visible_ && state_ != INACTIVE)
101  {
102  if (has_cursor_)
103  {
104  QApplication::restoreOverrideCursor();
105  has_cursor_ = false;
106  }
107  state_ = INACTIVE;
108  }
109 }
110 
111 bool PlaceableWindowProxy::eventFilter(QObject *, QEvent *event)
112 {
113  // This should never happen, but doesn't hurt to be defensive.
114  if (!target_)
115  {
116  return false;
117  }
118 
119  if (!visible_)
120  {
121  return false;
122  }
123 
124  switch (event->type())
125  {
126  case QEvent::MouseButtonPress:
127  return handleMousePress(static_cast<QMouseEvent*>(event));
128  case QEvent::MouseButtonRelease:
129  return handleMouseRelease(static_cast<QMouseEvent*>(event));
130  case QEvent::MouseMove:
131  return handleMouseMove(static_cast<QMouseEvent*>(event));
132  case QEvent::Resize:
133  return handleResize(static_cast<QResizeEvent*>(event));
134  default:
135  return false;
136  }
137 }
138 
140 {
141  if (!visible_)
142  {
143  return false;
144  }
145 
146  if (!rect_.contains(event->pos()))
147  {
148  // We don't care about anything outside the rect.
149  return false;
150  }
151 
152  if (state_ != INACTIVE)
153  {
154  // We're already doing something, so we don't want to enter
155  // another state. But we also don't want someone else to start
156  // doing something, so we filter out the press.
157  return true;
158  }
159 
160  if (event->button() == Qt::LeftButton)
161  {
162  start_rect_ = rect_;
163  start_point_ = event->pos();
164  state_ = getNextState(event->localPos());
165  qWarning("changing state to %d", state_);
166  return true;
167  }
168 
169  // Event if we're not doing anything, we want to present a
170  // consistent interface that says "this region is belongs to me", so
171  // we filter out events.
172  return true;
173 }
174 
176 {
177  if (!visible_)
178  {
179  return false;
180  }
181 
182  if (state_ == INACTIVE)
183  {
184  return false;
185  }
186 
187  if (event->button() == Qt::LeftButton)
188  {
189  state_ = INACTIVE;
190  return true;
191  }
192 
193  return false;
194 }
195 
197 {
198  if (!visible_)
199  {
200  return false;
201  }
202 
203  if (state_ == INACTIVE)
204  {
205  if (!rect_.contains(event->localPos()))
206  {
207  if (has_cursor_)
208  {
209  QApplication::restoreOverrideCursor();
210  has_cursor_ = false;
211  }
212  return false;
213  }
214 
215  // The mouse cursor is over the rect, so we're going to change the
216  // cursor to indicate the state the user would enter by clicking.
217 
218  Qt::CursorShape shape;
219  switch(getNextState(event->localPos()))
220  {
221  case MOVE_TOP_LEFT:
222  case MOVE_BOTTOM_RIGHT:
223  shape = Qt::SizeFDiagCursor;
224  break;
225  case MOVE_TOP_RIGHT:
226  case MOVE_BOTTOM_LEFT:
227  shape = Qt::SizeBDiagCursor;
228  break;
229  default:
230  shape = Qt::SizeAllCursor;
231  }
232 
233  if (has_cursor_)
234  {
235  QApplication::changeOverrideCursor(QCursor(shape));
236  }
237  else
238  {
239  QApplication::setOverrideCursor(QCursor(shape));
240  has_cursor_ = true;
241  }
242 
243  return true;
244  }
245 
246  QPointF dp = event->localPos() - start_point_;
247 
248  // todo: enforce minimum size & constrain aspect ratio for resizes.
249  if (state_ == MOVE_ALL)
250  {
251  rect_ = start_rect_.translated(dp);
252  }
253  else if (state_ == MOVE_TOP_LEFT)
254  {
256  start_rect_.bottomRight(),
257  start_rect_.topLeft(),
258  event->localPos());
259  rect_.moveBottomRight(start_rect_.bottomRight());
260  }
261  else if (state_ == MOVE_BOTTOM_LEFT)
262  {
264  start_rect_.topRight(),
265  start_rect_.bottomLeft(),
266  event->localPos());
267  rect_.moveTopRight(start_rect_.topRight());
268  }
269  else if (state_ == MOVE_BOTTOM_RIGHT)
270  {
272  start_rect_.topLeft(),
273  start_rect_.bottomRight(),
274  event->localPos());
275  rect_.moveTopLeft(start_rect_.topLeft());
276  }
277  else if (state_ == MOVE_TOP_RIGHT)
278  {
280  start_rect_.bottomLeft(),
281  start_rect_.topRight(),
282  event->localPos());
283  rect_.moveBottomLeft(start_rect_.bottomLeft());
284  }
285  else
286  {
287  qWarning("Unhandled state in PlaceableWindowProxy: %d", state_);
288  }
289 
290  return true;
291 }
292 
294  const QPointF &p1,
295  const QPointF &p2,
296  const QPointF &p3) const
297 {
298  QPointF v1 = p2 - p1;
299  QPointF v2 = p3 - p1;
300 
301  double d = v1.x()*v2.y() - v1.y()*v2.x();
302  if (d < 0)
303  {
304  double new_width = std::abs(p3.x() - p1.x());
305  if (new_width < 10)
306  {
307  new_width = 10;
308  }
309 
310  double new_height = rect.height() / rect.width() * new_width;
311  return QRectF(0, 0, new_width, new_height);
312  }
313  else
314  {
315  double new_height = std::abs(p3.y() - p1.y());
316  if (new_height < 10)
317  {
318  new_height = 10;
319  }
320 
321  double new_width = rect.width() / rect.height() * new_height;
322  return QRectF(0, 0, new_width, new_height);
323  }
324 }
325 
326 
327 bool PlaceableWindowProxy::handleResize(QResizeEvent *event)
328 {
329  // QRectF overlap(rect_);
330 
331  // double w = event->oldSize().width() - rect_.width();
332  // double h = event->oldsize().height() - rect_.height();
333 
334  // double s_x = rect_.left() / w;
335  // double s_y = rect_.right() / h;
336 
337  // We always want to pass the resize event along to other widgets.
338  return false;
339 }
340 
341 void PlaceableWindowProxy::timerEvent(QTimerEvent *event)
342 {
343  if (event->timerId() == win_resize_timer_)
344  {
345  killTimer(win_resize_timer_);
346  win_resize_timer_ = -1;
347  if (target_)
348  {
349  winResize(target_->size());
350  }
351  }
352 }
353 
355 {
356 }
357 
358 void PlaceableWindowProxy::winResize(const QSize &size)
359 {
360 }
361 
363  const QPointF &pt) const
364 {
365  if (!rect_.contains(pt))
366  {
367  return INACTIVE;
368  }
369 
370  const double threshold = 10.0;
371  double near_left = pt.x() - rect_.left() < threshold;
372  double near_top = pt.y() - rect_.top() < threshold;
373  double near_right = rect_.right() - pt.x() < threshold;
374  double near_bottom = rect_.bottom() - pt.y() < threshold;
375 
376  if (near_top && near_left)
377  {
378  return MOVE_TOP_LEFT;
379  }
380  else if (near_top && near_right)
381  {
382  return MOVE_TOP_RIGHT;
383  }
384  else if (near_bottom && near_left)
385  {
386  return MOVE_BOTTOM_LEFT;
387  }
388  else if (near_bottom && near_right)
389  {
390  return MOVE_BOTTOM_RIGHT;
391  }
392  else
393  {
394  return MOVE_ALL;
395  }
396 }
397 } // namespace mapviz_plugins
d
#define NULL
bool eventFilter(QObject *object, QEvent *event)
State getNextState(const QPointF &pt) const
QRectF resizeHelper(const QRectF &rect, const QPointF &p1, const QPointF &p2, const QPointF &p3) const


mapviz_plugins
Author(s): Marc Alban
autogenerated on Thu Jun 6 2019 19:25:16