Chris@127: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@127: Chris@127: /* Chris@127: Sonic Visualiser Chris@127: An audio file viewer and annotation editor. Chris@127: Centre for Digital Music, Queen Mary, University of London. Chris@127: This file copyright 2006 Chris Cannam. Chris@127: Chris@127: This program is free software; you can redistribute it and/or Chris@127: modify it under the terms of the GNU General Public License as Chris@127: published by the Free Software Foundation; either version 2 of the Chris@127: License, or (at your option) any later version. See the file Chris@127: COPYING included with this distribution for more information. Chris@127: */ Chris@127: Chris@127: #include "Panner.h" Chris@128: #include "layer/Layer.h" Chris@128: #include "data/model/Model.h" Chris@127: #include "base/ZoomConstraint.h" Chris@127: Chris@127: #include Chris@127: #include Chris@127: #include Chris@127: Chris@127: using std::cerr; Chris@127: using std::endl; Chris@127: Chris@127: Panner::Panner(QWidget *w) : Chris@127: View(w, false), Chris@127: m_clickedInRange(false) Chris@127: { Chris@127: setObjectName(tr("Panner")); Chris@127: m_followPan = false; Chris@127: m_followZoom = false; Chris@127: } Chris@127: Chris@127: void Chris@127: Panner::modelChanged(size_t startFrame, size_t endFrame) Chris@127: { Chris@127: View::modelChanged(startFrame, endFrame); Chris@127: } Chris@127: Chris@127: void Chris@127: Panner::modelReplaced() Chris@127: { Chris@127: View::modelReplaced(); Chris@127: } Chris@127: Chris@127: void Chris@127: Panner::registerView(View *widget) Chris@127: { Chris@127: m_widgets.insert(widget); Chris@127: update(); Chris@127: } Chris@127: Chris@127: void Chris@127: Panner::unregisterView(View *widget) Chris@127: { Chris@127: m_widgets.erase(widget); Chris@127: update(); Chris@127: } Chris@127: Chris@127: void Chris@127: Panner::viewManagerCentreFrameChanged(void *p, unsigned long f, bool) Chris@127: { Chris@127: // std::cerr << "Panner[" << this << "]::viewManagerCentreFrameChanged(" Chris@127: // << p << ", " << f << ")" << std::endl; Chris@127: Chris@127: if (p == this) return; Chris@127: if (m_widgets.find(p) != m_widgets.end()) { Chris@127: update(); Chris@127: } Chris@127: } Chris@127: Chris@127: void Chris@127: Panner::viewManagerZoomLevelChanged(void *p, unsigned long z, bool) Chris@127: { Chris@127: if (p == this) return; Chris@127: if (m_widgets.find(p) != m_widgets.end()) { Chris@127: update(); Chris@127: } Chris@127: } Chris@127: Chris@127: void Chris@127: Panner::viewManagerPlaybackFrameChanged(unsigned long f) Chris@127: { Chris@127: bool changed = false; Chris@127: Chris@127: if (getXForFrame(m_playPointerFrame) != getXForFrame(f)) changed = true; Chris@127: m_playPointerFrame = f; Chris@127: Chris@127: if (changed) update(); Chris@127: } Chris@127: Chris@127: void Chris@127: Panner::paintEvent(QPaintEvent *e) Chris@127: { Chris@127: // Recalculate zoom in case the size of the widget has changed. Chris@127: Chris@127: size_t startFrame = getModelsStartFrame(); Chris@127: size_t frameCount = getModelsEndFrame() - getModelsStartFrame(); Chris@127: int zoomLevel = frameCount / width(); Chris@127: if (zoomLevel < 1) zoomLevel = 1; Chris@127: zoomLevel = getZoomConstraintBlockSize(zoomLevel, Chris@127: ZoomConstraint::RoundUp); Chris@127: if (zoomLevel != m_zoomLevel) { Chris@127: m_zoomLevel = zoomLevel; Chris@127: emit zoomLevelChanged(this, m_zoomLevel, m_followZoom); Chris@127: } Chris@127: size_t centreFrame = startFrame + m_zoomLevel * (width() / 2); Chris@127: if (centreFrame > (startFrame + getModelsEndFrame())/2) { Chris@127: centreFrame = (startFrame + getModelsEndFrame())/2; Chris@127: } Chris@127: if (centreFrame != m_centreFrame) { Chris@127: m_centreFrame = centreFrame; Chris@127: emit centreFrameChanged(this, m_centreFrame, false); Chris@127: } Chris@127: Chris@127: View::paintEvent(e); Chris@127: Chris@127: QPainter paint; Chris@127: paint.begin(this); Chris@127: Chris@127: QRect r(rect()); Chris@127: Chris@127: if (e) { Chris@127: r = e->rect(); Chris@127: paint.setClipRect(r); Chris@127: } Chris@127: Chris@127: paint.setPen(Qt::black); Chris@127: Chris@127: int y = 0; Chris@127: Chris@127: int prevx0 = -10; Chris@127: int prevx1 = -10; Chris@127: Chris@127: for (WidgetSet::iterator i = m_widgets.begin(); i != m_widgets.end(); ++i) { Chris@127: if (!*i) continue; Chris@127: Chris@127: View *w = (View *)*i; Chris@127: Chris@127: long f0 = w->getFrameForX(0); Chris@127: long f1 = w->getFrameForX(w->width()); Chris@127: Chris@127: int x0 = getXForFrame(f0); Chris@127: int x1 = getXForFrame(f1); Chris@127: Chris@127: if (x0 != prevx0 || x1 != prevx1) { Chris@127: y += height() / 10 + 1; Chris@127: prevx0 = x0; Chris@127: prevx1 = x1; Chris@127: } Chris@127: Chris@127: if (x1 <= x0) x1 = x0 + 1; Chris@127: Chris@127: paint.drawRect(x0, y, x1 - x0, height() - 2 * y); Chris@127: } Chris@127: Chris@127: paint.end(); Chris@127: } Chris@127: Chris@127: void Chris@127: Panner::mousePressEvent(QMouseEvent *e) Chris@127: { Chris@127: m_clickPos = e->pos(); Chris@127: for (WidgetSet::iterator i = m_widgets.begin(); i != m_widgets.end(); ++i) { Chris@127: if (*i) { Chris@127: m_clickedInRange = true; Chris@127: m_dragCentreFrame = ((View *)*i)->getCentreFrame(); Chris@127: break; Chris@127: } Chris@127: } Chris@127: } Chris@127: Chris@127: void Chris@127: Panner::mouseReleaseEvent(QMouseEvent *e) Chris@127: { Chris@127: if (m_clickedInRange) { Chris@127: mouseMoveEvent(e); Chris@127: } Chris@127: m_clickedInRange = false; Chris@127: } Chris@127: Chris@127: void Chris@127: Panner::mouseMoveEvent(QMouseEvent *e) Chris@127: { Chris@127: if (!m_clickedInRange) return; Chris@127: Chris@127: long xoff = int(e->x()) - int(m_clickPos.x()); Chris@127: long frameOff = xoff * m_zoomLevel; Chris@127: Chris@127: size_t newCentreFrame = m_dragCentreFrame; Chris@127: if (frameOff > 0) { Chris@127: newCentreFrame += frameOff; Chris@127: } else if (newCentreFrame >= size_t(-frameOff)) { Chris@127: newCentreFrame += frameOff; Chris@127: } else { Chris@127: newCentreFrame = 0; Chris@127: } Chris@127: Chris@127: if (newCentreFrame >= getModelsEndFrame()) { Chris@127: newCentreFrame = getModelsEndFrame(); Chris@127: if (newCentreFrame > 0) --newCentreFrame; Chris@127: } Chris@127: Chris@127: if (std::max(m_centreFrame, newCentreFrame) - Chris@127: std::min(m_centreFrame, newCentreFrame) > size_t(m_zoomLevel)) { Chris@127: emit centreFrameChanged(this, newCentreFrame, true); Chris@127: } Chris@127: } Chris@127: Chris@127: #ifdef INCLUDE_MOCFILES Chris@127: #include "Panner.moc.cpp" Chris@127: #endif Chris@127: