Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <mapviz_plugins/placeable_window_proxy.h>
00031
00032 #include <math.h>
00033 #include <cmath>
00034
00035 #include <QApplication>
00036 #include <QCursor>
00037 #include <QLine>
00038 #include <QMouseEvent>
00039 #include <QResizeEvent>
00040 #include <QTimerEvent>
00041 #include <QWidget>
00042
00043 #include <QDebug>
00044
00045 namespace mapviz_plugins
00046 {
00047 PlaceableWindowProxy::PlaceableWindowProxy()
00048 :
00049 target_(NULL),
00050 visible_(true),
00051 has_cursor_(false),
00052 state_(INACTIVE),
00053 win_resize_timer_(-1)
00054 {
00055 }
00056
00057 PlaceableWindowProxy::~PlaceableWindowProxy()
00058 {
00059 if (target_)
00060 {
00061 target_->removeEventFilter(this);
00062 }
00063 }
00064
00065 void PlaceableWindowProxy::setContainer(QWidget *target)
00066 {
00067 if (target_)
00068 {
00069 target_->removeEventFilter(this);
00070 }
00071
00072 target_ = target;
00073
00074 if (target_)
00075 {
00076 target_->installEventFilter(this);
00077 }
00078 }
00079
00080 QRect PlaceableWindowProxy::rect() const
00081 {
00082 return rect_.toRect();
00083 }
00084
00085 void PlaceableWindowProxy::setRect(const QRect &rect)
00086 {
00087 rect_ = QRectF(rect);
00088 state_ = INACTIVE;
00089 }
00090
00091 void PlaceableWindowProxy::setVisible(bool visible)
00092 {
00093 if (visible == visible_)
00094 {
00095 return;
00096 }
00097
00098 visible_ = visible;
00099
00100 if (!visible_ && state_ != INACTIVE)
00101 {
00102 if (has_cursor_)
00103 {
00104 QApplication::restoreOverrideCursor();
00105 has_cursor_ = false;
00106 }
00107 state_ = INACTIVE;
00108 }
00109 }
00110
00111 bool PlaceableWindowProxy::eventFilter(QObject *, QEvent *event)
00112 {
00113
00114 if (!target_)
00115 {
00116 return false;
00117 }
00118
00119 if (!visible_)
00120 {
00121 return false;
00122 }
00123
00124 switch (event->type())
00125 {
00126 case QEvent::MouseButtonPress:
00127 return handleMousePress(static_cast<QMouseEvent*>(event));
00128 case QEvent::MouseButtonRelease:
00129 return handleMouseRelease(static_cast<QMouseEvent*>(event));
00130 case QEvent::MouseMove:
00131 return handleMouseMove(static_cast<QMouseEvent*>(event));
00132 case QEvent::Resize:
00133 return handleResize(static_cast<QResizeEvent*>(event));
00134 default:
00135 return false;
00136 }
00137 }
00138
00139 bool PlaceableWindowProxy::handleMousePress(QMouseEvent *event)
00140 {
00141 if (!visible_)
00142 {
00143 return false;
00144 }
00145
00146 if (!rect_.contains(event->pos()))
00147 {
00148
00149 return false;
00150 }
00151
00152 if (state_ != INACTIVE)
00153 {
00154
00155
00156
00157 return true;
00158 }
00159
00160 if (event->button() == Qt::LeftButton)
00161 {
00162 start_rect_ = rect_;
00163 start_point_ = event->pos();
00164 #if QT_VERSION >= 0x050000
00165 state_ = getNextState(event->localPos());
00166 #else
00167 state_ = getNextState(event->posF());
00168 #endif
00169 qWarning("changing state to %d", state_);
00170 return true;
00171 }
00172
00173
00174
00175
00176 return true;
00177 }
00178
00179 bool PlaceableWindowProxy::handleMouseRelease(QMouseEvent *event)
00180 {
00181 if (!visible_)
00182 {
00183 return false;
00184 }
00185
00186 if (state_ == INACTIVE)
00187 {
00188 return false;
00189 }
00190
00191 if (event->button() == Qt::LeftButton)
00192 {
00193 state_ = INACTIVE;
00194 return true;
00195 }
00196
00197 return false;
00198 }
00199
00200 bool PlaceableWindowProxy::handleMouseMove(QMouseEvent *event)
00201 {
00202 if (!visible_)
00203 {
00204 return false;
00205 }
00206
00207 if (state_ == INACTIVE)
00208 {
00209 #if QT_VERSION >= 0x050000
00210 if (!rect_.contains(event->localPos()))
00211 #else
00212 if (!rect_.contains(event->posF()))
00213 #endif
00214 {
00215 if (has_cursor_)
00216 {
00217 QApplication::restoreOverrideCursor();
00218 has_cursor_ = false;
00219 }
00220 return false;
00221 }
00222
00223
00224
00225
00226 Qt::CursorShape shape;
00227 #if QT_VERSION >= 0x050000
00228 switch(getNextState(event->localPos()))
00229 #else
00230 switch(getNextState(event->posF()))
00231 #endif
00232 {
00233 case MOVE_TOP_LEFT:
00234 case MOVE_BOTTOM_RIGHT:
00235 shape = Qt::SizeFDiagCursor;
00236 break;
00237 case MOVE_TOP_RIGHT:
00238 case MOVE_BOTTOM_LEFT:
00239 shape = Qt::SizeBDiagCursor;
00240 break;
00241 default:
00242 shape = Qt::SizeAllCursor;
00243 }
00244
00245 if (has_cursor_)
00246 {
00247 QApplication::changeOverrideCursor(QCursor(shape));
00248 }
00249 else
00250 {
00251 QApplication::setOverrideCursor(QCursor(shape));
00252 has_cursor_ = true;
00253 }
00254
00255 return true;
00256 }
00257
00258 #if QT_VERSION >= 0x050000
00259 QPointF dp = event->localPos() - start_point_;
00260 #else
00261 QPointF dp = event->posF() - start_point_;
00262 #endif
00263
00264
00265 if (state_ == MOVE_ALL)
00266 {
00267 rect_ = start_rect_.translated(dp);
00268 }
00269 else if (state_ == MOVE_TOP_LEFT)
00270 {
00271 rect_= resizeHelper(start_rect_,
00272 start_rect_.bottomRight(),
00273 start_rect_.topLeft(),
00274 #if QT_VERSION >= 0x050000
00275 event->localPos());
00276 #else
00277 event->posF());
00278 #endif
00279 rect_.moveBottomRight(start_rect_.bottomRight());
00280 }
00281 else if (state_ == MOVE_BOTTOM_LEFT)
00282 {
00283 rect_= resizeHelper(start_rect_,
00284 start_rect_.topRight(),
00285 start_rect_.bottomLeft(),
00286 #if QT_VERSION >= 0x050000
00287 event->localPos());
00288 #else
00289 event->posF());
00290 #endif
00291 rect_.moveTopRight(start_rect_.topRight());
00292 }
00293 else if (state_ == MOVE_BOTTOM_RIGHT)
00294 {
00295 rect_= resizeHelper(start_rect_,
00296 start_rect_.topLeft(),
00297 start_rect_.bottomRight(),
00298 #if QT_VERSION >= 0x050000
00299 event->localPos());
00300 #else
00301 event->posF());
00302 #endif
00303 rect_.moveTopLeft(start_rect_.topLeft());
00304 }
00305 else if (state_ == MOVE_TOP_RIGHT)
00306 {
00307 rect_= resizeHelper(start_rect_,
00308 start_rect_.bottomLeft(),
00309 start_rect_.topRight(),
00310 #if QT_VERSION >= 0x050000
00311 event->localPos());
00312 #else
00313 event->posF());
00314 #endif
00315 rect_.moveBottomLeft(start_rect_.bottomLeft());
00316 }
00317 else
00318 {
00319 qWarning("Unhandled state in PlaceableWindowProxy: %d", state_);
00320 }
00321
00322 return true;
00323 }
00324
00325 QRectF PlaceableWindowProxy::resizeHelper(const QRectF &rect,
00326 const QPointF &p1,
00327 const QPointF &p2,
00328 const QPointF &p3) const
00329 {
00330 QPointF v1 = p2 - p1;
00331 QPointF v2 = p3 - p1;
00332
00333 double d = v1.x()*v2.y() - v1.y()*v2.x();
00334 if (d < 0)
00335 {
00336 double new_width = std::abs(p3.x() - p1.x());
00337 if (new_width < 10)
00338 {
00339 new_width = 10;
00340 }
00341
00342 double new_height = rect.height() / rect.width() * new_width;
00343 return QRectF(0, 0, new_width, new_height);
00344 }
00345 else
00346 {
00347 double new_height = std::abs(p3.y() - p1.y());
00348 if (new_height < 10)
00349 {
00350 new_height = 10;
00351 }
00352
00353 double new_width = rect.width() / rect.height() * new_height;
00354 return QRectF(0, 0, new_width, new_height);
00355 }
00356 }
00357
00358
00359 bool PlaceableWindowProxy::handleResize(QResizeEvent *event)
00360 {
00361
00362 return false;
00363 }
00364
00365 void PlaceableWindowProxy::timerEvent(QTimerEvent *event)
00366 {
00367 if (event->timerId() == win_resize_timer_)
00368 {
00369 killTimer(win_resize_timer_);
00370 win_resize_timer_ = -1;
00371 if (target_)
00372 {
00373 winResize(target_->size());
00374 }
00375 }
00376 }
00377
00378 void PlaceableWindowProxy::rectResize(int dx, int dy)
00379 {
00380 }
00381
00382 void PlaceableWindowProxy::winResize(const QSize &size)
00383 {
00384 }
00385
00386 PlaceableWindowProxy::State PlaceableWindowProxy::getNextState(
00387 const QPointF &pt) const
00388 {
00389 if (!rect_.contains(pt))
00390 {
00391 return INACTIVE;
00392 }
00393
00394 const double threshold = 10.0;
00395 double near_left = pt.x() - rect_.left() < threshold;
00396 double near_top = pt.y() - rect_.top() < threshold;
00397 double near_right = rect_.right() - pt.x() < threshold;
00398 double near_bottom = rect_.bottom() - pt.y() < threshold;
00399
00400 if (near_top && near_left)
00401 {
00402 return MOVE_TOP_LEFT;
00403 }
00404 else if (near_top && near_right)
00405 {
00406 return MOVE_TOP_RIGHT;
00407 }
00408 else if (near_bottom && near_left)
00409 {
00410 return MOVE_BOTTOM_LEFT;
00411 }
00412 else if (near_bottom && near_right)
00413 {
00414 return MOVE_BOTTOM_RIGHT;
00415 }
00416 else
00417 {
00418 return MOVE_ALL;
00419 }
00420 }
00421 }