diff widgets/Panner.cpp @ 0:2a4f26e85b4c

initial import
author Chris Cannam
date Tue, 10 Jan 2006 16:33:16 +0000
parents
children 37b110168acf
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/widgets/Panner.cpp	Tue Jan 10 16:33:16 2006 +0000
@@ -0,0 +1,236 @@
+/* -*- c-basic-offset: 4 -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    A waveform viewer and audio annotation editor.
+    Chris Cannam, Queen Mary University of London, 2005
+    
+    This is experimental software.  Not for distribution.
+*/
+
+#include "Panner.h"
+#include "base/Layer.h"
+#include "base/Model.h"
+#include "base/ZoomConstraint.h"
+
+#include <QPaintEvent>
+#include <QPainter>
+#include <iostream>
+
+using std::cerr;
+using std::endl;
+
+Panner::Panner(QWidget *w) :
+    View(w, false),
+    m_clickedInRange(false)
+{
+    setObjectName(tr("Panner"));
+    m_followPan = false;
+    m_followZoom = false;
+}
+
+void
+Panner::modelChanged(size_t startFrame, size_t endFrame)
+{
+    View::modelChanged(startFrame, endFrame);
+}
+
+void
+Panner::modelReplaced()
+{
+    View::modelReplaced();
+}
+
+void
+Panner::registerView(View *widget)
+{
+    m_widgets[widget] = WidgetRec(0, -1);
+    update(); 
+}
+
+void
+Panner::unregisterView(View *widget)
+{
+    m_widgets.erase(widget);
+    update();
+}
+
+void
+Panner::viewManagerCentreFrameChanged(void *p, unsigned long f, bool)
+{
+//    std::cerr << "Panner[" << this << "]::viewManagerCentreFrameChanged(" 
+//	      << p << ", " << f << ")" << std::endl;
+
+    if (p == this) return;
+    if (m_widgets.find(p) != m_widgets.end()) {
+	m_widgets[p].first = f;
+	update();
+    }
+}
+
+void
+Panner::viewManagerZoomLevelChanged(void *p, unsigned long z, bool)
+{
+    if (p == this) return;
+    if (m_widgets.find(p) != m_widgets.end()) {
+	m_widgets[p].second = z;
+	update();
+    }
+}
+
+void
+Panner::viewManagerPlaybackFrameChanged(unsigned long f)
+{
+    bool changed = false;
+
+    if (m_playPointerFrame / m_zoomLevel != f / m_zoomLevel) changed = true;
+    m_playPointerFrame = f;
+
+    for (WidgetMap::iterator i = m_widgets.begin(); i != m_widgets.end(); ++i) {
+	unsigned long of = i->second.first;
+	i->second.first = f;
+	if (of / m_zoomLevel != f / m_zoomLevel) changed = true;
+    }
+
+    if (changed) update();
+}
+
+void
+Panner::paintEvent(QPaintEvent *e)
+{
+/*!!!
+    // Force View to recalculate zoom in case the size of the
+    // widget has changed.  (We need a better name/mechanism for this)
+    m_newModel = true;
+*/
+
+    // Recalculate zoom in case the size of the widget has changed.
+
+    size_t startFrame = getModelsStartFrame();
+    size_t frameCount = getModelsEndFrame() - getModelsStartFrame();
+    int zoomLevel = frameCount / width();
+    if (zoomLevel < 1) zoomLevel = 1;
+    zoomLevel = getZoomConstraintBlockSize(zoomLevel,
+					   ZoomConstraint::RoundUp);
+    if (zoomLevel != m_zoomLevel) {
+	m_zoomLevel = zoomLevel;
+	emit zoomLevelChanged(this, m_zoomLevel, m_followZoom);
+    }
+    size_t centreFrame = startFrame + m_zoomLevel * (width() / 2);
+    if (centreFrame > (startFrame + getModelsEndFrame())/2) {
+	centreFrame = (startFrame + getModelsEndFrame())/2;
+    }
+    if (centreFrame != m_centreFrame) {
+	m_centreFrame = centreFrame;
+	emit centreFrameChanged(this, m_centreFrame, false);
+    }
+
+    View::paintEvent(e);
+
+    QPainter paint;
+    paint.begin(this);
+
+    QRect r(rect());
+
+    if (e) {
+	r = e->rect();
+	paint.setClipRect(r);
+    }
+
+    paint.setPen(Qt::black);
+
+    int y = 0;
+    long prevCentre = 0;
+    long prevZoom = -1;
+
+    for (WidgetMap::iterator i = m_widgets.begin(); i != m_widgets.end(); ++i) {
+	if (!i->first) continue;
+
+	View *w = (View *)i->first;
+	if (i->second.second < 0) i->second.second = w->getZoomLevel();
+	if (i->second.second < 0) continue;
+
+	long c = (long)i->second.first;
+	long z = (long)i->second.second;
+
+	long f0 = c - (w->width() / 2) * z;
+	long f1 = c + (w->width() / 2) * z;
+
+	int x0 = (f0 - long(getCentreFrame())) / getZoomLevel() + width()/2;
+	int x1 = (f1 - long(getCentreFrame())) / getZoomLevel() + width()/2 - 1;
+
+	if (c != prevCentre || z != prevZoom) {
+	    y += height() / 10 + 1;
+	    prevCentre = c;
+	    prevZoom = z;
+	}
+	
+	paint.drawRect(x0, y, x1 - x0, height() - 2 * y);
+    }
+
+    paint.end();
+}
+
+void
+Panner::mousePressEvent(QMouseEvent *e)
+{
+    m_clickPos = e->pos();
+    for (WidgetMap::iterator i = m_widgets.begin(); i != m_widgets.end(); ++i) {
+	if (i->first && i->second.second >= 0) {
+	    m_clickedInRange = true;
+	    m_dragCentreFrame = i->second.first;
+	}
+    }
+}
+
+void
+Panner::mouseReleaseEvent(QMouseEvent *e)
+{
+    if (m_clickedInRange) {
+	mouseMoveEvent(e);
+    }
+    m_clickedInRange = false;
+}
+
+void
+Panner::mouseMoveEvent(QMouseEvent *e)
+{
+    if (!m_clickedInRange) return;
+
+/*!!!
+    long newFrame = getStartFrame() + e->x() * m_zoomLevel;
+
+    if (newFrame < 0) newFrame = 0;
+    if (newFrame >= getModelsEndFrame()) {
+	newFrame = getModelsEndFrame();
+	if (newFrame > 0) --newFrame;
+    }
+    emit centreFrameChanged(this, newFrame, true);
+*/
+
+    long xoff = int(e->x()) - int(m_clickPos.x());
+    long frameOff = xoff * m_zoomLevel;
+    
+    size_t newCentreFrame = m_dragCentreFrame;
+    if (frameOff > 0) {
+	newCentreFrame += frameOff;
+    } else if (newCentreFrame >= size_t(-frameOff)) {
+	newCentreFrame += frameOff;
+    } else {
+	newCentreFrame = 0;
+    }
+
+    if (newCentreFrame >= getModelsEndFrame()) {
+	newCentreFrame = getModelsEndFrame();
+	if (newCentreFrame > 0) --newCentreFrame;
+    }
+    
+    if (std::max(m_centreFrame, newCentreFrame) -
+	std::min(m_centreFrame, newCentreFrame) > size_t(m_zoomLevel)) {
+	emit centreFrameChanged(this, newCentreFrame, true);
+    }
+}
+
+#ifdef INCLUDE_MOCFILES
+#include "Panner.moc.cpp"
+#endif
+