mirror of
https://github.com/cookiengineer/audacity
synced 2025-12-15 09:01:12 +01:00
Command flag functions out of Menus.cpp, reducing its dependencies...
... Mostly into CommonCommandFlags.cpp, but some elsewhere, to avoid giving that new file problematic dependencies on LabelTrack, ControlToolBar, and EffectManager. Note that CutCopyAvailableFlag is critically ordered, for message purposes, only with AudioIONotAvailableFlag, the only flag with a message that it combines with in menu item definitions. The dependency on LabelTrack.cpp might not be a bad one later, if the track and its view can be separated, and that would allow CutCopyAvailableFlag to be put with the others. But much other work on LabelTrack must happen first.
This commit is contained in:
@@ -0,0 +1,356 @@
|
||||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
CommonCommandFlags.cpp
|
||||
|
||||
Paul Licameli split from Menus.cpp
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include "Audacity.h"
|
||||
#include "CommonCommandFlags.h"
|
||||
|
||||
#include "Experimental.h"
|
||||
|
||||
#include <wx/frame.h>
|
||||
|
||||
#include "AudioIO.h"
|
||||
#include "LabelTrack.h"
|
||||
#include "Menus.h"
|
||||
#include "NoteTrack.h"
|
||||
#include "Project.h"
|
||||
#include "ProjectAudioIO.h"
|
||||
#include "ProjectFileIO.h"
|
||||
#include "ProjectHistory.h"
|
||||
#include "ProjectSettings.h"
|
||||
#include "UndoManager.h"
|
||||
#include "ViewInfo.h"
|
||||
#include "WaveTrack.h"
|
||||
#include "commands/CommandManagerWindowClasses.h"
|
||||
#include "toolbars/ControlToolBar.h"
|
||||
|
||||
/*
|
||||
|
||||
This file registers functions implementing many of the tests for enabling of
|
||||
menu items. Sequence of a few of them has minor significance, but for most
|
||||
there is little reason to keep them in one file. Flags used only by one
|
||||
other file might instead be defined only where used.
|
||||
|
||||
They are collected here because Menus.cpp is too low level to have the
|
||||
dependencies implied by the include directives above -- it would make dependency
|
||||
cycles.
|
||||
|
||||
*/
|
||||
|
||||
// Really means, some track is selected, that isn't a time track
|
||||
bool TracksSelectedPred( const AudacityProject &project )
|
||||
{
|
||||
auto range = TrackList::Get( project ).Selected()
|
||||
- []( const Track *pTrack ){
|
||||
return track_cast<const TimeTrack*>( pTrack ); };
|
||||
return !range.empty();
|
||||
};
|
||||
|
||||
bool AudioIOBusyPred( const AudacityProject &project )
|
||||
{
|
||||
return AudioIOBase::Get()->IsAudioTokenActive(
|
||||
ProjectAudioIO::Get( project ).GetAudioIOToken());
|
||||
};
|
||||
|
||||
bool TimeSelectedPred( const AudacityProject &project )
|
||||
{
|
||||
// This is equivalent to check if there is a valid selection,
|
||||
// so it's used for Zoom to Selection too
|
||||
return !ViewInfo::Get( project ).selectedRegion.isPoint();
|
||||
};
|
||||
|
||||
const CommandFlagOptions cutCopyOptions{
|
||||
// In reporting the issue with cut or copy, we don't tell the user they could also select some text in a label.
|
||||
[]( const wxString &Name ) {
|
||||
// PRL: These strings have hard-coded mention of a certain shortcut key,
|
||||
// thus assuming the default shortcuts. That is questionable.
|
||||
wxString format;
|
||||
#ifdef EXPERIMENTAL_DA
|
||||
// i18n-hint: %s will be replaced by the name of an action, such as Normalize, Cut, Fade.
|
||||
format = _("You must first select some audio for '%s' to act on.\n\nCtrl + A selects all audio.");
|
||||
#else
|
||||
#ifdef __WXMAC__
|
||||
// i18n-hint: %s will be replaced by the name of an action, such as Normalize, Cut, Fade.
|
||||
format = _("Select the audio for %s to use (for example, Cmd + A to Select All) then try again."
|
||||
// No need to explain what a help button is for.
|
||||
// "\n\nClick the Help button to learn more about selection methods."
|
||||
);
|
||||
|
||||
#else
|
||||
// i18n-hint: %s will be replaced by the name of an action, such as Normalize, Cut, Fade.
|
||||
format = _("Select the audio for %s to use (for example, Ctrl + A to Select All) then try again."
|
||||
// No need to explain what a help button is for.
|
||||
// "\n\nClick the Help button to learn more about selection methods."
|
||||
);
|
||||
#endif
|
||||
return wxString::Format( format, Name );
|
||||
#endif
|
||||
},
|
||||
"Selecting_Audio_-_the_basics",
|
||||
XO("No Audio Selected")
|
||||
};
|
||||
|
||||
const ReservedCommandFlag
|
||||
// The sequence of these definitions has a minor significance in determining
|
||||
// which user error message has precedence if more than one might apply, so
|
||||
// they should be kept in this sequence in one .cpp file if it is important
|
||||
// to preserve that behavior. If they are dispersed to more than one file,
|
||||
// then the precedence will be unspecified.
|
||||
// The ordering of the flags that only disable the default message is not
|
||||
// significant.
|
||||
AudioIONotBusyFlag{
|
||||
[](const AudacityProject &project ){
|
||||
return !AudioIOBusyPred( project );
|
||||
},
|
||||
CommandFlagOptions{ []( const wxString& ) { return
|
||||
// This reason will not be shown, because options that require it will be greyed out.
|
||||
_("You can only do this when playing and recording are\nstopped. (Pausing is not sufficient.)");
|
||||
} }
|
||||
.QuickTest()
|
||||
.Priority( 1 )
|
||||
}, //lll
|
||||
StereoRequiredFlag{
|
||||
[](const AudacityProject &project){
|
||||
// True iff at least one stereo track is selected, i.e., at least
|
||||
// one right channel is selected.
|
||||
// TODO: more-than-two-channels
|
||||
auto range = TrackList::Get( project ).Selected<const WaveTrack>()
|
||||
- &Track::IsLeader;
|
||||
return !range.empty();
|
||||
},
|
||||
{ []( const wxString& ) { return
|
||||
// This reason will not be shown, because the stereo-to-mono is greyed out if not allowed.
|
||||
_("You must first select some stereo audio to perform this\naction. (You cannot use this with mono.)");
|
||||
} }
|
||||
}, //lda
|
||||
TimeSelectedFlag{
|
||||
TimeSelectedPred,
|
||||
cutCopyOptions
|
||||
},
|
||||
WaveTracksSelectedFlag{
|
||||
[](const AudacityProject &project){
|
||||
return !TrackList::Get( project ).Selected<const WaveTrack>().empty();
|
||||
},
|
||||
{ []( const wxString& ) { return
|
||||
_("You must first select some audio to perform this action.\n(Selecting other kinds of track won't work.)");
|
||||
} }
|
||||
},
|
||||
TracksExistFlag{
|
||||
[](const AudacityProject &project){
|
||||
return !TrackList::Get( project ).Any().empty();
|
||||
},
|
||||
CommandFlagOptions{}.DisableDefaultMessage()
|
||||
},
|
||||
TracksSelectedFlag{
|
||||
TracksSelectedPred,
|
||||
{ []( const wxString &Name ){ return wxString::Format(
|
||||
// i18n-hint: %s will be replaced by the name of an action, such as "Remove Tracks".
|
||||
_("\"%s\" requires one or more tracks to be selected."),
|
||||
Name
|
||||
); } }
|
||||
},
|
||||
TrackPanelHasFocus{
|
||||
[](const AudacityProject &project){
|
||||
for (auto w = wxWindow::FindFocus(); w; w = w->GetParent()) {
|
||||
if (dynamic_cast<const NonKeystrokeInterceptingWindow*>(w))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
CommandFlagOptions{}.DisableDefaultMessage()
|
||||
}; //lll
|
||||
|
||||
const ReservedCommandFlag
|
||||
AudioIOBusyFlag{
|
||||
AudioIOBusyPred,
|
||||
CommandFlagOptions{}.QuickTest()
|
||||
}, //lll
|
||||
CaptureNotBusyFlag{
|
||||
[](const AudacityProject &){
|
||||
auto gAudioIO = AudioIO::Get();
|
||||
return !(
|
||||
gAudioIO->IsBusy() &&
|
||||
gAudioIO->GetNumCaptureChannels() > 0
|
||||
);
|
||||
}
|
||||
},
|
||||
HasWaveDataFlag{
|
||||
[](const AudacityProject &project){
|
||||
auto range = TrackList::Get( project ).Any<const WaveTrack>()
|
||||
+ [](const WaveTrack *pTrack){
|
||||
return pTrack->GetEndTime() > pTrack->GetStartTime();
|
||||
};
|
||||
return !range.empty();
|
||||
}
|
||||
}; // jkc
|
||||
|
||||
const ReservedCommandFlag
|
||||
LabelTracksExistFlag{
|
||||
[](const AudacityProject &project){
|
||||
return !TrackList::Get( project ).Any<const LabelTrack>().empty();
|
||||
}
|
||||
},
|
||||
UnsavedChangesFlag{
|
||||
[](const AudacityProject &project){
|
||||
auto &undoManager = UndoManager::Get( project );
|
||||
return
|
||||
undoManager.UnsavedChanges()
|
||||
||
|
||||
!ProjectFileIO::Get( project ).IsProjectSaved()
|
||||
;
|
||||
}
|
||||
},
|
||||
HasLastEffectFlag{
|
||||
[](const AudacityProject &project){
|
||||
return !MenuManager::Get( project ).mLastEffect.empty();
|
||||
}
|
||||
},
|
||||
UndoAvailableFlag{
|
||||
[](const AudacityProject &project){
|
||||
return ProjectHistory::Get( project ).UndoAvailable();
|
||||
}
|
||||
},
|
||||
RedoAvailableFlag{
|
||||
[](const AudacityProject &project){
|
||||
return ProjectHistory::Get( project ).RedoAvailable();
|
||||
}
|
||||
},
|
||||
ZoomInAvailableFlag{
|
||||
[](const AudacityProject &project){
|
||||
return
|
||||
ViewInfo::Get( project ).ZoomInAvailable()
|
||||
&&
|
||||
!TrackList::Get( project ).Any().empty()
|
||||
;
|
||||
}
|
||||
},
|
||||
ZoomOutAvailableFlag{
|
||||
[](const AudacityProject &project){
|
||||
return
|
||||
ViewInfo::Get( project ).ZoomOutAvailable()
|
||||
&&
|
||||
!TrackList::Get( project ).Any().empty()
|
||||
;
|
||||
}
|
||||
},
|
||||
LabelsSelectedFlag{
|
||||
[](const AudacityProject &project){
|
||||
// At least one label track selected, having at least one label
|
||||
// completely within the time selection.
|
||||
const auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
|
||||
const auto &test = [&]( const LabelTrack *pTrack ){
|
||||
const auto &labels = pTrack->GetLabels();
|
||||
return std::any_of( labels.begin(), labels.end(),
|
||||
[&](const LabelStruct &label){
|
||||
return
|
||||
label.getT0() >= selectedRegion.t0()
|
||||
&&
|
||||
label.getT1() <= selectedRegion.t1()
|
||||
;
|
||||
}
|
||||
);
|
||||
};
|
||||
auto range = TrackList::Get( project ).Selected<const LabelTrack>()
|
||||
+ test;
|
||||
return !range.empty();
|
||||
}
|
||||
},
|
||||
PlayRegionLockedFlag{
|
||||
[](const AudacityProject &project){
|
||||
return ViewInfo::Get(project).playRegion.Locked();
|
||||
}
|
||||
}, //msmeyer
|
||||
PlayRegionNotLockedFlag{
|
||||
[](const AudacityProject &project){
|
||||
const auto &playRegion = ViewInfo::Get(project).playRegion;
|
||||
return !playRegion.Locked() && !playRegion.Empty();
|
||||
}
|
||||
}, //msmeyer
|
||||
WaveTracksExistFlag{
|
||||
[](const AudacityProject &project){
|
||||
return !TrackList::Get( project ).Any<const WaveTrack>().empty();
|
||||
}
|
||||
},
|
||||
NoteTracksExistFlag{
|
||||
[](const AudacityProject &project){
|
||||
return !TrackList::Get( project ).Any<const NoteTrack>().empty();
|
||||
}
|
||||
}, //gsw
|
||||
NoteTracksSelectedFlag{
|
||||
[](const AudacityProject &project){
|
||||
return !TrackList::Get( project ).Selected<const NoteTrack>().empty();
|
||||
}
|
||||
}, //gsw
|
||||
IsNotSyncLockedFlag{
|
||||
[](const AudacityProject &project){
|
||||
return !ProjectSettings::Get( project ).IsSyncLocked();
|
||||
}
|
||||
}, //awd
|
||||
IsSyncLockedFlag{
|
||||
[](const AudacityProject &project){
|
||||
return ProjectSettings::Get( project ).IsSyncLocked();
|
||||
}
|
||||
}, //awd
|
||||
NotMinimizedFlag{
|
||||
[](const AudacityProject &project){
|
||||
const wxWindow *focus = FindProjectFrame( &project );
|
||||
if (focus) {
|
||||
while (focus && focus->GetParent())
|
||||
focus = focus->GetParent();
|
||||
}
|
||||
return (focus &&
|
||||
!static_cast<const wxTopLevelWindow*>(focus)->IsIconized()
|
||||
);
|
||||
},
|
||||
CommandFlagOptions{}.QuickTest()
|
||||
}, // prl
|
||||
PausedFlag{
|
||||
[](const AudacityProject&){
|
||||
return AudioIOBase::Get()->IsPaused();
|
||||
},
|
||||
CommandFlagOptions{}.QuickTest()
|
||||
},
|
||||
PlayableTracksExistFlag{
|
||||
[](const AudacityProject &project){
|
||||
auto &tracks = TrackList::Get( project );
|
||||
return
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
!tracks.Any<const NoteTrack>().empty()
|
||||
||
|
||||
#endif
|
||||
!tracks.Any<const WaveTrack>().empty()
|
||||
;
|
||||
}
|
||||
},
|
||||
AudioTracksSelectedFlag{
|
||||
[](const AudacityProject &project){
|
||||
auto &tracks = TrackList::Get( project );
|
||||
return
|
||||
!tracks.Selected<const NoteTrack>().empty()
|
||||
// even if not EXPERIMENTAL_MIDI_OUT
|
||||
||
|
||||
tracks.Selected<const WaveTrack>().empty()
|
||||
;
|
||||
}
|
||||
},
|
||||
NoAutoSelect{
|
||||
[](const AudacityProject &){ return true; }
|
||||
} // jkc
|
||||
;
|
||||
|
||||
RegisteredMenuItemEnabler stopIfPaused{{
|
||||
PausedFlag,
|
||||
AudioIONotBusyFlag,
|
||||
[]( const AudacityProject &project ){
|
||||
return MenuManager::Get( project ).mStopIfWasPaused; },
|
||||
[]( AudacityProject &project, CommandFlag ){
|
||||
if ( MenuManager::Get( project ).mStopIfWasPaused )
|
||||
TransportActions::StopIfPaused( project );
|
||||
}
|
||||
}};
|
||||
|
||||
Reference in New Issue
Block a user