Move drawing (and updating) code for vertical rulers
This commit is contained in:
parent
fccb832e2d
commit
b45d1387dc
|
@ -43,67 +43,19 @@ audio tracks.
|
|||
|
||||
#include "Experimental.h"
|
||||
|
||||
#include "float_cast.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include <limits>
|
||||
#include <wx/utils.h>
|
||||
|
||||
#ifdef HAVE_ALLOCA_H
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
#include <wx/brush.h>
|
||||
#include <wx/colour.h>
|
||||
#include <wx/dc.h>
|
||||
#include <wx/dcmemory.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/graphics.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/pen.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/datetime.h>
|
||||
|
||||
#ifdef USE_MIDI
|
||||
#include "NoteTrack.h"
|
||||
#endif // USE_MIDI
|
||||
|
||||
#include "AColor.h"
|
||||
#include "BlockFile.h"
|
||||
#include "Envelope.h"
|
||||
#include "EnvelopeEditor.h"
|
||||
#include "NumberScale.h"
|
||||
#include "WaveClip.h"
|
||||
#include "LabelTrack.h"
|
||||
#include "TimeTrack.h"
|
||||
#include "AllThemeResources.h"
|
||||
#include "Prefs.h"
|
||||
#include "prefs/GUIPrefs.h"
|
||||
#include "TrackPanelDrawingContext.h"
|
||||
#include "ViewInfo.h"
|
||||
#include "WaveTrack.h"
|
||||
|
||||
#include "prefs/GUISettings.h"
|
||||
#include "prefs/SpectrogramSettings.h"
|
||||
#include "prefs/TracksPrefs.h"
|
||||
#include "prefs/WaveformSettings.h"
|
||||
#include "Spectrum.h"
|
||||
#include "ViewInfo.h"
|
||||
#include "widgets/Ruler.h"
|
||||
#include "AllThemeResources.h"
|
||||
#include "TrackPanelDrawingContext.h"
|
||||
#include "tracks/labeltrack/ui/LabelTrackView.h"
|
||||
#include "tracks/ui/TrackView.h"
|
||||
|
||||
|
||||
#undef PROFILE_WAVEFORM
|
||||
#ifdef PROFILE_WAVEFORM
|
||||
#ifdef __WXMSW__
|
||||
#include <time.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
double gWaveformTimeTotal = 0;
|
||||
int gWaveformTimeCount = 0;
|
||||
|
||||
#endif
|
||||
#include <wx/dc.h>
|
||||
|
||||
TrackArtist::TrackArtist( TrackPanel *parent_ )
|
||||
: parent( parent_ )
|
||||
|
@ -113,7 +65,6 @@ TrackArtist::TrackArtist( TrackPanel *parent_ )
|
|||
mSampleDisplay = 1;// Stem plots by default.
|
||||
|
||||
SetColours(0);
|
||||
vruler = std::make_unique<Ruler>();
|
||||
|
||||
UpdatePrefs();
|
||||
}
|
||||
|
@ -279,448 +230,6 @@ void TrackArt::DrawTrackName( TrackPanelDrawingContext &context, const Track * t
|
|||
dc.DrawText (t->GetName(), rect.x+15, rect.y+3); // move right 15 pixels to avoid overwriting <- symbol
|
||||
}
|
||||
|
||||
void TrackArt::DrawVRuler
|
||||
( TrackPanelDrawingContext &context, const Track *t, const wxRect & rect_,
|
||||
bool bSelected )
|
||||
{
|
||||
auto rect = rect_;
|
||||
--rect.width;
|
||||
|
||||
auto dc = &context.dc;
|
||||
bool highlight = false;
|
||||
#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
|
||||
highlight = rect.Contains(context.lastState.GetPosition());
|
||||
#endif
|
||||
|
||||
|
||||
// Label and Time tracks do not have a vruler
|
||||
// But give it a beveled area
|
||||
t->TypeSwitch(
|
||||
[&](const LabelTrack *) {
|
||||
wxRect bev = rect;
|
||||
bev.Inflate(-1, 0);
|
||||
bev.width += 1;
|
||||
AColor::BevelTrackInfo(*dc, true, bev);
|
||||
},
|
||||
|
||||
[&](const TimeTrack *) {
|
||||
wxRect bev = rect;
|
||||
bev.Inflate(-1, 0);
|
||||
bev.width += 1;
|
||||
AColor::BevelTrackInfo(*dc, true, bev);
|
||||
|
||||
// Right align the ruler
|
||||
wxRect rr = rect;
|
||||
rr.width--;
|
||||
if (t->vrulerSize.GetWidth() < rect.GetWidth()) {
|
||||
int adj = rr.GetWidth() - t->vrulerSize.GetWidth();
|
||||
rr.x += adj;
|
||||
rr.width -= adj;
|
||||
}
|
||||
|
||||
const auto artist = TrackArtist::Get( context );
|
||||
artist->UpdateVRuler(t, rr);
|
||||
|
||||
const auto &vruler = artist->vruler;
|
||||
vruler->SetTickColour( theTheme.Colour( clrTrackPanelText ));
|
||||
vruler->Draw(*dc);
|
||||
},
|
||||
|
||||
[&](const WaveTrack *) {
|
||||
// All waves have a ruler in the info panel
|
||||
// The ruler needs a bevelled surround.
|
||||
wxRect bev = rect;
|
||||
bev.Inflate(-1, 0);
|
||||
bev.width += 1;
|
||||
AColor::BevelTrackInfo(*dc, true, bev, highlight);
|
||||
|
||||
// Right align the ruler
|
||||
wxRect rr = rect;
|
||||
rr.width--;
|
||||
if (t->vrulerSize.GetWidth() < rect.GetWidth()) {
|
||||
int adj = rr.GetWidth() - t->vrulerSize.GetWidth();
|
||||
rr.x += adj;
|
||||
rr.width -= adj;
|
||||
}
|
||||
|
||||
const auto artist = TrackArtist::Get( context );
|
||||
artist->UpdateVRuler(t, rr);
|
||||
|
||||
const auto &vruler = artist->vruler;
|
||||
vruler->SetTickColour( theTheme.Colour( clrTrackPanelText ));
|
||||
vruler->Draw(*dc);
|
||||
}
|
||||
|
||||
#ifdef USE_MIDI
|
||||
,
|
||||
[&](const NoteTrack *track) {
|
||||
// The note track draws a vertical keyboard to label pitches
|
||||
const auto artist = TrackArtist::Get( context );
|
||||
artist->UpdateVRuler(t, rect);
|
||||
|
||||
dc->SetPen(highlight ? AColor::uglyPen : *wxTRANSPARENT_PEN);
|
||||
dc->SetBrush(*wxWHITE_BRUSH);
|
||||
wxRect bev = rect;
|
||||
bev.x++;
|
||||
bev.width--;
|
||||
dc->DrawRectangle(bev);
|
||||
|
||||
rect.y += 1;
|
||||
rect.height -= 1;
|
||||
|
||||
NoteTrackDisplayData data = NoteTrackDisplayData(track, rect);
|
||||
|
||||
wxPen hilitePen;
|
||||
hilitePen.SetColour(120, 120, 120);
|
||||
wxBrush blackKeyBrush;
|
||||
blackKeyBrush.SetColour(70, 70, 70);
|
||||
|
||||
dc->SetBrush(blackKeyBrush);
|
||||
|
||||
int fontSize = 10;
|
||||
#ifdef __WXMSW__
|
||||
fontSize = 8;
|
||||
#endif
|
||||
|
||||
wxFont labelFont(fontSize, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
|
||||
dc->SetFont(labelFont);
|
||||
|
||||
int octave = 0;
|
||||
int obottom = data.GetOctaveBottom(octave);
|
||||
int marg = data.GetNoteMargin();
|
||||
|
||||
while (obottom >= rect.y) {
|
||||
dc->SetPen(*wxBLACK_PEN);
|
||||
for (int white = 0; white < 7; white++) {
|
||||
int pos = data.GetWhitePos(white);
|
||||
if (obottom - pos > rect.y + marg + 1 &&
|
||||
// don't draw too close to margin line -- it's annoying
|
||||
obottom - pos < rect.y + rect.height - marg - 3)
|
||||
AColor::Line(*dc, rect.x, obottom - pos,
|
||||
rect.x + rect.width, obottom - pos);
|
||||
}
|
||||
wxRect br = rect;
|
||||
br.height = data.GetPitchHeight(1);
|
||||
br.x++;
|
||||
br.width = 17;
|
||||
for (int black = 0; black < 5; black++) {
|
||||
br.y = obottom - data.GetBlackPos(black);
|
||||
if (br.y > rect.y + marg - 2 && br.y + br.height < rect.y + rect.height - marg) {
|
||||
dc->SetPen(hilitePen);
|
||||
dc->DrawRectangle(br);
|
||||
dc->SetPen(*wxBLACK_PEN);
|
||||
AColor::Line(*dc,
|
||||
br.x + 1, br.y + br.height - 1,
|
||||
br.x + br.width - 1, br.y + br.height - 1);
|
||||
AColor::Line(*dc,
|
||||
br.x + br.width - 1, br.y + 1,
|
||||
br.x + br.width - 1, br.y + br.height - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (octave >= 1 && octave <= 10) {
|
||||
wxString s;
|
||||
// ISO standard: A440 is in the 4th octave, denoted
|
||||
// A4 <- the "4" should be a subscript.
|
||||
s.Printf(wxT("C%d"), octave - 1);
|
||||
wxCoord width, height;
|
||||
dc->GetTextExtent(s, &width, &height);
|
||||
if (obottom - height + 4 > rect.y &&
|
||||
obottom + 4 < rect.y + rect.height) {
|
||||
dc->SetTextForeground(wxColour(60, 60, 255));
|
||||
dc->DrawText(s, rect.x + rect.width - width,
|
||||
obottom - height + 2);
|
||||
}
|
||||
}
|
||||
obottom = data.GetOctaveBottom(++octave);
|
||||
}
|
||||
// draw lines delineating the out-of-bounds margins
|
||||
dc->SetPen(*wxBLACK_PEN);
|
||||
// you would think the -1 offset here should be -2 to match the
|
||||
// adjustment to rect.y (see above), but -1 produces correct output
|
||||
AColor::Line(*dc, rect.x, rect.y + marg - 1, rect.x + rect.width, rect.y + marg - 1);
|
||||
// since the margin gives us the bottom of the line,
|
||||
// the extra -1 gets us to the top
|
||||
AColor::Line(*dc, rect.x, rect.y + rect.height - marg - 1,
|
||||
rect.x + rect.width, rect.y + rect.height - marg - 1);
|
||||
|
||||
}
|
||||
#endif // USE_MIDI
|
||||
);
|
||||
}
|
||||
|
||||
void TrackArtist::UpdateVRuler(const Track *t, const wxRect & rect)
|
||||
{
|
||||
auto update = t->TypeSwitch<bool>(
|
||||
[] (const LabelTrack *) {
|
||||
// Label tracks do not have a vruler
|
||||
return false;
|
||||
},
|
||||
|
||||
[&](const TimeTrack *tt) {
|
||||
float min, max;
|
||||
min = tt->GetRangeLower() * 100.0;
|
||||
max = tt->GetRangeUpper() * 100.0;
|
||||
|
||||
vruler->SetDbMirrorValue( 0.0 );
|
||||
vruler->SetBounds(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height-1);
|
||||
vruler->SetOrientation(wxVERTICAL);
|
||||
vruler->SetRange(max, min);
|
||||
vruler->SetFormat((tt->GetDisplayLog()) ? Ruler::RealLogFormat : Ruler::RealFormat);
|
||||
vruler->SetUnits(wxT(""));
|
||||
vruler->SetLabelEdges(false);
|
||||
vruler->SetLog(tt->GetDisplayLog());
|
||||
return true;
|
||||
},
|
||||
|
||||
[&](const WaveTrack *wt) {
|
||||
// All waves have a ruler in the info panel
|
||||
// The ruler needs a bevelled surround.
|
||||
const float dBRange =
|
||||
wt->GetWaveformSettings().dBRange;
|
||||
|
||||
const int display = wt->GetDisplay();
|
||||
|
||||
if (display == WaveTrackViewConstants::Waveform) {
|
||||
WaveformSettings::ScaleType scaleType =
|
||||
wt->GetWaveformSettings().scaleType;
|
||||
|
||||
if (scaleType == WaveformSettings::stLinear) {
|
||||
// Waveform
|
||||
|
||||
float min, max;
|
||||
wt->GetDisplayBounds(&min, &max);
|
||||
if (wt->GetLastScaleType() != scaleType &&
|
||||
wt->GetLastScaleType() != -1)
|
||||
{
|
||||
// do a translation into the linear space
|
||||
wt->SetLastScaleType();
|
||||
wt->SetLastdBRange();
|
||||
float sign = (min >= 0 ? 1 : -1);
|
||||
if (min != 0.) {
|
||||
min = DB_TO_LINEAR(fabs(min) * dBRange - dBRange);
|
||||
if (min < 0.0)
|
||||
min = 0.0;
|
||||
min *= sign;
|
||||
}
|
||||
sign = (max >= 0 ? 1 : -1);
|
||||
|
||||
if (max != 0.) {
|
||||
max = DB_TO_LINEAR(fabs(max) * dBRange - dBRange);
|
||||
if (max < 0.0)
|
||||
max = 0.0;
|
||||
max *= sign;
|
||||
}
|
||||
wt->SetDisplayBounds(min, max);
|
||||
}
|
||||
|
||||
vruler->SetDbMirrorValue( 0.0 );
|
||||
vruler->SetBounds(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height - 1);
|
||||
vruler->SetOrientation(wxVERTICAL);
|
||||
vruler->SetRange(max, min);
|
||||
vruler->SetFormat(Ruler::RealFormat);
|
||||
vruler->SetUnits(wxT(""));
|
||||
vruler->SetLabelEdges(false);
|
||||
vruler->SetLog(false);
|
||||
}
|
||||
else {
|
||||
wxASSERT(scaleType == WaveformSettings::stLogarithmic);
|
||||
scaleType = WaveformSettings::stLogarithmic;
|
||||
|
||||
vruler->SetUnits(wxT(""));
|
||||
|
||||
float min, max;
|
||||
wt->GetDisplayBounds(&min, &max);
|
||||
float lastdBRange;
|
||||
|
||||
if (wt->GetLastScaleType() != scaleType &&
|
||||
wt->GetLastScaleType() != -1)
|
||||
{
|
||||
// do a translation into the dB space
|
||||
wt->SetLastScaleType();
|
||||
wt->SetLastdBRange();
|
||||
float sign = (min >= 0 ? 1 : -1);
|
||||
if (min != 0.) {
|
||||
min = (LINEAR_TO_DB(fabs(min)) + dBRange) / dBRange;
|
||||
if (min < 0.0)
|
||||
min = 0.0;
|
||||
min *= sign;
|
||||
}
|
||||
sign = (max >= 0 ? 1 : -1);
|
||||
|
||||
if (max != 0.) {
|
||||
max = (LINEAR_TO_DB(fabs(max)) + dBRange) / dBRange;
|
||||
if (max < 0.0)
|
||||
max = 0.0;
|
||||
max *= sign;
|
||||
}
|
||||
wt->SetDisplayBounds(min, max);
|
||||
}
|
||||
else if (dBRange != (lastdBRange = wt->GetLastdBRange())) {
|
||||
wt->SetLastdBRange();
|
||||
// Remap the max of the scale
|
||||
float newMax = max;
|
||||
|
||||
// This commented out code is problematic.
|
||||
// min and max may be correct, and this code cause them to change.
|
||||
#ifdef ONLY_LABEL_POSITIVE
|
||||
const float sign = (max >= 0 ? 1 : -1);
|
||||
if (max != 0.) {
|
||||
|
||||
// Ugh, duplicating from TrackPanel.cpp
|
||||
#define ZOOMLIMIT 0.001f
|
||||
|
||||
const float extreme = LINEAR_TO_DB(2);
|
||||
// recover dB value of max
|
||||
const float dB = std::min(extreme, (float(fabs(max)) * lastdBRange - lastdBRange));
|
||||
// find NEW scale position, but old max may get trimmed if the db limit rises
|
||||
// Don't trim it to zero though, but leave max and limit distinct
|
||||
newMax = sign * std::max(ZOOMLIMIT, (dBRange + dB) / dBRange);
|
||||
// Adjust the min of the scale if we can,
|
||||
// so the db Limit remains where it was on screen, but don't violate extremes
|
||||
if (min != 0.)
|
||||
min = std::max(-extreme, newMax * min / max);
|
||||
}
|
||||
#endif
|
||||
wt->SetDisplayBounds(min, newMax);
|
||||
}
|
||||
|
||||
// Old code was if ONLY_LABEL_POSITIVE were defined.
|
||||
// it uses the +1 to 0 range only.
|
||||
// the enabled code uses +1 to -1, and relies on set ticks labelling knowing about
|
||||
// the dB scale.
|
||||
#ifdef ONLY_LABEL_POSITIVE
|
||||
if (max > 0) {
|
||||
#endif
|
||||
int top = 0;
|
||||
float topval = 0;
|
||||
int bot = rect.height;
|
||||
float botval = -dBRange;
|
||||
|
||||
#ifdef ONLY_LABEL_POSITIVE
|
||||
if (min < 0) {
|
||||
bot = top + (int)((max / (max - min))*(bot - top));
|
||||
min = 0;
|
||||
}
|
||||
|
||||
if (max > 1) {
|
||||
top += (int)((max - 1) / (max - min) * (bot - top));
|
||||
max = 1;
|
||||
}
|
||||
|
||||
if (max < 1 && max > 0)
|
||||
topval = -((1 - max) * dBRange);
|
||||
|
||||
if (min > 0) {
|
||||
botval = -((1 - min) * dBRange);
|
||||
}
|
||||
#else
|
||||
topval = -((1 - max) * dBRange);
|
||||
botval = -((1 - min) * dBRange);
|
||||
vruler->SetDbMirrorValue( dBRange );
|
||||
#endif
|
||||
vruler->SetBounds(rect.x, rect.y + top, rect.x + rect.width, rect.y + bot - 1);
|
||||
vruler->SetOrientation(wxVERTICAL);
|
||||
vruler->SetRange(topval, botval);
|
||||
#ifdef ONLY_LABEL_POSITIVE
|
||||
}
|
||||
else
|
||||
vruler->SetBounds(0.0, 0.0, 0.0, 0.0); // A.C.H I couldn't find a way to just disable it?
|
||||
#endif
|
||||
vruler->SetFormat(Ruler::RealLogFormat);
|
||||
vruler->SetLabelEdges(true);
|
||||
vruler->SetLog(false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
wxASSERT(display == WaveTrackViewConstants::Spectrum);
|
||||
const SpectrogramSettings &settings = wt->GetSpectrogramSettings();
|
||||
float minFreq, maxFreq;
|
||||
wt->GetSpectrumBounds(&minFreq, &maxFreq);
|
||||
vruler->SetDbMirrorValue( 0.0 );
|
||||
|
||||
switch (settings.scaleType) {
|
||||
default:
|
||||
wxASSERT(false);
|
||||
case SpectrogramSettings::stLinear:
|
||||
{
|
||||
// Spectrum
|
||||
|
||||
if (rect.height < 60)
|
||||
return false;
|
||||
|
||||
/*
|
||||
draw the ruler
|
||||
we will use Hz if maxFreq is < 2000, otherwise we represent kHz,
|
||||
and append to the numbers a "k"
|
||||
*/
|
||||
vruler->SetBounds(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height - 1);
|
||||
vruler->SetOrientation(wxVERTICAL);
|
||||
vruler->SetFormat(Ruler::RealFormat);
|
||||
vruler->SetLabelEdges(true);
|
||||
// use kHz in scale, if appropriate
|
||||
if (maxFreq >= 2000) {
|
||||
vruler->SetRange((maxFreq / 1000.), (minFreq / 1000.));
|
||||
vruler->SetUnits(wxT("k"));
|
||||
}
|
||||
else {
|
||||
// use Hz
|
||||
vruler->SetRange((int)(maxFreq), (int)(minFreq));
|
||||
vruler->SetUnits(wxT(""));
|
||||
}
|
||||
vruler->SetLog(false);
|
||||
}
|
||||
break;
|
||||
case SpectrogramSettings::stLogarithmic:
|
||||
case SpectrogramSettings::stMel:
|
||||
case SpectrogramSettings::stBark:
|
||||
case SpectrogramSettings::stErb:
|
||||
case SpectrogramSettings::stPeriod:
|
||||
{
|
||||
// SpectrumLog
|
||||
|
||||
if (rect.height < 10)
|
||||
return false;
|
||||
|
||||
/*
|
||||
draw the ruler
|
||||
we will use Hz if maxFreq is < 2000, otherwise we represent kHz,
|
||||
and append to the numbers a "k"
|
||||
*/
|
||||
vruler->SetBounds(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height - 1);
|
||||
vruler->SetOrientation(wxVERTICAL);
|
||||
vruler->SetFormat(Ruler::IntFormat);
|
||||
vruler->SetLabelEdges(true);
|
||||
vruler->SetRange(maxFreq, minFreq);
|
||||
vruler->SetUnits(wxT(""));
|
||||
vruler->SetLog(true);
|
||||
NumberScale scale(
|
||||
wt->GetSpectrogramSettings().GetScale( minFreq, maxFreq )
|
||||
.Reversal() );
|
||||
vruler->SetNumberScale(&scale);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef USE_MIDI
|
||||
,
|
||||
[&](const NoteTrack *) {
|
||||
// The note track isn't drawing a ruler at all!
|
||||
// But it needs to!
|
||||
vruler->SetBounds(rect.x, rect.y, rect.x + 1, rect.y + rect.height-1);
|
||||
vruler->SetOrientation(wxVERTICAL);
|
||||
return true;
|
||||
}
|
||||
#endif // USE_MIDI
|
||||
);
|
||||
|
||||
if (update)
|
||||
vruler->GetMaxSize(&t->vrulerSize.x, &t->vrulerSize.y);
|
||||
}
|
||||
|
||||
/// Takes a value between min and max and returns a value between
|
||||
/// height and 0
|
||||
/// \todo Should this function move int GuiWaveTrack where it can
|
||||
|
|
|
@ -28,10 +28,8 @@
|
|||
|
||||
class wxRect;
|
||||
|
||||
class NoteTrack;
|
||||
class TrackList;
|
||||
class TrackPanel;
|
||||
class Ruler;
|
||||
class SelectedRegion;
|
||||
class Track;
|
||||
class TrackPanel;
|
||||
|
@ -39,8 +37,6 @@ struct TrackPanelDrawingContext;
|
|||
class ZoomInfo;
|
||||
|
||||
namespace TrackArt {
|
||||
void DrawVRuler(TrackPanelDrawingContext &context,
|
||||
const Track *t, const wxRect & rect, bool bSelected );
|
||||
|
||||
void DrawTrackNames(TrackPanelDrawingContext &context,
|
||||
const TrackList *tracks,
|
||||
|
@ -72,6 +68,7 @@ public:
|
|||
PassTracks,
|
||||
PassMargins,
|
||||
PassBorders,
|
||||
PassControls,
|
||||
|
||||
NPasses
|
||||
};
|
||||
|
@ -93,8 +90,6 @@ public:
|
|||
void UpdatePrefs() override;
|
||||
void UpdateSelectedPrefs( int id ) override;
|
||||
|
||||
void UpdateVRuler(const Track *t, const wxRect & rect);
|
||||
|
||||
TrackPanel *parent;
|
||||
|
||||
// Preference values
|
||||
|
@ -126,8 +121,6 @@ public:
|
|||
wxPen muteClippedPen;
|
||||
wxPen blankSelectedPen;
|
||||
|
||||
std::unique_ptr<Ruler> vruler;
|
||||
|
||||
#ifdef EXPERIMENTAL_FFT_Y_GRID
|
||||
bool fftYGridOld;
|
||||
#endif //EXPERIMENTAL_FFT_Y_GRID
|
||||
|
|
|
@ -944,23 +944,22 @@ void TrackPanel::DrawEverythingElse(TrackPanelDrawingContext &context,
|
|||
+ IsVisibleTrack{ GetProject() } ) {
|
||||
const auto channels = TrackList::Channels(leaderTrack);
|
||||
bool focused = false;
|
||||
wxRect teamRect = trackRect;
|
||||
teamRect.height = 0;
|
||||
trackRect.height = 0;
|
||||
bool first = true;
|
||||
for (auto channel : channels) {
|
||||
focused = focused || mAx->IsFocused(channel);
|
||||
auto &view = TrackView::Get( *channel );
|
||||
if (first)
|
||||
first = false,
|
||||
teamRect.y = view.GetY() - mViewInfo->vpos + kTopMargin;
|
||||
teamRect.height += view.GetHeight();
|
||||
trackRect.y = view.GetY() - mViewInfo->vpos + kTopMargin;
|
||||
trackRect.height += view.GetHeight();
|
||||
}
|
||||
|
||||
if (focused) {
|
||||
focusRect = teamRect;
|
||||
focusRect = trackRect;
|
||||
focusRect.height -= kSeparatorThickness;
|
||||
}
|
||||
DrawOutside(context, leaderTrack, teamRect);
|
||||
DrawOutside(context, leaderTrack, trackRect);
|
||||
|
||||
// Believe it or not, we can speed up redrawing if we don't
|
||||
// redraw the vertical ruler when only the waveform data has
|
||||
|
@ -971,24 +970,6 @@ void TrackPanel::DrawEverythingElse(TrackPanelDrawingContext &context,
|
|||
// wxPrintf(wxT("Update Region: %d %d %d %d\n"),
|
||||
// rbox.x, rbox.y, rbox.width, rbox.height);
|
||||
#endif
|
||||
|
||||
for (auto channel : channels) {
|
||||
auto &view = TrackView::Get( *channel );
|
||||
bool bSelected = channel->GetSelected();
|
||||
channel = channel->SubstitutePendingChangedTrack().get();
|
||||
trackRect.y = view.GetY() - mViewInfo->vpos + kTopMargin;
|
||||
trackRect.height = view.GetHeight();
|
||||
if (region.Contains(
|
||||
0, trackRect.y, mViewInfo->GetLeftOffset(), trackRect.height)) {
|
||||
wxRect rect{
|
||||
mViewInfo->GetVRulerOffset(),
|
||||
trackRect.y,
|
||||
mViewInfo->GetVRulerWidth() + 1,
|
||||
trackRect.height - kSeparatorThickness
|
||||
};
|
||||
TrackArt::DrawVRuler(context, channel, rect, bSelected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto target = Target();
|
||||
|
@ -1086,7 +1067,7 @@ void TrackPanel::HighlightFocusedTrack(wxDC * dc, const wxRect & rect)
|
|||
|
||||
void TrackPanel::UpdateVRulers()
|
||||
{
|
||||
for (auto t : GetTracks()->Any< const WaveTrack >())
|
||||
for (auto t : GetTracks()->Any< WaveTrack >())
|
||||
UpdateTrackVRuler(t);
|
||||
|
||||
UpdateVRulerSize();
|
||||
|
@ -1100,7 +1081,7 @@ void TrackPanel::UpdateVRuler(Track *t)
|
|||
UpdateVRulerSize();
|
||||
}
|
||||
|
||||
void TrackPanel::UpdateTrackVRuler(const Track *t)
|
||||
void TrackPanel::UpdateTrackVRuler(Track *t)
|
||||
{
|
||||
wxASSERT(t);
|
||||
if (!t)
|
||||
|
@ -1115,7 +1096,7 @@ void TrackPanel::UpdateTrackVRuler(const Track *t)
|
|||
for (auto channel : TrackList::Channels(t)) {
|
||||
auto &view = TrackView::Get( *channel );
|
||||
rect.height = view.GetHeight() - (kTopMargin + kBottomMargin);
|
||||
mTrackArtist->UpdateVRuler(channel, rect);
|
||||
TrackVRulerControls::Get( *channel ).UpdateRuler( rect );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@ class AUDACITY_DLL_API TrackPanel final
|
|||
|
||||
void UpdateVRulers();
|
||||
void UpdateVRuler(Track *t);
|
||||
void UpdateTrackVRuler(const Track *t);
|
||||
void UpdateTrackVRuler(Track *t);
|
||||
void UpdateVRulerSize();
|
||||
|
||||
protected:
|
||||
|
|
|
@ -13,6 +13,38 @@ Paul Licameli split from TrackPanel.cpp
|
|||
|
||||
#include "../../../HitTestResult.h"
|
||||
|
||||
#include "../../../AColor.h"
|
||||
#include "../../../TrackArtist.h"
|
||||
#include "../../../TrackPanelDrawingContext.h"
|
||||
|
||||
LabelTrackVRulerControls::~LabelTrackVRulerControls()
|
||||
{
|
||||
}
|
||||
|
||||
void LabelTrackVRulerControls::Draw(
|
||||
TrackPanelDrawingContext &context,
|
||||
const wxRect &rect_, unsigned iPass )
|
||||
{
|
||||
TrackVRulerControls::Draw( context, rect_, iPass );
|
||||
|
||||
// Draw on a later pass because the bevel overpaints one pixel
|
||||
// out of bounds on the bottom
|
||||
|
||||
if ( iPass == TrackArtist::PassControls ) {
|
||||
auto rect = rect_;
|
||||
--rect.width;
|
||||
--rect.height;
|
||||
|
||||
auto dc = &context.dc;
|
||||
wxRect bev = rect;
|
||||
bev.Inflate(-1, 0);
|
||||
bev.width += 1;
|
||||
AColor::BevelTrackInfo(*dc, true, bev);
|
||||
}
|
||||
}
|
||||
|
||||
void LabelTrackVRulerControls::UpdateRuler( const wxRect &rect )
|
||||
{
|
||||
// Label tracks do not have a vruler
|
||||
// do nothing
|
||||
}
|
||||
|
|
|
@ -26,6 +26,17 @@ public:
|
|||
LabelTrackVRulerControls( const std::shared_ptr<TrackView> &pTrackView )
|
||||
: TrackVRulerControls( pTrackView ) {}
|
||||
~LabelTrackVRulerControls();
|
||||
|
||||
private:
|
||||
|
||||
// TrackPanelDrawable implementation
|
||||
void Draw(
|
||||
TrackPanelDrawingContext &context,
|
||||
const wxRect &rect, unsigned iPass ) override;
|
||||
|
||||
// TrackVRulerControls implementation
|
||||
void UpdateRuler( const wxRect &rect ) override;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,8 +19,15 @@ Paul Licameli split from TrackPanel.cpp
|
|||
#include "../../../../NoteTrack.h"
|
||||
#include "../../../../ProjectHistory.h"
|
||||
#include "../../../../RefreshCode.h"
|
||||
#include "../../../../TrackArtist.h"
|
||||
#include "../../../../TrackPanelMouseEvent.h"
|
||||
|
||||
#include "../../../../AColor.h"
|
||||
#include "../../../../Experimental.h"
|
||||
#include "../../../../TrackPanelDrawingContext.h"
|
||||
#include "../../../../widgets/Ruler.h"
|
||||
|
||||
#include <wx/dc.h>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
NoteTrackVRulerControls::~NoteTrackVRulerControls()
|
||||
|
@ -86,4 +93,140 @@ unsigned NoteTrackVRulerControls::HandleWheelRotation
|
|||
return RefreshCell | UpdateVRuler;
|
||||
}
|
||||
|
||||
void NoteTrackVRulerControls::Draw(
|
||||
TrackPanelDrawingContext &context,
|
||||
const wxRect &rect_, unsigned iPass )
|
||||
{
|
||||
TrackVRulerControls::Draw( context, rect_, iPass );
|
||||
|
||||
// Draw on a later pass like other vertical rulers,
|
||||
// although the bevel is done a little differently
|
||||
|
||||
if ( iPass == TrackArtist::PassControls ) {
|
||||
// The note track draws a vertical keyboard to label pitches
|
||||
auto track = std::static_pointer_cast<NoteTrack>( FindTrack() );
|
||||
if ( !track )
|
||||
return;
|
||||
|
||||
auto rect = rect_;
|
||||
--rect.width;
|
||||
--rect.height;
|
||||
|
||||
bool highlight = false;
|
||||
#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
|
||||
highlight = rect.Contains(context.lastState.GetPosition());
|
||||
#endif
|
||||
|
||||
const auto artist = TrackArtist::Get( context );
|
||||
UpdateRuler(rect);
|
||||
|
||||
auto dc = &context.dc;
|
||||
|
||||
dc->SetPen(highlight ? AColor::uglyPen : *wxTRANSPARENT_PEN);
|
||||
dc->SetBrush(*wxWHITE_BRUSH);
|
||||
wxRect bev = rect;
|
||||
bev.x++;
|
||||
bev.width--;
|
||||
dc->DrawRectangle(bev);
|
||||
|
||||
rect.y += 1;
|
||||
rect.height -= 1;
|
||||
|
||||
NoteTrackDisplayData data{ track.get(), rect };
|
||||
|
||||
wxPen hilitePen;
|
||||
hilitePen.SetColour(120, 120, 120);
|
||||
wxBrush blackKeyBrush;
|
||||
blackKeyBrush.SetColour(70, 70, 70);
|
||||
|
||||
dc->SetBrush(blackKeyBrush);
|
||||
|
||||
int fontSize = 10;
|
||||
#ifdef __WXMSW__
|
||||
fontSize = 8;
|
||||
#endif
|
||||
|
||||
wxFont labelFont(fontSize, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
|
||||
dc->SetFont(labelFont);
|
||||
|
||||
int octave = 0;
|
||||
int obottom = data.GetOctaveBottom(octave);
|
||||
int marg = data.GetNoteMargin();
|
||||
|
||||
while (obottom >= rect.y) {
|
||||
dc->SetPen(*wxBLACK_PEN);
|
||||
for (int white = 0; white < 7; white++) {
|
||||
int pos = data.GetWhitePos(white);
|
||||
if (obottom - pos > rect.y + marg + 1 &&
|
||||
// don't draw too close to margin line -- it's annoying
|
||||
obottom - pos < rect.y + rect.height - marg - 3)
|
||||
AColor::Line(*dc, rect.x, obottom - pos,
|
||||
rect.x + rect.width, obottom - pos);
|
||||
}
|
||||
wxRect br = rect;
|
||||
br.height = data.GetPitchHeight(1);
|
||||
br.x++;
|
||||
br.width = 17;
|
||||
for (int black = 0; black < 5; black++) {
|
||||
br.y = obottom - data.GetBlackPos(black);
|
||||
if (br.y > rect.y + marg - 2 && br.y + br.height < rect.y + rect.height - marg) {
|
||||
dc->SetPen(hilitePen);
|
||||
dc->DrawRectangle(br);
|
||||
dc->SetPen(*wxBLACK_PEN);
|
||||
AColor::Line(*dc,
|
||||
br.x + 1, br.y + br.height - 1,
|
||||
br.x + br.width - 1, br.y + br.height - 1);
|
||||
AColor::Line(*dc,
|
||||
br.x + br.width - 1, br.y + 1,
|
||||
br.x + br.width - 1, br.y + br.height - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (octave >= 1 && octave <= 10) {
|
||||
wxString s;
|
||||
// ISO standard: A440 is in the 4th octave, denoted
|
||||
// A4 <- the "4" should be a subscript.
|
||||
s.Printf(wxT("C%d"), octave - 1);
|
||||
wxCoord width, height;
|
||||
dc->GetTextExtent(s, &width, &height);
|
||||
if (obottom - height + 4 > rect.y &&
|
||||
obottom + 4 < rect.y + rect.height) {
|
||||
dc->SetTextForeground(wxColour(60, 60, 255));
|
||||
dc->DrawText(s, rect.x + rect.width - width,
|
||||
obottom - height + 2);
|
||||
}
|
||||
}
|
||||
obottom = data.GetOctaveBottom(++octave);
|
||||
}
|
||||
// draw lines delineating the out-of-bounds margins
|
||||
dc->SetPen(*wxBLACK_PEN);
|
||||
// you would think the -1 offset here should be -2 to match the
|
||||
// adjustment to rect.y (see above), but -1 produces correct output
|
||||
AColor::Line(*dc, rect.x, rect.y + marg - 1, rect.x + rect.width, rect.y + marg - 1);
|
||||
// since the margin gives us the bottom of the line,
|
||||
// the extra -1 gets us to the top
|
||||
AColor::Line(*dc, rect.x, rect.y + rect.height - marg - 1,
|
||||
rect.x + rect.width, rect.y + rect.height - marg - 1);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void NoteTrackVRulerControls::UpdateRuler( const wxRect &rect )
|
||||
{
|
||||
// The note track isn't drawing a ruler at all!
|
||||
// But it needs to!
|
||||
|
||||
const auto nt = std::static_pointer_cast< NoteTrack >( FindTrack() );
|
||||
if (!nt)
|
||||
return;
|
||||
|
||||
static Ruler ruler;
|
||||
const auto vruler = &ruler;
|
||||
|
||||
vruler->SetBounds(rect.x, rect.y, rect.x + 1, rect.y + rect.height-1);
|
||||
vruler->SetOrientation(wxVERTICAL);
|
||||
|
||||
vruler->GetMaxSize( &nt->vrulerSize.x, &nt->vrulerSize.y );
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -35,6 +35,14 @@ public:
|
|||
AudacityProject *pProject) override;
|
||||
|
||||
private:
|
||||
// TrackPanelDrawable implementation
|
||||
void Draw(
|
||||
TrackPanelDrawingContext &context,
|
||||
const wxRect &rect, unsigned iPass ) override;
|
||||
|
||||
// TrackVRulerControls implementation
|
||||
void UpdateRuler( const wxRect &rect ) override;
|
||||
|
||||
std::weak_ptr<NoteTrackVZoomHandle> mVZoomHandle;
|
||||
};
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@ Paul Licameli split from TrackPanel.cpp
|
|||
|
||||
#include "WaveTrackVZoomHandle.h"
|
||||
|
||||
#include "../../../../Experimental.h"
|
||||
|
||||
#include "../../../../HitTestResult.h"
|
||||
#include "../../../../NumberScale.h"
|
||||
#include "../../../../prefs/SpectrogramSettings.h"
|
||||
|
@ -22,6 +24,12 @@ Paul Licameli split from TrackPanel.cpp
|
|||
#include "../../../../TrackPanelMouseEvent.h"
|
||||
#include "../../../../WaveTrack.h"
|
||||
|
||||
#include "../../../../AColor.h"
|
||||
#include "../../../../AllThemeResources.h"
|
||||
#include "../../../../TrackArtist.h"
|
||||
#include "../../../../TrackPanelDrawingContext.h"
|
||||
#include "../../../../widgets/Ruler.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
WaveTrackVRulerControls::~WaveTrackVRulerControls()
|
||||
{
|
||||
|
@ -198,3 +206,302 @@ unsigned WaveTrackVRulerControls::HandleWheelRotation
|
|||
|
||||
return RefreshCell | UpdateVRuler;
|
||||
}
|
||||
|
||||
namespace {
|
||||
Ruler &ruler()
|
||||
{
|
||||
static Ruler theRuler;
|
||||
return theRuler;
|
||||
}
|
||||
}
|
||||
|
||||
void WaveTrackVRulerControls::Draw(
|
||||
TrackPanelDrawingContext &context,
|
||||
const wxRect &rect_, unsigned iPass )
|
||||
{
|
||||
TrackVRulerControls::Draw( context, rect_, iPass );
|
||||
|
||||
// Draw on a later pass because the bevel overpaints one pixel
|
||||
// out of bounds on the bottom
|
||||
|
||||
if ( iPass == TrackArtist::PassControls ) {
|
||||
auto rect = rect_;
|
||||
--rect.width;
|
||||
--rect.height;
|
||||
|
||||
auto dc = &context.dc;
|
||||
|
||||
// All waves have a ruler in the info panel
|
||||
// The ruler needs a bevelled surround.
|
||||
wxRect bev = rect;
|
||||
bev.Inflate(-1, 0);
|
||||
bev.width += 1;
|
||||
|
||||
bool highlight = false;
|
||||
#ifdef EXPERIMENTAL_TRACK_PANEL_HIGHLIGHTING
|
||||
highlight = rect.Contains(context.lastState.GetPosition());
|
||||
#endif
|
||||
|
||||
AColor::BevelTrackInfo(*dc, true, bev, highlight);
|
||||
|
||||
// Right align the ruler
|
||||
wxRect rr = rect;
|
||||
rr.width--;
|
||||
|
||||
auto t = FindTrack();
|
||||
if ( !t )
|
||||
return;
|
||||
|
||||
if ( t->vrulerSize.GetWidth() < rect.GetWidth()) {
|
||||
int adj = rr.GetWidth() - t->vrulerSize.GetWidth();
|
||||
rr.x += adj;
|
||||
rr.width -= adj;
|
||||
}
|
||||
|
||||
UpdateRuler(rr);
|
||||
|
||||
auto vruler = &ruler();
|
||||
|
||||
vruler->SetTickColour( theTheme.Colour( clrTrackPanelText ));
|
||||
vruler->Draw(*dc);
|
||||
}
|
||||
}
|
||||
|
||||
void WaveTrackVRulerControls::UpdateRuler( const wxRect &rect )
|
||||
{
|
||||
const auto wt = std::static_pointer_cast< WaveTrack >( FindTrack() );
|
||||
if (!wt)
|
||||
return;
|
||||
auto vruler = &ruler();
|
||||
|
||||
// All waves have a ruler in the info panel
|
||||
// The ruler needs a bevelled surround.
|
||||
const float dBRange =
|
||||
wt->GetWaveformSettings().dBRange;
|
||||
|
||||
const int display = wt->GetDisplay();
|
||||
|
||||
if (display == WaveTrackViewConstants::Waveform) {
|
||||
WaveformSettings::ScaleType scaleType =
|
||||
wt->GetWaveformSettings().scaleType;
|
||||
|
||||
if (scaleType == WaveformSettings::stLinear) {
|
||||
// Waveform
|
||||
|
||||
float min, max;
|
||||
wt->GetDisplayBounds(&min, &max);
|
||||
if (wt->GetLastScaleType() != scaleType &&
|
||||
wt->GetLastScaleType() != -1)
|
||||
{
|
||||
// do a translation into the linear space
|
||||
wt->SetLastScaleType();
|
||||
wt->SetLastdBRange();
|
||||
float sign = (min >= 0 ? 1 : -1);
|
||||
if (min != 0.) {
|
||||
min = DB_TO_LINEAR(fabs(min) * dBRange - dBRange);
|
||||
if (min < 0.0)
|
||||
min = 0.0;
|
||||
min *= sign;
|
||||
}
|
||||
sign = (max >= 0 ? 1 : -1);
|
||||
|
||||
if (max != 0.) {
|
||||
max = DB_TO_LINEAR(fabs(max) * dBRange - dBRange);
|
||||
if (max < 0.0)
|
||||
max = 0.0;
|
||||
max *= sign;
|
||||
}
|
||||
wt->SetDisplayBounds(min, max);
|
||||
}
|
||||
|
||||
vruler->SetDbMirrorValue( 0.0 );
|
||||
vruler->SetBounds(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height - 1);
|
||||
vruler->SetOrientation(wxVERTICAL);
|
||||
vruler->SetRange(max, min);
|
||||
vruler->SetFormat(Ruler::RealFormat);
|
||||
vruler->SetUnits(wxT(""));
|
||||
vruler->SetLabelEdges(false);
|
||||
vruler->SetLog(false);
|
||||
}
|
||||
else {
|
||||
wxASSERT(scaleType == WaveformSettings::stLogarithmic);
|
||||
scaleType = WaveformSettings::stLogarithmic;
|
||||
|
||||
vruler->SetUnits(wxT(""));
|
||||
|
||||
float min, max;
|
||||
wt->GetDisplayBounds(&min, &max);
|
||||
float lastdBRange;
|
||||
|
||||
if (wt->GetLastScaleType() != scaleType &&
|
||||
wt->GetLastScaleType() != -1)
|
||||
{
|
||||
// do a translation into the dB space
|
||||
wt->SetLastScaleType();
|
||||
wt->SetLastdBRange();
|
||||
float sign = (min >= 0 ? 1 : -1);
|
||||
if (min != 0.) {
|
||||
min = (LINEAR_TO_DB(fabs(min)) + dBRange) / dBRange;
|
||||
if (min < 0.0)
|
||||
min = 0.0;
|
||||
min *= sign;
|
||||
}
|
||||
sign = (max >= 0 ? 1 : -1);
|
||||
|
||||
if (max != 0.) {
|
||||
max = (LINEAR_TO_DB(fabs(max)) + dBRange) / dBRange;
|
||||
if (max < 0.0)
|
||||
max = 0.0;
|
||||
max *= sign;
|
||||
}
|
||||
wt->SetDisplayBounds(min, max);
|
||||
}
|
||||
else if (dBRange != (lastdBRange = wt->GetLastdBRange())) {
|
||||
wt->SetLastdBRange();
|
||||
// Remap the max of the scale
|
||||
float newMax = max;
|
||||
|
||||
// This commented out code is problematic.
|
||||
// min and max may be correct, and this code cause them to change.
|
||||
#ifdef ONLY_LABEL_POSITIVE
|
||||
const float sign = (max >= 0 ? 1 : -1);
|
||||
if (max != 0.) {
|
||||
|
||||
// Ugh, duplicating from TrackPanel.cpp
|
||||
#define ZOOMLIMIT 0.001f
|
||||
|
||||
const float extreme = LINEAR_TO_DB(2);
|
||||
// recover dB value of max
|
||||
const float dB = std::min(extreme, (float(fabs(max)) * lastdBRange - lastdBRange));
|
||||
// find NEW scale position, but old max may get trimmed if the db limit rises
|
||||
// Don't trim it to zero though, but leave max and limit distinct
|
||||
newMax = sign * std::max(ZOOMLIMIT, (dBRange + dB) / dBRange);
|
||||
// Adjust the min of the scale if we can,
|
||||
// so the db Limit remains where it was on screen, but don't violate extremes
|
||||
if (min != 0.)
|
||||
min = std::max(-extreme, newMax * min / max);
|
||||
}
|
||||
#endif
|
||||
wt->SetDisplayBounds(min, newMax);
|
||||
}
|
||||
|
||||
// Old code was if ONLY_LABEL_POSITIVE were defined.
|
||||
// it uses the +1 to 0 range only.
|
||||
// the enabled code uses +1 to -1, and relies on set ticks labelling knowing about
|
||||
// the dB scale.
|
||||
#ifdef ONLY_LABEL_POSITIVE
|
||||
if (max > 0) {
|
||||
#endif
|
||||
int top = 0;
|
||||
float topval = 0;
|
||||
int bot = rect.height;
|
||||
float botval = -dBRange;
|
||||
|
||||
#ifdef ONLY_LABEL_POSITIVE
|
||||
if (min < 0) {
|
||||
bot = top + (int)((max / (max - min))*(bot - top));
|
||||
min = 0;
|
||||
}
|
||||
|
||||
if (max > 1) {
|
||||
top += (int)((max - 1) / (max - min) * (bot - top));
|
||||
max = 1;
|
||||
}
|
||||
|
||||
if (max < 1 && max > 0)
|
||||
topval = -((1 - max) * dBRange);
|
||||
|
||||
if (min > 0) {
|
||||
botval = -((1 - min) * dBRange);
|
||||
}
|
||||
#else
|
||||
topval = -((1 - max) * dBRange);
|
||||
botval = -((1 - min) * dBRange);
|
||||
vruler->SetDbMirrorValue( dBRange );
|
||||
#endif
|
||||
vruler->SetBounds(rect.x, rect.y + top, rect.x + rect.width, rect.y + bot - 1);
|
||||
vruler->SetOrientation(wxVERTICAL);
|
||||
vruler->SetRange(topval, botval);
|
||||
#ifdef ONLY_LABEL_POSITIVE
|
||||
}
|
||||
else
|
||||
vruler->SetBounds(0.0, 0.0, 0.0, 0.0); // A.C.H I couldn't find a way to just disable it?
|
||||
#endif
|
||||
vruler->SetFormat(Ruler::RealLogFormat);
|
||||
vruler->SetLabelEdges(true);
|
||||
vruler->SetLog(false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
wxASSERT(display == WaveTrackViewConstants::Spectrum);
|
||||
const SpectrogramSettings &settings = wt->GetSpectrogramSettings();
|
||||
float minFreq, maxFreq;
|
||||
wt->GetSpectrumBounds(&minFreq, &maxFreq);
|
||||
vruler->SetDbMirrorValue( 0.0 );
|
||||
|
||||
switch (settings.scaleType) {
|
||||
default:
|
||||
wxASSERT(false);
|
||||
case SpectrogramSettings::stLinear:
|
||||
{
|
||||
// Spectrum
|
||||
|
||||
if (rect.height < 60)
|
||||
return;
|
||||
|
||||
/*
|
||||
draw the ruler
|
||||
we will use Hz if maxFreq is < 2000, otherwise we represent kHz,
|
||||
and append to the numbers a "k"
|
||||
*/
|
||||
vruler->SetBounds(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height - 1);
|
||||
vruler->SetOrientation(wxVERTICAL);
|
||||
vruler->SetFormat(Ruler::RealFormat);
|
||||
vruler->SetLabelEdges(true);
|
||||
// use kHz in scale, if appropriate
|
||||
if (maxFreq >= 2000) {
|
||||
vruler->SetRange((maxFreq / 1000.), (minFreq / 1000.));
|
||||
vruler->SetUnits(wxT("k"));
|
||||
}
|
||||
else {
|
||||
// use Hz
|
||||
vruler->SetRange((int)(maxFreq), (int)(minFreq));
|
||||
vruler->SetUnits(wxT(""));
|
||||
}
|
||||
vruler->SetLog(false);
|
||||
}
|
||||
break;
|
||||
case SpectrogramSettings::stLogarithmic:
|
||||
case SpectrogramSettings::stMel:
|
||||
case SpectrogramSettings::stBark:
|
||||
case SpectrogramSettings::stErb:
|
||||
case SpectrogramSettings::stPeriod:
|
||||
{
|
||||
// SpectrumLog
|
||||
|
||||
if (rect.height < 10)
|
||||
return;
|
||||
|
||||
/*
|
||||
draw the ruler
|
||||
we will use Hz if maxFreq is < 2000, otherwise we represent kHz,
|
||||
and append to the numbers a "k"
|
||||
*/
|
||||
vruler->SetBounds(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height - 1);
|
||||
vruler->SetOrientation(wxVERTICAL);
|
||||
vruler->SetFormat(Ruler::IntFormat);
|
||||
vruler->SetLabelEdges(true);
|
||||
vruler->SetRange(maxFreq, minFreq);
|
||||
vruler->SetUnits(wxT(""));
|
||||
vruler->SetLog(true);
|
||||
NumberScale scale(
|
||||
wt->GetSpectrogramSettings().GetScale( minFreq, maxFreq )
|
||||
.Reversal() );
|
||||
vruler->SetNumberScale(&scale);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vruler->GetMaxSize( &wt->vrulerSize.x, &wt->vrulerSize.y );
|
||||
}
|
||||
|
|
|
@ -35,6 +35,14 @@ public:
|
|||
AudacityProject *pProject) override;
|
||||
void DoZoomPreset( int i);
|
||||
private:
|
||||
// TrackPanelDrawable implementation
|
||||
void Draw(
|
||||
TrackPanelDrawingContext &context,
|
||||
const wxRect &rect, unsigned iPass ) override;
|
||||
|
||||
// TrackVRulerControls implementation
|
||||
void UpdateRuler( const wxRect &rect ) override;
|
||||
|
||||
std::weak_ptr<WaveTrackVZoomHandle> mVZoomHandle;
|
||||
};
|
||||
|
||||
|
|
|
@ -13,6 +13,86 @@ Paul Licameli split from TrackPanel.cpp
|
|||
|
||||
#include "../../../HitTestResult.h"
|
||||
|
||||
#include "../../../AColor.h"
|
||||
#include "../../../AllThemeResources.h"
|
||||
#include "../../../TimeTrack.h"
|
||||
#include "../../../TrackArtist.h"
|
||||
#include "../../../TrackPanelDrawingContext.h"
|
||||
#include "../../../widgets/Ruler.h"
|
||||
|
||||
TimeTrackVRulerControls::~TimeTrackVRulerControls()
|
||||
{
|
||||
}
|
||||
|
||||
namespace {
|
||||
Ruler &ruler()
|
||||
{
|
||||
static Ruler theRuler;
|
||||
return theRuler;
|
||||
}
|
||||
}
|
||||
|
||||
void TimeTrackVRulerControls::Draw(
|
||||
TrackPanelDrawingContext &context,
|
||||
const wxRect &rect_, unsigned iPass )
|
||||
{
|
||||
TrackVRulerControls::Draw( context, rect_, iPass );
|
||||
|
||||
// Draw on a later pass because the bevel overpaints one pixel
|
||||
// out of bounds on the bottom
|
||||
|
||||
if ( iPass == TrackArtist::PassControls ) {
|
||||
auto t = FindTrack();
|
||||
if ( !t )
|
||||
return;
|
||||
|
||||
auto rect = rect_;
|
||||
--rect.width;
|
||||
--rect.height;
|
||||
|
||||
auto dc = &context.dc;
|
||||
wxRect bev = rect;
|
||||
bev.Inflate(-1, 0);
|
||||
bev.width += 1;
|
||||
AColor::BevelTrackInfo(*dc, true, bev);
|
||||
|
||||
// Right align the ruler
|
||||
wxRect rr = rect;
|
||||
rr.width--;
|
||||
if (t && t->vrulerSize.GetWidth() < rect.GetWidth()) {
|
||||
int adj = rr.GetWidth() - t->vrulerSize.GetWidth();
|
||||
rr.x += adj;
|
||||
rr.width -= adj;
|
||||
}
|
||||
|
||||
UpdateRuler(rr);
|
||||
|
||||
auto vruler = &ruler();
|
||||
|
||||
vruler->SetTickColour( theTheme.Colour( clrTrackPanelText ));
|
||||
vruler->Draw(*dc);
|
||||
}
|
||||
}
|
||||
|
||||
void TimeTrackVRulerControls::UpdateRuler( const wxRect &rect )
|
||||
{
|
||||
const auto tt = std::static_pointer_cast< TimeTrack >( FindTrack() );
|
||||
if (!tt)
|
||||
return;
|
||||
auto vruler = &ruler();
|
||||
|
||||
float min, max;
|
||||
min = tt->GetRangeLower() * 100.0;
|
||||
max = tt->GetRangeUpper() * 100.0;
|
||||
|
||||
vruler->SetDbMirrorValue( 0.0 );
|
||||
vruler->SetBounds(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height-1);
|
||||
vruler->SetOrientation(wxVERTICAL);
|
||||
vruler->SetRange(max, min);
|
||||
vruler->SetFormat((tt->GetDisplayLog()) ? Ruler::RealLogFormat : Ruler::RealFormat);
|
||||
vruler->SetUnits(wxT(""));
|
||||
vruler->SetLabelEdges(false);
|
||||
vruler->SetLog(tt->GetDisplayLog());
|
||||
|
||||
vruler->GetMaxSize( &tt->vrulerSize.x, &tt->vrulerSize.y );
|
||||
}
|
||||
|
|
|
@ -25,6 +25,17 @@ public:
|
|||
TimeTrackVRulerControls( const std::shared_ptr<TrackView> &pTrackView )
|
||||
: TrackVRulerControls( pTrackView ) {}
|
||||
~TimeTrackVRulerControls();
|
||||
|
||||
private:
|
||||
|
||||
// TrackPanelDrawable implementation
|
||||
void Draw(
|
||||
TrackPanelDrawingContext &context,
|
||||
const wxRect &rect, unsigned iPass ) override;
|
||||
|
||||
// TrackVRulerControls implementation
|
||||
void UpdateRuler( const wxRect &rect ) override;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -114,3 +114,14 @@ void TrackVRulerControls::Draw(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
wxRect TrackVRulerControls::DrawingArea(
|
||||
const wxRect &rect, const wxRect &, unsigned iPass )
|
||||
{
|
||||
// Common area change for all subclasses when drawing the controls
|
||||
// A bevel extends below one pixel outside of the hit-test area
|
||||
if ( iPass == TrackArtist::PassControls )
|
||||
return { rect.x, rect.y, rect.width, rect.height + 1 };
|
||||
else
|
||||
return rect;
|
||||
}
|
||||
|
|
|
@ -43,6 +43,10 @@ public:
|
|||
( wxDC *dc, const wxRect &cellRect, const wxRect &panelRect,
|
||||
int zoomStart, int zoomEnd);
|
||||
|
||||
// Modify the ruler rectangle, and related display parameters,
|
||||
// cached in the associated track
|
||||
virtual void UpdateRuler( const wxRect &rect ) = 0;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<Track> DoFindTrack() override;
|
||||
|
||||
|
@ -51,6 +55,9 @@ protected:
|
|||
TrackPanelDrawingContext &context,
|
||||
const wxRect &rect, unsigned iPass ) override;
|
||||
|
||||
wxRect DrawingArea(
|
||||
const wxRect &rect, const wxRect &panelRect, unsigned iPass ) override;
|
||||
|
||||
Track *GetTrack() const;
|
||||
|
||||
std::weak_ptr<TrackView> mwTrackView;
|
||||
|
|
Loading…
Reference in New Issue