annotate src/panned.cpp @ 606:372b191247da

Add carriage return to hgignore file before new material, if it didn't end with one before
author Chris Cannam
date Tue, 03 Jul 2012 11:39:03 +0100
parents 533519ebc0cb
children ae67ea0af696
rev   line source
Chris@57 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
cannam@45 2
cannam@45 3 /*
Chris@57 4 EasyMercurial
cannam@45 5
Chris@57 6 Based on HgExplorer by Jari Korhonen
Chris@57 7 Copyright (c) 2010 Jari Korhonen
Chris@560 8 Copyright (c) 2012 Chris Cannam
Chris@560 9 Copyright (c) 2012 Queen Mary, University of London
Chris@57 10
cannam@45 11 This program is free software; you can redistribute it and/or
cannam@45 12 modify it under the terms of the GNU General Public License as
cannam@45 13 published by the Free Software Foundation; either version 2 of the
cannam@45 14 License, or (at your option) any later version. See the file
cannam@45 15 COPYING included with this distribution for more information.
cannam@45 16 */
cannam@45 17
cannam@45 18 #include "panned.h"
Chris@131 19 #include "debug.h"
cannam@45 20
cannam@45 21 #include <QScrollBar>
Chris@53 22 #include <QWheelEvent>
Chris@168 23 #include <QTimer>
Chris@168 24
Chris@168 25 #include <cmath>
cannam@45 26
cannam@45 27 #include <iostream>
cannam@45 28
Chris@168 29 Panned::Panned() :
Chris@168 30 m_dragging(false)
cannam@45 31 {
Chris@168 32 m_dragTimer = new QTimer(this);
Chris@168 33 m_dragTimerMs = 50;
Chris@168 34 connect(m_dragTimer, SIGNAL(timeout()), this, SLOT(dragTimerTimeout()));
Chris@56 35 setRenderHints(QPainter::Antialiasing |
Chris@56 36 QPainter::TextAntialiasing);
cannam@45 37 }
cannam@45 38
cannam@45 39 void
cannam@45 40 Panned::resizeEvent(QResizeEvent *ev)
cannam@45 41 {
Chris@131 42 DEBUG << "Panned::resizeEvent()" << endl;
Chris@131 43
Chris@60 44 QPointF nearpt = mapToScene(0, 0);
Chris@60 45 QPointF farpt = mapToScene(width(), height());
Chris@60 46 QSizeF sz(farpt.x()-nearpt.x(), farpt.y()-nearpt.y());
Chris@60 47 QRectF pr(nearpt, sz);
cannam@45 48
Chris@132 49 QGraphicsView::resizeEvent(ev);
Chris@132 50
cannam@45 51 if (pr != m_pannedRect) {
Chris@132 52 DEBUG << "Panned: setting panned rect to " << pr << endl;
cannam@45 53 m_pannedRect = pr;
Chris@133 54 centerOn(pr.center());
Chris@133 55 emit pannedRectChanged(pr);
Chris@133 56 }
Chris@133 57 }
Chris@133 58
Chris@133 59 void
Chris@133 60 Panned::setScene(QGraphicsScene *s)
Chris@133 61 {
Chris@133 62 if (!scene()) {
Chris@133 63 QGraphicsView::setScene(s);
Chris@133 64 return;
Chris@133 65 }
Chris@133 66
Chris@133 67 QPointF nearpt = mapToScene(0, 0);
Chris@133 68 QPointF farpt = mapToScene(width(), height());
Chris@133 69 QSizeF sz(farpt.x()-nearpt.x(), farpt.y()-nearpt.y());
Chris@133 70 QRectF pr(nearpt, sz);
Chris@133 71
Chris@133 72 QGraphicsView::setScene(s);
Chris@133 73
Chris@133 74 DEBUG << "Panned::setScene: pr = " << pr << ", sceneRect = " << sceneRect() << endl;
Chris@133 75
Chris@133 76 if (scene() && sceneRect().intersects(pr)) {
Chris@133 77 DEBUG << "Panned::setScene: restoring old rect " << pr << endl;
Chris@133 78 m_pannedRect = pr;
Chris@133 79 centerOn(pr.center());
cannam@45 80 emit pannedRectChanged(pr);
cannam@45 81 }
cannam@45 82 }
cannam@45 83
cannam@45 84 void
cannam@45 85 Panned::paintEvent(QPaintEvent *e)
cannam@45 86 {
cannam@45 87 QGraphicsView::paintEvent(e);
cannam@45 88 }
cannam@45 89
cannam@45 90 void
cannam@45 91 Panned::drawForeground(QPainter *paint, const QRectF &)
cannam@45 92 {
Chris@60 93 QPointF nearpt = mapToScene(0, 0);
Chris@60 94 QPointF farpt = mapToScene(width(), height());
Chris@60 95 QSizeF sz(farpt.x()-nearpt.x(), farpt.y()-nearpt.y());
Chris@60 96 QRectF pr(nearpt, sz);
cannam@45 97
cannam@45 98 if (pr != m_pannedRect) {
Chris@133 99 DEBUG << "Panned::drawForeground: visible rect " << pr << " differs from panned rect " << m_pannedRect << ", updating panned rect" <<endl;
cannam@45 100 if (pr.x() != m_pannedRect.x()) emit pannedContentsScrolled();
cannam@45 101 m_pannedRect = pr;
cannam@45 102 emit pannedRectChanged(pr);
cannam@45 103 }
cannam@45 104 }
cannam@45 105
cannam@45 106 void
Chris@53 107 Panned::zoomIn()
Chris@53 108 {
Chris@53 109 QMatrix m = matrix();
Chris@53 110 m.scale(1.0 / 1.1, 1.0 / 1.1);
Chris@53 111 setMatrix(m);
Chris@53 112 }
Chris@53 113
Chris@53 114 void
Chris@53 115 Panned::zoomOut()
Chris@53 116 {
Chris@53 117 QMatrix m = matrix();
Chris@53 118 m.scale(1.1, 1.1);
Chris@53 119 setMatrix(m);
Chris@53 120 }
Chris@53 121
Chris@53 122 void
cannam@45 123 Panned::slotSetPannedRect(QRectF pr)
cannam@45 124 {
cannam@45 125 centerOn(pr.center());
cannam@45 126 // setSceneRect(pr);
cannam@45 127 // m_pannedRect = pr;
cannam@45 128 }
cannam@45 129
cannam@45 130 void
cannam@45 131 Panned::wheelEvent(QWheelEvent *ev)
cannam@45 132 {
Chris@53 133 if (ev->modifiers() & Qt::ControlModifier) {
Chris@53 134 int d = ev->delta();
Chris@53 135 if (d > 0) {
Chris@53 136 while (d > 0) {
Chris@53 137 zoomOut();
Chris@53 138 d -= 120;
Chris@53 139 }
Chris@53 140 } else {
Chris@53 141 while (d < 0) {
Chris@53 142 zoomIn();
Chris@53 143 d += 120;
Chris@53 144 }
Chris@53 145 }
Chris@53 146 } else {
Chris@53 147 emit wheelEventReceived(ev);
Chris@53 148 QGraphicsView::wheelEvent(ev);
Chris@53 149 }
cannam@45 150 }
cannam@45 151
cannam@45 152 void
cannam@45 153 Panned::slotEmulateWheelEvent(QWheelEvent *ev)
cannam@45 154 {
cannam@45 155 QGraphicsView::wheelEvent(ev);
cannam@45 156 }
cannam@45 157
cannam@45 158 void
Chris@168 159 Panned::mousePressEvent(QMouseEvent *ev)
Chris@168 160 {
Chris@168 161 if (dragMode() != QGraphicsView::ScrollHandDrag ||
Chris@168 162 ev->button() != Qt::LeftButton) {
Chris@168 163 QGraphicsView::mousePressEvent(ev);
Chris@168 164 return;
Chris@168 165 }
Chris@168 166
Chris@168 167 DEBUG << "Panned::mousePressEvent: have left button in drag mode" << endl;
Chris@168 168
Chris@168 169 setDragMode(QGraphicsView::NoDrag);
Chris@168 170 QGraphicsView::mousePressEvent(ev);
Chris@168 171 setDragMode(QGraphicsView::ScrollHandDrag);
Chris@168 172
Chris@168 173 if (!ev->isAccepted()) {
Chris@168 174 ev->accept();
Chris@168 175 m_dragging = true;
Chris@168 176 m_lastDragPos = ev->pos();
Chris@403 177 m_lastDragStart = ev->pos();
Chris@168 178 m_lastOrigin = QPoint(horizontalScrollBar()->value(),
Chris@168 179 verticalScrollBar()->value());
Chris@168 180 m_velocity = QPointF(0, 0);
Chris@168 181 m_dragTimer->start(m_dragTimerMs);
Chris@403 182 m_dragDirection = UnknownDrag;
Chris@403 183 }
Chris@403 184 }
Chris@403 185
Chris@403 186 void
Chris@403 187 Panned::updateDragDirection(QPoint pos)
Chris@403 188 {
Chris@403 189 if (m_dragDirection == FreeDrag) {
Chris@403 190 return;
Chris@168 191 }
Chris@168 192
Chris@403 193 QPoint overall = pos - m_lastDragStart;
Chris@403 194
Chris@403 195 int smallThreshold = 10;
Chris@403 196 int largeThreshold = 30;
Chris@403 197 int dx = qAbs(overall.x());
Chris@403 198 int dy = qAbs(overall.y());
Chris@403 199
Chris@403 200 switch (m_dragDirection) {
Chris@403 201
Chris@403 202 case UnknownDrag:
Chris@403 203 if (dx > smallThreshold) {
Chris@403 204 if (dy > smallThreshold) {
Chris@403 205 m_dragDirection = FreeDrag;
Chris@403 206 } else {
Chris@403 207 m_dragDirection = HorizontalDrag;
Chris@403 208 }
Chris@403 209 } else if (dy > smallThreshold) {
Chris@403 210 m_dragDirection = VerticalDrag;
Chris@403 211 }
Chris@403 212 break;
Chris@403 213
Chris@403 214 case HorizontalDrag:
Chris@403 215 if (dy > largeThreshold) {
Chris@403 216 m_dragDirection = FreeDrag;
Chris@403 217 }
Chris@403 218 break;
Chris@403 219
Chris@403 220 case VerticalDrag:
Chris@403 221 if (dx > largeThreshold) {
Chris@403 222 m_dragDirection = FreeDrag;
Chris@403 223 }
Chris@403 224 break;
Chris@403 225 };
Chris@168 226 }
Chris@168 227
Chris@168 228 void
Chris@168 229 Panned::mouseMoveEvent(QMouseEvent *ev)
Chris@168 230 {
Chris@168 231 if (!m_dragging) {
Chris@168 232 QGraphicsView::mouseMoveEvent(ev);
Chris@168 233 return;
Chris@168 234 }
Chris@168 235 DEBUG << "Panned::mouseMoveEvent: dragging" << endl;
Chris@168 236 ev->accept();
Chris@403 237 updateDragDirection(ev->pos());
Chris@168 238 QScrollBar *hBar = horizontalScrollBar();
Chris@168 239 QScrollBar *vBar = verticalScrollBar();
Chris@168 240 QPoint delta = ev->pos() - m_lastDragPos;
Chris@403 241 if (m_dragDirection != VerticalDrag) {
Chris@403 242 hBar->setValue(hBar->value() +
Chris@403 243 (isRightToLeft() ? delta.x() : -delta.x()));
Chris@403 244 }
Chris@403 245 if (m_dragDirection != HorizontalDrag) {
Chris@403 246 vBar->setValue(vBar->value() - delta.y());
Chris@403 247 }
Chris@168 248 m_lastDragPos = ev->pos();
Chris@168 249 }
Chris@168 250
Chris@168 251 void
Chris@168 252 Panned::mouseReleaseEvent(QMouseEvent *ev)
Chris@168 253 {
Chris@168 254 if (!m_dragging) {
Chris@168 255 QGraphicsView::mouseReleaseEvent(ev);
Chris@168 256 return;
Chris@168 257 }
Chris@168 258 DEBUG << "Panned::mouseReleaseEvent: dragging" << endl;
Chris@168 259 ev->accept();
Chris@168 260 m_dragging = false;
Chris@168 261 }
Chris@168 262
Chris@168 263 void
Chris@168 264 Panned::dragTimerTimeout()
Chris@168 265 {
Chris@168 266 QPoint origin = QPoint(horizontalScrollBar()->value(),
Chris@168 267 verticalScrollBar()->value());
Chris@168 268 if (m_dragging) {
Chris@168 269 m_velocity = QPointF
Chris@168 270 (float(origin.x() - m_lastOrigin.x()) / m_dragTimerMs,
Chris@168 271 float(origin.y() - m_lastOrigin.y()) / m_dragTimerMs);
Chris@168 272 m_lastOrigin = origin;
Chris@168 273 DEBUG << "Panned::dragTimerTimeout: velocity = " << m_velocity << endl;
Chris@168 274 } else {
Chris@168 275 if (origin == m_lastOrigin) {
Chris@168 276 m_dragTimer->stop();
Chris@168 277 }
Chris@168 278 float x = m_velocity.x(), y = m_velocity.y();
Chris@168 279 if (fabsf(x) > 1.0/m_dragTimerMs) x = x * 0.9f;
Chris@168 280 else x = 0.f;
Chris@168 281 if (fabsf(y) > 1.0/m_dragTimerMs) y = y * 0.9f;
Chris@168 282 else y = 0.f;
Chris@168 283 m_velocity = QPointF(x, y);
Chris@168 284 DEBUG << "Panned::dragTimerTimeout: velocity adjusted to " << m_velocity << endl;
Chris@168 285 m_lastOrigin = origin;
Chris@168 286 //!!! need to store origin in floats
Chris@403 287 if (m_dragDirection != VerticalDrag) {
Chris@403 288 horizontalScrollBar()->setValue(m_lastOrigin.x() +
Chris@403 289 m_velocity.x() * m_dragTimerMs);
Chris@403 290 }
Chris@403 291 if (m_dragDirection != HorizontalDrag) {
Chris@403 292 verticalScrollBar()->setValue(m_lastOrigin.y() +
Chris@403 293 m_velocity.y() * m_dragTimerMs);
Chris@403 294 }
Chris@168 295 }
Chris@168 296 }
Chris@168 297
Chris@168 298 void
cannam@45 299 Panned::leaveEvent(QEvent *)
cannam@45 300 {
cannam@45 301 emit mouseLeaves();
cannam@45 302 }