mirror of
https://github.com/cookiengineer/audacity
synced 2025-08-01 08:29:27 +02:00
Each popup menu item can carry a callback to check or disable it
This commit is contained in:
parent
00a419a280
commit
db3543500c
@ -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();
|
||||
|
@ -85,8 +85,6 @@ public:
|
||||
static PopupMenuTable &Instance();
|
||||
|
||||
private:
|
||||
void InitMenu(wxMenu *pMenu) override;
|
||||
|
||||
void OnSpectrumScaleType(wxCommandEvent &evt);
|
||||
};
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
|
@ -85,8 +85,6 @@ public:
|
||||
static PopupMenuTable &Instance();
|
||||
|
||||
private:
|
||||
virtual void InitMenu(wxMenu *pMenu) override;
|
||||
|
||||
void OnWaveformScaleType(wxCommandEvent &evt);
|
||||
};
|
||||
|
||||
|
@ -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 *)
|
||||
|
@ -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()
|
||||
|
||||
|
@ -80,7 +80,6 @@ void PopupMenuBuilder::DoBeginGroup( Registry::GroupItem &item, const Path &path
|
||||
void PopupMenuBuilder::DoEndGroup( Registry::GroupItem &item, const Path &path )
|
||||
{
|
||||
if ( auto pItem = dynamic_cast<PopupSubMenu*>(&item) ) {
|
||||
pItem->table.InitMenu( mMenu );
|
||||
if ( !pItem->caption.empty() ) {
|
||||
auto subMenu = std::move( mMenus.back() );
|
||||
mMenus.pop_back();
|
||||
@ -118,6 +117,9 @@ void PopupMenuBuilder::DoVisit( Registry::SingleItem &item, const Path &path )
|
||||
// redundant
|
||||
pEntry->handler.InitUserData( mpUserData );
|
||||
|
||||
if ( pEntry->init )
|
||||
pEntry->init( pEntry->handler, *mMenu, pEntry->id );
|
||||
|
||||
mMenu->pParent->Bind(
|
||||
wxEVT_COMMAND_MENU_SELECTED, pEntry->func, &pEntry->handler, pEntry->id);
|
||||
}
|
||||
@ -146,10 +148,11 @@ void PopupMenuTable::ExtendMenu( wxMenu &menu, PopupMenuTable &table )
|
||||
|
||||
void PopupMenuTable::Append(
|
||||
const Identifier &stringId, PopupMenuTableEntry::Type type, int id,
|
||||
const TranslatableString &string, wxCommandEventFunction memFn)
|
||||
const TranslatableString &string, wxCommandEventFunction memFn,
|
||||
const PopupMenuTableEntry::InitFunction &init )
|
||||
{
|
||||
mStack.back()->items.push_back( std::make_unique<Entry>(
|
||||
stringId, type, id, string, memFn, *this
|
||||
stringId, type, id, string, memFn, *this, init
|
||||
) );
|
||||
}
|
||||
|
||||
@ -200,10 +203,6 @@ void PopupMenu::Disconnect()
|
||||
}
|
||||
}
|
||||
|
||||
void PopupMenuHandler::InitMenu(wxMenu *)
|
||||
{
|
||||
}
|
||||
|
||||
// static
|
||||
std::unique_ptr<wxMenu> PopupMenuTable::BuildMenu
|
||||
( wxEvtHandler *pParent, PopupMenuTable *pTable, void *pUserData )
|
||||
|
@ -20,6 +20,7 @@ tables, and automatically attaches and detaches the event handlers.
|
||||
|
||||
class wxCommandEvent;
|
||||
class wxString;
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <wx/menu.h> // to inherit wxMenu
|
||||
#include "../MemoryX.h"
|
||||
@ -33,22 +34,27 @@ class PopupMenuTable;
|
||||
struct PopupMenuTableEntry : Registry::SingleItem
|
||||
{
|
||||
enum Type { Item, RadioItem, CheckItem };
|
||||
using InitFunction =
|
||||
std::function< void( PopupMenuHandler &handler, wxMenu &menu, int id ) >;
|
||||
|
||||
Type type;
|
||||
int id;
|
||||
TranslatableString caption;
|
||||
wxCommandEventFunction func;
|
||||
PopupMenuHandler &handler;
|
||||
InitFunction init;
|
||||
|
||||
PopupMenuTableEntry( const Identifier &stringId,
|
||||
Type type_, int id_, const TranslatableString &caption_,
|
||||
wxCommandEventFunction func_, PopupMenuHandler &handler_ )
|
||||
wxCommandEventFunction func_, PopupMenuHandler &handler_,
|
||||
InitFunction init_ )
|
||||
: SingleItem{ stringId }
|
||||
, type(type_)
|
||||
, id(id_)
|
||||
, caption(caption_)
|
||||
, func(func_)
|
||||
, handler( handler_ )
|
||||
, init( init_ )
|
||||
{}
|
||||
|
||||
~PopupMenuTableEntry() override;
|
||||
@ -84,11 +90,6 @@ public:
|
||||
// May be called more than once before the menu opens.
|
||||
virtual void InitUserData(void *pUserData) = 0;
|
||||
|
||||
// Called when the menu is about to pop up.
|
||||
// Your chance to enable and disable items.
|
||||
// Default implementation does nothing.
|
||||
virtual void InitMenu(wxMenu *pMenu);
|
||||
|
||||
// Called when menu is destroyed.
|
||||
// May be called more than once.
|
||||
virtual void DestroyMenu() = 0;
|
||||
@ -131,19 +132,26 @@ protected:
|
||||
// To be used in implementations of Populate():
|
||||
void Append(
|
||||
const Identifier &stringId, PopupMenuTableEntry::Type type, int id,
|
||||
const TranslatableString &string, wxCommandEventFunction memFn);
|
||||
const TranslatableString &string, wxCommandEventFunction memFn,
|
||||
// This callback might check or disable a menu item:
|
||||
const PopupMenuTableEntry::InitFunction &init );
|
||||
|
||||
void AppendItem( const Identifier &stringId, int id,
|
||||
const TranslatableString &string, wxCommandEventFunction memFn )
|
||||
{ Append( stringId, PopupMenuTableEntry::Item, id, string, memFn ); }
|
||||
const TranslatableString &string, wxCommandEventFunction memFn,
|
||||
// This callback might check or disable a menu item:
|
||||
const PopupMenuTableEntry::InitFunction &init = {} )
|
||||
{ Append( stringId, PopupMenuTableEntry::Item, id, string, memFn, init ); }
|
||||
|
||||
void AppendRadioItem( const Identifier &stringId, int id,
|
||||
const TranslatableString &string, wxCommandEventFunction memFn )
|
||||
{ Append( stringId, PopupMenuTableEntry::RadioItem, id, string, memFn ); }
|
||||
const TranslatableString &string, wxCommandEventFunction memFn,
|
||||
// This callback might check or disable a menu item:
|
||||
const PopupMenuTableEntry::InitFunction &init = {} )
|
||||
{ Append( stringId, PopupMenuTableEntry::RadioItem, id, string, memFn, init ); }
|
||||
|
||||
void AppendCheckItem( const Identifier &stringId, int id,
|
||||
const TranslatableString &string, wxCommandEventFunction memFn )
|
||||
{ Append( stringId, PopupMenuTableEntry::CheckItem, id, string, memFn ); }
|
||||
const TranslatableString &string, wxCommandEventFunction memFn,
|
||||
const PopupMenuTableEntry::InitFunction &init = {} )
|
||||
{ Append( stringId, PopupMenuTableEntry::CheckItem, id, string, memFn, init ); }
|
||||
|
||||
void BeginSection( const Identifier &name );
|
||||
void EndSection();
|
||||
@ -166,7 +174,6 @@ which inherits from PopupMenuTable,
|
||||
|
||||
DECLARE_POPUP_MENU(MyTable);
|
||||
virtual void InitUserData(void *pUserData);
|
||||
virtual void InitMenu(wxMenu *pMenu);
|
||||
virtual void DestroyMenu();
|
||||
|
||||
Then in MyTable.cpp,
|
||||
@ -177,11 +184,6 @@ void MyTable::InitUserData(void *pUserData)
|
||||
auto pData = static_cast<MyData*>(pUserData);
|
||||
}
|
||||
|
||||
void MyTable::InitMenu(wxMenu *pMenu)
|
||||
{
|
||||
// enable or disable menu items
|
||||
}
|
||||
|
||||
void MyTable::DestroyMenu()
|
||||
{
|
||||
// Do cleanup
|
||||
@ -192,7 +194,14 @@ BEGIN_POPUP_MENU(MyTable)
|
||||
// you only need a sequence of calls:
|
||||
|
||||
AppendItem("Cut",
|
||||
OnCutSelectedTextID, XO("Cu&t"), POPUP_MENU_FN( OnCutSelectedText ) );
|
||||
OnCutSelectedTextID, XO("Cu&t"), POPUP_MENU_FN( OnCutSelectedText ),
|
||||
// optional argument:
|
||||
[](PopupMenuHandler &handler, wxMenu &menu, int id)
|
||||
{
|
||||
auto data = static_cast<MyTable&>( handler ).pData;
|
||||
// maybe enable or disable the menu item
|
||||
}
|
||||
);
|
||||
// etc.
|
||||
|
||||
END_POPUP_MENU()
|
||||
|
Loading…
x
Reference in New Issue
Block a user