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 #if QT_VERSION >= 0x050000
165  state_ = getNextState(event->localPos());
166 #else
167  state_ = getNextState(event->posF());
168 #endif
169  qWarning("changing state to %d", state_);
170  return true;
171  }
172 
173  // Event if we're not doing anything, we want to present a
174  // consistent interface that says "this region is belongs to me", so
175  // we filter out events.
176  return true;
177 }
178 
180 {
181  if (!visible_)
182  {
183  return false;
184  }
185 
186  if (state_ == INACTIVE)
187  {
188  return false;
189  }
190 
191  if (event->button() == Qt::LeftButton)
192  {
193  state_ = INACTIVE;
194  return true;
195  }
196 
197  return false;
198 }
199 
201 {
202  if (!visible_)
203  {
204  return false;
205  }
206 
207  if (state_ == INACTIVE)
208  {
209 #if QT_VERSION >= 0x050000
210  if (!rect_.contains(event->localPos()))
211 #else
212  if (!rect_.contains(event->posF()))
213 #endif
214  {
215  if (has_cursor_)
216  {
217  QApplication::restoreOverrideCursor();
218  has_cursor_ = false;
219  }
220  return false;
221  }
222 
223  // The mouse cursor is over the rect, so we're going to change the
224  // cursor to indicate the state the user would enter by clicking.
225 
226  Qt::CursorShape shape;
227 #if QT_VERSION >= 0x050000
228  switch(getNextState(event->localPos()))
229 #else
230  switch(getNextState(event->posF()))
231 #endif
232  {
233  case MOVE_TOP_LEFT:
234  case MOVE_BOTTOM_RIGHT:
235  shape = Qt::SizeFDiagCursor;
236  break;
237  case MOVE_TOP_RIGHT:
238  case MOVE_BOTTOM_LEFT:
239  shape = Qt::SizeBDiagCursor;
240  break;
241  default:
242  shape = Qt::SizeAllCursor;
243  }
244 
245  if (has_cursor_)
246  {
247  QApplication::changeOverrideCursor(QCursor(shape));
248  }
249  else
250  {
251  QApplication::setOverrideCursor(QCursor(shape));
252  has_cursor_ = true;
253  }
254 
255  return true;
256  }
257 
258 #if QT_VERSION >= 0x050000
259  QPointF dp = event->localPos() - start_point_;
260 #else
261  QPointF dp = event->posF() - start_point_;
262 #endif
263 
264  // todo: enforce minimum size & constrain aspect ratio for resizes.
265  if (state_ == MOVE_ALL)
266  {
267  rect_ = start_rect_.translated(dp);
268  }
269  else if (state_ == MOVE_TOP_LEFT)
270  {
272  start_rect_.bottomRight(),
273  start_rect_.topLeft(),
274 #if QT_VERSION >= 0x050000
275  event->localPos());
276 #else
277  event->posF());
278 #endif
279  rect_.moveBottomRight(start_rect_.bottomRight());
280  }
281  else if (state_ == MOVE_BOTTOM_LEFT)
282  {
284  start_rect_.topRight(),
285  start_rect_.bottomLeft(),
286 #if QT_VERSION >= 0x050000
287  event->localPos());
288 #else
289  event->posF());
290 #endif
291  rect_.moveTopRight(start_rect_.topRight());
292  }
293  else if (state_ == MOVE_BOTTOM_RIGHT)
294  {
296  start_rect_.topLeft(),
297  start_rect_.bottomRight(),
298 #if QT_VERSION >= 0x050000
299  event->localPos());
300 #else
301  event->posF());
302 #endif
303  rect_.moveTopLeft(start_rect_.topLeft());
304  }
305  else if (state_ == MOVE_TOP_RIGHT)
306  {
308  start_rect_.bottomLeft(),
309  start_rect_.topRight(),
310 #if QT_VERSION >= 0x050000
311  event->localPos());
312 #else
313  event->posF());
314 #endif
315  rect_.moveBottomLeft(start_rect_.bottomLeft());
316  }
317  else
318  {
319  qWarning("Unhandled state in PlaceableWindowProxy: %d", state_);
320  }
321 
322  return true;
323 }
324 
326  const QPointF &p1,
327  const QPointF &p2,
328  const QPointF &p3) const
329 {
330  QPointF v1 = p2 - p1;
331  QPointF v2 = p3 - p1;
332 
333  double d = v1.x()*v2.y() - v1.y()*v2.x();
334  if (d < 0)
335  {
336  double new_width = std::abs(p3.x() - p1.x());
337  if (new_width < 10)
338  {
339  new_width = 10;
340  }
341 
342  double new_height = rect.height() / rect.width() * new_width;
343  return QRectF(0, 0, new_width, new_height);
344  }
345  else
346  {
347  double new_height = std::abs(p3.y() - p1.y());
348  if (new_height < 10)
349  {
350  new_height = 10;
351  }
352 
353  double new_width = rect.width() / rect.height() * new_height;
354  return QRectF(0, 0, new_width, new_height);
355  }
356 }
357 
358 
359 bool PlaceableWindowProxy::handleResize(QResizeEvent *event)
360 {
361  // We always want to pass the resize event along to other widgets.
362  return false;
363 }
364 
365 void PlaceableWindowProxy::timerEvent(QTimerEvent *event)
366 {
367  if (event->timerId() == win_resize_timer_)
368  {
369  killTimer(win_resize_timer_);
370  win_resize_timer_ = -1;
371  if (target_)
372  {
373  winResize(target_->size());
374  }
375  }
376 }
377 
379 {
380 }
381 
382 void PlaceableWindowProxy::winResize(const QSize &size)
383 {
384 }
385 
387  const QPointF &pt) const
388 {
389  if (!rect_.contains(pt))
390  {
391  return INACTIVE;
392  }
393 
394  const double threshold = 10.0;
395  double near_left = pt.x() - rect_.left() < threshold;
396  double near_top = pt.y() - rect_.top() < threshold;
397  double near_right = rect_.right() - pt.x() < threshold;
398  double near_bottom = rect_.bottom() - pt.y() < threshold;
399 
400  if (near_top && near_left)
401  {
402  return MOVE_TOP_LEFT;
403  }
404  else if (near_top && near_right)
405  {
406  return MOVE_TOP_RIGHT;
407  }
408  else if (near_bottom && near_left)
409  {
410  return MOVE_BOTTOM_LEFT;
411  }
412  else if (near_bottom && near_right)
413  {
414  return MOVE_BOTTOM_RIGHT;
415  }
416  else
417  {
418  return MOVE_ALL;
419  }
420 }
421 } // namespace mapviz_plugins
d
#define NULL
State getNextState(const QPointF &pt) const
bool eventFilter(QObject *object, QEvent *event)
QRectF resizeHelper(const QRectF &rect, const QPointF &p1, const QPointF &p2, const QPointF &p3) const


mapviz_plugins
Author(s): Marc Alban
autogenerated on Fri Dec 16 2022 03:59:33