mirror of
https://github.com/cookiengineer/audacity
synced 2025-07-24 16:38:07 +02:00
Dynamic registry of sub-views replaces exhaustive switches on type...
... Such switches were in the TCP context menu for wave tracks, SetTrackVisualsCommand, Nyquist (choosing the string for 'view property of *tracks*), and the Tracks preferences panel. This will allow easier, non-intrusive addition of other kinds of track visualizations.
This commit is contained in:
commit
30999ab134
@ -87,9 +87,10 @@ public:
|
||||
|
||||
const wxString &Internal() const { return mInternal; }
|
||||
const TranslatableString &Msgid() const { return mMsgid; }
|
||||
const TranslatableString Stripped() const { return mMsgid.Stripped(); }
|
||||
const wxString Translation() const { return mMsgid.Translation(); }
|
||||
const wxString StrippedTranslation() const
|
||||
{ return mMsgid.Stripped().Translation(); }
|
||||
{ return Stripped().Translation(); }
|
||||
|
||||
bool empty() const { return mInternal.empty(); }
|
||||
|
||||
|
@ -467,6 +467,8 @@ public:
|
||||
TranslatableString Stripped( unsigned options = MenuCodes ) const
|
||||
{ return TranslatableString{ *this }.Strip( options ); }
|
||||
|
||||
wxString StrippedTranslation() const { return Stripped().Translation(); }
|
||||
|
||||
private:
|
||||
static const Formatter NullContextFormatter;
|
||||
|
||||
|
@ -214,7 +214,7 @@ public:
|
||||
EnumValueSymbols symbols,
|
||||
long defaultSymbol,
|
||||
|
||||
std::initializer_list< Enum > values, // must have same size as symbols
|
||||
std::vector< Enum > values, // must have same size as symbols
|
||||
const wxString &oldKey = {}
|
||||
)
|
||||
: EnumSettingBase{
|
||||
|
@ -402,7 +402,7 @@ wxChoice * ShuttleGuiBase::AddChoice( const TranslatableString &Prompt,
|
||||
wxDefaultPosition,
|
||||
wxDefaultSize,
|
||||
transform_container<wxArrayString>(
|
||||
choices, std::mem_fn( &TranslatableString::Translation ) ),
|
||||
choices, std::mem_fn( &TranslatableString::StrippedTranslation ) ),
|
||||
GetStyle( 0 ) );
|
||||
|
||||
pChoice->SetMinSize( { 180, -1 } );// Use -1 for 'default size' - Platform specific.
|
||||
@ -2421,7 +2421,7 @@ void ShuttleGui::SetMinSize( wxWindow *window, const TranslatableStrings & items
|
||||
{
|
||||
SetMinSize( window,
|
||||
transform_container<wxArrayStringEx>(
|
||||
items, std::mem_fn( &TranslatableString::Translation ) ) );
|
||||
items, std::mem_fn( &TranslatableString::StrippedTranslation ) ) );
|
||||
}
|
||||
|
||||
void ShuttleGui::SetMinSize( wxWindow *window, const wxArrayStringEx & items )
|
||||
|
@ -248,20 +248,6 @@ static const EnumValueSymbol kColourStrings[nColours] =
|
||||
};
|
||||
|
||||
|
||||
enum kDisplayTypes
|
||||
{
|
||||
kWaveform,
|
||||
kSpectrogram,
|
||||
nDisplayTypes
|
||||
};
|
||||
|
||||
static const EnumValueSymbol kDisplayTypeStrings[nDisplayTypes] =
|
||||
{
|
||||
// These are acceptable dual purpose internal/visible names
|
||||
{ XO("Waveform") },
|
||||
{ XO("Spectrogram") },
|
||||
};
|
||||
|
||||
enum kScaleTypes
|
||||
{
|
||||
kLinear,
|
||||
@ -292,10 +278,22 @@ static const EnumValueSymbol kZoomTypeStrings[nZoomTypes] =
|
||||
{ XO("HalfWave") },
|
||||
};
|
||||
|
||||
static EnumValueSymbols DiscoverSubViewTypes()
|
||||
{
|
||||
const auto &types = WaveTrackSubView::AllTypes();
|
||||
return transform_container< EnumValueSymbols >(
|
||||
types, std::mem_fn( &WaveTrackSubView::Type::name ) );
|
||||
}
|
||||
|
||||
bool SetTrackVisualsCommand::DefineParams( ShuttleParams & S ){
|
||||
SetTrackBase::DefineParams( S );
|
||||
S.OptionalN( bHasHeight ).Define( mHeight, wxT("Height"), 120, 44, 2000 );
|
||||
S.OptionalN( bHasDisplayType ).DefineEnum( mDisplayType, wxT("Display"), kWaveform, kDisplayTypeStrings, nDisplayTypes );
|
||||
|
||||
{
|
||||
auto symbols = DiscoverSubViewTypes();
|
||||
S.OptionalN( bHasDisplayType ).DefineEnum( mDisplayType, wxT("Display"), 0, symbols.data(), symbols.size() );
|
||||
}
|
||||
|
||||
S.OptionalN( bHasScaleType ).DefineEnum( mScaleType, wxT("Scale"), kLinear, kScaleTypeStrings, nScaleTypes );
|
||||
S.OptionalN( bHasColour ).DefineEnum( mColour, wxT("Color"), kColour0, kColourStrings, nColours );
|
||||
S.OptionalN( bHasVZoom ).DefineEnum( mVZoom, wxT("VZoom"), kReset, kZoomTypeStrings, nZoomTypes );
|
||||
@ -318,8 +316,15 @@ void SetTrackVisualsCommand::PopulateOrExchange(ShuttleGui & S)
|
||||
S.Optional( bHasHeight ).TieNumericTextBox( XO("Height:"), mHeight );
|
||||
S.Optional( bHasColour ).TieChoice( XO("Color:"), mColour,
|
||||
Msgids( kColourStrings, nColours ) );
|
||||
S.Optional( bHasDisplayType ).TieChoice( XO("Display:"), mDisplayType,
|
||||
Msgids( kDisplayTypeStrings, nDisplayTypes ) );
|
||||
|
||||
{
|
||||
auto symbols = DiscoverSubViewTypes();
|
||||
auto typeNames = transform_container<TranslatableStrings>(
|
||||
symbols, std::mem_fn( &EnumValueSymbol::Stripped ) );
|
||||
S.Optional( bHasDisplayType ).TieChoice( XO("Display:"), mDisplayType,
|
||||
typeNames );
|
||||
}
|
||||
|
||||
S.Optional( bHasScaleType ).TieChoice( XO("Scale:"), mScaleType,
|
||||
Msgids( kScaleTypeStrings, nScaleTypes ) );
|
||||
S.Optional( bHasVZoom ).TieChoice( XO("VZoom:"), mVZoom,
|
||||
@ -355,10 +360,7 @@ bool SetTrackVisualsCommand::ApplyInner(const CommandContext & context, Track *
|
||||
|
||||
if( wt && bHasDisplayType )
|
||||
WaveTrackView::Get( *wt ).SetDisplay(
|
||||
(mDisplayType == kWaveform) ?
|
||||
WaveTrackViewConstants::Waveform
|
||||
: WaveTrackViewConstants::Spectrum
|
||||
);
|
||||
WaveTrackSubView::AllTypes()[ mDisplayType ].id );
|
||||
if( wt && bHasScaleType )
|
||||
wt->GetIndependentWaveformSettings().scaleType =
|
||||
(mScaleType==kLinear) ?
|
||||
|
@ -551,9 +551,10 @@ bool NyquistEffect::Init()
|
||||
for ( auto t :
|
||||
TrackList::Get( *project ).Selected< const WaveTrack >() ) {
|
||||
const auto displays = WaveTrackView::Get(*t).GetDisplays();
|
||||
bool hasSpectral =
|
||||
make_iterator_range( displays.begin(), displays.end())
|
||||
.contains( WaveTrackViewConstants::Spectrum );
|
||||
bool hasSpectral = (displays.end() != std::find(
|
||||
displays.begin(), displays.end(),
|
||||
WaveTrackSubView::Type{ WaveTrackViewConstants::Spectrum, {} }
|
||||
) );
|
||||
if ( !hasSpectral ||
|
||||
!(t->GetSpectrogramSettings().SpectralSelectionEnabled())) {
|
||||
bAllowSpectralEditing = false;
|
||||
@ -1090,21 +1091,16 @@ bool NyquistEffect::ProcessOne()
|
||||
wxString bitFormat;
|
||||
wxString spectralEditp;
|
||||
|
||||
using namespace WaveTrackViewConstants;
|
||||
mCurTrack[0]->TypeSwitch(
|
||||
[&](const WaveTrack *wt) {
|
||||
type = wxT("wave");
|
||||
spectralEditp = mCurTrack[0]->GetSpectrogramSettings().SpectralSelectionEnabled()? wxT("T") : wxT("NIL");
|
||||
auto displays = WaveTrackView::Get( *wt ).GetDisplays();
|
||||
auto format = [&]( decltype(displays[0]) display ){
|
||||
switch ( display )
|
||||
{
|
||||
case Waveform:
|
||||
return wxT("\"Waveform\"");
|
||||
case Spectrum:
|
||||
return wxT("\"Spectrogram\"");
|
||||
default: return wxT("NIL");
|
||||
}
|
||||
auto format = [&]( decltype(displays[0]) display ) {
|
||||
// Get the English name of the view type, without menu codes,
|
||||
// as a string that Lisp can examine
|
||||
return wxString::Format( wxT("\"%s\""),
|
||||
display.name.Stripped().Debug() );
|
||||
};
|
||||
if (displays.empty())
|
||||
view = wxT("NIL");
|
||||
|
@ -36,8 +36,11 @@ void DoNextPeakFrequency(AudacityProject &project, bool up)
|
||||
const WaveTrack *pTrack {};
|
||||
for ( auto wt : tracks.Selected< const WaveTrack >() ) {
|
||||
const auto displays = WaveTrackView::Get( *wt ).GetDisplays();
|
||||
if ( make_iterator_range( displays.begin(), displays.end() )
|
||||
.contains( WaveTrackViewConstants::Spectrum) ) {
|
||||
bool hasSpectrum = (displays.end() != std::find(
|
||||
displays.begin(), displays.end(),
|
||||
WaveTrackSubView::Type{ WaveTrackViewConstants::Spectrum, {} }
|
||||
) );
|
||||
if ( hasSpectrum ) {
|
||||
pTrack = wt;
|
||||
break;
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include "../Prefs.h"
|
||||
#include "../ShuttleGui.h"
|
||||
#include "../tracks/playabletrack/wavetrack/ui/WaveTrackView.h"
|
||||
|
||||
int TracksPrefs::iPreferencePinned = -1;
|
||||
|
||||
@ -81,8 +82,6 @@ namespace {
|
||||
const auto key2 = wxT("/GUI/DefaultViewModeChoice");
|
||||
const auto key3 = wxT("/GUI/DefaultViewModeChoiceNew");
|
||||
|
||||
const EnumValueSymbol waveformSymbol{ XO("Waveform") };
|
||||
const EnumValueSymbol spectrumSymbol{ XO("Spectrogram") };
|
||||
const wxString obsoleteValue{ wxT("WaveformDB") };
|
||||
};
|
||||
|
||||
@ -100,6 +99,9 @@ public:
|
||||
// to avoid confusing version 2.1.0 if it reads the preference file afterwards.
|
||||
// Prefer the NEW preference key if it is present
|
||||
|
||||
static const EnumValueSymbol waveformSymbol{ XO("Waveform") };
|
||||
static const EnumValueSymbol spectrumSymbol{ XO("Spectrogram") };
|
||||
|
||||
WaveTrackViewConstants::Display viewMode;
|
||||
int oldMode;
|
||||
wxString newValue;
|
||||
@ -143,23 +145,26 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
static TracksViewModeEnumSetting viewModeSetting{
|
||||
key3,
|
||||
{
|
||||
{ waveformSymbol },
|
||||
{ spectrumSymbol }
|
||||
},
|
||||
0, // Waveform
|
||||
|
||||
{
|
||||
WaveTrackViewConstants::Waveform,
|
||||
WaveTrackViewConstants::Spectrum
|
||||
}
|
||||
};
|
||||
static TracksViewModeEnumSetting viewModeSetting()
|
||||
{
|
||||
// Do a delayed computation, so that registration of sub-view types completes
|
||||
// first
|
||||
const auto &types = WaveTrackSubView::AllTypes();
|
||||
auto symbols = transform_container< EnumValueSymbols >(
|
||||
types, std::mem_fn( &WaveTrackSubView::Type::name ) );
|
||||
auto ids = transform_container< std::vector< WaveTrackSubView::Display > >(
|
||||
types, std::mem_fn( &WaveTrackSubView::Type::id ) );
|
||||
return {
|
||||
key3,
|
||||
symbols,
|
||||
0, // Waveform
|
||||
ids
|
||||
};
|
||||
}
|
||||
|
||||
WaveTrackViewConstants::Display TracksPrefs::ViewModeChoice()
|
||||
{
|
||||
return viewModeSetting.ReadEnum();
|
||||
return viewModeSetting().ReadEnum();
|
||||
}
|
||||
|
||||
WaveformSettings::ScaleTypeValues TracksPrefs::WaveformScaleChoice()
|
||||
@ -344,7 +349,7 @@ void TracksPrefs::PopulateOrExchange(ShuttleGui & S)
|
||||
#endif
|
||||
|
||||
S.TieChoice(XO("Default &view mode:"),
|
||||
viewModeSetting );
|
||||
viewModeSetting() );
|
||||
|
||||
S.TieChoice(XO("Default Waveform scale:"),
|
||||
waveformScaleSetting );
|
||||
|
@ -150,7 +150,7 @@ void WaveformSettings::NextHigherDBRange()
|
||||
const TranslatableStrings &WaveformSettings::GetScaleNames()
|
||||
{
|
||||
static const TranslatableStrings result{
|
||||
// Keep in correspondence with enum WaveTrack::WaveTrackDisplay:
|
||||
// Keep in correspondence with ScaleTypeValues:
|
||||
XO("Linear"),
|
||||
XO("dB"),
|
||||
};
|
||||
|
@ -30,6 +30,13 @@ Paul Licameli split from WaveTrackView.cpp
|
||||
#include <wx/dcmemory.h>
|
||||
#include <wx/graphics.h>
|
||||
|
||||
static WaveTrackSubView::Type sType{
|
||||
WaveTrackViewConstants::Spectrum,
|
||||
{ wxT("Spectrogram"), XO("&Spectrogram") }
|
||||
};
|
||||
|
||||
static WaveTrackSubView::RegisteredType reg{ sType };
|
||||
|
||||
SpectrumView::~SpectrumView() = default;
|
||||
|
||||
bool SpectrumView::IsSpectral() const
|
||||
@ -73,9 +80,9 @@ void SpectrumView::DoSetMinimized( bool minimized )
|
||||
TrackView::DoSetMinimized( minimized );
|
||||
}
|
||||
|
||||
WaveTrackViewConstants::Display SpectrumView::SubViewType() const
|
||||
auto SpectrumView::SubViewType() const -> const Type &
|
||||
{
|
||||
return WaveTrackViewConstants::Spectrum;
|
||||
return sType;
|
||||
}
|
||||
|
||||
std::shared_ptr<TrackVRulerControls> SpectrumView::DoGetVRulerControls()
|
||||
|
@ -24,7 +24,7 @@ public:
|
||||
using WaveTrackSubView::WaveTrackSubView;
|
||||
~SpectrumView() override;
|
||||
|
||||
virtual WaveTrackViewConstants::Display SubViewType() const override;
|
||||
const Type &SubViewType() const override;
|
||||
|
||||
std::shared_ptr<TrackVRulerControls> DoGetVRulerControls() override;
|
||||
|
||||
|
@ -104,6 +104,8 @@ std::vector<UIHandlePtr> WaveTrackControls::HitTest
|
||||
}
|
||||
|
||||
enum {
|
||||
reserveDisplays = 100,
|
||||
|
||||
OnRate8ID = 30000, // <---
|
||||
OnRate11ID, // |
|
||||
OnRate16ID, // |
|
||||
@ -123,8 +125,9 @@ enum {
|
||||
OnFloatID, // <---
|
||||
|
||||
OnMultiViewID,
|
||||
OnWaveformID,
|
||||
OnSpectrumID,
|
||||
|
||||
OnSetDisplayId, lastDisplayId = (OnSetDisplayId + reserveDisplays - 1),
|
||||
|
||||
OnSpectrogramSettingsID,
|
||||
|
||||
OnChannelLeftID,
|
||||
@ -620,6 +623,16 @@ void WaveTrackMenuTable::InitUserData(void *pUserData)
|
||||
mpData = static_cast<PlayableTrackControls::InitMenuData*>(pUserData);
|
||||
}
|
||||
|
||||
static WaveTrackSubView::Types AllTypes()
|
||||
{
|
||||
auto result = WaveTrackSubView::AllTypes();
|
||||
if ( result.size() > reserveDisplays ) {
|
||||
wxASSERT( false );
|
||||
result.resize( reserveDisplays );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void WaveTrackMenuTable::InitMenu(Menu *pMenu)
|
||||
{
|
||||
WaveTrack *const pTrack = static_cast<WaveTrack*>(mpData->pTrack);
|
||||
@ -631,16 +644,40 @@ void WaveTrackMenuTable::InitMenu(Menu *pMenu)
|
||||
if (multiView)
|
||||
checkedIds.push_back( OnMultiViewID );
|
||||
|
||||
bool hasSpectrum = false;
|
||||
int uniqueDisplay = 0;
|
||||
{
|
||||
// Find the set of type ids of the shown displays, disregarding their
|
||||
// top-to-bottom arrangement
|
||||
auto displays = view.GetDisplays();
|
||||
const auto end = displays.end();
|
||||
auto iter = displays.begin();
|
||||
std::sort( iter, end );
|
||||
|
||||
const auto displays = view.GetDisplays();
|
||||
for ( auto display : displays ) {
|
||||
auto id = (display == WaveTrackViewConstants::Waveform)
|
||||
? OnWaveformID
|
||||
: OnSpectrumID;
|
||||
checkedIds.push_back( id );
|
||||
if ( displays.size() == 1 )
|
||||
uniqueDisplay = id;
|
||||
// Check the corresponding menu items, and decide which if any has
|
||||
// the unique check
|
||||
int displayId = OnSetDisplayId;
|
||||
int nDisplays = 0;
|
||||
for ( const auto &type : AllTypes() ) {
|
||||
if ( iter != end && iter->id == type.id ) {
|
||||
checkedIds.push_back( displayId );
|
||||
uniqueDisplay = displayId;
|
||||
++iter;
|
||||
++nDisplays;
|
||||
|
||||
// Unfortunately this special knowledge of the Spectrum view type
|
||||
// remains. In future, either let a registry system insert this
|
||||
// menu item, or (better) move it to the context menu of the
|
||||
// Spectrum vertical ruler.
|
||||
// (But the latter won't be satisfactory without a means to
|
||||
// open that other context menu with keystrokes only, and that
|
||||
// would require some notion of a focused sub-view.)
|
||||
hasSpectrum = ( type.id == WaveTrackViewConstants::Spectrum );
|
||||
}
|
||||
++displayId;
|
||||
}
|
||||
if ( nDisplays > 1 )
|
||||
uniqueDisplay = 0;
|
||||
}
|
||||
|
||||
if ( multiView && uniqueDisplay )
|
||||
@ -652,9 +689,6 @@ void WaveTrackMenuTable::InitMenu(Menu *pMenu)
|
||||
// We can't change them on the fly yet anyway.
|
||||
auto gAudioIO = AudioIOBase::Get();
|
||||
const bool bAudioBusy = gAudioIO->IsBusy();
|
||||
bool hasSpectrum =
|
||||
make_iterator_range( displays.begin(), displays.end() )
|
||||
.contains( WaveTrackViewConstants::Spectrum );
|
||||
pMenu->Enable(OnSpectrogramSettingsID, hasSpectrum && !bAudioBusy);
|
||||
|
||||
AudacityProject *const project = &mpData->project;
|
||||
@ -733,13 +767,14 @@ BEGIN_POPUP_MENU(WaveTrackMenuTable)
|
||||
if ( WaveTrackSubViews::slots() > 1 )
|
||||
POPUP_MENU_CHECK_ITEM(OnMultiViewID, XO("&Multi-view"), OnMultiView)
|
||||
|
||||
if ( view.GetMultiView() ) {
|
||||
POPUP_MENU_CHECK_ITEM(OnWaveformID, XO("Wa&veform"), OnSetDisplay)
|
||||
POPUP_MENU_CHECK_ITEM(OnSpectrumID, XO("&Spectrogram"), OnSetDisplay)
|
||||
}
|
||||
else {
|
||||
POPUP_MENU_RADIO_ITEM(OnWaveformID, XO("Wa&veform"), OnSetDisplay)
|
||||
POPUP_MENU_RADIO_ITEM(OnSpectrumID, XO("&Spectrogram"), OnSetDisplay)
|
||||
int id = OnSetDisplayId;
|
||||
for ( const auto &type : AllTypes() ) {
|
||||
if ( view.GetMultiView() ) {
|
||||
POPUP_MENU_CHECK_ITEM(id++, type.name.Msgid(), OnSetDisplay)
|
||||
}
|
||||
else {
|
||||
POPUP_MENU_RADIO_ITEM(id++, type.name.Msgid(), OnSetDisplay)
|
||||
}
|
||||
}
|
||||
|
||||
POPUP_MENU_ITEM(OnSpectrogramSettingsID, XO("S&pectrogram Settings..."), OnSpectrogramSettings)
|
||||
@ -761,9 +796,10 @@ BEGIN_POPUP_MENU(WaveTrackMenuTable)
|
||||
|
||||
if ( pTrack ) {
|
||||
const auto displays = view.GetDisplays();
|
||||
bool hasWaveform =
|
||||
make_iterator_range( displays.begin(), displays.end() )
|
||||
.contains( WaveTrackViewConstants::Waveform );
|
||||
bool hasWaveform = (displays.end() != std::find(
|
||||
displays.begin(), displays.end(),
|
||||
WaveTrackSubView::Type{ WaveTrackViewConstants::Waveform, {} }
|
||||
) );
|
||||
if( hasWaveform ){
|
||||
POPUP_MENU_SEPARATOR()
|
||||
POPUP_MENU_SUB_MENU(OnWaveColorID, XO("&Wave Color"), WaveColorMenuTable)
|
||||
@ -784,7 +820,7 @@ void WaveTrackMenuTable::OnMultiView(wxCommandEvent & event)
|
||||
bool multi = !view.GetMultiView();
|
||||
const auto &displays = view.GetDisplays();
|
||||
const auto display = displays.empty()
|
||||
? WaveTrackViewConstants::Waveform : *displays.begin();
|
||||
? WaveTrackViewConstants::Waveform : displays.begin()->id;
|
||||
for (const auto channel : TrackList::Channels(pTrack)) {
|
||||
auto &channelView = WaveTrackView::Get( *channel );
|
||||
channelView.SetMultiView( multi );
|
||||
@ -799,24 +835,18 @@ void WaveTrackMenuTable::OnMultiView(wxCommandEvent & event)
|
||||
/// Set the Display mode based on the menu choice in the Track Menu.
|
||||
void WaveTrackMenuTable::OnSetDisplay(wxCommandEvent & event)
|
||||
{
|
||||
using namespace WaveTrackViewConstants;
|
||||
int idInt = event.GetId();
|
||||
wxASSERT(idInt >= OnWaveformID && idInt <= OnSpectrumID);
|
||||
wxASSERT(idInt >= OnSetDisplayId &&
|
||||
idInt <= lastDisplayId);
|
||||
const auto pTrack = static_cast<WaveTrack*>(mpData->pTrack);
|
||||
|
||||
WaveTrackView::WaveTrackDisplay id;
|
||||
switch (idInt) {
|
||||
default:
|
||||
case OnWaveformID:
|
||||
id = Waveform; break;
|
||||
case OnSpectrumID:
|
||||
id = Spectrum; break;
|
||||
}
|
||||
auto id = AllTypes()[ idInt - OnSetDisplayId ].id;
|
||||
|
||||
auto &view = WaveTrackView::Get( *pTrack );
|
||||
if ( view.GetMultiView() ) {
|
||||
for (auto channel : TrackList::Channels(pTrack)) {
|
||||
if ( !WaveTrackView::Get( *channel ).ToggleSubView( id ) ) {
|
||||
if ( !WaveTrackView::Get( *channel )
|
||||
.ToggleSubView( WaveTrackView::Display{ id } ) ) {
|
||||
// Trying to toggle off the last sub-view. It was refused.
|
||||
// Decide what to do here. Turn off multi-view instead?
|
||||
// PRL: I don't agree that it makes sense
|
||||
@ -827,12 +857,13 @@ void WaveTrackMenuTable::OnSetDisplay(wxCommandEvent & event)
|
||||
}
|
||||
else {
|
||||
const auto displays = view.GetDisplays();
|
||||
const bool wrongType = !(displays.size() == 1 && displays[0] == id);
|
||||
const bool wrongType =
|
||||
!(displays.size() == 1 && displays[0].id == id);
|
||||
if (wrongType) {
|
||||
for (auto channel : TrackList::Channels(pTrack)) {
|
||||
channel->SetLastScaleType();
|
||||
WaveTrackView::Get( *channel )
|
||||
.SetDisplay(WaveTrackView::WaveTrackDisplay(id));
|
||||
.SetDisplay( WaveTrackView::Display{ id } );
|
||||
}
|
||||
|
||||
AudacityProject *const project = &mpData->project;
|
||||
@ -886,7 +917,7 @@ void WaveTrackMenuTable::OnSpectrogramSettings(wxCommandEvent &)
|
||||
// factories.push_back(WaveformPrefsFactory( pTrack ));
|
||||
factories.push_back(SpectrumPrefsFactory( pTrack ));
|
||||
const int page =
|
||||
// (pTrack->GetDisplay() == WaveTrack::Spectrum) ? 1 :
|
||||
// (pTrack->GetDisplay() == WaveTrackViewConstants::Spectrum) ? 1 :
|
||||
0;
|
||||
|
||||
auto title = XO("%s:").Format( pTrack->GetName() );
|
||||
|
@ -40,6 +40,53 @@ Paul Licameli split from TrackPanel.cpp
|
||||
#include "../../../ui/ButtonHandle.h"
|
||||
#include "../../../../TrackInfo.h"
|
||||
|
||||
namespace {
|
||||
class Registry {
|
||||
public:
|
||||
using Type = WaveTrackSubView::Type;
|
||||
using Types = std::vector< Type >;
|
||||
|
||||
void Append( Type type )
|
||||
{
|
||||
types.emplace_back( std::move( type ) );
|
||||
sorted = false;
|
||||
}
|
||||
|
||||
Types &Get()
|
||||
{
|
||||
if ( !sorted ) {
|
||||
auto begin = types.begin(), end = types.end();
|
||||
std::sort( begin, end );
|
||||
// We don't want duplicate ids!
|
||||
wxASSERT( end == std::adjacent_find( begin, end ) );
|
||||
sorted = true;
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
private:
|
||||
Types types;
|
||||
bool sorted = false;
|
||||
};
|
||||
|
||||
Registry &GetRegistry()
|
||||
{
|
||||
static Registry result;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
WaveTrackSubView::RegisteredType::RegisteredType( Type type )
|
||||
{
|
||||
GetRegistry().Append( std::move( type ) );
|
||||
}
|
||||
|
||||
// static
|
||||
auto WaveTrackSubView::AllTypes() -> const Types &
|
||||
{
|
||||
return GetRegistry().Get();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
using WaveTrackSubViewPtrs = std::vector< std::shared_ptr< WaveTrackSubView > >;
|
||||
@ -842,12 +889,13 @@ WaveTrackView::DoDetailedHitTest
|
||||
return { false, results };
|
||||
}
|
||||
|
||||
auto WaveTrackView::GetDisplays() const -> std::vector<WaveTrackDisplay>
|
||||
auto WaveTrackView::GetDisplays() const
|
||||
-> std::vector< WaveTrackSubView::Type >
|
||||
{
|
||||
BuildSubViews();
|
||||
|
||||
// Collect the display types of visible views and sort them by position
|
||||
using Pair = std::pair< int, WaveTrackDisplay >;
|
||||
using Pair = std::pair< int, WaveTrackSubView::Type >;
|
||||
std::vector< Pair > pairs;
|
||||
size_t ii = 0;
|
||||
WaveTrackSubViews::ForEach( [&]( const WaveTrackSubView &subView ){
|
||||
@ -857,24 +905,24 @@ auto WaveTrackView::GetDisplays() const -> std::vector<WaveTrackDisplay>
|
||||
++ii;
|
||||
} );
|
||||
std::sort( pairs.begin(), pairs.end() );
|
||||
std::vector<WaveTrackDisplay> results;
|
||||
std::vector< WaveTrackSubView::Type > results;
|
||||
for ( const auto &pair : pairs )
|
||||
results.push_back( pair.second );
|
||||
return results;
|
||||
}
|
||||
|
||||
void WaveTrackView::SetDisplay(WaveTrackDisplay display, bool exclusive)
|
||||
void WaveTrackView::SetDisplay(Display display, bool exclusive)
|
||||
{
|
||||
BuildSubViews();
|
||||
DoSetDisplay( display, exclusive );
|
||||
}
|
||||
|
||||
bool WaveTrackView::ToggleSubView(WaveTrackDisplay display)
|
||||
bool WaveTrackView::ToggleSubView(Display display)
|
||||
{
|
||||
size_t ii = 0;
|
||||
size_t found = 0;
|
||||
if ( WaveTrackSubViews::FindIf( [&]( const WaveTrackSubView &subView ) {
|
||||
if ( subView.SubViewType() == display ) {
|
||||
if ( subView.SubViewType().id == display ) {
|
||||
found = ii;
|
||||
return true;
|
||||
}
|
||||
@ -927,7 +975,7 @@ bool WaveTrackView::ToggleSubView(WaveTrackDisplay display)
|
||||
// If exclusive, make the chosen view take up all the height. Else,
|
||||
// partition equally, putting the specified view on top.
|
||||
// Be sure the sequence in which the other views appear is determinate.
|
||||
void WaveTrackView::DoSetDisplay(WaveTrackDisplay display, bool exclusive)
|
||||
void WaveTrackView::DoSetDisplay(Display display, bool exclusive)
|
||||
{
|
||||
// Some generality here anticipating more than two views.
|
||||
// The order of sub-views in the array is not specified, so make it definite
|
||||
@ -935,7 +983,7 @@ void WaveTrackView::DoSetDisplay(WaveTrackDisplay display, bool exclusive)
|
||||
size_t ii = 0;
|
||||
std::vector< std::pair< WaveTrackViewConstants::Display, size_t > > pairs;
|
||||
WaveTrackSubViews::ForEach( [&pairs, &ii]( WaveTrackSubView &subView ){
|
||||
pairs.push_back( { subView.SubViewType(), ii++ } );
|
||||
pairs.push_back( { subView.SubViewType().id, ii++ } );
|
||||
} );
|
||||
std::sort( pairs.begin(), pairs.end() );
|
||||
|
||||
|
@ -13,19 +13,44 @@ Paul Licameli split from class WaveTrack
|
||||
|
||||
#include "../../../ui/CommonTrackView.h"
|
||||
#include "../../../../ClientData.h"
|
||||
#include "audacity/ComponentInterface.h"
|
||||
namespace WaveTrackViewConstants{ enum Display : int; }
|
||||
|
||||
class CutlineHandle;
|
||||
class TranslatableString;
|
||||
class WaveTrack;
|
||||
class WaveTrackView;
|
||||
|
||||
class WaveTrackSubView : public CommonTrackView
|
||||
{
|
||||
public:
|
||||
|
||||
using Display = WaveTrackViewConstants::Display;
|
||||
struct Type {
|
||||
// Identifies the type session-wide, and determines relative position in
|
||||
// menus listing all types
|
||||
Display id;
|
||||
// The translation is suitable for the track control panel drop-down,
|
||||
// and it may contain a menu accelerator
|
||||
EnumValueSymbol name;
|
||||
|
||||
bool operator < ( const Type &other ) const { return id < other.id; }
|
||||
bool operator == ( const Type &other ) const { return id == other.id; }
|
||||
};
|
||||
using Types = std::vector< Type >;
|
||||
|
||||
// Typically a file scope statically constructed object
|
||||
struct RegisteredType {
|
||||
RegisteredType( Type type );
|
||||
};
|
||||
|
||||
// Discover all registered types
|
||||
static const Types &AllTypes();
|
||||
|
||||
explicit
|
||||
WaveTrackSubView( WaveTrackView &waveTrackView );
|
||||
|
||||
virtual WaveTrackViewConstants::Display SubViewType() const = 0;
|
||||
virtual const Type &SubViewType() const = 0;
|
||||
|
||||
std::pair<
|
||||
bool, // if true, hit-testing is finished
|
||||
@ -67,6 +92,8 @@ class WaveTrackView final
|
||||
WaveTrackView &operator=( const WaveTrackView& ) = delete;
|
||||
|
||||
public:
|
||||
using Display = WaveTrackViewConstants::Display;
|
||||
|
||||
static WaveTrackView &Get( WaveTrack &track );
|
||||
static const WaveTrackView &Get( const WaveTrack &track );
|
||||
|
||||
@ -91,10 +118,8 @@ public:
|
||||
const std::shared_ptr<WaveTrack> &wt,
|
||||
CommonTrackView &view);
|
||||
|
||||
using WaveTrackDisplay = WaveTrackViewConstants::Display;
|
||||
|
||||
std::vector<WaveTrackDisplay> GetDisplays() const;
|
||||
void SetDisplay(WaveTrackDisplay display, bool exclusive = true);
|
||||
std::vector< WaveTrackSubView::Type > GetDisplays() const;
|
||||
void SetDisplay(Display display, bool exclusive = true);
|
||||
|
||||
const WaveTrackSubViewPlacements &SavePlacements() const
|
||||
{ return mPlacements; }
|
||||
@ -103,7 +128,7 @@ public:
|
||||
|
||||
// Return true if successful. Fails if you try to toggle off the only
|
||||
// sub-view.
|
||||
bool ToggleSubView( WaveTrackDisplay id );
|
||||
bool ToggleSubView( Display id );
|
||||
|
||||
// Get all the sub-views, in a sequence that is unspecified but in
|
||||
// correspondence with the result of SavePlacements
|
||||
@ -117,7 +142,7 @@ public:
|
||||
|
||||
private:
|
||||
void BuildSubViews() const;
|
||||
void DoSetDisplay(WaveTrackDisplay display, bool exclusive = true);
|
||||
void DoSetDisplay(Display display, bool exclusive = true);
|
||||
|
||||
// TrackPanelDrawable implementation
|
||||
void Draw(
|
||||
|
@ -36,6 +36,13 @@ Paul Licameli split from WaveTrackView.cpp
|
||||
#include <wx/graphics.h>
|
||||
#include <wx/dc.h>
|
||||
|
||||
static WaveTrackSubView::Type sType{
|
||||
WaveTrackViewConstants::Waveform,
|
||||
{ wxT("Waveform"), XO("Wa&veform") }
|
||||
};
|
||||
|
||||
static WaveTrackSubView::RegisteredType reg{ sType };
|
||||
|
||||
WaveformView::~WaveformView() = default;
|
||||
|
||||
std::vector<UIHandlePtr> WaveformView::DetailedHitTest(
|
||||
@ -119,9 +126,9 @@ void WaveformView::DoSetMinimized( bool minimized )
|
||||
TrackView::DoSetMinimized( minimized );
|
||||
}
|
||||
|
||||
WaveTrackViewConstants::Display WaveformView::SubViewType() const
|
||||
auto WaveformView::SubViewType() const -> const Type &
|
||||
{
|
||||
return WaveTrackViewConstants::Waveform;
|
||||
return sType;
|
||||
}
|
||||
|
||||
std::shared_ptr<TrackVRulerControls> WaveformView::DoGetVRulerControls()
|
||||
|
@ -26,7 +26,7 @@ public:
|
||||
using WaveTrackSubView::WaveTrackSubView;
|
||||
~WaveformView() override;
|
||||
|
||||
virtual WaveTrackViewConstants::Display SubViewType() const override;
|
||||
const Type &SubViewType() const override;
|
||||
|
||||
std::shared_ptr<TrackVRulerControls> DoGetVRulerControls() override;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user