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 state_ = getNextState(event->posF());
00165 qWarning("changing state to %d", state_);
00166 return true;
00167 }
00168
00169
00170
00171
00172 return true;
00173 }
00174
00175 bool PlaceableWindowProxy::handleMouseRelease(QMouseEvent *event)
00176 {
00177 if (!visible_)
00178 {
00179 return false;
00180 }
00181
00182 if (state_ == INACTIVE)
00183 {
00184 return false;
00185 }
00186
00187 if (event->button() == Qt::LeftButton)
00188 {
00189 state_ = INACTIVE;
00190 return true;
00191 }
00192
00193 return false;
00194 }
00195
00196 bool PlaceableWindowProxy::handleMouseMove(QMouseEvent *event)
00197 {
00198 if (!visible_)
00199 {
00200 return false;
00201 }
00202
00203 if (state_ == INACTIVE)
00204 {
00205 if (!rect_.contains(event->posF()))
00206 {
00207 if (has_cursor_)
00208 {
00209 QApplication::restoreOverrideCursor();
00210 has_cursor_ = false;
00211 }
00212 return false;
00213 }
00214
00215
00216
00217
00218 Qt::CursorShape shape;
00219 switch(getNextState(event->posF()))
00220 {
00221 case MOVE_TOP_LEFT:
00222 case MOVE_BOTTOM_RIGHT:
00223 shape = Qt::SizeFDiagCursor;
00224 break;
00225 case MOVE_TOP_RIGHT:
00226 case MOVE_BOTTOM_LEFT:
00227 shape = Qt::SizeBDiagCursor;
00228 break;
00229 default:
00230 shape = Qt::SizeAllCursor;
00231 }
00232
00233 if (has_cursor_)
00234 {
00235 QApplication::changeOverrideCursor(QCursor(shape));
00236 }
00237 else
00238 {
00239 QApplication::setOverrideCursor(QCursor(shape));
00240 has_cursor_ = true;
00241 }
00242
00243 return true;
00244 }
00245
00246 QPointF dp = event->posF() - start_point_;
00247
00248
00249 if (state_ == MOVE_ALL)
00250 {
00251 rect_ = start_rect_.translated(dp);
00252 }
00253 else if (state_ == MOVE_TOP_LEFT)
00254 {
00255 rect_= resizeHelper(start_rect_,
00256 start_rect_.bottomRight(),
00257 start_rect_.topLeft(),
00258 event->posF());
00259 rect_.moveBottomRight(start_rect_.bottomRight());
00260 }
00261 else if (state_ == MOVE_BOTTOM_LEFT)
00262 {
00263 rect_= resizeHelper(start_rect_,
00264 start_rect_.topRight(),
00265 start_rect_.bottomLeft(),
00266 event->posF());
00267 rect_.moveTopRight(start_rect_.topRight());
00268 }
00269 else if (state_ == MOVE_BOTTOM_RIGHT)
00270 {
00271 rect_= resizeHelper(start_rect_,
00272 start_rect_.topLeft(),
00273 start_rect_.bottomRight(),
00274 event->posF());
00275 rect_.moveTopLeft(start_rect_.topLeft());
00276 }
00277 else if (state_ == MOVE_TOP_RIGHT)
00278 {
00279 rect_= resizeHelper(start_rect_,
00280 start_rect_.bottomLeft(),
00281 start_rect_.topRight(),
00282 event->posF());
00283 rect_.moveBottomLeft(start_rect_.bottomLeft());
00284 }
00285 else
00286 {
00287 qWarning("Unhandled state in PlaceableWindowProxy: %d", state_);
00288 }
00289
00290 return true;
00291 }
00292
00293 QRectF PlaceableWindowProxy::resizeHelper(const QRectF &rect,
00294 const QPointF &p1,
00295 const QPointF &p2,
00296 const QPointF &p3) const
00297 {
00298 QPointF v1 = p2 - p1;
00299 QPointF v2 = p3 - p1;
00300
00301 double d = v1.x()*v2.y() - v1.y()*v2.x();
00302 if (d < 0)
00303 {
00304 double new_width = std::abs(p3.x() - p1.x());
00305 if (new_width < 10)
00306 {
00307 new_width = 10;
00308 }
00309
00310 double new_height = rect.height() / rect.width() * new_width;
00311 return QRectF(0, 0, new_width, new_height);
00312 }
00313 else
00314 {
00315 double new_height = std::abs(p3.y() - p1.y());
00316 if (new_height < 10)
00317 {
00318 new_height = 10;
00319 }
00320
00321 double new_width = rect.width() / rect.height() * new_height;
00322 return QRectF(0, 0, new_width, new_height);
00323 }
00324 }
00325
00326
00327 bool PlaceableWindowProxy::handleResize(QResizeEvent *event)
00328 {
00329
00330 return false;
00331 }
00332
00333 void PlaceableWindowProxy::timerEvent(QTimerEvent *event)
00334 {
00335 if (event->timerId() == win_resize_timer_)
00336 {
00337 killTimer(win_resize_timer_);
00338 win_resize_timer_ = -1;
00339 if (target_)
00340 {
00341 winResize(target_->size());
00342 }
00343 }
00344 }
00345
00346 void PlaceableWindowProxy::rectResize(int dx, int dy)
00347 {
00348 }
00349
00350 void PlaceableWindowProxy::winResize(const QSize &size)
00351 {
00352 }
00353
00354 PlaceableWindowProxy::State PlaceableWindowProxy::getNextState(
00355 const QPointF &pt) const
00356 {
00357 if (!rect_.contains(pt))
00358 {
00359 return INACTIVE;
00360 }
00361
00362 const double threshold = 10.0;
00363 double near_left = pt.x() - rect_.left() < threshold;
00364 double near_top = pt.y() - rect_.top() < threshold;
00365 double near_right = rect_.right() - pt.x() < threshold;
00366 double near_bottom = rect_.bottom() - pt.y() < threshold;
00367
00368 if (near_top && near_left)
00369 {
00370 return MOVE_TOP_LEFT;
00371 }
00372 else if (near_top && near_right)
00373 {
00374 return MOVE_TOP_RIGHT;
00375 }
00376 else if (near_bottom && near_left)
00377 {
00378 return MOVE_BOTTOM_LEFT;
00379 }
00380 else if (near_bottom && near_right)
00381 {
00382 return MOVE_BOTTOM_RIGHT;
00383 }
00384 else
00385 {
00386 return MOVE_ALL;
00387 }
00388 }
00389 }