comparison widgets/Panner.cpp @ 0:2a4f26e85b4c

initial import
author Chris Cannam
date Tue, 10 Jan 2006 16:33:16 +0000
parents
children 37b110168acf
comparison
equal deleted inserted replaced
-1:000000000000 0:2a4f26e85b4c
1 /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 A waveform viewer and audio annotation editor.
5 Chris Cannam, Queen Mary University of London, 2005
6
7 This is experimental software. Not for distribution.
8 */
9
10 #include "Panner.h"
11 #include "base/Layer.h"
12 #include "base/Model.h"
13 #include "base/ZoomConstraint.h"
14
15 #include <QPaintEvent>
16 #include <QPainter>
17 #include <iostream>
18
19 using std::cerr;
20 using std::endl;
21
22 Panner::Panner(QWidget *w) :
23 View(w, false),
24 m_clickedInRange(false)
25 {
26 setObjectName(tr("Panner"));
27 m_followPan = false;
28 m_followZoom = false;
29 }
30
31 void
32 Panner::modelChanged(size_t startFrame, size_t endFrame)
33 {
34 View::modelChanged(startFrame, endFrame);
35 }
36
37 void
38 Panner::modelReplaced()
39 {
40 View::modelReplaced();
41 }
42
43 void
44 Panner::registerView(View *widget)
45 {
46 m_widgets[widget] = WidgetRec(0, -1);
47 update();
48 }
49
50 void
51 Panner::unregisterView(View *widget)
52 {
53 m_widgets.erase(widget);
54 update();
55 }
56
57 void
58 Panner::viewManagerCentreFrameChanged(void *p, unsigned long f, bool)
59 {
60 // std::cerr << "Panner[" << this << "]::viewManagerCentreFrameChanged("
61 // << p << ", " << f << ")" << std::endl;
62
63 if (p == this) return;
64 if (m_widgets.find(p) != m_widgets.end()) {
65 m_widgets[p].first = f;
66 update();
67 }
68 }
69
70 void
71 Panner::viewManagerZoomLevelChanged(void *p, unsigned long z, bool)
72 {
73 if (p == this) return;
74 if (m_widgets.find(p) != m_widgets.end()) {
75 m_widgets[p].second = z;
76 update();
77 }
78 }
79
80 void
81 Panner::viewManagerPlaybackFrameChanged(unsigned long f)
82 {
83 bool changed = false;
84
85 if (m_playPointerFrame / m_zoomLevel != f / m_zoomLevel) changed = true;
86 m_playPointerFrame = f;
87
88 for (WidgetMap::iterator i = m_widgets.begin(); i != m_widgets.end(); ++i) {
89 unsigned long of = i->second.first;
90 i->second.first = f;
91 if (of / m_zoomLevel != f / m_zoomLevel) changed = true;
92 }
93
94 if (changed) update();
95 }
96
97 void
98 Panner::paintEvent(QPaintEvent *e)
99 {
100 /*!!!
101 // Force View to recalculate zoom in case the size of the
102 // widget has changed. (We need a better name/mechanism for this)
103 m_newModel = true;
104 */
105
106 // Recalculate zoom in case the size of the widget has changed.
107
108 size_t startFrame = getModelsStartFrame();
109 size_t frameCount = getModelsEndFrame() - getModelsStartFrame();
110 int zoomLevel = frameCount / width();
111 if (zoomLevel < 1) zoomLevel = 1;
112 zoomLevel = getZoomConstraintBlockSize(zoomLevel,
113 ZoomConstraint::RoundUp);
114 if (zoomLevel != m_zoomLevel) {
115 m_zoomLevel = zoomLevel;
116 emit zoomLevelChanged(this, m_zoomLevel, m_followZoom);
117 }
118 size_t centreFrame = startFrame + m_zoomLevel * (width() / 2);
119 if (centreFrame > (startFrame + getModelsEndFrame())/2) {
120 centreFrame = (startFrame + getModelsEndFrame())/2;
121 }
122 if (centreFrame != m_centreFrame) {
123 m_centreFrame = centreFrame;
124 emit centreFrameChanged(this, m_centreFrame, false);
125 }
126
127 View::paintEvent(e);
128
129 QPainter paint;
130 paint.begin(this);
131
132 QRect r(rect());
133
134 if (e) {
135 r = e->rect();
136 paint.setClipRect(r);
137 }
138
139 paint.setPen(Qt::black);
140
141 int y = 0;
142 long prevCentre = 0;
143 long prevZoom = -1;
144
145 for (WidgetMap::iterator i = m_widgets.begin(); i != m_widgets.end(); ++i) {
146 if (!i->first) continue;
147
148 View *w = (View *)i->first;
149 if (i->second.second < 0) i->second.second = w->getZoomLevel();
150 if (i->second.second < 0) continue;
151
152 long c = (long)i->second.first;
153 long z = (long)i->second.second;
154
155 long f0 = c - (w->width() / 2) * z;
156 long f1 = c + (w->width() / 2) * z;
157
158 int x0 = (f0 - long(getCentreFrame())) / getZoomLevel() + width()/2;
159 int x1 = (f1 - long(getCentreFrame())) / getZoomLevel() + width()/2 - 1;
160
161 if (c != prevCentre || z != prevZoom) {
162 y += height() / 10 + 1;
163 prevCentre = c;
164 prevZoom = z;
165 }
166
167 paint.drawRect(x0, y, x1 - x0, height() - 2 * y);
168 }
169
170 paint.end();
171 }
172
173 void
174 Panner::mousePressEvent(QMouseEvent *e)
175 {
176 m_clickPos = e->pos();
177 for (WidgetMap::iterator i = m_widgets.begin(); i != m_widgets.end(); ++i) {
178 if (i->first && i->second.second >= 0) {
179 m_clickedInRange = true;
180 m_dragCentreFrame = i->second.first;
181 }
182 }
183 }
184
185 void
186 Panner::mouseReleaseEvent(QMouseEvent *e)
187 {
188 if (m_clickedInRange) {
189 mouseMoveEvent(e);
190 }
191 m_clickedInRange = false;
192 }
193
194 void
195 Panner::mouseMoveEvent(QMouseEvent *e)
196 {
197 if (!m_clickedInRange) return;
198
199 /*!!!
200 long newFrame = getStartFrame() + e->x() * m_zoomLevel;
201
202 if (newFrame < 0) newFrame = 0;
203 if (newFrame >= getModelsEndFrame()) {
204 newFrame = getModelsEndFrame();
205 if (newFrame > 0) --newFrame;
206 }
207 emit centreFrameChanged(this, newFrame, true);
208 */
209
210 long xoff = int(e->x()) - int(m_clickPos.x());
211 long frameOff = xoff * m_zoomLevel;
212
213 size_t newCentreFrame = m_dragCentreFrame;
214 if (frameOff > 0) {
215 newCentreFrame += frameOff;
216 } else if (newCentreFrame >= size_t(-frameOff)) {
217 newCentreFrame += frameOff;
218 } else {
219 newCentreFrame = 0;
220 }
221
222 if (newCentreFrame >= getModelsEndFrame()) {
223 newCentreFrame = getModelsEndFrame();
224 if (newCentreFrame > 0) --newCentreFrame;
225 }
226
227 if (std::max(m_centreFrame, newCentreFrame) -
228 std::min(m_centreFrame, newCentreFrame) > size_t(m_zoomLevel)) {
229 emit centreFrameChanged(this, newCentreFrame, true);
230 }
231 }
232
233 #ifdef INCLUDE_MOCFILES
234 #include "Panner.moc.cpp"
235 #endif
236