-
Notifications
You must be signed in to change notification settings - Fork 0
/
scrollareapannable.cpp
136 lines (113 loc) · 3.43 KB
/
scrollareapannable.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include "scrollareapannable.h"
#include <QMouseEvent>
#include <QScrollBar>
#include <QDebug>
#define ZOOM_SPEED (0.075)
const double ScrollAreaPannable::WheelStep = 15. / 120.; //can be used for zoomBy
ScrollAreaPannable::ScrollAreaPannable(QWidget *parent):
QScrollArea (parent),
min_width(width()), min_height(height()),
mousePosPan(0,0),
maxZoom(0,0),
currentMode(MouseMode::mmMove),
pressedAtMode(MouseMode::mmMove)
{
}
void ScrollAreaPannable::zoomSize(int w, int h)
{
setWidgetResizable(false);
widget()->resize(w, h);
}
void ScrollAreaPannable::zoomFitWindow()
{
zoomSize(min_width, min_height);
}
void ScrollAreaPannable::zoom1_1()
{
setWidgetResizable(true);
}
void ScrollAreaPannable::zoomBy(double times)
{
times *= ZOOM_SPEED;
int w = static_cast<decltype(w)>(widget()->width() + widget()->width() * times);
int h = static_cast<decltype(h)>(widget()->height()+ widget()->height() * times);
if (w < min_width || h < min_height)
zoomSize(min_width, min_height);
else
{
if (w > maxZoom.width() || h > maxZoom.height())
zoomSize(maxZoom.width(), maxZoom.height());
else
zoomSize(w, h);
}
}
void ScrollAreaPannable::setMaxZoom(const QSize &maxz)
{
double p = static_cast<double>(maxz.width()) / maxz.height();
auto mh = std::max(height(), maxz.height());
auto mw = std::max(static_cast<decltype(mh)>(mh * p), maxz.width());
maxZoom = QSize(mw, mh);
min_height = std::min(height(), maxz.height());
min_width = static_cast<decltype(min_width)>(p * min_height);
}
QSize ScrollAreaPannable::getCurrentZoomedSize() const
{
if (widgetResizable())
return maxZoom;
else
return widget()->size();
}
void ScrollAreaPannable::setMouseMode(int mode)
{
currentMode = static_cast<MouseMode>(mode);
}
void ScrollAreaPannable::mousePressEvent(QMouseEvent *e)
{
pressedAtMode = currentMode; //user can switch mode using keyboard while holding mouse, avoiding crap
if (e->button() == Qt::LeftButton)
{
mousePosPan = e->pos();
if (currentMode == MouseMode::mmMove)
setCursor(Qt::OpenHandCursor);
if (currentMode == MouseMode::mmSelect)
{
setCursor(Qt::CrossCursor);
}
}
}
//keyboard events are filtered and intercepted by mainform (because it should do preview model calls too), so to add keys - do it there
void ScrollAreaPannable::mouseMoveEvent(QMouseEvent *e)
{
//use QRubberBand Class, Luke!
if (e->buttons() == Qt::LeftButton)
{
if (pressedAtMode == MouseMode::mmMove)
{
setCursor(Qt::ClosedHandCursor);
QPoint diff = mousePosPan - e->pos();
mousePosPan = e->pos();
verticalScrollBar()-> setValue(verticalScrollBar()->value() + diff.y());
horizontalScrollBar()->setValue(horizontalScrollBar()->value() + diff.x());
}
}
}
void ScrollAreaPannable::mouseReleaseEvent(QMouseEvent *e)
{
Q_UNUSED(e);
mousePosPan = QPoint(0, 0);
setCursor(Qt::ArrowCursor);
}
void ScrollAreaPannable::wheelEvent(QWheelEvent *event)
{
if (event->modifiers() == Qt::ShiftModifier || event->buttons() == Qt::LeftButton)
{
auto angle = event->angleDelta();
double val = (angle.y() + angle.x()) / 120.;
zoomBy(val);
}
else
{
event->ignore();
QScrollArea::wheelEvent(event);
}
}