1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-15 23:59:37 +02:00

Wave track view type stored in the views not the tracks...

... and some latent support added for multiple views.

Still unsettled is what Nyquist should do with tracks with multiple view types;
for now only pass one of them.
This commit is contained in:
Paul Licameli 2019-07-10 10:21:07 -04:00
commit f4b370d1e2
22 changed files with 288 additions and 127 deletions

View File

@ -97,15 +97,6 @@ WaveTrack::WaveTrack(const std::shared_ptr<DirManager> &projDirManager, sampleFo
}
}
// Force creation always:
WaveformSettings &settings = GetIndependentWaveformSettings();
mDisplay = TracksPrefs::ViewModeChoice();
if (mDisplay == WaveTrackViewConstants::obsoleteWaveformDBDisplay) {
mDisplay = WaveTrackViewConstants::Waveform;
settings.scaleType = WaveformSettings::stLogarithmic;
}
mLegacyProjectFileOffset = 0;
mFormat = format;
@ -161,7 +152,6 @@ void WaveTrack::Init(const WaveTrack &orig)
mOldGain[1] = 0.0;
SetDefaultName(orig.GetDefaultName());
SetName(orig.GetName());
mDisplay = orig.mDisplay;
mDisplayMin = orig.mDisplayMin;
mDisplayMax = orig.mDisplayMax;
mSpectrumMin = orig.mSpectrumMin;
@ -196,7 +186,6 @@ void WaveTrack::Merge(const Track &orig)
{
orig.TypeSwitch( [&](const WaveTrack *pwt) {
const WaveTrack &wt = *pwt;
mDisplay = wt.mDisplay;
mGain = wt.mGain;
mPan = wt.mPan;
mDisplayMin = wt.mDisplayMin;

View File

@ -17,7 +17,6 @@
#include <wx/longlong.h>
#include "WaveTrackLocation.h"
#include "tracks/playabletrack/wavetrack/ui/WaveTrackViewConstants.h"
class ProgressDialog;
@ -523,17 +522,12 @@ private:
// Set the unique autosave ID
void SetAutoSaveIdent(int id);
using WaveTrackDisplay = WaveTrackViewConstants::Display;
int GetLastScaleType() const { return mLastScaleType; }
void SetLastScaleType() const;
int GetLastdBRange() const { return mLastdBRange; }
void SetLastdBRange() const;
WaveTrackDisplay GetDisplay() const { return mDisplay; }
void SetDisplay(WaveTrackDisplay display) { mDisplay = display; }
void GetDisplayBounds(float *min, float *max) const;
void SetDisplayBounds(float min, float max) const;
void GetSpectrumBounds(float *min, float *max) const;
@ -568,7 +562,6 @@ private:
mutable float mSpectrumMin;
mutable float mSpectrumMax;
WaveTrackDisplay mDisplay;
mutable int mLastScaleType; // last scale type choice
mutable int mLastdBRange;
mutable std::vector <Location> mDisplayLocationsCache;

View File

@ -44,7 +44,8 @@ SetTrackAudioCommand and SetTrackVisualsCommand.
#include "../prefs/SpectrogramSettings.h"
#include "../Shuttle.h"
#include "../ShuttleGui.h"
#include "../tracks/ui/TrackView.h"
#include "../tracks/playabletrack/wavetrack/ui/WaveTrackView.h"
#include "../tracks/playabletrack/wavetrack/ui/WaveTrackViewConstants.h"
#include "CommandContext.h"
SetTrackBase::SetTrackBase(){
@ -353,7 +354,7 @@ bool SetTrackVisualsCommand::ApplyInner(const CommandContext & context, Track *
TrackView::Get( *t ).SetHeight( mHeight );
if( wt && bHasDisplayType )
wt->SetDisplay(
WaveTrackView::Get( *wt ).SetDisplay(
(mDisplayType == kWaveform) ?
WaveTrackViewConstants::Waveform
: WaveTrackViewConstants::Spectrum

View File

@ -68,6 +68,8 @@ greater use in future.
#include "../widgets/ProgressDialog.h"
#include "../ondemand/ODManager.h"
#include "TimeWarper.h"
#include "../tracks/playabletrack/wavetrack/ui/WaveTrackView.h"
#include "../tracks/playabletrack/wavetrack/ui/WaveTrackViewConstants.h"
#include "../widgets/HelpSystem.h"
#include "../widgets/NumericTextCtrl.h"
#include "../widgets/AudacityMessageBox.h"
@ -2360,7 +2362,8 @@ void Effect::Preview(bool dryOnly)
mixLeft->Offset(-mixLeft->GetStartTime());
mixLeft->SetSelected(true);
mixLeft->SetDisplay(WaveTrackViewConstants::NoDisplay);
WaveTrackView::Get( *mixLeft )
.SetDisplay(WaveTrackViewConstants::NoDisplay);
auto pLeft = mTracks->Add( mixLeft );
Track *pRight{};
if (mixRight) {
@ -2375,8 +2378,8 @@ void Effect::Preview(bool dryOnly)
if (src->GetSelected() || mPreviewWithNotSelected) {
auto dest = src->Copy(mT0, t1);
dest->SetSelected(src->GetSelected());
static_cast<WaveTrack*>(dest.get())
->SetDisplay(WaveTrackViewConstants::NoDisplay);
WaveTrackView::Get( *static_cast<WaveTrack*>(dest.get()) )
.SetDisplay(WaveTrackViewConstants::NoDisplay);
mTracks->Add( dest );
}
}

View File

@ -73,6 +73,8 @@ effects from this one class.
#include "../../wxFileNameWrapper.h"
#include "../../prefs/GUIPrefs.h"
#include "../../prefs/WaveformSettings.h"
#include "../../tracks/playabletrack/wavetrack/ui/WaveTrackView.h"
#include "../../tracks/playabletrack/wavetrack/ui/WaveTrackViewConstants.h"
#include "../../widgets/NumericTextCtrl.h"
#include "../../widgets/ProgressDialog.h"
@ -542,7 +544,11 @@ bool NyquistEffect::Init()
for ( auto t :
TrackList::Get( *project ).Selected< const WaveTrack >() ) {
if (t->GetDisplay() != WaveTrackViewConstants::Spectrum ||
const auto displays = WaveTrackView::Get(*t).GetDisplays();
bool hasSpectral =
make_iterator_range( displays.begin(), displays.end())
.contains( WaveTrackViewConstants::Spectrum );
if ( !hasSpectral ||
!(t->GetSpectrogramSettings().SpectralSelectionEnabled())) {
bAllowSpectralEditing = false;
break;
@ -1066,7 +1072,12 @@ bool NyquistEffect::ProcessOne()
[&](const WaveTrack *wt) {
type = wxT("wave");
spectralEditp = mCurTrack[0]->GetSpectrogramSettings().SpectralSelectionEnabled()? wxT("T") : wxT("NIL");
switch (wt->GetDisplay())
// To do: accommodate split views
auto viewType = WaveTrackViewConstants::NoDisplay;
auto displays = WaveTrackView::Get( *wt ).GetDisplays();
if (!displays.empty())
viewType = displays[0];
switch ( viewType )
{
case Waveform:
view = (mCurTrack[0]->GetWaveformSettings().scaleType == 0) ? wxT("\"Waveform\"") : wxT("\"Waveform (dB)\"");

View File

@ -21,6 +21,8 @@
#include "../commands/CommandManager.h"
#include "../toolbars/ControlToolBar.h"
#include "../tracks/ui/SelectHandle.h"
#include "../tracks/playabletrack/wavetrack/ui/WaveTrackView.h"
#include "../tracks/playabletrack/wavetrack/ui/WaveTrackViewConstants.h"
// private helper classes and functions
namespace {
@ -33,8 +35,9 @@ void DoNextPeakFrequency(AudacityProject &project, bool up)
// Find the first selected wave track that is in a spectrogram view.
const WaveTrack *pTrack {};
for ( auto wt : tracks.Selected< const WaveTrack >() ) {
const int display = wt->GetDisplay();
if (display == WaveTrackViewConstants::Spectrum) {
const auto displays = WaveTrackView::Get( *wt ).GetDisplays();
if ( make_iterator_range( displays.begin(), displays.end() )
.contains( WaveTrackViewConstants::Spectrum) ) {
pTrack = wt;
break;
}

View File

@ -31,6 +31,7 @@
#include "../TrackPanel.h"
#include "../WaveTrack.h"
#include "../tracks/playabletrack/wavetrack/ui/WaveTrackView.h"
#include <algorithm>
@ -48,7 +49,7 @@ SpectrumPrefs::SpectrumPrefs(wxWindow * parent, wxWindowID winid, WaveTrack *wt)
wt->GetSpectrumBounds(&mOrigMin, &mOrigMax);
mTempSettings.maxFreq = mOrigMax;
mTempSettings.minFreq = mOrigMin;
mOrigDisplay = mWt->GetDisplay();
mOrigPlacements = WaveTrackView::Get( *mWt ).SavePlacements();
}
else {
mTempSettings = mOrigSettings = SpectrogramSettings::defaults();
@ -423,7 +424,7 @@ void SpectrumPrefs::Rollback()
if (mWt && isOpenPage) {
auto channels = TrackList::Channels(mWt);
for (auto channel : channels)
channel->SetDisplay(mOrigDisplay);
WaveTrackView::Get( *channel ).RestorePlacements( mOrigPlacements );
}
if (isOpenPage) {
@ -470,7 +471,8 @@ void SpectrumPrefs::Preview()
if (mWt && isOpenPage) {
for (auto channel : TrackList::Channels(mWt))
channel->SetDisplay(WaveTrackViewConstants::Spectrum);
WaveTrackView::Get( *channel )
.SetDisplay( WaveTrackViewConstants::Spectrum );
}
if (isOpenPage) {

View File

@ -23,6 +23,7 @@
#include "../Experimental.h"
#include <vector>
#include <wx/defs.h>
#include "../tracks/playabletrack/wavetrack/ui/WaveTrackViewConstants.h"
@ -38,6 +39,7 @@ struct FFTParam;
class ShuttleGui;
class SpectrogramSettings;
class WaveTrack;
struct WaveTrackSubViewPlacement;
#define SPECTRUM_PREFS_PLUGIN_SYMBOL ComponentInterfaceSymbol{ XO("Spectrum") }
@ -98,7 +100,7 @@ class SpectrumPrefs final : public PrefsPanel
SpectrogramSettings mTempSettings, mOrigSettings;
WaveTrackViewConstants::Display mOrigDisplay;
std::vector<WaveTrackSubViewPlacement> mOrigPlacements;
float mOrigMin, mOrigMax;
bool mPopulating;

View File

@ -27,6 +27,8 @@ Paul Licameli
#include "../TrackPanel.h"
#include "../ShuttleGui.h"
#include "../WaveTrack.h"
#include "../tracks/playabletrack/wavetrack/ui/WaveTrackView.h"
#include "../tracks/playabletrack/wavetrack/ui/WaveTrackViewConstants.h"
WaveformPrefs::WaveformPrefs(wxWindow * parent, wxWindowID winid, WaveTrack *wt)
/* i18n-hint: A waveform is a visual representation of vibration */
@ -184,7 +186,8 @@ bool WaveformPrefs::Commit()
if (mWt && isOpenPage) {
for (auto channel : TrackList::Channels(mWt))
channel->SetDisplay(WaveTrackViewConstants::Waveform);
WaveTrackView::Get( *channel )
.SetDisplay( WaveTrackViewConstants::Waveform );
}
if (isOpenPage) {

View File

@ -120,10 +120,6 @@ UIHandlePtr SampleHandle::HitTest
/// editable sample
const auto wavetrack = pTrack.get();
const int displayType = wavetrack->GetDisplay();
if (WaveTrackViewConstants::Waveform != displayType)
return {}; // Not a wave, so return.
const double tt =
adjustTime(wavetrack, viewInfo.PositionToTime(state.m_x, rect.x));
if (!SampleResolutionTest(viewInfo, wavetrack, tt, rect.width))
@ -178,17 +174,6 @@ namespace {
(const wxMouseEvent &event,
const wxRect &rect, const ViewInfo &viewInfo, WaveTrack *wt, int width)
{
//Get out of here if we shouldn't be drawing right now:
//If we aren't displaying the waveform, Display a message dialog
const int display = wt->GetDisplay();
if (WaveTrackViewConstants::Waveform != display)
{
AudacityMessageBox(_(
"To use Draw, choose 'Waveform' or 'Waveform (dB)' in the Track Dropdown Menu."),
_("Draw Tool"));
return false;
}
//If we aren't zoomed in far enough, show a message dialog.
const double time = adjustTime(wt, viewInfo.PositionToTime(event.m_x, rect.x));
if (!SampleResolutionTest(viewInfo, wt, time, width))

View File

@ -15,6 +15,7 @@ Paul Licameli split from WaveTrackView.cpp
#include "SpectrumVRulerControls.h"
#include "WaveTrackView.h"
#include "WaveTrackViewConstants.h"
#include "../../../../AColor.h"
#include "../../../../Prefs.h"
@ -31,6 +32,11 @@ Paul Licameli split from WaveTrackView.cpp
SpectrumView::~SpectrumView() = default;
bool SpectrumView::IsSpectral() const
{
return true;
}
std::vector<UIHandlePtr> SpectrumView::DetailedHitTest(
const TrackPanelMouseState &state,
const AudacityProject *pProject, int currentTool, bool bMultiTool )

View File

@ -28,6 +28,7 @@ public:
std::shared_ptr<TrackVRulerControls> DoGetVRulerControls() override;
bool IsSpectral() const override;
private:
// TrackPanelDrawable implementation

View File

@ -16,7 +16,7 @@ Paul Licameli split from TrackPanel.cpp
#include "../../ui/PlayableTrackButtonHandles.h"
#include "WaveTrackSliderHandles.h"
#include "../../../ui/TrackView.h"
#include "WaveTrackView.h"
#include "../../../../AudioIOBase.h"
#include "../../../../CellularPanel.h"
#include "../../../../Menus.h"
@ -599,19 +599,23 @@ void WaveTrackMenuTable::InitMenu(Menu *pMenu, void *pUserData)
std::vector<int> checkedIds;
const int display = pTrack->GetDisplay();
checkedIds.push_back(
display == WaveTrackViewConstants::Waveform
? (pTrack->GetWaveformSettings().isLinear()
? OnWaveformID : OnWaveformDBID)
: OnSpectrumID);
const auto displays = WaveTrackView::Get( *pTrack ).GetDisplays();
for ( auto display : displays ) {
checkedIds.push_back(
display == WaveTrackViewConstants::Waveform
? (pTrack->GetWaveformSettings().isLinear()
? OnWaveformID : OnWaveformDBID)
: OnSpectrumID);
}
// Bug 1253. Shouldn't open preferences if audio is busy.
// We can't change them on the fly yet anyway.
auto gAudioIO = AudioIOBase::Get();
const bool bAudioBusy = gAudioIO->IsBusy();
pMenu->Enable(OnSpectrogramSettingsID,
(display == WaveTrackViewConstants::Spectrum) && !bAudioBusy);
bool hasSpectrum =
make_iterator_range( displays.begin(), displays.end() )
.contains( WaveTrackViewConstants::Spectrum );
pMenu->Enable(OnSpectrogramSettingsID, hasSpectrum && !bAudioBusy);
AudacityProject *const project = ::GetActiveProject();
auto &tracks = TrackList::Get( *project );
@ -683,9 +687,9 @@ void WaveTrackMenuTable::InitMenu(Menu *pMenu, void *pUserData)
BEGIN_POPUP_MENU(WaveTrackMenuTable)
POPUP_MENU_SEPARATOR()
POPUP_MENU_RADIO_ITEM(OnWaveformID, _("Wa&veform"), OnSetDisplay)
POPUP_MENU_RADIO_ITEM(OnWaveformDBID, _("&Waveform (dB)"), OnSetDisplay)
POPUP_MENU_RADIO_ITEM(OnSpectrumID, _("&Spectrogram"), OnSetDisplay)
POPUP_MENU_CHECK_ITEM(OnWaveformID, _("Wa&veform"), OnSetDisplay)
POPUP_MENU_CHECK_ITEM(OnWaveformDBID, _("&Waveform (dB)"), OnSetDisplay)
POPUP_MENU_CHECK_ITEM(OnSpectrumID, _("&Spectrogram"), OnSetDisplay)
POPUP_MENU_ITEM(OnSpectrogramSettingsID, _("S&pectrogram Settings..."), OnSpectrogramSettings)
POPUP_MENU_SEPARATOR()
@ -702,9 +706,15 @@ BEGIN_POPUP_MENU(WaveTrackMenuTable)
#endif
WaveTrack *const pTrack = static_cast<WaveTrack*>(mpTrack);
if( pTrack && pTrack->GetDisplay() != WaveTrackViewConstants::Spectrum ){
POPUP_MENU_SEPARATOR()
POPUP_MENU_SUB_MENU(OnWaveColorID, _("&Wave Color"), WaveColorMenuTable)
if ( pTrack ) {
const auto displays = WaveTrackView::Get( *pTrack ).GetDisplays();
bool hasWaveform =
make_iterator_range( displays.begin(), displays.end() )
.contains( WaveTrackViewConstants::Waveform );
if( hasWaveform ){
POPUP_MENU_SEPARATOR()
POPUP_MENU_SUB_MENU(OnWaveColorID, _("&Wave Color"), WaveColorMenuTable)
}
}
POPUP_MENU_SEPARATOR()
@ -723,7 +733,7 @@ void WaveTrackMenuTable::OnSetDisplay(wxCommandEvent & event)
const auto pTrack = static_cast<WaveTrack*>(mpData->pTrack);
bool linear = false;
WaveTrack::WaveTrackDisplay id;
WaveTrackView::WaveTrackDisplay id;
switch (idInt) {
default:
case OnWaveformID:
@ -734,14 +744,16 @@ void WaveTrackMenuTable::OnSetDisplay(wxCommandEvent & event)
id = Spectrum; break;
}
const bool wrongType = pTrack->GetDisplay() != id;
const auto displays = WaveTrackView::Get( *pTrack ).GetDisplays();
const bool wrongType = !(displays.size() == 1 && displays[0] == id);
const bool wrongScale =
(id == Waveform &&
pTrack->GetWaveformSettings().isLinear() != linear);
if (wrongType || wrongScale) {
for (auto channel : TrackList::Channels(pTrack)) {
channel->SetLastScaleType();
channel->SetDisplay(WaveTrack::WaveTrackDisplay(id));
WaveTrackView::Get( *channel )
.SetDisplay(WaveTrackView::WaveTrackDisplay(id));
if (wrongScale)
channel->GetIndependentWaveformSettings().scaleType = linear
? WaveformSettings::stLinear
@ -876,8 +888,8 @@ void WaveTrackMenuTable::OnMergeStereo(wxCommandEvent &)
// Set NEW track heights and minimized state
auto
&view = TrackView::Get( *pTrack ),
&partnerView = TrackView::Get( *partner );
&view = WaveTrackView::Get( *pTrack ),
&partnerView = WaveTrackView::Get( *partner );
view.SetMinimized(false);
partnerView.SetMinimized(false);
int AverageHeight = (view.GetHeight() + partnerView.GetHeight()) / 2;
@ -886,6 +898,8 @@ void WaveTrackMenuTable::OnMergeStereo(wxCommandEvent &)
view.SetMinimized(bBothMinimizedp);
partnerView.SetMinimized(bBothMinimizedp);
partnerView.RestorePlacements( view.SavePlacements() );
//On Demand - join the queues together.
if (ODManager::IsInstanceCreated())
if (!ODManager::Instance()

View File

@ -22,19 +22,57 @@ Paul Licameli split from TrackPanel.cpp
#include "../../../../TrackPanelMouseEvent.h"
#include "../../../../ViewInfo.h"
#include "../../../../prefs/SpectrogramSettings.h"
#include "../../../../prefs/WaveformSettings.h"
#include "../../../../prefs/TracksPrefs.h"
#include "../../../ui/TimeShiftHandle.h"
WaveTrackView &WaveTrackView::Get( WaveTrack &track )
{
return static_cast< WaveTrackView& >( TrackView::Get( track ) );
}
const WaveTrackView &WaveTrackView::Get( const WaveTrack &track )
{
return Get( const_cast<WaveTrack&>( track ) );
}
WaveTrackView::WaveTrackView( const std::shared_ptr<Track> &pTrack )
: CommonTrackView{ pTrack }
{
WaveTrackSubViews::BuildAll();
auto display = TracksPrefs::ViewModeChoice();
// Force creation always:
WaveformSettings &settings = static_cast< WaveTrack* >( pTrack.get() )
->GetIndependentWaveformSettings();
if (display == WaveTrackViewConstants::obsoleteWaveformDBDisplay) {
display = WaveTrackViewConstants::Waveform;
settings.scaleType = WaveformSettings::stLogarithmic;
}
mPlacements.resize( WaveTrackSubViews::size() );
SetDisplay( display );
}
WaveTrackView::~WaveTrackView()
{
}
void WaveTrackView::CopyTo( Track &track ) const
{
TrackView::CopyTo( track );
auto &other = TrackView::Get( track );
if ( const auto pOther = dynamic_cast< WaveTrackView* >( &other ) ) {
// only one field is important to preserve in undo/redo history
pOther->RestorePlacements( SavePlacements() );
}
}
std::vector<UIHandlePtr> WaveTrackView::DetailedHitTest
(const TrackPanelMouseState &st,
const AudacityProject *pProject, int currentTool, bool bMultiTool)
@ -75,23 +113,72 @@ WaveTrackView::DoDetailedHitTest
return { false, results };
}
auto WaveTrackView::GetSubViews( const wxRect &rect ) -> Refinement
auto WaveTrackView::GetDisplays() const -> std::vector<WaveTrackDisplay>
{
auto wt = static_cast<WaveTrack*>( FindTrack().get() );
auto display = wt->GetDisplay();
std::shared_ptr<TrackView> pSubView;
// Collect the display types of visible views and sort them by position
using Pair = std::pair< int, WaveTrackDisplay >;
std::vector< Pair > pairs;
size_t ii = 0;
WaveTrackSubViews::ForEach( [&]( const WaveTrackSubView &subView ){
auto &placement = mPlacements[ii];
if ( placement.fraction > 0 )
pairs.emplace_back( placement.index, subView.SubViewType() );
++ii;
} );
std::sort( pairs.begin(), pairs.end() );
std::vector<WaveTrackDisplay> results;
for ( const auto &pair : pairs )
results.push_back( pair.second );
return results;
}
void WaveTrackView::SetDisplay(WaveTrackDisplay display)
{
size_t ii = 0;
WaveTrackSubViews::ForEach( [&,display]( WaveTrackSubView &subView ){
if ( subView.SubViewType() == display )
pSubView = subView.shared_from_this();
mPlacements[ii] = { 0, 1.0 };
else
mPlacements[ii] = { -1, 0.0 };
++ii;
} );
if ( !pSubView )
return {};
return {
{
rect.GetTop(),
pSubView
}
};
}
auto WaveTrackView::GetSubViews( const wxRect &rect ) -> Refinement
{
// Collect the visible views
using Pair = std::pair< float, std::shared_ptr< TrackView > >;
std::vector< Pair > pairs( mPlacements.size() );
size_t ii = 0;
float total = 0;
WaveTrackSubViews::ForEach( [&]( WaveTrackSubView &subView ){
const auto &placement = mPlacements[ii];
auto index = placement.index;
auto fraction = placement.fraction;
if ( index >= 0 && fraction > 0.0 )
total += fraction,
pairs[ index ] = { fraction, subView.shared_from_this() };
++ii;
} );
// Remove views we don't need
auto begin = pairs.begin(), end = pairs.end(),
newEnd = std::remove_if( begin, end,
[]( const Pair &item ){ return !item.second; } );
pairs.erase( newEnd, end );
// Assign coordinates
Refinement results;
results.reserve( pairs.size() );
float partial = 0;
const auto top = rect.GetTop();
const auto height = rect.GetHeight();
for ( const auto &pair : pairs ) {
results.emplace_back( top + (partial / total) * height, pair.second );
partial += pair.first;
}
return results;
}
void WaveTrackView::DoSetMinimized( bool minimized )

View File

@ -24,6 +24,12 @@ public:
virtual WaveTrackViewConstants::Display SubViewType() const = 0;
};
struct WaveTrackSubViewPlacement {
int index;
float fraction;
};
using WaveTrackSubViewPlacements = std::vector< WaveTrackSubViewPlacement >;
class WaveTrackView;
using WaveTrackSubViews = ClientData::Site<
WaveTrackView, WaveTrackSubView, ClientData::SkipCopying, std::shared_ptr
@ -37,10 +43,16 @@ class WaveTrackView final
WaveTrackView &operator=( const WaveTrackView& ) = delete;
public:
static WaveTrackView &Get( WaveTrack &track );
static const WaveTrackView &Get( const WaveTrack &track );
explicit
WaveTrackView( const std::shared_ptr<Track> &pTrack );
~WaveTrackView() override;
// Preserve some view state too for undo/redo purposes
void CopyTo( Track &track ) const override;
std::shared_ptr<TrackVRulerControls> DoGetVRulerControls() override;
// CommonTrackView implementation
@ -55,6 +67,16 @@ public:
const std::shared_ptr<WaveTrack> &wt,
CommonTrackView &view);
using WaveTrackDisplay = WaveTrackViewConstants::Display;
std::vector<WaveTrackDisplay> GetDisplays() const;
void SetDisplay(WaveTrackDisplay display);
const WaveTrackSubViewPlacements &SavePlacements() const
{ return mPlacements; }
void RestorePlacements( const WaveTrackSubViewPlacements &placements )
{ mPlacements = placements; }
private:
// TrackPanelDrawable implementation
void Draw(
@ -71,6 +93,8 @@ private:
protected:
void DoSetMinimized( bool minimized ) override;
WaveTrackSubViewPlacements mPlacements;
};
// Helper for drawing routines

View File

@ -15,6 +15,7 @@ Paul Licameli split from WaveTrackView.cpp
#include "WaveformVRulerControls.h"
#include "WaveTrackView.h"
#include "WaveTrackViewConstants.h"
#include "CutlineHandle.h"
#include "SampleHandle.h"

View File

@ -73,7 +73,7 @@ std::vector<UIHandlePtr> CommonTrackView::HitTest
// Finally, default of all is adjustment of the selection box.
if ( isMultiTool || currentTool == selectTool ) {
result = SelectHandle::HitTest(
mSelectHandle, st, pProject, FindTrack() );
mSelectHandle, st, pProject, shared_from_this() );
if (result)
results.push_back(result);
}

View File

@ -98,12 +98,6 @@ UIHandlePtr EnvelopeHandle::WaveTrackHitTest
if (!envelope)
return {};
const int displayType = wt->GetDisplay();
// Not an envelope hit, unless we're using a type of wavetrack display
// suitable for envelopes operations, ie one of the Wave displays.
if (displayType != WaveTrackViewConstants::Waveform)
return {}; // No envelope, not a hit, so return.
// Get envelope point, range 0.0 to 1.0
const bool dB = !wt->GetWaveformSettings().isLinear();
@ -188,9 +182,6 @@ UIHandle::Result EnvelopeHandle::Click
if (pTrack)
result = pTrack->TypeSwitch< decltype(RefreshNone) >(
[&](WaveTrack *wt) {
if (wt->GetDisplay() != WaveTrackViewConstants::Waveform)
return Cancelled;
if (!mEnvelope)
return Cancelled;

View File

@ -128,13 +128,16 @@ namespace
}
// This returns true if we're a spectral editing track.
inline bool isSpectralSelectionTrack(const Track *pTrack) {
return pTrack && pTrack->TypeSwitch< bool >( [&](const WaveTrack *wt) {
const SpectrogramSettings &settings = wt->GetSpectrogramSettings();
const int display = wt->GetDisplay();
return (display == WaveTrackViewConstants::Spectrum) &&
settings.SpectralSelectionEnabled();
});
inline bool isSpectralSelectionView(const TrackView *pTrackView) {
return
pTrackView &&
pTrackView->IsSpectral() &&
pTrackView->FindTrack() &&
pTrackView->FindTrack()->TypeSwitch< bool >(
[&](const WaveTrack *wt) {
const SpectrogramSettings &settings = wt->GetSpectrogramSettings();
return settings.SpectralSelectionEnabled();
});
}
enum SelectionBoundary {
@ -187,7 +190,7 @@ namespace
SelectionBoundary ChooseBoundary
(const ViewInfo &viewInfo,
wxCoord xx, wxCoord yy, const Track *pTrack, const wxRect &rect,
wxCoord xx, wxCoord yy, const TrackView *pTrackView, const wxRect &rect,
bool mayDragWidth, bool onlyWithinSnapDistance,
double *pPinValue = NULL)
{
@ -220,9 +223,11 @@ namespace
// within the time boundaries
if (!viewInfo.selectedRegion.isPoint() &&
t0 <= selend && selend < t1 &&
isSpectralSelectionTrack(pTrack)) {
isSpectralSelectionView(pTrackView)) {
// Spectral selection track is always wave
const WaveTrack *const wt = static_cast<const WaveTrack*>(pTrack);
auto pTrack = pTrackView->FindTrack();
const WaveTrack *const wt =
static_cast<const WaveTrack*>(pTrack.get());
const wxInt64 bottomSel = (f0 >= 0)
? FrequencyToPosition(wt, f0, rect.y, rect.height)
: rect.y + rect.height;
@ -374,7 +379,7 @@ namespace
UIHandlePtr SelectHandle::HitTest
(std::weak_ptr<SelectHandle> &holder,
const TrackPanelMouseState &st, const AudacityProject *pProject,
const std::shared_ptr<Track> &pTrack)
const std::shared_ptr<TrackView> &pTrackView)
{
// This handle is a little special because there may be some state to
// preserve during movement before the click.
@ -393,13 +398,14 @@ UIHandlePtr SelectHandle::HitTest
const auto &viewInfo = ViewInfo::Get( *pProject );
auto result = std::make_shared<SelectHandle>(
pTrack, oldUseSnap, TrackList::Get( *pProject ), st, viewInfo );
pTrackView, oldUseSnap, TrackList::Get( *pProject ), st, viewInfo );
result = AssignUIHandlePtr(holder, result);
//Make sure we are within the selected track
// Adjusting the selection edges can be turned off in
// the preferences...
auto pTrack = pTrackView->FindTrack();
if (!pTrack->GetSelected() || !viewInfo.bAdjustSelectionEdges)
{
return result;
@ -438,16 +444,17 @@ UIHandle::Result SelectHandle::NeedChangeHighlight
}
SelectHandle::SelectHandle
( const std::shared_ptr<Track> &pTrack, bool useSnap,
( const std::shared_ptr<TrackView> &pTrackView, bool useSnap,
const TrackList &trackList,
const TrackPanelMouseState &st, const ViewInfo &viewInfo )
: mpTrack{ pTrack }
: mpView{ pTrackView }
, mSnapManager{ std::make_shared<SnapManager>(&trackList, &viewInfo) }
{
const wxMouseState &state = st.state;
mRect = st.rect;
auto time = std::max(0.0, viewInfo.PositionToTime(state.m_x, mRect.x));
auto pTrack = pTrackView->FindTrack();
mSnapStart = mSnapManager->Snap(pTrack.get(), time, false);
if (mSnapStart.snappedPoint)
mSnapStart.outCoord += mRect.x;
@ -531,8 +538,12 @@ UIHandle::Result SelectHandle::Click
using namespace RefreshCode;
const auto pView = mpView.lock();
if ( !pView )
return Cancelled;
wxMouseEvent &event = evt.event;
const auto sTrack = TrackList::Get( *pProject ).Lock(mpTrack);
const auto sTrack = TrackList::Get( *pProject ).Lock( FindTrack() );
const auto pTrack = sTrack.get();
auto &trackPanel = TrackPanel::Get( *pProject );
auto &viewInfo = ViewInfo::Get( *pProject );
@ -620,7 +631,8 @@ UIHandle::Result SelectHandle::Click
double value;
// Shift-click, choose closest boundary
SelectionBoundary boundary =
ChooseBoundary(viewInfo, xx, event.m_y, pTrack, mRect, false, false, &value);
ChooseBoundary(viewInfo, xx, event.m_y,
pView.get(), mRect, false, false, &value);
mSelectionBoundary = boundary;
switch (boundary) {
case SBLeft:
@ -686,7 +698,7 @@ UIHandle::Result SelectHandle::Click
if (viewInfo.bAdjustSelectionEdges) {
#ifdef EXPERIMENTAL_SPECTRAL_EDITING
if (mFreqSelMode == FREQ_SEL_SNAPPING_CENTER &&
isSpectralSelectionTrack(pTrack)) {
isSpectralSelectionView(pView.get())) {
// This code is no longer reachable, but it had a place in the
// spectral selection prototype. It used to be that you could be
// in a center-frequency-snapping mode that was not a mouse drag
@ -714,7 +726,8 @@ UIHandle::Result SelectHandle::Click
// Not shift-down, choose boundary only within snapping
double value;
SelectionBoundary boundary =
ChooseBoundary(viewInfo, xx, event.m_y, pTrack, mRect, true, true, &value);
ChooseBoundary(viewInfo, xx, event.m_y,
pView.get(), mRect, true, true, &value);
mSelectionBoundary = boundary;
switch (boundary) {
case SBNone:
@ -766,7 +779,8 @@ UIHandle::Result SelectHandle::Click
// If we didn't move a selection boundary, start a NEW selection
selectionState.SelectNone( trackList );
#ifdef EXPERIMENTAL_SPECTRAL_EDITING
StartFreqSelection (viewInfo, event.m_y, mRect.y, mRect.height, pTrack);
StartFreqSelection (viewInfo, event.m_y, mRect.y, mRect.height,
pView.get());
#endif
StartSelection(pProject);
selectionState.SelectTrack( *pTrack, true, true );
@ -791,6 +805,10 @@ UIHandle::Result SelectHandle::Drag
{
using namespace RefreshCode;
const auto pView = mpView.lock();
if ( !pView )
return Cancelled;
auto &viewInfo = ViewInfo::Get( *pProject );
const wxMouseEvent &event = evt.event;
@ -814,7 +832,7 @@ UIHandle::Result SelectHandle::Drag
}
// Also fuhggeddaboudit if not in a track.
auto pTrack = TrackList::Get( *pProject ).Lock(mpTrack);
auto pTrack = TrackList::Get( *pProject ).Lock( FindTrack() );
if (!pTrack)
return RefreshNone;
@ -850,7 +868,7 @@ UIHandle::Result SelectHandle::Drag
if (mFreqSelMode == FREQ_SEL_SNAPPING_CENTER &&
!viewInfo.selectedRegion.isPoint())
MoveSnappingFreqSelection
(pProject, viewInfo, y, mRect.y, mRect.height, pTrack.get());
(pProject, viewInfo, y, mRect.y, mRect.height, pView.get());
else
#endif
if ( TrackList::Get( *pProject ).Lock(mFreqSelTrack) == pTrack )
@ -883,7 +901,11 @@ HitTestPreview SelectHandle::Preview
// Moved out of snapping; revert to un-escaped state
mUseSnap = true;
auto pTrack = mpTrack.lock();
const auto pView = mpView.lock();
if ( !pView )
return {};
auto pTrack = FindTrack().lock();
if (!pTrack)
return {};
@ -937,7 +959,8 @@ HitTestPreview SelectHandle::Preview
// choose boundaries only in snapping tolerance,
// and may choose center.
SelectionBoundary boundary =
ChooseBoundary(viewInfo, xx, state.m_y, pTrack.get(), rect, !bModifierDown, !bModifierDown);
ChooseBoundary(viewInfo, xx, state.m_y,
pView.get(), rect, !bModifierDown, !bModifierDown);
SetTipAndCursorForBoundary(boundary, !bShiftDown, tip, pCursor);
}
@ -949,7 +972,7 @@ HitTestPreview SelectHandle::Preview
// and drag width.
#ifdef EXPERIMENTAL_SPECTRAL_EDITING
if ((mFreqSelMode == FREQ_SEL_SNAPPING_CENTER) &&
isSpectralSelectionTrack(pTrack)) {
isSpectralSelectionView(pView)) {
// Not shift-down, but center frequency snapping toggle is on
tip = _("Click and drag to set frequency bandwidth.");
pCursor = &*envelopeCursor;
@ -966,7 +989,8 @@ HitTestPreview SelectHandle::Preview
const bool bCtrlDown = state.ControlDown();
const bool bModifierDown = bShiftDown || bCtrlDown;
SelectionBoundary boundary = ChooseBoundary(
viewInfo, xx, state.m_y, pTrack.get(), rect, !bModifierDown, !bModifierDown);
viewInfo, xx, state.m_y,
pView.get(), rect, !bModifierDown, !bModifierDown);
SetTipAndCursorForBoundary(boundary, !bShiftDown, tip, pCursor);
}
@ -1034,6 +1058,15 @@ wxRect SelectHandle::DrawingArea(
return rect;
}
std::weak_ptr<Track> SelectHandle::FindTrack()
{
auto pView = mpView.lock();
if (!pView)
return {};
else
return pView->FindTrack();
}
void SelectHandle::Connect(AudacityProject *pProject)
{
mTimerHandler = std::make_shared<TimerHandler>( this, pProject );
@ -1113,7 +1146,7 @@ void SelectHandle::TimerHandler::OnTimer(wxCommandEvent &event)
}
}
auto pTrack = mParent->mpTrack.lock(); // TrackList::Lock() ?
auto pTrack = mParent->FindTrack().lock(); // TrackList::Lock() ?
if (mParent->mAutoScrolling && pTrack) {
// AS: To keep the selection working properly as we scroll,
// we fake a mouse event (remember, this method is called
@ -1164,7 +1197,7 @@ void SelectHandle::AdjustSelection
auto pTrack = Track::SharedPointer( track );
if (!pTrack)
pTrack = TrackList::Get( *pProject ).Lock(mpTrack);
pTrack = TrackList::Get( *pProject ).Lock( FindTrack() );
if (pTrack && mSnapManager.get()) {
bool rightEdge = (selend > mSelStart);
@ -1216,15 +1249,15 @@ void SelectHandle::AssignSelection
void SelectHandle::StartFreqSelection(ViewInfo &viewInfo,
int mouseYCoordinate, int trackTopEdge,
int trackHeight, Track *pTrack)
int trackHeight, TrackView *pTrackView)
{
mFreqSelTrack.reset();
mFreqSelMode = FREQ_SEL_INVALID;
mFreqSelPin = SelectedRegion::UndefinedFrequency;
if (isSpectralSelectionTrack(pTrack)) {
if (isSpectralSelectionView(pTrackView)) {
// Spectral selection track is always wave
auto shTrack = pTrack->SharedPointer<const WaveTrack>();
auto shTrack = pTrackView->FindTrack()->SharedPointer<const WaveTrack>();
mFreqSelTrack = shTrack;
mFreqSelMode = FREQ_SEL_FREE;
mFreqSelPin =
@ -1386,11 +1419,12 @@ void SelectHandle::StartSnappingFreqSelection
void SelectHandle::MoveSnappingFreqSelection
(AudacityProject *pProject, ViewInfo &viewInfo, int mouseYCoordinate,
int trackTopEdge,
int trackHeight, Track *pTrack)
int trackHeight, TrackView *pTrackView)
{
auto pTrack = pTrackView->FindTrack().get();
if (pTrack &&
pTrack->GetSelected() &&
isSpectralSelectionTrack(pTrack)) {
isSpectralSelectionView(pTrackView)) {
// Spectral selection track is always wave
WaveTrack *const wt = static_cast<WaveTrack*>(pTrack);
// PRL:

View File

@ -21,6 +21,7 @@ class SelectionStateChanger;
class SnapManager;
class SpectrumAnalyst;
class Track;
class TrackView;
class TrackList;
class ViewInfo;
class WaveTrack;
@ -32,7 +33,7 @@ class SelectHandle : public UIHandle
public:
explicit SelectHandle
(const std::shared_ptr<Track> &pTrack, bool useSnap,
(const std::shared_ptr<TrackView> &pTrackView, bool useSnap,
const TrackList &trackList,
const TrackPanelMouseState &st, const ViewInfo &viewInfo);
@ -41,7 +42,7 @@ public:
static UIHandlePtr HitTest
(std::weak_ptr<SelectHandle> &holder,
const TrackPanelMouseState &state, const AudacityProject *pProject,
const std::shared_ptr<Track> &pTrack);
const std::shared_ptr<TrackView> &pTrackView);
SelectHandle &operator=(const SelectHandle&) = default;
@ -78,6 +79,8 @@ public:
const SelectHandle &newState);
private:
std::weak_ptr<Track> FindTrack();
void Connect(AudacityProject *pProject);
void StartSelection(AudacityProject *pProject);
@ -89,7 +92,7 @@ private:
void StartFreqSelection
(ViewInfo &viewInfo, int mouseYCoordinate, int trackTopEdge,
int trackHeight, Track *pTrack);
int trackHeight, TrackView *pTrackView);
void AdjustFreqSelection
(const WaveTrack *wt,
ViewInfo &viewInfo, int mouseYCoordinate, int trackTopEdge,
@ -104,7 +107,7 @@ private:
void MoveSnappingFreqSelection
(AudacityProject *pProject, ViewInfo &viewInfo, int mouseYCoordinate,
int trackTopEdge,
int trackHeight, Track *pTrack);
int trackHeight, TrackView *pTrackView);
public:
// This is needed to implement a command assignable to keystrokes
static void SnapCenterOnce
@ -124,7 +127,7 @@ private:
// (const ViewInfo &viewInfo, double hintFrequency, bool logF);
std::weak_ptr<Track> mpTrack;
std::weak_ptr<TrackView> mpView;
wxRect mRect{};
SelectedRegion mInitialSelection{};

View File

@ -114,6 +114,11 @@ auto TrackView::GetSubViews( const wxRect &rect ) -> Refinement
return { { rect.GetTop(), shared_from_this() } };
}
bool TrackView::IsSpectral() const
{
return false;
}
void TrackView::DoSetMinimized(bool isMinimized)
{
mMinimized = isMinimized;

View File

@ -73,6 +73,9 @@ public:
> >;
virtual Refinement GetSubViews( const wxRect &rect );
// default is false
virtual bool IsSpectral() const;
virtual void DoSetMinimized( bool isMinimized );
protected: