1
0
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:
Paul Licameli 2020-01-18 20:33:19 -05:00
commit 30999ab134
16 changed files with 244 additions and 117 deletions

View File

@ -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(); }

View File

@ -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;

View File

@ -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{

View File

@ -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 )

View File

@ -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) ?

View File

@ -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");

View File

@ -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;
}

View File

@ -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 );

View File

@ -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"),
};

View File

@ -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()

View File

@ -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;

View File

@ -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() );

View File

@ -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() );

View File

@ -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(

View File

@ -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()

View File

@ -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;