# HG changeset patch # User Chris Cannam # Date 1386156908 0 # Node ID e77b1673e17e5ec7096debacff3ccf1bee9d005a # Parent 6d9624e0ac55e10e0d02add2766651ac5bf6e1b5 Pull out log and linear vertical scales into their own classes, make some improvements to log numbering diff -r 6d9624e0ac55 -r e77b1673e17e layer/FlexiNoteLayer.cpp --- a/layer/FlexiNoteLayer.cpp Tue Dec 03 18:06:44 2013 +0000 +++ b/layer/FlexiNoteLayer.cpp Wed Dec 04 11:35:08 2013 +0000 @@ -860,19 +860,29 @@ int FlexiNoteLayer::getVerticalScaleWidth(View *, bool, QPainter &paint) const { - return 10; + if (m_verticalScale == LinearScale || + m_verticalScale == AutoAlignScale) { + return 0; + } else { + return 10; + } } void FlexiNoteLayer::paintVerticalScale(View *v, bool, QPainter &paint, QRect) const { - float fmin, fmax; - bool log; - QString unit; - if (!getValueExtents(fmin, fmax, log, unit)) return; - PianoScale().paintPianoVertical - (v, paint, QRect(0, 0, 10, v->height()), fmin, fmax); - paint.drawLine(10, 0, 10, v->height()); + if (m_verticalScale == LinearScale || + m_verticalScale == AutoAlignScale) { + return; + } else { + float fmin, fmax; + bool log; + QString unit; + if (!getValueExtents(fmin, fmax, log, unit)) return; + PianoScale().paintPianoVertical + (v, paint, QRect(0, 0, 10, v->height()), fmin, fmax); + paint.drawLine(10, 0, 10, v->height()); + } } void diff -r 6d9624e0ac55 -r e77b1673e17e layer/LinearNumericalScale.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/layer/LinearNumericalScale.cpp Wed Dec 04 11:35:08 2013 +0000 @@ -0,0 +1,105 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2006-2013 Chris Cannam and QMUL. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#include "LinearNumericalScale.h" +#include "VerticalScaleLayer.h" + +#include + +#include + +#include "view/View.h" + +int +LinearNumericalScale::getWidth(View *v, + QPainter &paint) +{ + return paint.fontMetrics().width("-000.000"); +} + +void +LinearNumericalScale::paintVertical(View *v, + const VerticalScaleLayer *layer, + QPainter &paint, + int x0, + float minf, + float maxf) +{ + int h = v->height(); + + int n = 10; + + float val = minf; + float inc = (maxf - val) / n; + + char buffer[40]; + + int w = getWidth(v, paint) + x0; + + float round = 1.f; + int dp = 0; + if (inc > 0) { + int prec = trunc(log10f(inc)); + prec -= 1; + if (prec < 0) dp = -prec; + round = powf(10.f, prec); +#ifdef DEBUG_TIME_VALUE_LAYER + cerr << "inc = " << inc << ", round = " << round << ", dp = " << dp << endl; +#endif + } + + int prevy = -1; + + for (int i = 0; i < n; ++i) { + + int y, ty; + bool drawText = true; + + float dispval = val; + + if (i == n-1 && + v->height() < paint.fontMetrics().height() * (n*2)) { + if (layer->getScaleUnits() != "") drawText = false; + } + dispval = lrintf(val / round) * round; + +#ifdef DEBUG_TIME_VALUE_LAYER + cerr << "val = " << val << ", dispval = " << dispval << endl; +#endif + + y = layer->getYForValue(v, dispval); + + ty = y - paint.fontMetrics().height() + paint.fontMetrics().ascent() + 2; + + if (prevy >= 0 && (prevy - y) < paint.fontMetrics().height()) { + val += inc; + continue; + } + + sprintf(buffer, "%.*f", dp, dispval); + + QString label = QString(buffer); + + paint.drawLine(w - 5, y, w, y); + + if (drawText) { + paint.drawText(w - paint.fontMetrics().width(label) - 13, + ty, label); + } + + prevy = y; + val += inc; + } +} diff -r 6d9624e0ac55 -r e77b1673e17e layer/LinearNumericalScale.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/layer/LinearNumericalScale.h Wed Dec 04 11:35:08 2013 +0000 @@ -0,0 +1,36 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2006-2013 Chris Cannam and QMUL. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef LINEAR_NUMERICAL_SCALE_H +#define LINEAR_NUMERICAL_SCALE_H + +#include + +class QPainter; +class View; +class VerticalScaleLayer; + +class LinearNumericalScale +{ +public: + int getWidth(View *v, QPainter &paint); + + void paintVertical + (View *v, const VerticalScaleLayer *layer, QPainter &paint, int x0, + float minf, float maxf); +}; + +#endif + diff -r 6d9624e0ac55 -r e77b1673e17e layer/LogNumericalScale.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/layer/LogNumericalScale.cpp Wed Dec 04 11:35:08 2013 +0000 @@ -0,0 +1,118 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2006-2013 Chris Cannam and QMUL. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#include "LogNumericalScale.h" +#include "VerticalScaleLayer.h" + +#include "base/LogRange.h" + +#include + +#include + +#include "view/View.h" + +//#define DEBUG_TIME_VALUE_LAYER 1 + +int +LogNumericalScale::getWidth(View *, + QPainter &paint) +{ + return paint.fontMetrics().width("-000.00"); +} + +void +LogNumericalScale::paintVertical(View *v, + const VerticalScaleLayer *layer, + QPainter &paint, + int x0, + float minlog, + float maxlog) +{ + int w = getWidth(v, paint) + x0; + + int n = 10; + + float val = minlog; + float inc = (maxlog - val) / n; // even increments of log scale + + // smallest increment as displayed + float minDispInc = LogRange::unmap(minlog + inc) - LogRange::unmap(minlog); + +#ifdef DEBUG_TIME_VALUE_LAYER + cerr << "min = " << minlog << ", max = " << maxlog << ", inc = " << inc << ", minDispInc = " << minDispInc << endl; +#endif + + char buffer[40]; + + float round = 1.f; + int dp = 0; + + if (minDispInc > 0) { + int prec = trunc(log10f(minDispInc)); + if (prec < 0) dp = -prec; + round = powf(10.f, prec); +#ifdef DEBUG_TIME_VALUE_LAYER + cerr << "round = " << round << ", prec = " << prec << ", dp = " << dp << endl; +#endif + } + + int prevy = -1; + + for (int i = 0; i < n; ++i) { + + int y, ty; + bool drawText = true; + + if (i == n-1 && + v->height() < paint.fontMetrics().height() * (n*2)) { + if (layer->getScaleUnits() != "") drawText = false; + } + + float dispval = LogRange::unmap(val); + dispval = floor(dispval / round) * round; + +#ifdef DEBUG_TIME_VALUE_LAYER + cerr << "val = " << val << ", dispval = " << dispval << endl; +#endif + + y = layer->getYForValue(v, dispval); + + ty = y - paint.fontMetrics().height() + paint.fontMetrics().ascent() + 2; + + if (prevy >= 0 && (prevy - y) < paint.fontMetrics().height()) { + val += inc; + continue; + } + + double dv = dispval; + int digits = trunc(log10f(dv)); + int sf = dp + (digits > 0 ? digits : 0); + if (sf < 4) sf = 4; + sprintf(buffer, "%.*g", sf, dv); + + QString label = QString(buffer); + + paint.drawLine(w - 5, y, w, y); + + if (drawText) { + paint.drawText(w - paint.fontMetrics().width(label) - 6, + ty, label); + } + + prevy = y; + val += inc; + } +} diff -r 6d9624e0ac55 -r e77b1673e17e layer/LogNumericalScale.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/layer/LogNumericalScale.h Wed Dec 04 11:35:08 2013 +0000 @@ -0,0 +1,36 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2006-2013 Chris Cannam and QMUL. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef LOG_NUMERICAL_SCALE_H +#define LOG_NUMERICAL_SCALE_H + +#include + +class QPainter; +class View; +class VerticalScaleLayer; + +class LogNumericalScale +{ +public: + int getWidth(View *v, QPainter &paint); + + void paintVertical + (View *v, const VerticalScaleLayer *layer, QPainter &paint, int x0, + float minlog, float maxlog); +}; + +#endif + diff -r 6d9624e0ac55 -r e77b1673e17e layer/TimeValueLayer.cpp --- a/layer/TimeValueLayer.cpp Tue Dec 03 18:06:44 2013 +0000 +++ b/layer/TimeValueLayer.cpp Wed Dec 04 11:35:08 2013 +0000 @@ -31,6 +31,8 @@ #include "ColourMapper.h" #include "PianoScale.h" +#include "LinearNumericalScale.h" +#include "LogNumericalScale.h" #include #include @@ -144,6 +146,13 @@ return SingleColourLayer::getPropertyGroupName(name); } +QString +TimeValueLayer::getScaleUnits() const +{ + if (m_model) return m_model->getScaleUnits(); + else return ""; +} + int TimeValueLayer::getPropertyRangeAndValue(const PropertyName &name, int *min, int *max, int *deflt) const @@ -179,7 +188,7 @@ if (deflt) *deflt = 0; if (m_model) { val = UnitDatabase::getInstance()->getUnitId - (m_model->getScaleUnits()); + (getScaleUnits()); } } else if (name == "Draw Segment Division Lines") { @@ -327,7 +336,7 @@ logarithmic = (m_verticalScale == LogScale); - unit = m_model->getScaleUnits(); + unit = getScaleUnits(); if (m_derivative) { max = std::max(fabsf(min), fabsf(max)); @@ -595,7 +604,7 @@ RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate()); QString text; - QString unit = m_model->getScaleUnits(); + QString unit = getScaleUnits(); if (unit != "") unit = " " + unit; if (points.begin()->label == "") { @@ -770,7 +779,7 @@ if (shouldAutoAlign()) { - if (!v->getValueExtents(m_model->getScaleUnits(), min, max, log)) { + if (!v->getValueExtents(getScaleUnits(), min, max, log)) { min = m_model->getValueMinimum(); max = m_model->getValueMaximum(); } else if (log) { @@ -840,7 +849,7 @@ TimeValueLayer::shouldAutoAlign() const { if (!m_model) return false; - QString unit = m_model->getScaleUnits(); + QString unit = getScaleUnits(); return (m_verticalScale == AutoAlignScale && unit != ""); } @@ -1196,9 +1205,14 @@ } int -TimeValueLayer::getVerticalScaleWidth(View *, bool, QPainter &paint) const +TimeValueLayer::getVerticalScaleWidth(View *v, bool, QPainter &paint) const { - int w = paint.fontMetrics().width("-000.000"); + int w = 0; + if (m_verticalScale == LogScale) { + w = LogNumericalScale().getWidth(v, paint); + } else { + w = LinearNumericalScale().getWidth(v, paint); + } if (m_plotStyle == PlotSegmentation) return w + 20; else return w + 10; } @@ -1208,6 +1222,7 @@ { if (!m_model) return; +/* int h = v->height(); int n = 10; @@ -1234,7 +1249,7 @@ int tx = 5; int boxx = 5, boxy = 5; - if (m_model->getScaleUnits() != "") { + if (getScaleUnits() != "") { boxy += paint.fontMetrics().height(); } int boxw = 10, boxh = h - boxy - 5; @@ -1285,7 +1300,7 @@ } else { if (i == n-1 && v->height() < paint.fontMetrics().height() * (n*2)) { - if (m_model->getScaleUnits() != "") drawText = false; + if (getScaleUnits() != "") drawText = false; } dispval = lrintf(val / round) * round; #ifdef DEBUG_TIME_VALUE_LAYER @@ -1334,20 +1349,38 @@ prevy = y; val += inc; } - - if (m_model->getScaleUnits() != "") { +*/ + float min, max; + bool logarithmic; + getScaleExtents(v, min, max, logarithmic); + + int w = getVerticalScaleWidth(v, false, paint); + int h = v->height(); + + if (m_plotStyle == PlotSegmentation) { + + //!!! todo! + + } else { + + if (logarithmic) { + LogNumericalScale().paintVertical(v, this, paint, 0, min, max); + } else { + LinearNumericalScale().paintVertical(v, this, paint, 0, min, max); + } + + if (logarithmic && (getScaleUnits() == "Hz")) { + PianoScale().paintPianoVertical + (v, paint, QRect(w - 10, 0, 10, h), + LogRange::unmap(min), + LogRange::unmap(max)); + paint.drawLine(w, 0, w, h); + } + } + + if (getScaleUnits() != "") { paint.drawText(5, 5 + paint.fontMetrics().ascent(), - m_model->getScaleUnits()); - } - - if (logarithmic && - (m_model->getScaleUnits() == "Hz") && - (m_plotStyle != PlotSegmentation)) { - float fmin, fmax; - getDisplayExtents(fmin, fmax); - PianoScale().paintPianoVertical - (v, paint, QRect(w, 0, 10, h), fmin, fmax); - paint.drawLine(w + 10, 0, w + 10, h); + getScaleUnits()); } } @@ -1614,7 +1647,7 @@ ItemEditDialog::ShowTime | ItemEditDialog::ShowValue | ItemEditDialog::ShowText, - m_model->getScaleUnits()); + getScaleUnits()); dialog->setFrameTime(point.frame); dialog->setValue(point.value); diff -r 6d9624e0ac55 -r e77b1673e17e layer/TimeValueLayer.h --- a/layer/TimeValueLayer.h Tue Dec 03 18:06:44 2013 +0000 +++ b/layer/TimeValueLayer.h Wed Dec 04 11:35:08 2013 +0000 @@ -17,6 +17,7 @@ #define _TIME_VALUE_LAYER_H_ #include "SingleColourLayer.h" +#include "VerticalScaleLayer.h" #include "data/model/SparseTimeValueModel.h" #include @@ -25,7 +26,7 @@ class View; class QPainter; -class TimeValueLayer : public SingleColourLayer +class TimeValueLayer : public SingleColourLayer, public VerticalScaleLayer { Q_OBJECT @@ -149,10 +150,13 @@ } } + /// VerticalScaleLayer methods + virtual void getScaleExtents(View *, float &min, float &max, bool &log) const; + virtual int getYForValue(View *, float value) const; + virtual float getValueForY(View *, int y) const; + virtual QString getScaleUnits() const; + protected: - void getScaleExtents(View *, float &min, float &max, bool &log) const; - int getYForValue(View *, float value) const; - float getValueForY(View *, int y) const; QColor getColourForValue(View *v, float value) const; bool shouldAutoAlign() const; diff -r 6d9624e0ac55 -r e77b1673e17e layer/VerticalScaleLayer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/layer/VerticalScaleLayer.h Wed Dec 04 11:35:08 2013 +0000 @@ -0,0 +1,29 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2006-2013 Chris Cannam and QMUL. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef VERTICAL_SCALE_LAYER_H +#define VERTICAL_SCALE_LAYER_H + +class VerticalScaleLayer +{ +public: + virtual void getScaleExtents(View *, float &min, float &max, bool &log) const = 0; + virtual int getYForValue(View *, float value) const = 0; + virtual float getValueForY(View *, int y) const = 0; + virtual QString getScaleUnits() const = 0; +}; + +#endif + diff -r 6d9624e0ac55 -r e77b1673e17e svgui.pro --- a/svgui.pro Tue Dec 03 18:06:44 2013 +0000 +++ b/svgui.pro Wed Dec 04 11:35:08 2013 +0000 @@ -30,12 +30,14 @@ HEADERS += layer/Colour3DPlotLayer.h \ layer/ColourDatabase.h \ layer/ColourMapper.h \ + layer/FlexiNoteLayer.h \ layer/ImageLayer.h \ layer/ImageRegionFinder.h \ layer/Layer.h \ layer/LayerFactory.h \ + layer/LinearNumericalScale.h \ + layer/LogNumericalScale.h \ layer/NoteLayer.h \ - layer/FlexiNoteLayer.h \ layer/PaintAssistant.h \ layer/PianoScale.h \ layer/RegionLayer.h \ @@ -48,16 +50,19 @@ layer/TimeInstantLayer.h \ layer/TimeRulerLayer.h \ layer/TimeValueLayer.h \ + layer/VerticalScaleLayer.h \ layer/WaveformLayer.h SOURCES += layer/Colour3DPlotLayer.cpp \ layer/ColourDatabase.cpp \ layer/ColourMapper.cpp \ + layer/FlexiNoteLayer.cpp \ layer/ImageLayer.cpp \ layer/ImageRegionFinder.cpp \ layer/Layer.cpp \ layer/LayerFactory.cpp \ + layer/LinearNumericalScale.cpp \ + layer/LogNumericalScale.cpp \ layer/NoteLayer.cpp \ - layer/FlexiNoteLayer.cpp \ layer/PaintAssistant.cpp \ layer/PianoScale.cpp \ layer/RegionLayer.cpp \