1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-11-14 09:03:54 +01:00

Each popup menu item can carry a callback to check or disable it

This commit is contained in:
Paul Licameli
2020-02-08 16:36:21 -05:00
parent 00a419a280
commit db3543500c
9 changed files with 295 additions and 316 deletions

View File

@@ -265,16 +265,6 @@ PopupMenuTable &SpectrumVRulerMenuTable::Instance()
return instance;
}
void SpectrumVRulerMenuTable::InitMenu(wxMenu *pMenu)
{
WaveTrackVRulerMenuTable::InitMenu(pMenu);
WaveTrack *const wt = mpData->pTrack;
const int id =
OnFirstSpectrumScaleID + (int)(wt->GetSpectrogramSettings().scaleType);
pMenu->Check(id, true);
}
BEGIN_POPUP_MENU(SpectrumVRulerMenuTable)
BeginSection( "Scales" );
@@ -283,7 +273,17 @@ BeginSection( "Scales" );
for (int ii = 0, nn = names.size(); ii < nn; ++ii) {
AppendRadioItem( names[ii].Internal(),
OnFirstSpectrumScaleID + ii, names[ii].Msgid(),
POPUP_MENU_FN( OnSpectrumScaleType ) );
POPUP_MENU_FN( OnSpectrumScaleType ),
[]( PopupMenuHandler &handler, wxMenu &menu, int id ){
WaveTrack *const wt =
static_cast<SpectrumVRulerMenuTable&>( handler )
.mpData->pTrack;
if ( id ==
OnFirstSpectrumScaleID +
(int)(wt->GetSpectrogramSettings().scaleType ) )
menu.Check(id, true);
}
);
}
}
EndSection();

View File

@@ -85,8 +85,6 @@ public:
static PopupMenuTable &Instance();
private:
void InitMenu(wxMenu *pMenu) override;
void OnSpectrumScaleType(wxCommandEvent &evt);
};

View File

@@ -43,22 +43,6 @@ Paul Licameli split from TrackPanel.cpp
#include <wx/frame.h>
#include <wx/sizer.h>
namespace
{
/// Puts a check mark at a given position in a menu.
template<typename Pred>
void SetMenuChecks(wxMenu & menu, const Pred &pred)
{
for (auto &item : menu.GetMenuItems())
{
if (item->IsCheckable()) {
auto id = item->GetId();
menu.Check(id, pred(id));
}
}
}
}
WaveTrackControls::~WaveTrackControls()
{
}
@@ -148,21 +132,38 @@ enum {
};
namespace {
using ValueFinder = std::function< int( WaveTrack& ) >;
// A function that makes functions that check and enable sub-menu items,
// parametrized by how you get the relevant value from a track's settings
template< typename Table >
PopupMenuTableEntry::InitFunction initFn( const ValueFinder &findValue )
{
return [findValue]( PopupMenuHandler &handler, wxMenu &menu, int id ){
auto pData = static_cast<Table&>( handler ).mpData;
const auto pTrack = static_cast<WaveTrack*>(pData->pTrack);
auto &project = pData->project;
bool unsafe = ProjectAudioIO::Get( project ).IsAudioActive();
menu.Check( id, id == findValue( *pTrack ) );
menu.Enable( id, !unsafe );
};
};
}
//=============================================================================
// Table class for a sub-menu
class WaveColorMenuTable : public PopupMenuTable
struct WaveColorMenuTable : PopupMenuTable
{
WaveColorMenuTable()
: PopupMenuTable( "WaveColor", XO("&Wave Color") )
{}
DECLARE_POPUP_MENU(WaveColorMenuTable);
public:
static WaveColorMenuTable &Instance();
private:
void InitUserData(void *pUserData) override;
void InitMenu(wxMenu *pMenu) override;
void DestroyMenu() override
{
@@ -171,7 +172,7 @@ private:
PlayableTrackControls::InitMenuData *mpData{};
int IdOfWaveColor(int WaveColor);
static int IdOfWaveColor(int WaveColor);
void OnWaveColorChange(wxCommandEvent & event);
};
@@ -186,34 +187,27 @@ void WaveColorMenuTable::InitUserData(void *pUserData)
mpData = static_cast<PlayableTrackControls::InitMenuData*>(pUserData);
}
void WaveColorMenuTable::InitMenu(wxMenu *pMenu)
{
WaveTrack *const pTrack = static_cast<WaveTrack*>(mpData->pTrack);
auto WaveColorId = IdOfWaveColor( pTrack->GetWaveColorIndex());
SetMenuChecks(*pMenu, [=](int id){ return id == WaveColorId; });
AudacityProject *const project = &mpData->project;
bool unsafe = ProjectAudioIO::Get( *project ).IsAudioActive();
for (int i = OnInstrument1ID; i <= OnInstrument4ID; i++) {
pMenu->Enable(i, !unsafe);
}
}
const TranslatableString GetWaveColorStr(int colorIndex)
{
return XO("Instrument %i").Format( colorIndex+1 );
}
BEGIN_POPUP_MENU(WaveColorMenuTable)
static const auto fn = initFn< WaveColorMenuTable >(
[]( WaveTrack &track ){
return IdOfWaveColor( track.GetWaveColorIndex() );
}
);
AppendRadioItem( "Instrument1", OnInstrument1ID,
GetWaveColorStr(0), POPUP_MENU_FN( OnWaveColorChange ) );
GetWaveColorStr(0), POPUP_MENU_FN( OnWaveColorChange ), fn );
AppendRadioItem( "Instrument2", OnInstrument2ID,
GetWaveColorStr(1), POPUP_MENU_FN( OnWaveColorChange ) );
GetWaveColorStr(1), POPUP_MENU_FN( OnWaveColorChange ), fn );
AppendRadioItem( "Instrument3", OnInstrument3ID,
GetWaveColorStr(2), POPUP_MENU_FN( OnWaveColorChange ) );
GetWaveColorStr(2), POPUP_MENU_FN( OnWaveColorChange ), fn );
AppendRadioItem( "Instrument4", OnInstrument4ID,
GetWaveColorStr(3), POPUP_MENU_FN( OnWaveColorChange ) );
GetWaveColorStr(3), POPUP_MENU_FN( OnWaveColorChange ), fn );
END_POPUP_MENU()
/// Converts a WaveColor enumeration to a wxWidgets menu item Id.
@@ -249,19 +243,16 @@ void WaveColorMenuTable::OnWaveColorChange(wxCommandEvent & event)
//=============================================================================
// Table class for a sub-menu
class FormatMenuTable : public PopupMenuTable
struct FormatMenuTable : PopupMenuTable
{
FormatMenuTable()
: PopupMenuTable{ "SampleFormat", XO("&Format") }
{}
DECLARE_POPUP_MENU(FormatMenuTable);
public:
static FormatMenuTable &Instance();
private:
void InitUserData(void *pUserData) override;
void InitMenu(wxMenu *pMenu) override;
void DestroyMenu() override
{
@@ -270,7 +261,7 @@ private:
PlayableTrackControls::InitMenuData *mpData{};
int IdOfFormat(int format);
static int IdOfFormat(int format);
void OnFormatChange(wxCommandEvent & event);
};
@@ -286,26 +277,21 @@ void FormatMenuTable::InitUserData(void *pUserData)
mpData = static_cast<PlayableTrackControls::InitMenuData*>(pUserData);
}
void FormatMenuTable::InitMenu(wxMenu *pMenu)
{
WaveTrack *const pTrack = static_cast<WaveTrack*>(mpData->pTrack);
auto formatId = IdOfFormat(pTrack->GetSampleFormat());
SetMenuChecks(*pMenu, [=](int id){ return id == formatId; });
AudacityProject *const project = &mpData->project;
bool unsafe = ProjectAudioIO::Get( *project ).IsAudioActive();
for (int i = On16BitID; i <= OnFloatID; i++) {
pMenu->Enable(i, !unsafe);
}
}
BEGIN_POPUP_MENU(FormatMenuTable)
static const auto fn = initFn< FormatMenuTable >(
[]( WaveTrack &track ){
return IdOfFormat( track.GetSampleFormat() );
}
);
AppendRadioItem( "16Bit", On16BitID,
GetSampleFormatStr(int16Sample), POPUP_MENU_FN( OnFormatChange ) );
GetSampleFormatStr(int16Sample), POPUP_MENU_FN( OnFormatChange ), fn );
AppendRadioItem("24Bit", On24BitID,
GetSampleFormatStr( int24Sample), POPUP_MENU_FN( OnFormatChange ) );
GetSampleFormatStr( int24Sample), POPUP_MENU_FN( OnFormatChange ), fn );
AppendRadioItem( "Float", OnFloatID,
GetSampleFormatStr(floatSample), POPUP_MENU_FN( OnFormatChange ) );
GetSampleFormatStr(floatSample), POPUP_MENU_FN( OnFormatChange ), fn );
END_POPUP_MENU()
/// Converts a format enumeration to a wxWidgets menu item Id.
@@ -372,19 +358,16 @@ void FormatMenuTable::OnFormatChange(wxCommandEvent & event)
//=============================================================================
// Table class for a sub-menu
class RateMenuTable : public PopupMenuTable
struct RateMenuTable : PopupMenuTable
{
RateMenuTable()
: PopupMenuTable{ "SampleRate", XO("Rat&e") }
{}
DECLARE_POPUP_MENU(RateMenuTable);
public:
static RateMenuTable &Instance();
private:
void InitUserData(void *pUserData) override;
void InitMenu(wxMenu *pMenu) override;
void DestroyMenu() override
{
@@ -393,7 +376,7 @@ private:
PlayableTrackControls::InitMenuData *mpData{};
int IdOfRate(int rate);
static int IdOfRate(int rate);
void SetRate(WaveTrack * pTrack, double rate);
void OnRateChange(wxCommandEvent & event);
@@ -411,36 +394,30 @@ void RateMenuTable::InitUserData(void *pUserData)
mpData = static_cast<PlayableTrackControls::InitMenuData*>(pUserData);
}
void RateMenuTable::InitMenu(wxMenu *pMenu)
{
WaveTrack *const pTrack = static_cast<WaveTrack*>(mpData->pTrack);
const auto rateId = IdOfRate((int)pTrack->GetRate());
SetMenuChecks(*pMenu, [=](int id){ return id == rateId; });
AudacityProject *const project = &mpData->project;
bool unsafe = ProjectAudioIO::Get( *project ).IsAudioActive();
for (int i = OnRate8ID; i <= OnRateOtherID; i++) {
pMenu->Enable(i, !unsafe);
}
}
// Because of Bug 1780 we can't use AppendRadioItem
// If we did, we'd get no message when clicking on Other...
// when it is already selected.
BEGIN_POPUP_MENU(RateMenuTable)
AppendCheckItem( "8000", OnRate8ID, XO("8000 Hz"), POPUP_MENU_FN( OnRateChange ) );
AppendCheckItem( "11025", OnRate11ID, XO("11025 Hz"), POPUP_MENU_FN( OnRateChange ) );
AppendCheckItem( "16000", OnRate16ID, XO("16000 Hz"), POPUP_MENU_FN( OnRateChange ) );
AppendCheckItem( "22050", OnRate22ID, XO("22050 Hz"), POPUP_MENU_FN( OnRateChange ) );
AppendCheckItem( "44100", OnRate44ID, XO("44100 Hz"), POPUP_MENU_FN( OnRateChange ) );
AppendCheckItem( "48000", OnRate48ID, XO("48000 Hz"), POPUP_MENU_FN( OnRateChange ) );
AppendCheckItem( "88200", OnRate88ID, XO("88200 Hz"), POPUP_MENU_FN( OnRateChange ) );
AppendCheckItem( "96000", OnRate96ID, XO("96000 Hz"), POPUP_MENU_FN( OnRateChange ) );
AppendCheckItem( "176400", OnRate176ID, XO("176400 Hz"), POPUP_MENU_FN( OnRateChange ) );
AppendCheckItem( "192000", OnRate192ID, XO("192000 Hz"), POPUP_MENU_FN( OnRateChange ) );
AppendCheckItem( "352800", OnRate352ID, XO("352800 Hz"), POPUP_MENU_FN( OnRateChange ) );
AppendCheckItem( "384000", OnRate384ID, XO("384000 Hz"), POPUP_MENU_FN( OnRateChange ) );
AppendCheckItem( "Other", OnRateOtherID, XO("&Other..."), POPUP_MENU_FN( OnRateOther ) );
static const auto fn = initFn< RateMenuTable >(
[]( WaveTrack &track ){
return IdOfRate( (int)track.GetRate() );
}
);
AppendCheckItem( "8000", OnRate8ID, XO("8000 Hz"), POPUP_MENU_FN( OnRateChange ), fn );
AppendCheckItem( "11025", OnRate11ID, XO("11025 Hz"), POPUP_MENU_FN( OnRateChange ), fn );
AppendCheckItem( "16000", OnRate16ID, XO("16000 Hz"), POPUP_MENU_FN( OnRateChange ), fn );
AppendCheckItem( "22050", OnRate22ID, XO("22050 Hz"), POPUP_MENU_FN( OnRateChange ), fn );
AppendCheckItem( "44100", OnRate44ID, XO("44100 Hz"), POPUP_MENU_FN( OnRateChange ), fn );
AppendCheckItem( "48000", OnRate48ID, XO("48000 Hz"), POPUP_MENU_FN( OnRateChange ), fn );
AppendCheckItem( "88200", OnRate88ID, XO("88200 Hz"), POPUP_MENU_FN( OnRateChange ), fn );
AppendCheckItem( "96000", OnRate96ID, XO("96000 Hz"), POPUP_MENU_FN( OnRateChange ), fn );
AppendCheckItem( "176400", OnRate176ID, XO("176400 Hz"), POPUP_MENU_FN( OnRateChange ), fn );
AppendCheckItem( "192000", OnRate192ID, XO("192000 Hz"), POPUP_MENU_FN( OnRateChange ), fn );
AppendCheckItem( "352800", OnRate352ID, XO("352800 Hz"), POPUP_MENU_FN( OnRateChange ), fn );
AppendCheckItem( "384000", OnRate384ID, XO("384000 Hz"), POPUP_MENU_FN( OnRateChange ), fn );
AppendCheckItem( "Other", OnRateOtherID, XO("&Other..."), POPUP_MENU_FN( OnRateOther ), fn );
END_POPUP_MENU()
const int nRates = 12;
@@ -573,19 +550,16 @@ void RateMenuTable::OnRateOther(wxCommandEvent &)
//=============================================================================
// Class defining common command handlers for mono and stereo tracks
class WaveTrackMenuTable : public PopupMenuTable
struct WaveTrackMenuTable : PopupMenuTable
{
public:
static WaveTrackMenuTable &Instance( Track * pTrack);
Track * mpTrack{};
protected:
WaveTrackMenuTable()
: PopupMenuTable{ "WaveTrack" }
{}
void InitUserData(void *pUserData) override;
void InitMenu(wxMenu *pMenu) override;
void DestroyMenu() override
{
@@ -639,146 +613,81 @@ static std::vector<WaveTrackSubViewType> AllTypes()
return result;
}
void WaveTrackMenuTable::InitMenu(wxMenu *pMenu)
{
WaveTrack *const pTrack = static_cast<WaveTrack*>(mpData->pTrack);
std::vector<int> checkedIds;
const auto &view = WaveTrackView::Get( *pTrack );
auto multiView = view.GetMultiView();
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 );
// 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 )
// Bug2275 residual
// Disable the checking-off of the only sub-view
pMenu->Enable( uniqueDisplay, false );
// Bug 1253. Shouldn't open preferences if audio is busy.
// We can't change them on the fly yet anyway.
auto gAudioIO = AudioIOBase::Get();
if ( hasSpectrum )
pMenu->Enable(OnSpectrogramSettingsID, !gAudioIO->IsBusy());
AudacityProject *const project = &mpData->project;
auto &tracks = TrackList::Get( *project );
bool unsafe = RealtimeEffectManager::Get().RealtimeIsActive() &&
ProjectAudioIO::Get( *project ).IsAudioActive();
auto nChannels = TrackList::Channels(pTrack).size();
const bool isMono = ( nChannels == 1 );
const bool isStereo = ( nChannels == 2 );
// Maybe more than stereo tracks some time?
if ( isMono )
{
WaveTrack *const pTrack2 = static_cast<WaveTrack*>(mpData->pTrack);
auto next = * ++ tracks.Find(pTrack2);
if (isMono) {
const bool canMakeStereo =
(next &&
TrackList::Channels(next).size() == 1 &&
track_cast<WaveTrack*>(next));
pMenu->Enable(OnMergeStereoID, canMakeStereo && !unsafe);
int itemId;
switch (pTrack2->GetChannel()) {
case Track::LeftChannel:
itemId = OnChannelLeftID;
break;
case Track::RightChannel:
itemId = OnChannelRightID;
break;
default:
itemId = OnChannelMonoID;
break;
}
checkedIds.push_back(itemId);
}
}
else
{
pMenu->Enable(OnMergeStereoID, false);
}
SetMenuChecks(*pMenu, [&](int id){
auto end = checkedIds.end();
return end != std::find(checkedIds.begin(), end, id);
});
// Enable this only for properly stereo tracks:
pMenu->Enable(OnSwapChannelsID, isStereo && !unsafe);
pMenu->Enable(OnSplitStereoID, !isMono && !unsafe);
#ifndef EXPERIMENTAL_DA
// Can be achieved by split stereo and then dragging pan slider.
pMenu->Enable(OnSplitStereoMonoID, !isMono && !unsafe);
#endif
// Several menu items no longer needed....
#if 0
pMenu->Enable(OnChannelMonoID, isMono);
pMenu->Enable(OnChannelLeftID, isMono);
pMenu->Enable(OnChannelRightID, isMono);
#endif
}
BEGIN_POPUP_MENU(WaveTrackMenuTable)
// Functions usable "now" (list population time) and also "later"
// (in callbacks to check and disable items)
static const auto findTrack =
[]( PopupMenuHandler &handler ) -> WaveTrack & {
return *static_cast< WaveTrack* >(
static_cast< WaveTrackMenuTable& >( handler ).mpData->pTrack);
};
WaveTrack *const pTrack = static_cast<WaveTrack*>(mpTrack);
static const auto isMono =
[]( PopupMenuHandler &handler ) -> bool {
return 1 == TrackList::Channels( &findTrack( handler ) ).size();
};
static const auto isUnsafe =
[]( PopupMenuHandler &handler ) -> bool {
auto &project =
static_cast< WaveTrackMenuTable& >( handler ).mpData->project;
return RealtimeEffectManager::Get().RealtimeIsActive() &&
ProjectAudioIO::Get( project ).IsAudioActive();
};
const auto pTrack = &findTrack( *this );
const auto &view = WaveTrackView::Get( *pTrack );
BeginSection( "SubViews" );
if ( WaveTrackSubViews::slots() > 1 )
AppendCheckItem( "MultiView", OnMultiViewID, XO("&Multi-view"), POPUP_MENU_FN( OnMultiView ) );
AppendCheckItem( "MultiView", OnMultiViewID, XO("&Multi-view"),
POPUP_MENU_FN( OnMultiView ),
[]( PopupMenuHandler &handler, wxMenu &menu, int id ){
auto &track = findTrack( handler );
const auto &view = WaveTrackView::Get( track );
menu.Check( id, view.GetMultiView() );
}
);
int id = OnSetDisplayId;
for ( const auto &type : AllTypes() ) {
static const auto initFn = []( bool radio ){ return
[radio]( PopupMenuHandler &handler, wxMenu &menu, int id ){
// Find all known sub-view types
const auto allTypes = AllTypes();
// How to convert a type to a menu item id
const auto IdForType =
[&allTypes]( const WaveTrackSubViewType &type ) -> int {
const auto begin = allTypes.begin();
return OnSetDisplayId +
(std::find( begin, allTypes.end(), type ) - begin);
};
auto &track = findTrack( handler );
const auto &view = WaveTrackView::Get( track );
const auto displays = view.GetDisplays();
const auto end = displays.end();
bool check = (end !=
std::find_if( displays.begin(), end,
[&]( const WaveTrackSubViewType &type ){
return id == IdForType( type ); } ) );
menu.Check( id, check );
// Bug2275 residual
// Disable the checking-off of the only sub-view
if ( !radio && displays.size() == 1 && check )
menu.Enable( id, false );
};
};
if ( view.GetMultiView() ) {
AppendCheckItem( type.name.Internal(), id++, type.name.Msgid(), POPUP_MENU_FN( OnSetDisplay ) );
AppendCheckItem( type.name.Internal(), id++, type.name.Msgid(),
POPUP_MENU_FN( OnSetDisplay ), initFn( false ) );
}
else {
AppendRadioItem( type.name.Internal(), id++, type.name.Msgid(), POPUP_MENU_FN( OnSetDisplay ) );
AppendRadioItem( type.name.Internal(), id++, type.name.Msgid(),
POPUP_MENU_FN( OnSetDisplay ), initFn( true ) );
}
}
EndSection();
@@ -801,8 +710,21 @@ BEGIN_POPUP_MENU(WaveTrackMenuTable)
WaveTrackSubView::Type{ WaveTrackViewConstants::Spectrum, {} }
) );
if( hasSpectrum ){
// In future, we might move this 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.)
BeginSection( "SpectrogramSettings" );
AppendItem( "SpectrogramSettings", OnSpectrogramSettingsID, XO("S&pectrogram Settings..."), POPUP_MENU_FN( OnSpectrogramSettings ) );
AppendItem( "SpectrogramSettings", OnSpectrogramSettingsID, XO("S&pectrogram Settings..."), POPUP_MENU_FN( OnSpectrogramSettings ),
[]( PopupMenuHandler &handler, wxMenu &menu, int id ){
// Bug 1253. Shouldn't open preferences if audio is busy.
// We can't change them on the fly yet anyway.
auto gAudioIO = AudioIOBase::Get();
menu.Enable(id, !gAudioIO->IsBusy());
}
);
EndSection();
}
@@ -811,16 +733,65 @@ BEGIN_POPUP_MENU(WaveTrackMenuTable)
BeginSection( "Channels" );
// If these are enabled again, choose a hot key for Mono that does not conflict
// with Multi View
// AppendRadioItem(OnChannelMonoID, XO("&Mono"), OnChannelChange)
// AppendRadioItem(OnChannelLeftID, XO("&Left Channel"), OnChannelChange)
// AppendRadioItem(OnChannelRightID, XO("R&ight Channel"), OnChannelChange)
AppendItem( "MakeStereo", OnMergeStereoID, XO("Ma&ke Stereo Track"), POPUP_MENU_FN( OnMergeStereo ) );
// AppendRadioItem(OnChannelMonoID, XO("&Mono"),
// POPUP_MENU_FN( OnChannelChange ),
// []( PopupMenuHandler &handler, wxMenu &menu, int id ){
// menu.Enable( id, isMono( handler ) );
// menu.Check( id, findTrack( handler ).GetChannel() == Track::MonoChannel );
// }
// );
// AppendRadioItem(OnChannelLeftID, XO("&Left Channel"),
// POPUP_MENU_FN( OnChannelChange ),
// []( PopupMenuHandler &handler, wxMenu &menu, int id ){
// menu.Enable( id, isMono( handler ) );
// menu.Check( id, findTrack( handler ).GetChannel() == Track::LeftChannel );
// }
// );
// AppendRadioItem(OnChannelRightID, XO("R&ight Channel"),
// POPUP_MENU_FN( OnChannelChange ),
// []( PopupMenuHandler &handler, wxMenu &menu, int id ){
// menu.Enable( id, isMono( handler ) );
// menu.Check( id, findTrack( handler ).GetChannel() == Track::RightChannel );
// }
// );
AppendItem( "MakeStereo", OnMergeStereoID, XO("Ma&ke Stereo Track"),
POPUP_MENU_FN( OnMergeStereo ),
[]( PopupMenuHandler &handler, wxMenu &menu, int id ){
bool canMakeStereo = !isUnsafe( handler ) && isMono( handler );
if ( canMakeStereo ) {
AudacityProject &project =
static_cast< WaveTrackMenuTable& >( handler ).mpData->project;
auto &tracks = TrackList::Get( project );
auto &track = findTrack( handler );
auto next = * ++ tracks.Find(&track);
canMakeStereo =
(next &&
TrackList::Channels(next).size() == 1 &&
track_cast<WaveTrack*>(next));
}
menu.Enable( id, canMakeStereo );
}
);
AppendItem( "Swap", OnSwapChannelsID, XO("Swap Stereo &Channels"), POPUP_MENU_FN( OnSwapChannels ) );
AppendItem( "Split", OnSplitStereoID, XO("Spl&it Stereo Track"), POPUP_MENU_FN( OnSplitStereo ) );
AppendItem( "Swap", OnSwapChannelsID, XO("Swap Stereo &Channels"),
POPUP_MENU_FN( OnSwapChannels ),
[]( PopupMenuHandler &handler, wxMenu &menu, int id ){
bool isStereo =
2 == TrackList::Channels( &findTrack( handler ) ).size();
menu.Enable( id, isStereo && !isUnsafe( handler ) );
}
);
static const auto enableSplitStereo =
[]( PopupMenuHandler &handler, wxMenu &menu, int id ){
menu.Enable( id, !isMono( handler ) && !isUnsafe( handler ) );
};
AppendItem( "Split", OnSplitStereoID, XO("Spl&it Stereo Track"),
POPUP_MENU_FN( OnSplitStereo ), enableSplitStereo );
// DA: Uses split stereo track and then drag pan sliders for split-stereo-to-mono
#ifndef EXPERIMENTAL_DA
AppendItem( "SplitToMono", OnSplitStereoMonoID, XO("Split Stereo to Mo&no"), POPUP_MENU_FN( OnSplitStereoMono ) );
AppendItem( "SplitToMono", OnSplitStereoMonoID, XO("Split Stereo to Mo&no"), POPUP_MENU_FN( OnSplitStereoMono ), enableSplitStereo );
#endif
EndSection();

View File

@@ -266,17 +266,6 @@ PopupMenuTable &WaveformVRulerMenuTable::Instance()
return instance;
}
void WaveformVRulerMenuTable::InitMenu(wxMenu *pMenu)
{
WaveTrackVRulerMenuTable::InitMenu(pMenu);
// DB setting is already on track drop down.
WaveTrack *const wt = mpData->pTrack;
const int id =
OnFirstWaveformScaleID + (int)(wt->GetWaveformSettings().scaleType);
pMenu->Check(id, true);
}
BEGIN_POPUP_MENU(WaveformVRulerMenuTable)
BeginSection( "Scales" );
@@ -285,7 +274,17 @@ BEGIN_POPUP_MENU(WaveformVRulerMenuTable)
for (int ii = 0, nn = names.size(); ii < nn; ++ii) {
AppendRadioItem( names[ii].Internal(),
OnFirstWaveformScaleID + ii, names[ii].Msgid(),
POPUP_MENU_FN( OnWaveformScaleType ) );
POPUP_MENU_FN( OnWaveformScaleType ),
[]( PopupMenuHandler &handler, wxMenu &menu, int id ){
const auto pData =
static_cast< WaveformVRulerMenuTable& >( handler ).mpData;
WaveTrack *const wt = pData->pTrack;
if ( id ==
OnFirstWaveformScaleID +
(int)(wt->GetWaveformSettings().scaleType) )
menu.Check(id, true);
}
);
}
}
EndSection();

View File

@@ -85,8 +85,6 @@ public:
static PopupMenuTable &Instance();
private:
virtual void InitMenu(wxMenu *pMenu) override;
void OnWaveformScaleType(wxCommandEvent &evt);
};

View File

@@ -54,17 +54,6 @@ private:
mpData = static_cast<CommonTrackControls::InitMenuData*>(pUserData);
}
void InitMenu(wxMenu *pMenu) override
{
TimeTrack *const pTrack = static_cast<TimeTrack*>(mpData->pTrack);
pMenu->Check(OnTimeTrackLogIntID, pTrack->GetInterpolateLog());
auto isLog = pTrack->GetDisplayLog();
pMenu->Check(OnTimeTrackLinID, !isLog);
pMenu->Check(OnTimeTrackLogID, isLog);
}
void DestroyMenu() override
{
mpData = nullptr;
@@ -162,15 +151,34 @@ void TimeTrackMenuTable::OnTimeTrackLogInt(wxCommandEvent & /*event*/)
}
BEGIN_POPUP_MENU(TimeTrackMenuTable)
static const auto findTrack = []( PopupMenuHandler &handler ){
return static_cast<TimeTrack*>(
static_cast<TimeTrackMenuTable&>( handler ).mpData->pTrack );
};
BeginSection( "Scales" );
AppendRadioItem( "Linear", OnTimeTrackLinID, XO("&Linear scale"), POPUP_MENU_FN( OnTimeTrackLin ) );
AppendRadioItem( "Log", OnTimeTrackLogID, XO("L&ogarithmic scale"), POPUP_MENU_FN( OnTimeTrackLog ) );
AppendRadioItem( "Linear", OnTimeTrackLinID, XO("&Linear scale"),
POPUP_MENU_FN( OnTimeTrackLin ),
[]( PopupMenuHandler &handler, wxMenu &menu, int id ){
menu.Check( id, !findTrack(handler)->GetDisplayLog() );
} );
AppendRadioItem( "Log", OnTimeTrackLogID, XO("L&ogarithmic scale"),
POPUP_MENU_FN( OnTimeTrackLog ),
[]( PopupMenuHandler &handler, wxMenu &menu, int id ){
menu.Check( id, findTrack(handler)->GetDisplayLog() );
} );
EndSection();
BeginSection( "Other" );
AppendItem( "Range", OnSetTimeTrackRangeID, XO("&Range..."), POPUP_MENU_FN( OnSetTimeTrackRange ) );
AppendCheckItem( "LogInterp", OnTimeTrackLogIntID, XO("Logarithmic &Interpolation"), POPUP_MENU_FN( OnTimeTrackLogInt) );
AppendItem( "Range", OnSetTimeTrackRangeID, XO("&Range..."),
POPUP_MENU_FN( OnSetTimeTrackRange ) );
AppendCheckItem( "LogInterp", OnTimeTrackLogIntID,
XO("Logarithmic &Interpolation"), POPUP_MENU_FN( OnTimeTrackLogInt),
[]( PopupMenuHandler &handler, wxMenu &menu, int id ){
menu.Check( id, findTrack(handler)->GetInterpolateLog() );
} );
EndSection();
END_POPUP_MENU()
PopupMenuTable *TimeTrackControls::GetMenuExtension(Track *)

View File

@@ -93,7 +93,6 @@ private:
void OnMoveTrack(wxCommandEvent &event);
void InitUserData(void *pUserData) override;
void InitMenu(wxMenu *pMenu) override;
void DestroyMenu() override
{
@@ -114,19 +113,17 @@ void TrackMenuTable::InitUserData(void *pUserData)
mpData = static_cast<CommonTrackControls::InitMenuData*>(pUserData);
}
void TrackMenuTable::InitMenu(wxMenu *pMenu)
{
Track *const pTrack = mpData->pTrack;
const auto &tracks = TrackList::Get( mpData->project );
pMenu->Enable(OnMoveUpID, tracks.CanMoveUp(pTrack));
pMenu->Enable(OnMoveDownID, tracks.CanMoveDown(pTrack));
pMenu->Enable(OnMoveTopID, tracks.CanMoveUp(pTrack));
pMenu->Enable(OnMoveBottomID, tracks.CanMoveDown(pTrack));
}
BEGIN_POPUP_MENU(TrackMenuTable)
static const auto enableIfCanMove = [](bool up){ return
[up]( PopupMenuHandler &handler, wxMenu &menu, int id ){
auto pData = static_cast<TrackMenuTable&>( handler ).mpData;
const auto &tracks = TrackList::Get( pData->project );
Track *const pTrack = pData->pTrack;
menu.Enable( id,
up ? tracks.CanMoveUp(pTrack) : tracks.CanMoveDown(pTrack) );
};
};
BeginSection( "Basic" );
AppendItem( "Name", OnSetNameID, XO("&Name..."), POPUP_MENU_FN( OnSetName ) );
EndSection();
@@ -143,7 +140,7 @@ BEGIN_POPUP_MENU(TrackMenuTable)
GetKeyFromName(wxT("TrackMoveUp")).GET() ),
wxT("\t")
),
POPUP_MENU_FN( OnMoveTrack ) );
POPUP_MENU_FN( OnMoveTrack ), enableIfCanMove(true) );
AppendItem( "Down",
OnMoveDownID,
XO("Move Track &Down").Join(
@@ -153,7 +150,7 @@ BEGIN_POPUP_MENU(TrackMenuTable)
GetKeyFromName(wxT("TrackMoveDown")).GET() ),
wxT("\t")
),
POPUP_MENU_FN( OnMoveTrack ) );
POPUP_MENU_FN( OnMoveTrack ), enableIfCanMove(false) );
AppendItem( "Top",
OnMoveTopID,
XO("Move Track to &Top").Join(
@@ -163,7 +160,7 @@ BEGIN_POPUP_MENU(TrackMenuTable)
GetKeyFromName(wxT("TrackMoveTop")).GET() ),
wxT("\t")
),
POPUP_MENU_FN( OnMoveTrack ) );
POPUP_MENU_FN( OnMoveTrack ), enableIfCanMove(true) );
AppendItem( "Bottom",
OnMoveBottomID,
XO("Move Track to &Bottom").Join(
@@ -173,7 +170,7 @@ BEGIN_POPUP_MENU(TrackMenuTable)
GetKeyFromName(wxT("TrackMoveBottom")).GET() ),
wxT("\t")
),
POPUP_MENU_FN( OnMoveTrack ) );
POPUP_MENU_FN( OnMoveTrack ), enableIfCanMove(false) );
EndSection();
END_POPUP_MENU()