mirror of
https://github.com/cookiengineer/audacity
synced 2025-07-06 15:37:44 +02:00
Reduce dependencies of Menus, CommandManager, ToolManager...
... so that they and a few others will be in a small s.c.c. that breaks off the big one -- when the dependencies of Track and its subclasses on TrackPanel are severed.
This commit is contained in:
commit
d84ab5948d
@ -32,6 +32,7 @@ click from the menu into the actaul function to be called.
|
||||
#include "ShuttleGui.h"
|
||||
#include "Project.h"
|
||||
#include "commands/CommandManager.h"
|
||||
#include "CommonCommandFlags.h"
|
||||
|
||||
#if defined(__WXMSW__)
|
||||
#include <wx/init.h>
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <wx/toolbar.h>
|
||||
|
||||
#include "AudioIOBase.h"
|
||||
#include "CommonCommandFlags.h"
|
||||
#include "LabelTrack.h"
|
||||
#include "Menus.h"
|
||||
#include "ModuleManager.h"
|
||||
|
@ -62,6 +62,8 @@ src/CellularPanel.cpp
|
||||
src/CellularPanel.h
|
||||
src/Clipboard.cpp
|
||||
src/Clipboard.h
|
||||
src/CommonCommandFlags.cpp
|
||||
src/CommonCommandFlags.h
|
||||
src/CrashReport.cpp
|
||||
src/CrashReport.h
|
||||
src/ClassicThemeAsCeeCode.h
|
||||
|
@ -1216,9 +1216,9 @@
|
||||
5E135A3C229EDF2E0076E983 /* ProjectManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E135A3A229EDF2E0076E983 /* ProjectManager.cpp */; };
|
||||
5E135A45229EE4DE0076E983 /* ProjectFileIO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E135A43229EE4DE0076E983 /* ProjectFileIO.cpp */; };
|
||||
5E135A48229EE5530076E983 /* ProjectWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E135A46229EE5530076E983 /* ProjectWindow.cpp */; };
|
||||
5E135A5122A93DC60076E983 /* ProjectAudioManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E135A4F22A93DC60076E983 /* ProjectAudioManager.cpp */; };
|
||||
5E135A4B22A5F7560076E983 /* AudioIOBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E135A4922A5F7560076E983 /* AudioIOBase.cpp */; };
|
||||
5E135A4E22A62B7E0076E983 /* MeterPanelBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E135A4C22A62B7E0076E983 /* MeterPanelBase.cpp */; };
|
||||
5E135A5122A93DC60076E983 /* ProjectAudioManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E135A4F22A93DC60076E983 /* ProjectAudioManager.cpp */; };
|
||||
5E15123D1DB000C000702E29 /* UIHandle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E15123B1DB000C000702E29 /* UIHandle.cpp */; };
|
||||
5E15125A1DB000DC00702E29 /* LabelTrackControls.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E1512401DB000DC00702E29 /* LabelTrackControls.cpp */; };
|
||||
5E15125B1DB000DC00702E29 /* LabelTrackUI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E1512421DB000DC00702E29 /* LabelTrackUI.cpp */; };
|
||||
@ -1230,6 +1230,7 @@
|
||||
5E15126E1DB0010C00702E29 /* TrackControls.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E1512681DB0010C00702E29 /* TrackControls.cpp */; };
|
||||
5E15126F1DB0010C00702E29 /* TrackUI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E15126A1DB0010C00702E29 /* TrackUI.cpp */; };
|
||||
5E1512701DB0010C00702E29 /* TrackVRulerControls.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E15126B1DB0010C00702E29 /* TrackVRulerControls.cpp */; };
|
||||
5E15A9AF22B3F7710007CC43 /* CommonCommandFlags.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E15A9AD22B3F7710007CC43 /* CommonCommandFlags.cpp */; };
|
||||
5E16FF4D1FF9CE0B0085E1B8 /* LanguageNames.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5E16FF4C1FF9CE0B0085E1B8 /* LanguageNames.txt */; };
|
||||
5E17EF712298372D00B47301 /* EnvelopeEditor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E17EF6F2298372D00B47301 /* EnvelopeEditor.cpp */; };
|
||||
5E18CFF02291C31000E75250 /* ProjectFileIORegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E18CFEE2291C31000E75250 /* ProjectFileIORegistry.cpp */; };
|
||||
@ -3191,12 +3192,12 @@
|
||||
5E135A44229EE4DE0076E983 /* ProjectFileIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProjectFileIO.h; sourceTree = "<group>"; };
|
||||
5E135A46229EE5530076E983 /* ProjectWindow.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProjectWindow.cpp; sourceTree = "<group>"; };
|
||||
5E135A47229EE5530076E983 /* ProjectWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProjectWindow.h; sourceTree = "<group>"; };
|
||||
5E135A4F22A93DC60076E983 /* ProjectAudioManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProjectAudioManager.cpp; sourceTree = "<group>"; };
|
||||
5E135A5022A93DC60076E983 /* ProjectAudioManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProjectAudioManager.h; sourceTree = "<group>"; };
|
||||
5E135A4922A5F7560076E983 /* AudioIOBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AudioIOBase.cpp; sourceTree = "<group>"; };
|
||||
5E135A4A22A5F7560076E983 /* AudioIOBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioIOBase.h; sourceTree = "<group>"; };
|
||||
5E135A4C22A62B7E0076E983 /* MeterPanelBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MeterPanelBase.cpp; sourceTree = "<group>"; };
|
||||
5E135A4D22A62B7E0076E983 /* MeterPanelBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MeterPanelBase.h; sourceTree = "<group>"; };
|
||||
5E135A4F22A93DC60076E983 /* ProjectAudioManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProjectAudioManager.cpp; sourceTree = "<group>"; };
|
||||
5E135A5022A93DC60076E983 /* ProjectAudioManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProjectAudioManager.h; sourceTree = "<group>"; };
|
||||
5E1512381DB000C000702E29 /* HitTestResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HitTestResult.h; sourceTree = "<group>"; };
|
||||
5E1512391DB000C000702E29 /* RefreshCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RefreshCode.h; sourceTree = "<group>"; };
|
||||
5E15123A1DB000C000702E29 /* TrackPanelMouseEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackPanelMouseEvent.h; sourceTree = "<group>"; };
|
||||
@ -3219,6 +3220,8 @@
|
||||
5E15126A1DB0010C00702E29 /* TrackUI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TrackUI.cpp; sourceTree = "<group>"; };
|
||||
5E15126B1DB0010C00702E29 /* TrackVRulerControls.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TrackVRulerControls.cpp; sourceTree = "<group>"; };
|
||||
5E15126C1DB0010C00702E29 /* TrackVRulerControls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackVRulerControls.h; sourceTree = "<group>"; };
|
||||
5E15A9AD22B3F7710007CC43 /* CommonCommandFlags.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CommonCommandFlags.cpp; sourceTree = "<group>"; };
|
||||
5E15A9AE22B3F7710007CC43 /* CommonCommandFlags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommonCommandFlags.h; sourceTree = "<group>"; };
|
||||
5E16FF4C1FF9CE0B0085E1B8 /* LanguageNames.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = LanguageNames.txt; path = ../locale/LanguageNames.txt; sourceTree = "<group>"; };
|
||||
5E17EF6F2298372D00B47301 /* EnvelopeEditor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EnvelopeEditor.cpp; sourceTree = "<group>"; };
|
||||
5E17EF702298372D00B47301 /* EnvelopeEditor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EnvelopeEditor.h; sourceTree = "<group>"; };
|
||||
@ -4347,6 +4350,7 @@
|
||||
1790AFE809883BFD008A330A /* BlockFile.cpp */,
|
||||
5E0A1CDB20E95FF7001AAF8D /* CellularPanel.cpp */,
|
||||
5EFEAD9C22723E390077DFF6 /* Clipboard.cpp */,
|
||||
5E15A9AD22B3F7710007CC43 /* CommonCommandFlags.cpp */,
|
||||
5EFEADA122733DD30077DFF6 /* CrashReport.cpp */,
|
||||
1790AFF409883BFD008A330A /* CrossFade.cpp */,
|
||||
2849B4600A7444BE00ECF12D /* Dependencies.cpp */,
|
||||
@ -4464,6 +4468,7 @@
|
||||
5E0D233E21B468BF0057D7C3 /* ClientData.h */,
|
||||
5E6E060321BD98E700130DE0 /* ClientDataHelpers.h */,
|
||||
5EFEAD9D22723E390077DFF6 /* Clipboard.h */,
|
||||
5E15A9AE22B3F7710007CC43 /* CommonCommandFlags.h */,
|
||||
1790AFF009883BFD008A330A /* configtemplate.h */,
|
||||
5EFEADA222733DD30077DFF6 /* CrashReport.h */,
|
||||
1790AFF509883BFD008A330A /* CrossFade.h */,
|
||||
@ -8405,6 +8410,7 @@
|
||||
1790B18009883BFD008A330A /* BatchPrefs.cpp in Sources */,
|
||||
5E135A39229EDEBA0076E983 /* ProjectAudioIO.cpp in Sources */,
|
||||
1790B18109883BFD008A330A /* DirectoriesPrefs.cpp in Sources */,
|
||||
5E15A9AF22B3F7710007CC43 /* CommonCommandFlags.cpp in Sources */,
|
||||
1790B18309883BFD008A330A /* GUIPrefs.cpp in Sources */,
|
||||
1790B18409883BFD008A330A /* KeyConfigPrefs.cpp in Sources */,
|
||||
2806EF7A1B32532A00D1AB9A /* FileDialogPrivate.mm in Sources */,
|
||||
|
@ -749,6 +749,41 @@ bool MacroCommands::ApplyEffectCommand(
|
||||
return res;
|
||||
}
|
||||
|
||||
bool MacroCommands::HandleTextualCommand( CommandManager &commandManager,
|
||||
const CommandID & Str,
|
||||
const CommandContext & context, CommandFlag flags, bool alwaysEnabled)
|
||||
{
|
||||
switch ( commandManager.HandleTextualCommand(
|
||||
Str, context, flags, alwaysEnabled) ) {
|
||||
case CommandManager::CommandSuccess:
|
||||
return true;
|
||||
case CommandManager::CommandFailure:
|
||||
return false;
|
||||
case CommandManager::CommandNotFound:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Not one of the singleton commands.
|
||||
// We could/should try all the list-style commands.
|
||||
// instead we only try the effects.
|
||||
PluginManager & pm = PluginManager::Get();
|
||||
EffectManager & em = EffectManager::Get();
|
||||
const PluginDescriptor *plug = pm.GetFirstPlugin(PluginTypeEffect);
|
||||
while (plug)
|
||||
{
|
||||
if (em.GetCommandIdentifier(plug->GetID()) == Str)
|
||||
{
|
||||
return PluginActions::DoEffect(
|
||||
plug->GetID(), context,
|
||||
PluginActions::kConfigured);
|
||||
}
|
||||
plug = pm.GetNextPlugin(PluginTypeEffect);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroCommands::ApplyCommand( const wxString &friendlyCommand,
|
||||
const CommandID & command, const wxString & params,
|
||||
CommandContext const * pContext)
|
||||
@ -778,7 +813,8 @@ bool MacroCommands::ApplyCommand( const wxString &friendlyCommand,
|
||||
AudacityProject *project = GetActiveProject();
|
||||
auto &manager = CommandManager::Get( *project );
|
||||
if( pContext ){
|
||||
if( manager.HandleTextualCommand( command, *pContext, AlwaysEnabledFlag, AlwaysEnabledFlag ) )
|
||||
if( HandleTextualCommand(
|
||||
manager, command, *pContext, AlwaysEnabledFlag, true ) )
|
||||
return true;
|
||||
pContext->Status( wxString::Format(
|
||||
_("Your batch command of %s was not recognized."), friendlyCommand ));
|
||||
@ -787,7 +823,8 @@ bool MacroCommands::ApplyCommand( const wxString &friendlyCommand,
|
||||
else
|
||||
{
|
||||
const CommandContext context( *GetActiveProject() );
|
||||
if( manager.HandleTextualCommand( command, context, AlwaysEnabledFlag, AlwaysEnabledFlag ) )
|
||||
if( HandleTextualCommand(
|
||||
manager, command, context, AlwaysEnabledFlag, true ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -15,10 +15,12 @@
|
||||
#include <wx/defs.h>
|
||||
|
||||
#include "export/Export.h"
|
||||
#include "commands/CommandFlag.h"
|
||||
|
||||
class wxArrayString;
|
||||
class Effect;
|
||||
class CommandContext;
|
||||
class CommandManager;
|
||||
class AudacityProject;
|
||||
class wxArrayStringEx;
|
||||
|
||||
@ -57,6 +59,9 @@ class MacroCommands final {
|
||||
public:
|
||||
bool ApplyMacro( const MacroCommandsCatalog &catalog,
|
||||
const wxString & filename = {});
|
||||
static bool HandleTextualCommand( CommandManager &commandManager,
|
||||
const CommandID & Str,
|
||||
const CommandContext & context, CommandFlag flags, bool alwaysEnabled);
|
||||
bool ApplyCommand( const wxString &friendlyCommand,
|
||||
const CommandID & command, const wxString & params,
|
||||
CommandContext const * pContext=NULL );
|
||||
|
356
src/CommonCommandFlags.cpp
Normal file
356
src/CommonCommandFlags.cpp
Normal file
@ -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 );
|
||||
}
|
||||
}};
|
58
src/CommonCommandFlags.h
Normal file
58
src/CommonCommandFlags.h
Normal file
@ -0,0 +1,58 @@
|
||||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
CommonCommandFlags.cpp
|
||||
|
||||
Paul Licameli split from Menus.cpp
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef __AUDACITY_COMMON_COMMAND_FLAGS__
|
||||
#define __AUDACITY_COMMON_COMMAND_FLAGS__
|
||||
|
||||
#include "commands/CommandFlag.h"
|
||||
|
||||
bool TracksSelectedPred( const AudacityProject &project );
|
||||
bool AudioIOBusyPred( const AudacityProject &project );
|
||||
bool TimeSelectedPred( const AudacityProject &project );
|
||||
extern const CommandFlagOptions cutCopyOptions;
|
||||
|
||||
extern const ReservedCommandFlag
|
||||
AudioIONotBusyFlag,
|
||||
StereoRequiredFlag, //lda
|
||||
TimeSelectedFlag, // This is equivalent to check if there is a valid selection, so it's used for Zoom to Selection too
|
||||
WaveTracksSelectedFlag,
|
||||
TracksExistFlag,
|
||||
TracksSelectedFlag,
|
||||
TrackPanelHasFocus; //lll
|
||||
|
||||
extern const ReservedCommandFlag
|
||||
AudioIOBusyFlag, // lll
|
||||
CaptureNotBusyFlag,
|
||||
HasWaveDataFlag; // jkc
|
||||
|
||||
extern const ReservedCommandFlag
|
||||
LabelTracksExistFlag,
|
||||
UnsavedChangesFlag,
|
||||
HasLastEffectFlag,
|
||||
UndoAvailableFlag,
|
||||
RedoAvailableFlag,
|
||||
ZoomInAvailableFlag,
|
||||
ZoomOutAvailableFlag,
|
||||
LabelsSelectedFlag,
|
||||
PlayRegionLockedFlag, //msmeyer
|
||||
PlayRegionNotLockedFlag, //msmeyer
|
||||
WaveTracksExistFlag,
|
||||
NoteTracksExistFlag, //gsw
|
||||
NoteTracksSelectedFlag, //gsw
|
||||
IsNotSyncLockedFlag, //awd
|
||||
IsSyncLockedFlag, //awd
|
||||
NotMinimizedFlag, // prl
|
||||
PausedFlag, // jkc
|
||||
PlayableTracksExistFlag,
|
||||
AudioTracksSelectedFlag,
|
||||
NoAutoSelect // jkc
|
||||
;
|
||||
|
||||
#endif
|
@ -1012,7 +1012,7 @@ void LabelTrack::calculateFontHeight(wxDC & dc) const
|
||||
mFontHeight += CursorExtraHeight - (charLeading+charDescent);
|
||||
}
|
||||
|
||||
bool LabelTrack::IsTextSelected()
|
||||
bool LabelTrack::IsTextSelected() const
|
||||
{
|
||||
if (mSelIndex == -1)
|
||||
return false;
|
||||
|
@ -117,7 +117,7 @@ class AUDACITY_DLL_API LabelTrack final : public Track
|
||||
|
||||
bool IsGoodLabelFirstKey(const wxKeyEvent & evt);
|
||||
bool IsGoodLabelEditKey(const wxKeyEvent & evt);
|
||||
bool IsTextSelected();
|
||||
bool IsTextSelected() const;
|
||||
|
||||
void CreateCustomGlyphs();
|
||||
LabelTrack(const std::shared_ptr<DirManager> &projDirManager);
|
||||
@ -228,6 +228,7 @@ class AUDACITY_DLL_API LabelTrack final : public Track
|
||||
|
||||
int GetNumLabels() const;
|
||||
const LabelStruct *GetLabel(int index) const;
|
||||
const LabelArray &GetLabels() const { return mLabels; }
|
||||
|
||||
//This returns the index of the label we just added.
|
||||
int AddLabel(const SelectedRegion ®ion, const wxString &title = {},
|
||||
|
@ -133,6 +133,8 @@ audacity_SOURCES = \
|
||||
ClientDataHelpers.h \
|
||||
Clipboard.cpp \
|
||||
Clipboard.h \
|
||||
CommonCommandFlags.cpp \
|
||||
CommonCommandFlags.h \
|
||||
CrashReport.cpp \
|
||||
CrashReport.h \
|
||||
Dependencies.cpp \
|
||||
|
162
src/Makefile.in
162
src/Makefile.in
@ -297,41 +297,42 @@ am__audacity_SOURCES_DIST = BlockFile.cpp BlockFile.h DirManager.cpp \
|
||||
BatchCommands.h BatchProcessDialog.cpp BatchProcessDialog.h \
|
||||
Benchmark.cpp Benchmark.h CellularPanel.cpp CellularPanel.h \
|
||||
ClientData.h ClientDataHelpers.h Clipboard.cpp Clipboard.h \
|
||||
CrashReport.cpp CrashReport.h Dependencies.cpp Dependencies.h \
|
||||
DeviceChange.cpp DeviceChange.h DeviceManager.cpp \
|
||||
DeviceManager.h Diags.cpp Diags.h Envelope.cpp Envelope.h \
|
||||
EnvelopeEditor.cpp EnvelopeEditor.h Experimental.h FFmpeg.cpp \
|
||||
FFmpeg.h FFT.cpp FFT.h FileException.cpp FileException.h \
|
||||
FileIO.cpp FileIO.h FileNames.cpp FileNames.h float_cast.h \
|
||||
FreqWindow.cpp FreqWindow.h HelpText.cpp HelpText.h \
|
||||
HistoryWindow.cpp HistoryWindow.h HitTestResult.h \
|
||||
ImageManipulation.cpp ImageManipulation.h \
|
||||
InconsistencyException.cpp InconsistencyException.h \
|
||||
InterpolateAudio.cpp InterpolateAudio.h KeyboardCapture.cpp \
|
||||
KeyboardCapture.h LabelDialog.cpp LabelDialog.h LabelTrack.cpp \
|
||||
LabelTrack.h LangChoice.cpp LangChoice.h Languages.cpp \
|
||||
Languages.h Legacy.cpp Legacy.h Lyrics.cpp Lyrics.h \
|
||||
LyricsWindow.cpp LyricsWindow.h MacroMagic.h Matrix.cpp \
|
||||
Matrix.h MemoryX.h Menus.cpp Menus.h \
|
||||
MissingAliasFileDialog.cpp MissingAliasFileDialog.h Mix.cpp \
|
||||
Mix.h MixerBoard.cpp MixerBoard.h ModuleManager.cpp \
|
||||
ModuleManager.h NumberScale.h PitchName.cpp PitchName.h \
|
||||
PlatformCompatibility.cpp PlatformCompatibility.h \
|
||||
PluginManager.cpp PluginManager.h Printing.cpp Printing.h \
|
||||
Profiler.cpp Profiler.h Project.cpp Project.h \
|
||||
ProjectAudioIO.cpp ProjectAudioIO.h ProjectAudioManager.cpp \
|
||||
ProjectAudioManager.h ProjectFileIO.cpp ProjectFileIO.h \
|
||||
ProjectFileIORegistry.cpp ProjectFileIORegistry.h \
|
||||
ProjectFileManager.cpp ProjectFileManager.h ProjectFSCK.cpp \
|
||||
ProjectFSCK.h ProjectHistory.cpp ProjectHistory.h \
|
||||
ProjectManager.cpp ProjectManager.h \
|
||||
ProjectSelectionManager.cpp ProjectSelectionManager.h \
|
||||
ProjectSettings.cpp ProjectSettings.h ProjectWindow.cpp \
|
||||
ProjectWindow.h RealFFTf.cpp RealFFTf.h RealFFTf48x.cpp \
|
||||
RealFFTf48x.h RefreshCode.h Resample.cpp Resample.h \
|
||||
RevisionIdent.h RingBuffer.cpp RingBuffer.h Screenshot.cpp \
|
||||
Screenshot.h SelectedRegion.cpp SelectedRegion.h \
|
||||
SelectionState.cpp SelectionState.h Shuttle.cpp Shuttle.h \
|
||||
CommonCommandFlags.cpp CommonCommandFlags.h CrashReport.cpp \
|
||||
CrashReport.h Dependencies.cpp Dependencies.h DeviceChange.cpp \
|
||||
DeviceChange.h DeviceManager.cpp DeviceManager.h Diags.cpp \
|
||||
Diags.h Envelope.cpp Envelope.h EnvelopeEditor.cpp \
|
||||
EnvelopeEditor.h Experimental.h FFmpeg.cpp FFmpeg.h FFT.cpp \
|
||||
FFT.h FileException.cpp FileException.h FileIO.cpp FileIO.h \
|
||||
FileNames.cpp FileNames.h float_cast.h FreqWindow.cpp \
|
||||
FreqWindow.h HelpText.cpp HelpText.h HistoryWindow.cpp \
|
||||
HistoryWindow.h HitTestResult.h ImageManipulation.cpp \
|
||||
ImageManipulation.h InconsistencyException.cpp \
|
||||
InconsistencyException.h InterpolateAudio.cpp \
|
||||
InterpolateAudio.h KeyboardCapture.cpp KeyboardCapture.h \
|
||||
LabelDialog.cpp LabelDialog.h LabelTrack.cpp LabelTrack.h \
|
||||
LangChoice.cpp LangChoice.h Languages.cpp Languages.h \
|
||||
Legacy.cpp Legacy.h Lyrics.cpp Lyrics.h LyricsWindow.cpp \
|
||||
LyricsWindow.h MacroMagic.h Matrix.cpp Matrix.h MemoryX.h \
|
||||
Menus.cpp Menus.h MissingAliasFileDialog.cpp \
|
||||
MissingAliasFileDialog.h Mix.cpp Mix.h MixerBoard.cpp \
|
||||
MixerBoard.h ModuleManager.cpp ModuleManager.h NumberScale.h \
|
||||
PitchName.cpp PitchName.h PlatformCompatibility.cpp \
|
||||
PlatformCompatibility.h PluginManager.cpp PluginManager.h \
|
||||
Printing.cpp Printing.h Profiler.cpp Profiler.h Project.cpp \
|
||||
Project.h ProjectAudioIO.cpp ProjectAudioIO.h \
|
||||
ProjectAudioManager.cpp ProjectAudioManager.h \
|
||||
ProjectFileIO.cpp ProjectFileIO.h ProjectFileIORegistry.cpp \
|
||||
ProjectFileIORegistry.h ProjectFileManager.cpp \
|
||||
ProjectFileManager.h ProjectFSCK.cpp ProjectFSCK.h \
|
||||
ProjectHistory.cpp ProjectHistory.h ProjectManager.cpp \
|
||||
ProjectManager.h ProjectSelectionManager.cpp \
|
||||
ProjectSelectionManager.h ProjectSettings.cpp \
|
||||
ProjectSettings.h ProjectWindow.cpp ProjectWindow.h \
|
||||
RealFFTf.cpp RealFFTf.h RealFFTf48x.cpp RealFFTf48x.h \
|
||||
RefreshCode.h Resample.cpp Resample.h RevisionIdent.h \
|
||||
RingBuffer.cpp RingBuffer.h Screenshot.cpp Screenshot.h \
|
||||
SelectedRegion.cpp SelectedRegion.h SelectionState.cpp \
|
||||
SelectionState.h Shuttle.cpp Shuttle.h \
|
||||
ShuttleGetDefinition.cpp ShuttleGetDefinition.h ShuttleGui.cpp \
|
||||
ShuttleGui.h ShuttlePrefs.cpp ShuttlePrefs.h Snap.cpp Snap.h \
|
||||
SoundActivatedRecord.cpp SoundActivatedRecord.h Spectrum.cpp \
|
||||
@ -644,8 +645,9 @@ am_audacity_OBJECTS = $(am__objects_1) audacity-AboutDialog.$(OBJEXT) \
|
||||
audacity-BatchCommands.$(OBJEXT) \
|
||||
audacity-BatchProcessDialog.$(OBJEXT) \
|
||||
audacity-Benchmark.$(OBJEXT) audacity-CellularPanel.$(OBJEXT) \
|
||||
audacity-Clipboard.$(OBJEXT) audacity-CrashReport.$(OBJEXT) \
|
||||
audacity-Dependencies.$(OBJEXT) \
|
||||
audacity-Clipboard.$(OBJEXT) \
|
||||
audacity-CommonCommandFlags.$(OBJEXT) \
|
||||
audacity-CrashReport.$(OBJEXT) audacity-Dependencies.$(OBJEXT) \
|
||||
audacity-DeviceChange.$(OBJEXT) \
|
||||
audacity-DeviceManager.$(OBJEXT) audacity-Diags.$(OBJEXT) \
|
||||
audacity-Envelope.$(OBJEXT) audacity-EnvelopeEditor.$(OBJEXT) \
|
||||
@ -1376,41 +1378,42 @@ audacity_SOURCES = $(libaudacity_la_SOURCES) AboutDialog.cpp \
|
||||
BatchCommands.h BatchProcessDialog.cpp BatchProcessDialog.h \
|
||||
Benchmark.cpp Benchmark.h CellularPanel.cpp CellularPanel.h \
|
||||
ClientData.h ClientDataHelpers.h Clipboard.cpp Clipboard.h \
|
||||
CrashReport.cpp CrashReport.h Dependencies.cpp Dependencies.h \
|
||||
DeviceChange.cpp DeviceChange.h DeviceManager.cpp \
|
||||
DeviceManager.h Diags.cpp Diags.h Envelope.cpp Envelope.h \
|
||||
EnvelopeEditor.cpp EnvelopeEditor.h Experimental.h FFmpeg.cpp \
|
||||
FFmpeg.h FFT.cpp FFT.h FileException.cpp FileException.h \
|
||||
FileIO.cpp FileIO.h FileNames.cpp FileNames.h float_cast.h \
|
||||
FreqWindow.cpp FreqWindow.h HelpText.cpp HelpText.h \
|
||||
HistoryWindow.cpp HistoryWindow.h HitTestResult.h \
|
||||
ImageManipulation.cpp ImageManipulation.h \
|
||||
InconsistencyException.cpp InconsistencyException.h \
|
||||
InterpolateAudio.cpp InterpolateAudio.h KeyboardCapture.cpp \
|
||||
KeyboardCapture.h LabelDialog.cpp LabelDialog.h LabelTrack.cpp \
|
||||
LabelTrack.h LangChoice.cpp LangChoice.h Languages.cpp \
|
||||
Languages.h Legacy.cpp Legacy.h Lyrics.cpp Lyrics.h \
|
||||
LyricsWindow.cpp LyricsWindow.h MacroMagic.h Matrix.cpp \
|
||||
Matrix.h MemoryX.h Menus.cpp Menus.h \
|
||||
MissingAliasFileDialog.cpp MissingAliasFileDialog.h Mix.cpp \
|
||||
Mix.h MixerBoard.cpp MixerBoard.h ModuleManager.cpp \
|
||||
ModuleManager.h NumberScale.h PitchName.cpp PitchName.h \
|
||||
PlatformCompatibility.cpp PlatformCompatibility.h \
|
||||
PluginManager.cpp PluginManager.h Printing.cpp Printing.h \
|
||||
Profiler.cpp Profiler.h Project.cpp Project.h \
|
||||
ProjectAudioIO.cpp ProjectAudioIO.h ProjectAudioManager.cpp \
|
||||
ProjectAudioManager.h ProjectFileIO.cpp ProjectFileIO.h \
|
||||
ProjectFileIORegistry.cpp ProjectFileIORegistry.h \
|
||||
ProjectFileManager.cpp ProjectFileManager.h ProjectFSCK.cpp \
|
||||
ProjectFSCK.h ProjectHistory.cpp ProjectHistory.h \
|
||||
ProjectManager.cpp ProjectManager.h \
|
||||
ProjectSelectionManager.cpp ProjectSelectionManager.h \
|
||||
ProjectSettings.cpp ProjectSettings.h ProjectWindow.cpp \
|
||||
ProjectWindow.h RealFFTf.cpp RealFFTf.h RealFFTf48x.cpp \
|
||||
RealFFTf48x.h RefreshCode.h Resample.cpp Resample.h \
|
||||
RevisionIdent.h RingBuffer.cpp RingBuffer.h Screenshot.cpp \
|
||||
Screenshot.h SelectedRegion.cpp SelectedRegion.h \
|
||||
SelectionState.cpp SelectionState.h Shuttle.cpp Shuttle.h \
|
||||
CommonCommandFlags.cpp CommonCommandFlags.h CrashReport.cpp \
|
||||
CrashReport.h Dependencies.cpp Dependencies.h DeviceChange.cpp \
|
||||
DeviceChange.h DeviceManager.cpp DeviceManager.h Diags.cpp \
|
||||
Diags.h Envelope.cpp Envelope.h EnvelopeEditor.cpp \
|
||||
EnvelopeEditor.h Experimental.h FFmpeg.cpp FFmpeg.h FFT.cpp \
|
||||
FFT.h FileException.cpp FileException.h FileIO.cpp FileIO.h \
|
||||
FileNames.cpp FileNames.h float_cast.h FreqWindow.cpp \
|
||||
FreqWindow.h HelpText.cpp HelpText.h HistoryWindow.cpp \
|
||||
HistoryWindow.h HitTestResult.h ImageManipulation.cpp \
|
||||
ImageManipulation.h InconsistencyException.cpp \
|
||||
InconsistencyException.h InterpolateAudio.cpp \
|
||||
InterpolateAudio.h KeyboardCapture.cpp KeyboardCapture.h \
|
||||
LabelDialog.cpp LabelDialog.h LabelTrack.cpp LabelTrack.h \
|
||||
LangChoice.cpp LangChoice.h Languages.cpp Languages.h \
|
||||
Legacy.cpp Legacy.h Lyrics.cpp Lyrics.h LyricsWindow.cpp \
|
||||
LyricsWindow.h MacroMagic.h Matrix.cpp Matrix.h MemoryX.h \
|
||||
Menus.cpp Menus.h MissingAliasFileDialog.cpp \
|
||||
MissingAliasFileDialog.h Mix.cpp Mix.h MixerBoard.cpp \
|
||||
MixerBoard.h ModuleManager.cpp ModuleManager.h NumberScale.h \
|
||||
PitchName.cpp PitchName.h PlatformCompatibility.cpp \
|
||||
PlatformCompatibility.h PluginManager.cpp PluginManager.h \
|
||||
Printing.cpp Printing.h Profiler.cpp Profiler.h Project.cpp \
|
||||
Project.h ProjectAudioIO.cpp ProjectAudioIO.h \
|
||||
ProjectAudioManager.cpp ProjectAudioManager.h \
|
||||
ProjectFileIO.cpp ProjectFileIO.h ProjectFileIORegistry.cpp \
|
||||
ProjectFileIORegistry.h ProjectFileManager.cpp \
|
||||
ProjectFileManager.h ProjectFSCK.cpp ProjectFSCK.h \
|
||||
ProjectHistory.cpp ProjectHistory.h ProjectManager.cpp \
|
||||
ProjectManager.h ProjectSelectionManager.cpp \
|
||||
ProjectSelectionManager.h ProjectSettings.cpp \
|
||||
ProjectSettings.h ProjectWindow.cpp ProjectWindow.h \
|
||||
RealFFTf.cpp RealFFTf.h RealFFTf48x.cpp RealFFTf48x.h \
|
||||
RefreshCode.h Resample.cpp Resample.h RevisionIdent.h \
|
||||
RingBuffer.cpp RingBuffer.h Screenshot.cpp Screenshot.h \
|
||||
SelectedRegion.cpp SelectedRegion.h SelectionState.cpp \
|
||||
SelectionState.h Shuttle.cpp Shuttle.h \
|
||||
ShuttleGetDefinition.cpp ShuttleGetDefinition.h ShuttleGui.cpp \
|
||||
ShuttleGui.h ShuttlePrefs.cpp ShuttlePrefs.h Snap.cpp Snap.h \
|
||||
SoundActivatedRecord.cpp SoundActivatedRecord.h Spectrum.cpp \
|
||||
@ -2539,6 +2542,7 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-BlockFile.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-CellularPanel.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-Clipboard.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-CommonCommandFlags.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-CrashReport.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-Dependencies.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/audacity-DeviceChange.Po@am__quote@
|
||||
@ -3506,6 +3510,20 @@ audacity-Clipboard.obj: Clipboard.cpp
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o audacity-Clipboard.obj `if test -f 'Clipboard.cpp'; then $(CYGPATH_W) 'Clipboard.cpp'; else $(CYGPATH_W) '$(srcdir)/Clipboard.cpp'; fi`
|
||||
|
||||
audacity-CommonCommandFlags.o: CommonCommandFlags.cpp
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT audacity-CommonCommandFlags.o -MD -MP -MF $(DEPDIR)/audacity-CommonCommandFlags.Tpo -c -o audacity-CommonCommandFlags.o `test -f 'CommonCommandFlags.cpp' || echo '$(srcdir)/'`CommonCommandFlags.cpp
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/audacity-CommonCommandFlags.Tpo $(DEPDIR)/audacity-CommonCommandFlags.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CommonCommandFlags.cpp' object='audacity-CommonCommandFlags.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o audacity-CommonCommandFlags.o `test -f 'CommonCommandFlags.cpp' || echo '$(srcdir)/'`CommonCommandFlags.cpp
|
||||
|
||||
audacity-CommonCommandFlags.obj: CommonCommandFlags.cpp
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT audacity-CommonCommandFlags.obj -MD -MP -MF $(DEPDIR)/audacity-CommonCommandFlags.Tpo -c -o audacity-CommonCommandFlags.obj `if test -f 'CommonCommandFlags.cpp'; then $(CYGPATH_W) 'CommonCommandFlags.cpp'; else $(CYGPATH_W) '$(srcdir)/CommonCommandFlags.cpp'; fi`
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/audacity-CommonCommandFlags.Tpo $(DEPDIR)/audacity-CommonCommandFlags.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='CommonCommandFlags.cpp' object='audacity-CommonCommandFlags.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -c -o audacity-CommonCommandFlags.obj `if test -f 'CommonCommandFlags.cpp'; then $(CYGPATH_W) 'CommonCommandFlags.cpp'; else $(CYGPATH_W) '$(srcdir)/CommonCommandFlags.cpp'; fi`
|
||||
|
||||
audacity-CrashReport.o: CrashReport.cpp
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(audacity_CPPFLAGS) $(CPPFLAGS) $(audacity_CXXFLAGS) $(CXXFLAGS) -MT audacity-CrashReport.o -MD -MP -MF $(DEPDIR)/audacity-CrashReport.Tpo -c -o audacity-CrashReport.o `test -f 'CrashReport.cpp' || echo '$(srcdir)/'`CrashReport.cpp
|
||||
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/audacity-CrashReport.Tpo $(DEPDIR)/audacity-CrashReport.Po
|
||||
|
490
src/Menus.cpp
490
src/Menus.cpp
@ -30,30 +30,17 @@
|
||||
|
||||
#include "Experimental.h"
|
||||
|
||||
#include "AdornedRulerPanel.h"
|
||||
#include "AudioIO.h"
|
||||
#include "Clipboard.h"
|
||||
#include "LabelTrack.h"
|
||||
#include <wx/frame.h>
|
||||
|
||||
#include "ModuleManager.h"
|
||||
#ifdef USE_MIDI
|
||||
#include "NoteTrack.h"
|
||||
#endif // USE_MIDI
|
||||
#include "Prefs.h"
|
||||
#include "Project.h"
|
||||
#include "ProjectAudioIO.h"
|
||||
#include "ProjectFileIO.h"
|
||||
#include "ProjectHistory.h"
|
||||
#include "ProjectSettings.h"
|
||||
#include "ProjectWindow.h"
|
||||
#include "UndoManager.h"
|
||||
#include "ViewInfo.h"
|
||||
#include "commands/CommandManager.h"
|
||||
#include "commands/CommandManagerWindowClasses.h"
|
||||
#include "effects/EffectManager.h"
|
||||
#include "prefs/TracksPrefs.h"
|
||||
#include "toolbars/ControlToolBar.h"
|
||||
#include "toolbars/ToolManager.h"
|
||||
#include "widgets/FileHistory.h"
|
||||
#include "widgets/ErrorDialog.h"
|
||||
|
||||
#include <wx/menu.h>
|
||||
#include <wx/windowptr.h>
|
||||
@ -364,6 +351,13 @@ void MenuManager::ModifyUndoMenuItems(AudacityProject &project)
|
||||
}
|
||||
}
|
||||
|
||||
// Get hackcess to a protected method
|
||||
class wxFrameEx : public wxFrame
|
||||
{
|
||||
public:
|
||||
using wxFrame::DetachMenuBar;
|
||||
};
|
||||
|
||||
void MenuCreator::RebuildMenuBar(AudacityProject &project)
|
||||
{
|
||||
// On OSX, we can't rebuild the menus while a modal dialog is being shown
|
||||
@ -380,7 +374,7 @@ void MenuCreator::RebuildMenuBar(AudacityProject &project)
|
||||
// Delete the menus, since we will soon recreate them.
|
||||
// Rather oddly, the menus don't vanish as a result of doing this.
|
||||
{
|
||||
auto &window = ProjectWindow::Get( project );
|
||||
auto &window = static_cast<wxFrameEx&>( GetProjectFrame( project ) );
|
||||
wxWindowPtr<wxMenuBar> menuBar{ window.GetMenuBar() };
|
||||
window.DetachMenuBar();
|
||||
// menuBar gets deleted here
|
||||
@ -400,205 +394,66 @@ void MenuManager::OnUndoRedo( wxCommandEvent &evt )
|
||||
UpdateMenus();
|
||||
}
|
||||
|
||||
CommandFlag MenuManager::GetFocusedFrame(AudacityProject &project)
|
||||
{
|
||||
wxWindow *w = wxWindow::FindFocus();
|
||||
|
||||
while (w) {
|
||||
if (w == ToolManager::Get( project ).GetTopDock()) {
|
||||
return TopDockHasFocus;
|
||||
}
|
||||
|
||||
if (w == &AdornedRulerPanel::Get( project ))
|
||||
return RulerHasFocus;
|
||||
|
||||
if (dynamic_cast<NonKeystrokeInterceptingWindow*>(w)) {
|
||||
return TrackPanelHasFocus;
|
||||
}
|
||||
if (w == ToolManager::Get( project ).GetBotDock()) {
|
||||
return BotDockHasFocus;
|
||||
}
|
||||
|
||||
w = w->GetParent();
|
||||
namespace{
|
||||
using Predicates = std::vector< ReservedCommandFlag::Predicate >;
|
||||
Predicates &RegisteredPredicates()
|
||||
{
|
||||
static Predicates thePredicates;
|
||||
return thePredicates;
|
||||
}
|
||||
std::vector< CommandFlagOptions > &Options()
|
||||
{
|
||||
static std::vector< CommandFlagOptions > options;
|
||||
return options;
|
||||
}
|
||||
|
||||
return AlwaysEnabledFlag;
|
||||
}
|
||||
|
||||
ReservedCommandFlag::ReservedCommandFlag(
|
||||
const Predicate &predicate, const CommandFlagOptions &options )
|
||||
{
|
||||
static size_t sNextReservedFlag = 0;
|
||||
// This will throw std::out_of_range if the constant NCommandFlags is too
|
||||
// small
|
||||
set( sNextReservedFlag++ );
|
||||
RegisteredPredicates().emplace_back( predicate );
|
||||
Options().emplace_back( options );
|
||||
}
|
||||
|
||||
CommandFlag MenuManager::GetUpdateFlags( bool checkActive )
|
||||
{
|
||||
auto &project = mProject;
|
||||
|
||||
// This method determines all of the flags that determine whether
|
||||
// certain menu items and commands should be enabled or disabled,
|
||||
// and returns them in a bitfield. Note that if none of the flags
|
||||
// have changed, it's not necessary to even check for updates.
|
||||
auto flags = AlwaysEnabledFlag;
|
||||
|
||||
// static variable, used to remember flags for next time.
|
||||
static auto lastFlags = flags;
|
||||
static CommandFlag lastFlags;
|
||||
|
||||
// if (auto focus = wxWindow::FindFocus()) {
|
||||
auto &window = GetProjectFrame( project );
|
||||
if (wxWindow * focus = &window) {
|
||||
while (focus && focus->GetParent())
|
||||
focus = focus->GetParent();
|
||||
if (focus && !static_cast<wxTopLevelWindow*>(focus)->IsIconized())
|
||||
flags |= NotMinimizedFlag;
|
||||
CommandFlag flags, quickFlags;
|
||||
|
||||
const auto &options = Options();
|
||||
size_t ii = 0;
|
||||
for ( const auto &predicate : RegisteredPredicates() ) {
|
||||
if ( options[ii].quickTest ) {
|
||||
quickFlags[ii] = true;
|
||||
if( predicate( mProject ) )
|
||||
flags[ii] = true;
|
||||
}
|
||||
++ii;
|
||||
}
|
||||
|
||||
// These flags are cheap to calculate.
|
||||
auto gAudioIO = AudioIO::Get();
|
||||
if (!gAudioIO->IsAudioTokenActive(ProjectAudioIO::Get( project )
|
||||
.GetAudioIOToken()))
|
||||
flags |= AudioIONotBusyFlag;
|
||||
else
|
||||
flags |= AudioIOBusyFlag;
|
||||
|
||||
if( gAudioIO->IsPaused() )
|
||||
flags |= PausedFlag;
|
||||
else
|
||||
flags |= NotPausedFlag;
|
||||
|
||||
// quick 'short-circuit' return.
|
||||
if ( checkActive && !window.IsActive() ){
|
||||
const auto checkedFlags =
|
||||
NotMinimizedFlag | AudioIONotBusyFlag | AudioIOBusyFlag |
|
||||
PausedFlag | NotPausedFlag;
|
||||
// short cirucit return should preserve flags that have not been calculated.
|
||||
flags = (lastFlags & ~checkedFlags) | flags;
|
||||
lastFlags = flags;
|
||||
return flags;
|
||||
}
|
||||
|
||||
auto &viewInfo = ViewInfo::Get( project );
|
||||
const auto &selectedRegion = viewInfo.selectedRegion;
|
||||
|
||||
if (!selectedRegion.isPoint())
|
||||
flags |= TimeSelectedFlag;
|
||||
|
||||
auto &tracks = TrackList::Get( project );
|
||||
auto trackRange = tracks.Any();
|
||||
if ( trackRange )
|
||||
flags |= TracksExistFlag;
|
||||
trackRange.Visit(
|
||||
[&](LabelTrack *lt) {
|
||||
flags |= LabelTracksExistFlag;
|
||||
|
||||
if (lt->GetSelected()) {
|
||||
flags |= TracksSelectedFlag;
|
||||
for (int i = 0; i < lt->GetNumLabels(); i++) {
|
||||
const LabelStruct *ls = lt->GetLabel(i);
|
||||
if (ls->getT0() >= selectedRegion.t0() &&
|
||||
ls->getT1() <= selectedRegion.t1()) {
|
||||
flags |= LabelsSelectedFlag;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lt->IsTextSelected()) {
|
||||
flags |= CutCopyAvailableFlag;
|
||||
}
|
||||
},
|
||||
[&](WaveTrack *t) {
|
||||
flags |= WaveTracksExistFlag;
|
||||
flags |= PlayableTracksExistFlag;
|
||||
if (t->GetSelected()) {
|
||||
flags |= TracksSelectedFlag;
|
||||
// TODO: more-than-two-channels
|
||||
if (TrackList::Channels(t).size() > 1) {
|
||||
flags |= StereoRequiredFlag;
|
||||
}
|
||||
flags |= WaveTracksSelectedFlag;
|
||||
flags |= AudioTracksSelectedFlag;
|
||||
}
|
||||
if( t->GetEndTime() > t->GetStartTime() )
|
||||
flags |= HasWaveDataFlag;
|
||||
}
|
||||
#if defined(USE_MIDI)
|
||||
,
|
||||
[&](NoteTrack *nt) {
|
||||
flags |= NoteTracksExistFlag;
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
flags |= PlayableTracksExistFlag;
|
||||
#endif
|
||||
|
||||
if (nt->GetSelected()) {
|
||||
flags |= TracksSelectedFlag;
|
||||
flags |= NoteTracksSelectedFlag;
|
||||
flags |= AudioTracksSelectedFlag; // even if not EXPERIMENTAL_MIDI_OUT
|
||||
}
|
||||
}
|
||||
#endif
|
||||
);
|
||||
|
||||
if( Clipboard::Get().Duration() > 0 )
|
||||
flags |= ClipboardFlag;
|
||||
|
||||
auto &undoManager = UndoManager::Get( project );
|
||||
|
||||
if (undoManager.UnsavedChanges() ||
|
||||
!ProjectFileIO::Get( project ).IsProjectSaved())
|
||||
flags |= UnsavedChangesFlag;
|
||||
|
||||
if (!mLastEffect.empty())
|
||||
flags |= HasLastEffectFlag;
|
||||
|
||||
auto &history = ProjectHistory::Get( project );
|
||||
if (history.UndoAvailable())
|
||||
flags |= UndoAvailableFlag;
|
||||
|
||||
if (history.RedoAvailable())
|
||||
flags |= RedoAvailableFlag;
|
||||
|
||||
if (ViewInfo::Get( project ).ZoomInAvailable() && (flags & TracksExistFlag))
|
||||
flags |= ZoomInAvailableFlag;
|
||||
|
||||
if (ViewInfo::Get( project ).ZoomOutAvailable() && (flags & TracksExistFlag))
|
||||
flags |= ZoomOutAvailableFlag;
|
||||
|
||||
// TextClipFlag is currently unused (Jan 2017, 2.1.3 alpha)
|
||||
// and LabelTrack::IsTextClipSupported() is quite slow on Linux,
|
||||
// so disable for now (See bug 1575).
|
||||
// if ((flags & LabelTracksExistFlag) && LabelTrack::IsTextClipSupported())
|
||||
// flags |= TextClipFlag;
|
||||
|
||||
flags |= GetFocusedFrame(project);
|
||||
|
||||
const auto &playRegion = viewInfo.playRegion;
|
||||
if (playRegion.Locked())
|
||||
flags |= PlayRegionLockedFlag;
|
||||
else if (!playRegion.Empty())
|
||||
flags |= PlayRegionNotLockedFlag;
|
||||
|
||||
if (flags & AudioIONotBusyFlag) {
|
||||
if (flags & TimeSelectedFlag) {
|
||||
if (flags & TracksSelectedFlag) {
|
||||
flags |= CutCopyAvailableFlag;
|
||||
}
|
||||
if ( checkActive && !GetProjectFrame( mProject ).IsActive() )
|
||||
// quick 'short-circuit' return.
|
||||
flags = (lastFlags & ~quickFlags) | flags;
|
||||
else {
|
||||
ii = 0;
|
||||
for ( const auto &predicate : RegisteredPredicates() ) {
|
||||
if ( !options[ii].quickTest && predicate( mProject ) )
|
||||
flags[ii] = true;
|
||||
++ii;
|
||||
}
|
||||
}
|
||||
|
||||
if (FileHistory::Global().GetCount() > 0)
|
||||
flags |= HaveRecentFiles;
|
||||
|
||||
const auto &settings = ProjectSettings::Get( project );
|
||||
if (settings.IsSyncLocked())
|
||||
flags |= IsSyncLockedFlag;
|
||||
else
|
||||
flags |= IsNotSyncLockedFlag;
|
||||
|
||||
if (!EffectManager::Get().RealtimeIsActive())
|
||||
flags |= IsRealtimeNotActiveFlag;
|
||||
|
||||
if ( !( gAudioIO->IsBusy() && gAudioIO->GetNumCaptureChannels() > 0 ) )
|
||||
flags |= CaptureNotBusyFlag;
|
||||
|
||||
auto &bar = ControlToolBar::Get( project );
|
||||
if (bar.ControlToolBar::CanStopAudioStream())
|
||||
flags |= CanStopAudioStreamFlag;
|
||||
|
||||
lastFlags = flags;
|
||||
return flags;
|
||||
}
|
||||
@ -685,6 +540,22 @@ void MenuManager::ModifyToolbarMenus(AudacityProject &project)
|
||||
commandManager.Check(wxT("TypeToCreateLabel"), active);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
using MenuItemEnablers = std::vector<MenuItemEnabler>;
|
||||
MenuItemEnablers &Enablers()
|
||||
{
|
||||
static MenuItemEnablers enablers;
|
||||
return enablers;
|
||||
}
|
||||
}
|
||||
|
||||
RegisteredMenuItemEnabler::RegisteredMenuItemEnabler(
|
||||
const MenuItemEnabler &enabler )
|
||||
{
|
||||
Enablers().emplace_back( enabler );
|
||||
}
|
||||
|
||||
// checkActive is a temporary hack that should be removed as soon as we
|
||||
// get multiple effect preview working
|
||||
void MenuManager::UpdateMenus( bool checkActive )
|
||||
@ -698,6 +569,12 @@ void MenuManager::UpdateMenus( bool checkActive )
|
||||
return;
|
||||
|
||||
auto flags = GetUpdateFlags(checkActive);
|
||||
// Return from this function if nothing's changed since
|
||||
// the last time we were here.
|
||||
if (flags == mLastFlags)
|
||||
return;
|
||||
mLastFlags = flags;
|
||||
|
||||
auto flags2 = flags;
|
||||
|
||||
// We can enable some extra items if we have select-all-on-none.
|
||||
@ -705,68 +582,24 @@ void MenuManager::UpdateMenus( bool checkActive )
|
||||
//ANSWER: Because flags2 is used in the menu enable/disable.
|
||||
//The effect still needs flags to determine whether it will need
|
||||
//to actually do the 'select all' to make the command valid.
|
||||
if (mWhatIfNoSelection != 0)
|
||||
{
|
||||
if ((flags & TracksExistFlag))
|
||||
{
|
||||
flags2 |= TracksSelectedFlag;
|
||||
if ((flags & WaveTracksExistFlag))
|
||||
{
|
||||
flags2 |= TimeSelectedFlag
|
||||
| WaveTracksSelectedFlag
|
||||
| CutCopyAvailableFlag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( mStopIfWasPaused )
|
||||
{
|
||||
if( flags & PausedFlag ){
|
||||
flags2 |= AudioIONotBusyFlag;
|
||||
}
|
||||
for ( const auto &enabler : Enablers() ) {
|
||||
if (
|
||||
enabler.applicable( project ) &&
|
||||
(flags & enabler.actualFlags) == enabler.actualFlags
|
||||
)
|
||||
flags2 |= enabler.possibleFlags;
|
||||
}
|
||||
|
||||
// Return from this function if nothing's changed since
|
||||
// the last time we were here.
|
||||
if (flags == mLastFlags)
|
||||
return;
|
||||
mLastFlags = flags;
|
||||
|
||||
auto &commandManager = CommandManager::Get( project );
|
||||
|
||||
commandManager.EnableUsingFlags(flags2 , NoFlagsSpecified);
|
||||
|
||||
// With select-all-on-none, some items that we don't want enabled may have
|
||||
// been enabled, since we changed the flags. Here we manually disable them.
|
||||
// 0 is grey out, 1 is Autoselect, 2 is Give warnings.
|
||||
if (mWhatIfNoSelection != 0)
|
||||
{
|
||||
if (!(flags & TimeSelectedFlag) | !(flags & TracksSelectedFlag))
|
||||
{
|
||||
commandManager.Enable(wxT("SplitCut"), false);
|
||||
commandManager.Enable(wxT("SplitDelete"), false);
|
||||
}
|
||||
if (!(flags & WaveTracksSelectedFlag))
|
||||
{
|
||||
commandManager.Enable(wxT("Split"), false);
|
||||
}
|
||||
if (!(flags & TimeSelectedFlag) | !(flags & WaveTracksSelectedFlag))
|
||||
{
|
||||
commandManager.Enable(wxT("ExportSel"), false);
|
||||
commandManager.Enable(wxT("SplitNew"), false);
|
||||
}
|
||||
if (!(flags & TimeSelectedFlag) | !(flags & AudioTracksSelectedFlag))
|
||||
{
|
||||
commandManager.Enable(wxT("Trim"), false);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (flags & CutCopyAvailableFlag) {
|
||||
GetCommandManager()->Enable(wxT("Copy"), true);
|
||||
GetCommandManager()->Enable(wxT("Cut"), true);
|
||||
}
|
||||
#endif
|
||||
commandManager.EnableUsingFlags(
|
||||
flags2, // the "lax" flags
|
||||
(mWhatIfNoSelection == 0 ? flags2 : flags) // the "strict" flags
|
||||
);
|
||||
|
||||
MenuManager::ModifyToolbarMenus(project);
|
||||
}
|
||||
@ -794,74 +627,123 @@ void MenuCreator::RebuildAllMenuBars()
|
||||
}
|
||||
|
||||
bool MenuManager::ReportIfActionNotAllowed(
|
||||
const wxString & Name, CommandFlag & flags, CommandFlag flagsRqd, CommandFlag mask )
|
||||
const wxString & Name, CommandFlag & flags, CommandFlag flagsRqd )
|
||||
{
|
||||
auto &project = mProject;
|
||||
bool bAllowed = TryToMakeActionAllowed( flags, flagsRqd, mask );
|
||||
bool bAllowed = TryToMakeActionAllowed( flags, flagsRqd );
|
||||
if( bAllowed )
|
||||
return true;
|
||||
auto &cm = CommandManager::Get( project );
|
||||
cm.TellUserWhyDisallowed( Name, flags & mask, flagsRqd & mask);
|
||||
TellUserWhyDisallowed( Name, flags & flagsRqd, flagsRqd);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// Determines if flags for command are compatible with current state.
|
||||
/// If not, then try some recovery action to make it so.
|
||||
/// @return whether compatible or not after any actions taken.
|
||||
bool MenuManager::TryToMakeActionAllowed(
|
||||
CommandFlag & flags, CommandFlag flagsRqd, CommandFlag mask )
|
||||
CommandFlag & flags, CommandFlag flagsRqd )
|
||||
{
|
||||
auto &project = mProject;
|
||||
bool bAllowed;
|
||||
|
||||
if( !flags )
|
||||
if( flags.none() )
|
||||
flags = GetUpdateFlags();
|
||||
|
||||
bAllowed = ((flags & mask) == (flagsRqd & mask));
|
||||
if( bAllowed )
|
||||
return true;
|
||||
|
||||
// Why is action not allowed?
|
||||
// 1's wherever a required flag is missing.
|
||||
auto MissingFlags = (~flags & flagsRqd) & mask;
|
||||
|
||||
if( mStopIfWasPaused && (MissingFlags & AudioIONotBusyFlag ) ){
|
||||
TransportActions::StopIfPaused( project );
|
||||
// Hope this will now reflect stopped audio.
|
||||
flags = GetUpdateFlags();
|
||||
bAllowed = ((flags & mask) == (flagsRqd & mask));
|
||||
if( bAllowed )
|
||||
return true;
|
||||
// Visit the table of recovery actions
|
||||
auto &enablers = Enablers();
|
||||
auto iter = enablers.begin(), end = enablers.end();
|
||||
while ((flags & flagsRqd) != flagsRqd && iter != end) {
|
||||
const auto &enabler = *iter;
|
||||
auto MissingFlags = (~flags & flagsRqd);
|
||||
if (
|
||||
// Do we have the right precondition?
|
||||
(flags & enabler.actualFlags) == enabler.actualFlags
|
||||
&&
|
||||
// Can we get the condition we need?
|
||||
(MissingFlags & enabler.possibleFlags) == MissingFlags
|
||||
) {
|
||||
// Then try the function
|
||||
enabler.tryEnable( project, flagsRqd );
|
||||
flags = GetUpdateFlags();
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
|
||||
//We can only make the action allowed if we select audio when no selection.
|
||||
// IF not set up to select all audio when none, THEN return with failure.
|
||||
if( mWhatIfNoSelection != 1 )
|
||||
return false;
|
||||
|
||||
// Some effects disallow autoselection.
|
||||
if( flagsRqd & NoAutoSelect )
|
||||
return false;
|
||||
|
||||
// Why is action still not allowed?
|
||||
// 0's wherever a required flag is missing (or is don't care)
|
||||
MissingFlags = (flags & ~flagsRqd) & mask;
|
||||
|
||||
// IF selecting all audio won't do any good, THEN return with failure.
|
||||
if( !(flags & WaveTracksExistFlag) )
|
||||
return false;
|
||||
// returns if mask wants a zero in some flag and that's not present.
|
||||
// logic seems a bit peculiar and worth revisiting.
|
||||
if( (MissingFlags & ~( TimeSelectedFlag | WaveTracksSelectedFlag)) )
|
||||
return false;
|
||||
|
||||
// This was 'DoSelectSomething()'.
|
||||
// This made autoselect more confusing.
|
||||
// When autoselect triggers, it might not select all audio in all tracks.
|
||||
// So changed to DoSelectAllAudio.
|
||||
SelectActions::DoSelectAllAudio(project);
|
||||
flags = GetUpdateFlags();
|
||||
bAllowed = ((flags & mask) == (flagsRqd & mask));
|
||||
return bAllowed;
|
||||
return (flags & flagsRqd) == flagsRqd;
|
||||
}
|
||||
|
||||
void MenuManager::TellUserWhyDisallowed(
|
||||
const wxString & Name, CommandFlag flagsGot, CommandFlag flagsRequired )
|
||||
{
|
||||
// The default string for 'reason' is a catch all. I hope it won't ever be seen
|
||||
// and that we will get something more specific.
|
||||
auto reason = _("There was a problem with your last action. If you think\nthis is a bug, please tell us exactly where it occurred.");
|
||||
// The default title string is 'Disallowed'.
|
||||
auto untranslatedTitle = XO("Disallowed");
|
||||
wxString helpPage;
|
||||
|
||||
bool enableDefaultMessage = true;
|
||||
bool defaultMessage = true;
|
||||
|
||||
auto doOption = [&](const CommandFlagOptions &options) {
|
||||
if ( options.message ) {
|
||||
reason = options.message( Name );
|
||||
defaultMessage = false;
|
||||
if ( !options.title.empty() )
|
||||
untranslatedTitle = options.title;
|
||||
helpPage = options.helpPage;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
enableDefaultMessage =
|
||||
enableDefaultMessage && options.enableDefaultMessage;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const auto &alloptions = Options();
|
||||
auto missingFlags = flagsRequired & ~flagsGot;
|
||||
|
||||
// Find greatest priority
|
||||
unsigned priority = 0;
|
||||
for ( const auto &options : alloptions )
|
||||
priority = std::max( priority, options.priority );
|
||||
|
||||
// Visit all unsatisfied conditions' options, by descending priority,
|
||||
// stopping when we find a message
|
||||
++priority;
|
||||
while( priority-- ) {
|
||||
size_t ii = 0;
|
||||
for ( const auto &options : alloptions ) {
|
||||
if (
|
||||
priority == options.priority
|
||||
&&
|
||||
missingFlags[ii]
|
||||
&&
|
||||
doOption( options ) )
|
||||
goto done;
|
||||
|
||||
++ii;
|
||||
}
|
||||
}
|
||||
done:
|
||||
|
||||
if (
|
||||
// didn't find a message
|
||||
defaultMessage
|
||||
&&
|
||||
// did find a condition that suppresses the default message
|
||||
!enableDefaultMessage
|
||||
)
|
||||
return;
|
||||
|
||||
// Message is already translated but title is not yet
|
||||
auto title = ::GetCustomTranslation( untranslatedTitle );
|
||||
|
||||
// Does not have the warning icon...
|
||||
ShowErrorDialog(
|
||||
NULL,
|
||||
title,
|
||||
reason,
|
||||
helpPage);
|
||||
}
|
||||
|
13
src/Menus.h
13
src/Menus.h
@ -15,6 +15,7 @@
|
||||
#include <wx/string.h> // member variable
|
||||
#include "Prefs.h"
|
||||
#include "ClientData.h"
|
||||
#include "commands/CommandFlag.h"
|
||||
|
||||
class wxArrayString;
|
||||
class wxCommandEvent;
|
||||
@ -29,7 +30,6 @@ class ViewInfo;
|
||||
class WaveClip;
|
||||
class WaveTrack;
|
||||
|
||||
enum CommandFlag : unsigned long long;
|
||||
enum EffectType : int;
|
||||
|
||||
typedef wxString PluginID;
|
||||
@ -81,19 +81,20 @@ public:
|
||||
|
||||
// Command Handling
|
||||
bool ReportIfActionNotAllowed(
|
||||
const wxString & Name, CommandFlag & flags, CommandFlag flagsRqd,
|
||||
CommandFlag mask );
|
||||
const wxString & Name, CommandFlag & flags, CommandFlag flagsRqd );
|
||||
bool TryToMakeActionAllowed(
|
||||
CommandFlag & flags, CommandFlag flagsRqd, CommandFlag mask );
|
||||
CommandFlag & flags, CommandFlag flagsRqd );
|
||||
|
||||
|
||||
private:
|
||||
void OnUndoRedo( wxCommandEvent &evt );
|
||||
void TellUserWhyDisallowed(const wxString & Name, CommandFlag flagsGot,
|
||||
CommandFlag flagsRequired);
|
||||
|
||||
CommandFlag GetFocusedFrame(AudacityProject &project);
|
||||
void OnUndoRedo( wxCommandEvent &evt );
|
||||
|
||||
AudacityProject &mProject;
|
||||
|
||||
public:
|
||||
// 0 is grey out, 1 is Autoselect, 2 is Give warnings.
|
||||
int mWhatIfNoSelection;
|
||||
bool mStopIfWasPaused;
|
||||
|
@ -642,7 +642,7 @@ void ProjectFileIO::DeleteCurrentAutoSaveFile()
|
||||
}
|
||||
}
|
||||
|
||||
bool ProjectFileIO::IsProjectSaved() {
|
||||
bool ProjectFileIO::IsProjectSaved() const {
|
||||
auto &project = mProject;
|
||||
auto &dirManager = DirManager::Get( project );
|
||||
// This is true if a project was opened from an .aup
|
||||
|
@ -40,7 +40,7 @@ public:
|
||||
// recovery file
|
||||
void SetProjectTitle( int number = -1 );
|
||||
|
||||
bool IsProjectSaved();
|
||||
bool IsProjectSaved() const;
|
||||
|
||||
void Reset();
|
||||
|
||||
|
@ -59,7 +59,7 @@ void ProjectHistory::InitialState()
|
||||
undoManager.StateSaved();
|
||||
}
|
||||
|
||||
bool ProjectHistory::UndoAvailable()
|
||||
bool ProjectHistory::UndoAvailable() const
|
||||
{
|
||||
auto &project = mProject;
|
||||
auto &tracks = TrackList::Get( project );
|
||||
@ -68,7 +68,7 @@ bool ProjectHistory::UndoAvailable()
|
||||
!tracks.HasPendingTracks();
|
||||
}
|
||||
|
||||
bool ProjectHistory::RedoAvailable()
|
||||
bool ProjectHistory::RedoAvailable() const
|
||||
{
|
||||
auto &project = mProject;
|
||||
auto &tracks = TrackList::Get( project );
|
||||
|
@ -31,8 +31,8 @@ public:
|
||||
|
||||
void InitialState();
|
||||
void SetStateTo(unsigned int n);
|
||||
bool UndoAvailable();
|
||||
bool RedoAvailable();
|
||||
bool UndoAvailable() const;
|
||||
bool RedoAvailable() const;
|
||||
void PushState(const wxString &desc, const wxString &shortDesc); // use UndoPush::AUTOSAVE
|
||||
void PushState(const wxString &desc, const wxString &shortDesc, UndoPush flags);
|
||||
void RollbackState();
|
||||
|
@ -1513,7 +1513,7 @@ void ProjectWindow::OnMenu(wxCommandEvent & event)
|
||||
auto &commandManager = CommandManager::Get( project );
|
||||
bool handled = commandManager.HandleMenuID(
|
||||
event.GetId(), MenuManager::Get( project ).GetUpdateFlags(),
|
||||
NoFlagsSpecified);
|
||||
false);
|
||||
|
||||
if (handled)
|
||||
event.Skip(false);
|
||||
@ -1887,3 +1887,12 @@ void ProjectWindow::ZoomOutByFactor( double ZoomFactor )
|
||||
// newh = (newh > 0) ? newh : 0;
|
||||
TP_ScrollWindow(newh);
|
||||
}
|
||||
|
||||
static struct InstallTopPanelHook{ InstallTopPanelHook() {
|
||||
ToolManager::SetGetTopPanelHook(
|
||||
[]( wxWindow &window ){
|
||||
auto pProjectWindow = dynamic_cast< ProjectWindow* >( &window );
|
||||
return pProjectWindow ? pProjectWindow->GetTopPanel() : nullptr;
|
||||
}
|
||||
);
|
||||
}} installTopPanelHook;
|
||||
|
@ -79,8 +79,6 @@ public:
|
||||
};
|
||||
PlaybackScroller &GetPlaybackScroller() { return *mPlaybackScroller; }
|
||||
|
||||
using wxFrame::DetachMenuBar;
|
||||
|
||||
void SetNormalizedWindowState(wxRect pSizeAndLocation) { mNormalizedWindowState = pSizeAndLocation; }
|
||||
wxRect GetNormalizedWindowState() const { return mNormalizedWindowState; }
|
||||
|
||||
|
@ -388,7 +388,7 @@ void UndoManager::Redo(const Consumer &consumer)
|
||||
mProject.QueueEvent( safenew wxCommandEvent{ EVT_UNDO_OR_REDO } );
|
||||
}
|
||||
|
||||
bool UndoManager::UnsavedChanges()
|
||||
bool UndoManager::UnsavedChanges() const
|
||||
{
|
||||
return (saved != current) || HasODChangesFlag();
|
||||
}
|
||||
@ -418,7 +418,7 @@ void UndoManager::SetODChangesFlag()
|
||||
mODChangesMutex.Unlock();
|
||||
}
|
||||
|
||||
bool UndoManager::HasODChangesFlag()
|
||||
bool UndoManager::HasODChangesFlag() const
|
||||
{
|
||||
bool ret;
|
||||
mODChangesMutex.Lock();
|
||||
|
@ -152,7 +152,7 @@ class AUDACITY_DLL_API UndoManager
|
||||
bool UndoAvailable();
|
||||
bool RedoAvailable();
|
||||
|
||||
bool UnsavedChanges();
|
||||
bool UnsavedChanges() const;
|
||||
void StateSaved();
|
||||
|
||||
// Return value must first be calculated by CalculateSpaceUsage():
|
||||
@ -167,7 +167,7 @@ class AUDACITY_DLL_API UndoManager
|
||||
|
||||
///to mark as unsaved changes without changing the state/tracks.
|
||||
void SetODChangesFlag();
|
||||
bool HasODChangesFlag();
|
||||
bool HasODChangesFlag() const;
|
||||
void ResetODChangesFlag();
|
||||
|
||||
private:
|
||||
@ -184,7 +184,7 @@ class AUDACITY_DLL_API UndoManager
|
||||
unsigned long long mClipboardSpaceUsage {};
|
||||
|
||||
bool mODChanges;
|
||||
ODLock mODChangesMutex;//mODChanges is accessed from many threads.
|
||||
mutable ODLock mODChangesMutex;//mODChanges is accessed from many threads.
|
||||
|
||||
};
|
||||
|
||||
|
@ -11,134 +11,109 @@
|
||||
|
||||
// Flags used in command handling.
|
||||
|
||||
// These flags represent the majority of the states that affect
|
||||
// whether or not items in menus are enabled or disabled.
|
||||
enum CommandFlag : unsigned long long
|
||||
{
|
||||
AlwaysEnabledFlag = 0x00000000,
|
||||
#include <bitset>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <wx/string.h>
|
||||
|
||||
AudioIONotBusyFlag = 0x00000001,
|
||||
TimeSelectedFlag = 0x00000002, // This is equivalent to check if there is a valid selection, so it's used for Zoom to Selection too
|
||||
TracksSelectedFlag = 0x00000004,
|
||||
TracksExistFlag = 0x00000008,
|
||||
LabelTracksExistFlag = 0x00000010,
|
||||
WaveTracksSelectedFlag = 0x00000020,
|
||||
ClipboardFlag = 0x00000040,
|
||||
TextClipFlag = 0x00000040, // Same as Clipboard flag for now.
|
||||
UnsavedChangesFlag = 0x00000080,
|
||||
HasLastEffectFlag = 0x00000100,
|
||||
UndoAvailableFlag = 0x00000200,
|
||||
RedoAvailableFlag = 0x00000400,
|
||||
ZoomInAvailableFlag = 0x00000800,
|
||||
ZoomOutAvailableFlag = 0x00001000,
|
||||
StereoRequiredFlag = 0x00002000, //lda
|
||||
TopDockHasFocus = 0x00004000, //lll
|
||||
TrackPanelHasFocus = 0x00008000, //lll
|
||||
BotDockHasFocus = 0x00010000, //lll
|
||||
LabelsSelectedFlag = 0x00020000,
|
||||
AudioIOBusyFlag = 0x00040000, //lll
|
||||
PlayRegionLockedFlag = 0x00080000, //msmeyer
|
||||
PlayRegionNotLockedFlag= 0x00100000, //msmeyer
|
||||
CutCopyAvailableFlag = 0x00200000,
|
||||
WaveTracksExistFlag = 0x00400000,
|
||||
NoteTracksExistFlag = 0x00800000, //gsw
|
||||
NoteTracksSelectedFlag = 0x01000000, //gsw
|
||||
HaveRecentFiles = 0x02000000,
|
||||
IsNotSyncLockedFlag = 0x04000000, //awd
|
||||
IsSyncLockedFlag = 0x08000000, //awd
|
||||
IsRealtimeNotActiveFlag= 0x10000000, //lll
|
||||
CaptureNotBusyFlag = 0x20000000,
|
||||
CanStopAudioStreamFlag = 0x40000000,
|
||||
RulerHasFocus = 0x80000000ULL, // prl
|
||||
NotMinimizedFlag = 0x100000000ULL, // prl
|
||||
PausedFlag = 0x200000000ULL, // jkc
|
||||
NotPausedFlag = 0x400000000ULL, // jkc
|
||||
HasWaveDataFlag = 0x800000000ULL, // jkc
|
||||
PlayableTracksExistFlag = 0x1000000000ULL,
|
||||
AudioTracksSelectedFlag = 0x2000000000ULL,
|
||||
NoAutoSelect = 0x4000000000ULL, // jkc
|
||||
class AudacityProject;
|
||||
|
||||
NoFlagsSpecified = ~0ULL
|
||||
// Increase the template parameter as needed to allow more flags
|
||||
constexpr size_t NCommandFlags = 64;
|
||||
static_assert(
|
||||
NCommandFlags <= 8 * sizeof( unsigned long long ),
|
||||
"NoFlagsSpecified may have incorrect value"
|
||||
);
|
||||
|
||||
// Type to specify conditions for enabling of a menu item
|
||||
using CommandFlag = std::bitset<NCommandFlags>;
|
||||
|
||||
// Special constant values
|
||||
constexpr CommandFlag
|
||||
AlwaysEnabledFlag{}, // all zeroes
|
||||
NoFlagsSpecified{ ~0ULL }; // all ones
|
||||
|
||||
struct CommandFlagOptions{
|
||||
// Supplied the translated name of the command, returns a translated
|
||||
// error message
|
||||
using MessageFormatter = std::function< wxString( const wxString& ) >;
|
||||
|
||||
CommandFlagOptions() = default;
|
||||
CommandFlagOptions(
|
||||
const MessageFormatter &message_,
|
||||
const wxString &helpPage_ = {},
|
||||
const wxString &title_ = {}
|
||||
) : message{ message_ }, helpPage{ helpPage_ }, title{ title_ }
|
||||
{}
|
||||
|
||||
CommandFlagOptions && QuickTest() &&
|
||||
{ quickTest = true; return std::move( *this ); }
|
||||
CommandFlagOptions && DisableDefaultMessage() &&
|
||||
{ enableDefaultMessage = false; return std::move( *this ); }
|
||||
CommandFlagOptions && Priority( unsigned priority_ ) &&
|
||||
{ priority = priority_; return std::move( *this ); }
|
||||
|
||||
// null, or else computes non-default message for the dialog box when the
|
||||
// condition is not satisfied for the selected command
|
||||
MessageFormatter message;
|
||||
|
||||
// Title and help page are used only if a message function is given
|
||||
wxString helpPage;
|
||||
|
||||
// Empty, or non-default title for the dialog box when the
|
||||
// condition is not satisfied for the selected command
|
||||
// This string must be given UN-translated.
|
||||
wxString title;
|
||||
|
||||
// Conditions with higher "priority" are preferred over others in choosing
|
||||
// the help message
|
||||
unsigned priority = 0;
|
||||
|
||||
// If false, and no other condition with a message is unsatisfied, then
|
||||
// display no dialog box at all when this condition is not satisfied
|
||||
bool enableDefaultMessage = true;
|
||||
|
||||
// If true, assume this is a cheap test to be done always. If false, the
|
||||
// test may be skipped and the condition assumed to be unchanged since the
|
||||
// last more comprehensive testing
|
||||
bool quickTest = false;
|
||||
};
|
||||
|
||||
// Prevent accidental misuse with narrower types
|
||||
|
||||
bool operator == (CommandFlag, unsigned long) PROHIBITED;
|
||||
bool operator == (CommandFlag, long) PROHIBITED;
|
||||
bool operator == (unsigned long, CommandFlag) PROHIBITED;
|
||||
bool operator == (long, CommandFlag) PROHIBITED;
|
||||
|
||||
bool operator != (CommandFlag, unsigned long) PROHIBITED;
|
||||
bool operator != (CommandFlag, long) PROHIBITED;
|
||||
bool operator != (unsigned long, CommandFlag) PROHIBITED;
|
||||
bool operator != (long, CommandFlag) PROHIBITED;
|
||||
|
||||
CommandFlag operator & (CommandFlag, unsigned long) PROHIBITED;
|
||||
CommandFlag operator & (CommandFlag, long) PROHIBITED;
|
||||
CommandFlag operator & (unsigned long, CommandFlag) PROHIBITED;
|
||||
CommandFlag operator & (long, CommandFlag) PROHIBITED;
|
||||
|
||||
CommandFlag operator | (CommandFlag, unsigned long) PROHIBITED;
|
||||
CommandFlag operator | (CommandFlag, long) PROHIBITED;
|
||||
CommandFlag operator | (unsigned long, CommandFlag) PROHIBITED;
|
||||
CommandFlag operator | (long, CommandFlag) PROHIBITED;
|
||||
|
||||
CommandFlag operator ^ (CommandFlag, unsigned long) PROHIBITED;
|
||||
CommandFlag operator ^ (CommandFlag, long) PROHIBITED;
|
||||
CommandFlag operator ^ (unsigned long, CommandFlag) PROHIBITED;
|
||||
CommandFlag operator ^ (long, CommandFlag) PROHIBITED;
|
||||
|
||||
bool operator == (CommandFlag, unsigned int) PROHIBITED;
|
||||
bool operator == (CommandFlag, int) PROHIBITED;
|
||||
bool operator == (unsigned int, CommandFlag) PROHIBITED;
|
||||
bool operator == (int, CommandFlag) PROHIBITED;
|
||||
|
||||
bool operator != (CommandFlag, unsigned int) PROHIBITED;
|
||||
bool operator != (CommandFlag, int) PROHIBITED;
|
||||
bool operator != (unsigned int, CommandFlag) PROHIBITED;
|
||||
bool operator != (int, CommandFlag) PROHIBITED;
|
||||
|
||||
CommandFlag operator & (CommandFlag, unsigned int) PROHIBITED;
|
||||
CommandFlag operator & (CommandFlag, int) PROHIBITED;
|
||||
CommandFlag operator & (unsigned int, CommandFlag) PROHIBITED;
|
||||
CommandFlag operator & (int, CommandFlag) PROHIBITED;
|
||||
|
||||
CommandFlag operator | (CommandFlag, unsigned int) PROHIBITED;
|
||||
CommandFlag operator | (CommandFlag, int) PROHIBITED;
|
||||
CommandFlag operator | (unsigned int, CommandFlag) PROHIBITED;
|
||||
CommandFlag operator | (int, CommandFlag) PROHIBITED;
|
||||
|
||||
CommandFlag operator ^ (CommandFlag, unsigned int) PROHIBITED;
|
||||
CommandFlag operator ^ (CommandFlag, int) PROHIBITED;
|
||||
CommandFlag operator ^ (unsigned int, CommandFlag) PROHIBITED;
|
||||
CommandFlag operator ^ (int, CommandFlag) PROHIBITED;
|
||||
|
||||
// Supply the bitwise operations
|
||||
|
||||
inline constexpr CommandFlag operator ~ (CommandFlag flag)
|
||||
// Construct one statically to register (and reserve) a bit position in the set
|
||||
// an associate it with a test function; those with quickTest = true are cheap
|
||||
// to compute and always checked
|
||||
class ReservedCommandFlag : public CommandFlag
|
||||
{
|
||||
return static_cast<CommandFlag>( ~ static_cast<unsigned long long> (flag) );
|
||||
}
|
||||
inline constexpr CommandFlag operator & (CommandFlag lhs, CommandFlag rhs)
|
||||
{
|
||||
return static_cast<CommandFlag> (
|
||||
static_cast<unsigned long long>(lhs) &
|
||||
static_cast<unsigned long long>(rhs)
|
||||
);
|
||||
}
|
||||
inline constexpr CommandFlag operator | (CommandFlag lhs, CommandFlag rhs)
|
||||
{
|
||||
return static_cast<CommandFlag> (
|
||||
static_cast<unsigned long long>(lhs) |
|
||||
static_cast<unsigned long long>(rhs)
|
||||
);
|
||||
}
|
||||
inline CommandFlag & operator |= (CommandFlag &lhs, CommandFlag rhs)
|
||||
{
|
||||
lhs = lhs | rhs;
|
||||
return lhs;
|
||||
}
|
||||
public:
|
||||
using Predicate = std::function< bool( const AudacityProject& ) >;
|
||||
ReservedCommandFlag( const Predicate &predicate,
|
||||
const CommandFlagOptions &options = {} );
|
||||
};
|
||||
|
||||
using CommandMask = CommandFlag;
|
||||
// Widely used command flags, but this list need not be exhaustive. It may be
|
||||
// extended, with special purpose flags of limited use, by constucting static
|
||||
// ReservedCommandFlag values
|
||||
|
||||
// To describe auto-selection, stop-if-paused, etc.:
|
||||
// A structure describing a set of conditions, another set that might be
|
||||
// made true given the first, and the function that may make them true.
|
||||
// If a menu item requires the second set, while the first set is true,
|
||||
// then the enabler will be invoked (unless the menu item is constructed with
|
||||
// the useStrictFlags option, or the applicability test first returns false).
|
||||
// The item's full set of required flags is passed to the function.
|
||||
struct MenuItemEnabler {
|
||||
using Test = std::function< bool( const AudacityProject& ) >;
|
||||
using Action = std::function< void( AudacityProject&, CommandFlag ) >;
|
||||
|
||||
const CommandFlag &actualFlags;
|
||||
const CommandFlag &possibleFlags;
|
||||
Test applicable;
|
||||
Action tryEnable;
|
||||
};
|
||||
|
||||
// Typically this is statically constructed:
|
||||
struct RegisteredMenuItemEnabler{
|
||||
RegisteredMenuItemEnabler( const MenuItemEnabler &enabler );
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -96,12 +96,9 @@ CommandManager. It holds the callback for one command.
|
||||
|
||||
#include "../Menus.h"
|
||||
|
||||
#include "../PluginManager.h"
|
||||
#include "../Project.h"
|
||||
#include "../effects/EffectManager.h"
|
||||
#include "../widgets/LinkingHtmlWindow.h"
|
||||
#include "../widgets/AudacityMessageBox.h"
|
||||
#include "../widgets/ErrorDialog.h"
|
||||
#include "../widgets/HelpSystem.h"
|
||||
|
||||
|
||||
@ -525,10 +522,6 @@ void CommandManager::AddItem(const CommandID &name,
|
||||
|
||||
wxASSERT( flags != NoFlagsSpecified );
|
||||
|
||||
auto mask = options.mask;
|
||||
if (mask == NoFlagsSpecified)
|
||||
mask = flags;
|
||||
|
||||
CommandParameter cookedParameter;
|
||||
const auto ¶meter = options.parameter;
|
||||
if( parameter.empty() )
|
||||
@ -542,10 +535,11 @@ void CommandManager::AddItem(const CommandID &name,
|
||||
hasDialog,
|
||||
options.accel, CurrentMenu(), finder, callback,
|
||||
{}, 0, 0, options.bIsEffect, cookedParameter);
|
||||
entry->useStrictFlags = options.useStrictFlags;
|
||||
int ID = entry->id;
|
||||
wxString label = GetLabelWithDisabledAccel(entry);
|
||||
|
||||
SetCommandFlags(name, flags, mask);
|
||||
SetCommandFlags(name, flags);
|
||||
|
||||
|
||||
auto checkmark = options.check;
|
||||
@ -588,7 +582,7 @@ void CommandManager::AddItemList(const CommandID & name,
|
||||
i,
|
||||
cnt,
|
||||
bIsEffect);
|
||||
entry->mask = entry->flags = flags;
|
||||
entry->flags = flags;
|
||||
CurrentMenu()->Append(entry->id, GetLabel(entry));
|
||||
mbSeparatorAllowed = true;
|
||||
}
|
||||
@ -617,7 +611,7 @@ void CommandManager::AddCommand(const CommandID &name,
|
||||
|
||||
NewIdentifier(name, label_in, label_in, false, accel, NULL, finder, callback, {}, 0, 0, false, {});
|
||||
|
||||
SetCommandFlags(name, flags, flags);
|
||||
SetCommandFlags(name, flags);
|
||||
}
|
||||
|
||||
void CommandManager::AddGlobalCommand(const CommandID &name,
|
||||
@ -634,7 +628,6 @@ void CommandManager::AddGlobalCommand(const CommandID &name,
|
||||
entry->enabled = false;
|
||||
entry->isGlobal = true;
|
||||
entry->flags = AlwaysEnabledFlag;
|
||||
entry->mask = AlwaysEnabledFlag;
|
||||
}
|
||||
|
||||
void CommandManager::AddSeparator()
|
||||
@ -763,7 +756,7 @@ CommandListEntry *CommandManager::NewIdentifier(const CommandID & nameIn,
|
||||
entry->multi = multi;
|
||||
entry->index = index;
|
||||
entry->count = count;
|
||||
entry->flags = entry->mask = AlwaysEnabledFlag;
|
||||
entry->flags = AlwaysEnabledFlag;
|
||||
entry->enabled = true;
|
||||
entry->skipKeydown = (accel.Find(wxT("\tskipKeydown")) != wxNOT_FOUND);
|
||||
entry->wantKeyup = (accel.Find(wxT("\twantKeyup")) != wxNOT_FOUND) || entry->skipKeydown;
|
||||
@ -955,18 +948,25 @@ void CommandManager::Enable(const wxString &name, bool enabled)
|
||||
Enable(entry, enabled);
|
||||
}
|
||||
|
||||
void CommandManager::EnableUsingFlags(CommandFlag flags, CommandMask mask)
|
||||
void CommandManager::EnableUsingFlags(
|
||||
CommandFlag flags, CommandFlag strictFlags)
|
||||
{
|
||||
// strictFlags are a subset of flags. strictFlags represent the real
|
||||
// conditions now, but flags are the conditions that could be made true.
|
||||
// Some commands use strict flags only, refusing the chance to fix
|
||||
// conditions
|
||||
wxASSERT( (strictFlags & ~flags).none() );
|
||||
|
||||
for(const auto &entry : mCommandList) {
|
||||
if (entry->multi && entry->index != 0)
|
||||
continue;
|
||||
if( entry->isOccult )
|
||||
continue;
|
||||
|
||||
auto combinedMask = (mask & entry->mask);
|
||||
if (combinedMask) {
|
||||
bool enable = ((flags & combinedMask) ==
|
||||
(entry->flags & combinedMask));
|
||||
auto useFlags = entry->useStrictFlags ? strictFlags : flags;
|
||||
|
||||
if (entry->flags.any()) {
|
||||
bool enable = ((useFlags & entry->flags) == entry->flags);
|
||||
Enable(entry.get(), enable);
|
||||
}
|
||||
}
|
||||
@ -1018,69 +1018,6 @@ void CommandManager::SetKeyFromIndex(int i, const NormalizedKeyString &key)
|
||||
entry->key = key;
|
||||
}
|
||||
|
||||
void CommandManager::TellUserWhyDisallowed( const wxString & Name, CommandFlag flagsGot, CommandMask flagsRequired )
|
||||
{
|
||||
// The default string for 'reason' is a catch all. I hope it won't ever be seen
|
||||
// and that we will get something more specific.
|
||||
wxString reason = _("There was a problem with your last action. If you think\nthis is a bug, please tell us exactly where it occurred.");
|
||||
// The default title string is 'Disallowed'.
|
||||
wxString title = _("Disallowed");
|
||||
wxString helpPage;
|
||||
|
||||
auto missingFlags = flagsRequired & (~flagsGot );
|
||||
if( missingFlags & AudioIONotBusyFlag )
|
||||
// This reason will not be shown, because options that require it will be greyed our.
|
||||
reason = _("You can only do this when playing and recording are\nstopped. (Pausing is not sufficient.)");
|
||||
else if( missingFlags & StereoRequiredFlag )
|
||||
// This reason will not be shown, because the stereo-to-mono is greyed out if not allowed.
|
||||
reason = _("You must first select some stereo audio to perform this\naction. (You cannot use this with mono.)");
|
||||
// In reporting the issue with cut or copy, we don't tell the user they could also select some text in a label.
|
||||
else if(( missingFlags & TimeSelectedFlag ) || (missingFlags &CutCopyAvailableFlag )){
|
||||
title = _("No Audio Selected");
|
||||
#ifdef EXPERIMENTAL_DA
|
||||
// i18n-hint: %s will be replaced by the name of an action, such as Normalize, Cut, Fade.
|
||||
reason = wxString::Format( _("You must first select some audio for '%s' to act on.\n\nCtrl + A selects all audio."), Name );
|
||||
#else
|
||||
#ifdef __WXMAC__
|
||||
// i18n-hint: %s will be replaced by the name of an action, such as Normalize, Cut, Fade.
|
||||
reason = wxString::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."
|
||||
), Name );
|
||||
|
||||
#else
|
||||
// i18n-hint: %s will be replaced by the name of an action, such as Normalize, Cut, Fade.
|
||||
reason = wxString::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."
|
||||
), Name );
|
||||
#endif
|
||||
#endif
|
||||
helpPage = "Selecting_Audio_-_the_basics";
|
||||
}
|
||||
else if( missingFlags & WaveTracksSelectedFlag)
|
||||
reason = _("You must first select some audio to perform this action.\n(Selecting other kinds of track won't work.)");
|
||||
else if ( missingFlags & TracksSelectedFlag )
|
||||
// i18n-hint: %s will be replaced by the name of an action, such as "Remove Tracks".
|
||||
reason = wxString::Format(_("\"%s\" requires one or more tracks to be selected."), Name);
|
||||
// If the only thing wrong was no tracks, we do nothing and don't report a problem
|
||||
else if( missingFlags == TracksExistFlag )
|
||||
return;
|
||||
// Likewise return if it was just no tracks, and track panel did not have focus. (e.g. up-arrow to move track)
|
||||
else if( missingFlags == (TracksExistFlag | TrackPanelHasFocus) )
|
||||
return;
|
||||
// Likewise as above too...
|
||||
else if( missingFlags == TrackPanelHasFocus )
|
||||
return;
|
||||
|
||||
// Does not have the warning icon...
|
||||
ShowErrorDialog(
|
||||
NULL,
|
||||
title,
|
||||
reason,
|
||||
helpPage);
|
||||
}
|
||||
|
||||
wxString CommandManager::DescribeCommandsAndShortcuts
|
||||
(const TranslatedInternalString commands[], size_t nCommands) const
|
||||
{
|
||||
@ -1153,7 +1090,7 @@ bool CommandManager::FilterKeyEvent(AudacityProject *project, const wxKeyEvent &
|
||||
// LL: Why do they need to be disabled???
|
||||
entry->enabled = false;
|
||||
auto cleanup = valueRestorer( entry->enabled, true );
|
||||
return HandleCommandEntry(entry, NoFlagsSpecified, NoFlagsSpecified, &evt);
|
||||
return HandleCommandEntry(entry, NoFlagsSpecified, false, &evt);
|
||||
}
|
||||
|
||||
wxWindow * pFocus = wxWindow::FindFocus();
|
||||
@ -1227,12 +1164,12 @@ bool CommandManager::FilterKeyEvent(AudacityProject *project, const wxKeyEvent &
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return HandleCommandEntry(entry, flags, NoFlagsSpecified, &temp);
|
||||
return HandleCommandEntry(entry, flags, false, &temp);
|
||||
}
|
||||
|
||||
if (type == wxEVT_KEY_UP && entry->wantKeyup)
|
||||
{
|
||||
return HandleCommandEntry(entry, flags, NoFlagsSpecified, &temp);
|
||||
return HandleCommandEntry(entry, flags, false, &temp);
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -1243,7 +1180,7 @@ bool CommandManager::FilterKeyEvent(AudacityProject *project, const wxKeyEvent &
|
||||
///the command won't be executed unless the flags are compatible
|
||||
///with the command's flags.
|
||||
bool CommandManager::HandleCommandEntry(const CommandListEntry * entry,
|
||||
CommandFlag flags, CommandMask mask, const wxEvent * evt)
|
||||
CommandFlag flags, bool alwaysEnabled, const wxEvent * evt)
|
||||
{
|
||||
if (!entry )
|
||||
return false;
|
||||
@ -1253,8 +1190,7 @@ bool CommandManager::HandleCommandEntry(const CommandListEntry * entry,
|
||||
|
||||
auto proj = GetActiveProject();
|
||||
|
||||
auto combinedMask = (mask & entry->mask);
|
||||
if (combinedMask) {
|
||||
if (!alwaysEnabled && entry->flags.any()) {
|
||||
|
||||
wxASSERT( proj );
|
||||
if( !proj )
|
||||
@ -1266,7 +1202,7 @@ bool CommandManager::HandleCommandEntry(const CommandListEntry * entry,
|
||||
// NB: The call may have the side effect of changing flags.
|
||||
bool allowed =
|
||||
MenuManager::Get(*proj).ReportIfActionNotAllowed(
|
||||
NiceName, flags, entry->flags, combinedMask );
|
||||
NiceName, flags, entry->flags );
|
||||
// If the function was disallowed, it STILL should count as having been
|
||||
// handled (by doing nothing or by telling the user of the problem).
|
||||
// Otherwise we may get other handlers having a go at obeying the command.
|
||||
@ -1286,7 +1222,7 @@ bool CommandManager::HandleCommandEntry(const CommandListEntry * entry,
|
||||
///CommandManagerListener function. If you pass any flags,
|
||||
///the command won't be executed unless the flags are compatible
|
||||
///with the command's flags.
|
||||
bool CommandManager::HandleMenuID(int id, CommandFlag flags, CommandMask mask)
|
||||
bool CommandManager::HandleMenuID(int id, CommandFlag flags, bool alwaysEnabled)
|
||||
{
|
||||
CommandListEntry *entry = mCommandNumericIDHash[id];
|
||||
|
||||
@ -1294,16 +1230,18 @@ bool CommandManager::HandleMenuID(int id, CommandFlag flags, CommandMask mask)
|
||||
if (hook && hook(entry->name))
|
||||
return true;
|
||||
|
||||
return HandleCommandEntry( entry, flags, mask );
|
||||
return HandleCommandEntry( entry, flags, alwaysEnabled );
|
||||
}
|
||||
|
||||
/// HandleTextualCommand() allows us a limitted version of script/batch
|
||||
/// behavior, since we can get from a string command name to the actual
|
||||
/// code to run.
|
||||
bool CommandManager::HandleTextualCommand(const CommandID & Str, const CommandContext & context, CommandFlag flags, CommandMask mask)
|
||||
CommandManager::TextualCommandResult
|
||||
CommandManager::HandleTextualCommand(const CommandID & Str,
|
||||
const CommandContext & context, CommandFlag flags, bool alwaysEnabled)
|
||||
{
|
||||
if( Str.empty() )
|
||||
return false;
|
||||
return CommandFailure;
|
||||
// Linear search for now...
|
||||
for (const auto &entry : mCommandList)
|
||||
{
|
||||
@ -1316,7 +1254,8 @@ bool CommandManager::HandleTextualCommand(const CommandID & Str, const CommandCo
|
||||
// sub-menu name)
|
||||
Str == entry->labelPrefix )
|
||||
{
|
||||
return HandleCommandEntry( entry.get(), flags, mask);
|
||||
return HandleCommandEntry( entry.get(), flags, alwaysEnabled)
|
||||
? CommandSuccess : CommandFailure;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1324,34 +1263,12 @@ bool CommandManager::HandleTextualCommand(const CommandID & Str, const CommandCo
|
||||
// Handle multis too...
|
||||
if( Str == entry->name )
|
||||
{
|
||||
return HandleCommandEntry( entry.get(), flags, mask);
|
||||
return HandleCommandEntry( entry.get(), flags, alwaysEnabled)
|
||||
? CommandSuccess : CommandFailure;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Not one of the singleton commands.
|
||||
// We could/should try all the list-style commands.
|
||||
// instead we only try the effects.
|
||||
AudacityProject * proj = GetActiveProject();
|
||||
if( !proj )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
PluginManager & pm = PluginManager::Get();
|
||||
EffectManager & em = EffectManager::Get();
|
||||
const PluginDescriptor *plug = pm.GetFirstPlugin(PluginTypeEffect);
|
||||
while (plug)
|
||||
{
|
||||
if (em.GetCommandIdentifier(plug->GetID()) == Str)
|
||||
{
|
||||
return PluginActions::DoEffect(
|
||||
plug->GetID(), context,
|
||||
PluginActions::kConfigured);
|
||||
}
|
||||
plug = pm.GetNextPlugin(PluginTypeEffect);
|
||||
}
|
||||
|
||||
return false;
|
||||
return CommandNotFound;
|
||||
}
|
||||
|
||||
void CommandManager::GetCategories(wxArrayString &cats)
|
||||
@ -1609,13 +1526,11 @@ void CommandManager::EndOccultCommands()
|
||||
}
|
||||
|
||||
void CommandManager::SetCommandFlags(const CommandID &name,
|
||||
CommandFlag flags, CommandMask mask)
|
||||
CommandFlag flags)
|
||||
{
|
||||
CommandListEntry *entry = mCommandNameHash[name];
|
||||
if (entry) {
|
||||
if (entry)
|
||||
entry->flags = flags;
|
||||
entry->mask = mask;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__WXDEBUG__)
|
||||
@ -1671,3 +1586,4 @@ static struct InstallHandlers
|
||||
} );
|
||||
}
|
||||
} installHandlers;
|
||||
|
||||
|
@ -81,7 +81,7 @@ struct CommandListEntry
|
||||
bool isEffect;
|
||||
bool hasDialog;
|
||||
CommandFlag flags;
|
||||
CommandMask mask;
|
||||
bool useStrictFlags{ false };
|
||||
};
|
||||
|
||||
using MenuBarList = std::vector < MenuBarListEntry >;
|
||||
@ -158,20 +158,20 @@ class AUDACITY_DLL_API CommandManager final
|
||||
{ bIsEffect = true; return std::move(*this); }
|
||||
Options &&Parameter (const CommandParameter &value) &&
|
||||
{ parameter = value; return std::move(*this); }
|
||||
Options &&Mask (CommandMask value) &&
|
||||
{ mask = value; return std::move(*this); }
|
||||
Options &&LongName (const wxString &value) &&
|
||||
{ longName = value; return std::move(*this); }
|
||||
Options &&IsGlobal () &&
|
||||
{ global = true; return std::move(*this); }
|
||||
Options &&UseStrictFlags () &&
|
||||
{ useStrictFlags = true; return std::move(*this); }
|
||||
|
||||
const wxChar *accel{ wxT("") };
|
||||
int check{ -1 }; // default value means it's not a check item
|
||||
bool bIsEffect{ false };
|
||||
CommandParameter parameter{};
|
||||
CommandMask mask{ NoFlagsSpecified };
|
||||
wxString longName{}; // translated
|
||||
bool global{ false };
|
||||
bool useStrictFlags{ false };
|
||||
};
|
||||
|
||||
void AddItemList(const CommandID & name,
|
||||
@ -212,13 +212,14 @@ class AUDACITY_DLL_API CommandManager final
|
||||
void EndOccultCommands();
|
||||
|
||||
|
||||
void SetCommandFlags(const CommandID &name, CommandFlag flags, CommandMask mask);
|
||||
void SetCommandFlags(const CommandID &name, CommandFlag flags);
|
||||
|
||||
//
|
||||
// Modifying menus
|
||||
//
|
||||
|
||||
void EnableUsingFlags(CommandFlag flags, CommandMask mask);
|
||||
void EnableUsingFlags(
|
||||
CommandFlag flags, CommandFlag strictFlags);
|
||||
void Enable(const wxString &name, bool enabled);
|
||||
void Check(const CommandID &name, bool checked);
|
||||
void Modify(const wxString &name, const wxString &newLabel);
|
||||
@ -242,8 +243,17 @@ class AUDACITY_DLL_API CommandManager final
|
||||
// "permit" allows filtering even if the active window isn't a child of the project.
|
||||
// Lyrics and MixerTrackCluster classes use it.
|
||||
bool FilterKeyEvent(AudacityProject *project, const wxKeyEvent & evt, bool permit = false);
|
||||
bool HandleMenuID(int id, CommandFlag flags, CommandMask mask);
|
||||
bool HandleTextualCommand(const CommandID & Str, const CommandContext & context, CommandFlag flags, CommandMask mask);
|
||||
bool HandleMenuID(int id, CommandFlag flags, bool alwaysEnabled);
|
||||
|
||||
enum TextualCommandResult {
|
||||
CommandFailure,
|
||||
CommandSuccess,
|
||||
CommandNotFound
|
||||
};
|
||||
|
||||
TextualCommandResult
|
||||
HandleTextualCommand(const CommandID & Str,
|
||||
const CommandContext & context, CommandFlag flags, bool alwaysEnabled);
|
||||
|
||||
//
|
||||
// Accessing
|
||||
@ -285,7 +295,6 @@ class AUDACITY_DLL_API CommandManager final
|
||||
//
|
||||
|
||||
void WriteXML(XMLWriter &xmlFile) const /* not override */;
|
||||
void TellUserWhyDisallowed(const wxString & Name, CommandFlag flagsGot, CommandFlag flagsRequired);
|
||||
|
||||
///
|
||||
/// Formatting summaries that include shortcut keys
|
||||
@ -342,7 +351,8 @@ private:
|
||||
// Executing commands
|
||||
//
|
||||
|
||||
bool HandleCommandEntry(const CommandListEntry * entry, CommandFlag flags, CommandMask mask, const wxEvent * evt = NULL);
|
||||
bool HandleCommandEntry(const CommandListEntry * entry, CommandFlag flags,
|
||||
bool alwaysEnabled, const wxEvent * evt = NULL);
|
||||
|
||||
//
|
||||
// Modifying
|
||||
|
@ -32,6 +32,7 @@ small calculations of rectangles.
|
||||
#include <wx/valgen.h>
|
||||
|
||||
#include "../AdornedRulerPanel.h"
|
||||
#include "../BatchCommands.h"
|
||||
#include "../TrackPanel.h"
|
||||
#include "../effects/Effect.h"
|
||||
#include "../toolbars/ToolManager.h"
|
||||
@ -454,7 +455,8 @@ void ScreenshotCommand::CapturePreferences(
|
||||
gPrefs->Flush();
|
||||
CommandID Command{ wxT("Preferences") };
|
||||
const CommandContext projectContext( *pProject );
|
||||
if( !commandManager.HandleTextualCommand( Command, projectContext, AlwaysEnabledFlag, AlwaysEnabledFlag ) )
|
||||
if( !MacroCommands::HandleTextualCommand( commandManager,
|
||||
Command, projectContext, AlwaysEnabledFlag, true ) )
|
||||
{
|
||||
// using GET in a log message for devs' eyes only
|
||||
wxLogDebug("Command %s not found", Command.GET() );
|
||||
@ -614,7 +616,7 @@ void ScreenshotCommand::CaptureCommands(
|
||||
SetIdleHandler( IdleHandler );
|
||||
Str = Commands[i];
|
||||
const CommandContext projectContext( *pProject );
|
||||
if( !manager.HandleTextualCommand( Str, projectContext, AlwaysEnabledFlag, AlwaysEnabledFlag ) )
|
||||
if( !manager.HandleTextualCommand( Str, projectContext, AlwaysEnabledFlag, true ) )
|
||||
{
|
||||
wxLogDebug("Command %s not found", Str);
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ greater use in future.
|
||||
|
||||
#include "EffectManager.h"
|
||||
#include "../AudioIO.h"
|
||||
#include "../CommonCommandFlags.h"
|
||||
#include "../LabelTrack.h"
|
||||
#include "../Menus.h"
|
||||
#include "../Mix.h"
|
||||
@ -57,13 +58,11 @@ greater use in future.
|
||||
#include "../Project.h"
|
||||
#include "../ProjectAudioManager.h"
|
||||
#include "../ProjectSettings.h"
|
||||
#include "../PluginManager.h"
|
||||
#include "../ShuttleGui.h"
|
||||
#include "../Shuttle.h"
|
||||
#include "../ViewInfo.h"
|
||||
#include "../WaveTrack.h"
|
||||
#include "../commands/Command.h"
|
||||
#include "../commands/CommandFlag.h"
|
||||
#include "../toolbars/ControlToolBar.h"
|
||||
#include "../widgets/AButton.h"
|
||||
#include "../widgets/ProgressDialog.h"
|
||||
@ -3279,7 +3278,6 @@ void EffectUIHost::OnApply(wxCommandEvent & evt)
|
||||
MenuManager::Get(*mProject).ReportIfActionNotAllowed(
|
||||
mEffect->GetTranslatedName(),
|
||||
flags,
|
||||
WaveTracksSelectedFlag | TimeSelectedFlag,
|
||||
WaveTracksSelectedFlag | TimeSelectedFlag);
|
||||
if (!allowed)
|
||||
return;
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include "../CommonCommandFlags.h"
|
||||
#include "../ProjectHistory.h"
|
||||
#include "../ProjectSettings.h"
|
||||
#include "../TrackPanel.h"
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "../Audacity.h" // for USE_* macros
|
||||
#include "../AdornedRulerPanel.h"
|
||||
#include "../Clipboard.h"
|
||||
#include "../CommonCommandFlags.h"
|
||||
#include "../LabelTrack.h"
|
||||
#include "../Menus.h"
|
||||
#include "../NoteTrack.h"
|
||||
@ -1090,12 +1091,34 @@ static CommandHandlerObject &findCommandHandler(AudacityProject &) {
|
||||
|
||||
MenuTable::BaseItemPtr LabelEditMenus( AudacityProject &project );
|
||||
|
||||
const ReservedCommandFlag
|
||||
CutCopyAvailableFlag{
|
||||
[](const AudacityProject &project){
|
||||
auto range = TrackList::Get( project ).Any<const LabelTrack>()
|
||||
+ &LabelTrack::IsTextSelected;
|
||||
if ( !range.empty() )
|
||||
return true;
|
||||
|
||||
if (
|
||||
!AudioIOBusyPred( project )
|
||||
&&
|
||||
TimeSelectedPred( project )
|
||||
&&
|
||||
TracksSelectedPred( project )
|
||||
)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
},
|
||||
cutCopyOptions
|
||||
};
|
||||
|
||||
MenuTable::BaseItemPtr EditMenu( AudacityProject & )
|
||||
{
|
||||
using namespace MenuTable;
|
||||
using Options = CommandManager::Options;
|
||||
|
||||
constexpr auto NotBusyTimeAndTracksFlags =
|
||||
static const auto NotBusyTimeAndTracksFlags =
|
||||
AudioIONotBusyFlag | TimeSelectedFlag | TracksSelectedFlag;
|
||||
|
||||
// The default shortcut key for Redo is different on different platforms.
|
||||
@ -1135,12 +1158,10 @@ MenuTable::BaseItemPtr EditMenu( AudacityProject & )
|
||||
/* i18n-hint: (verb)*/
|
||||
Command( wxT("Cut"), XXO("Cu&t"), FN(OnCut),
|
||||
AudioIONotBusyFlag | CutCopyAvailableFlag | NoAutoSelect,
|
||||
Options{ wxT("Ctrl+X") }
|
||||
.Mask( AudioIONotBusyFlag | CutCopyAvailableFlag ) ),
|
||||
wxT("Ctrl+X") ),
|
||||
Command( wxT("Delete"), XXO("&Delete"), FN(OnDelete),
|
||||
AudioIONotBusyFlag | NoAutoSelect,
|
||||
Options{ wxT("Ctrl+K") }
|
||||
.Mask( AudioIONotBusyFlag ) ),
|
||||
wxT("Ctrl+K") ),
|
||||
/* i18n-hint: (verb)*/
|
||||
Command( wxT("Copy"), XXO("&Copy"), FN(OnCopy),
|
||||
AudioIONotBusyFlag | CutCopyAvailableFlag, wxT("Ctrl+C") ),
|
||||
@ -1156,10 +1177,12 @@ MenuTable::BaseItemPtr EditMenu( AudacityProject & )
|
||||
Menu( _("R&emove Special"),
|
||||
/* i18n-hint: (verb) Do a special kind of cut*/
|
||||
Command( wxT("SplitCut"), XXO("Spl&it Cut"), FN(OnSplitCut),
|
||||
NotBusyTimeAndTracksFlags, wxT("Ctrl+Alt+X") ),
|
||||
NotBusyTimeAndTracksFlags,
|
||||
Options{ wxT("Ctrl+Alt+X") }.UseStrictFlags() ),
|
||||
/* i18n-hint: (verb) Do a special kind of DELETE*/
|
||||
Command( wxT("SplitDelete"), XXO("Split D&elete"), FN(OnSplitDelete),
|
||||
NotBusyTimeAndTracksFlags, wxT("Ctrl+Alt+K") ),
|
||||
NotBusyTimeAndTracksFlags,
|
||||
Options{ wxT("Ctrl+Alt+K") }.UseStrictFlags() ),
|
||||
|
||||
Separator(),
|
||||
|
||||
@ -1170,7 +1193,7 @@ MenuTable::BaseItemPtr EditMenu( AudacityProject & )
|
||||
/* i18n-hint: (verb)*/
|
||||
Command( wxT("Trim"), XXO("Tri&m Audio"), FN(OnTrim),
|
||||
AudioIONotBusyFlag | TimeSelectedFlag | AudioTracksSelectedFlag,
|
||||
wxT("Ctrl+T") )
|
||||
Options{ wxT("Ctrl+T") }.UseStrictFlags() )
|
||||
),
|
||||
|
||||
Separator(),
|
||||
@ -1180,10 +1203,11 @@ MenuTable::BaseItemPtr EditMenu( AudacityProject & )
|
||||
Menu( _("Clip B&oundaries"),
|
||||
/* i18n-hint: (verb) It's an item on a menu. */
|
||||
Command( wxT("Split"), XXO("Sp&lit"), FN(OnSplit),
|
||||
AudioIONotBusyFlag | WaveTracksSelectedFlag, wxT("Ctrl+I") ),
|
||||
AudioIONotBusyFlag | WaveTracksSelectedFlag,
|
||||
Options{ wxT("Ctrl+I") }.UseStrictFlags() ),
|
||||
Command( wxT("SplitNew"), XXO("Split Ne&w"), FN(OnSplitNew),
|
||||
AudioIONotBusyFlag | TimeSelectedFlag | WaveTracksSelectedFlag,
|
||||
wxT("Ctrl+Alt+I") ),
|
||||
Options{ wxT("Ctrl+Alt+I") }.UseStrictFlags() ),
|
||||
|
||||
Separator(),
|
||||
|
||||
@ -1216,17 +1240,39 @@ MenuTable::BaseItemPtr ExtraEditMenu( AudacityProject & )
|
||||
{
|
||||
using namespace MenuTable;
|
||||
using Options = CommandManager::Options;
|
||||
constexpr auto flags =
|
||||
static const auto flags =
|
||||
AudioIONotBusyFlag | TracksSelectedFlag | TimeSelectedFlag;
|
||||
return Menu( _("&Edit"),
|
||||
Command( wxT("DeleteKey"), XXO("&Delete Key"), FN(OnDelete),
|
||||
(flags | NoAutoSelect),
|
||||
Options{ wxT("Backspace") }.Mask( flags ) ),
|
||||
wxT("Backspace") ),
|
||||
Command( wxT("DeleteKey2"), XXO("Delete Key&2"), FN(OnDelete),
|
||||
(flags | NoAutoSelect),
|
||||
Options{ wxT("Delete") }.Mask( flags ) )
|
||||
wxT("Delete") )
|
||||
);
|
||||
}
|
||||
|
||||
auto canSelectAll = [](const AudacityProject &project){
|
||||
return MenuManager::Get( project ).mWhatIfNoSelection != 0; };
|
||||
auto selectAll = []( AudacityProject &project, CommandFlag flagsRqd ){
|
||||
if ( MenuManager::Get( project ).mWhatIfNoSelection == 1 &&
|
||||
(flagsRqd & NoAutoSelect).none() )
|
||||
SelectActions::DoSelectAllAudio(project);
|
||||
};
|
||||
|
||||
RegisteredMenuItemEnabler selectTracks{{
|
||||
TracksExistFlag,
|
||||
TracksSelectedFlag,
|
||||
canSelectAll,
|
||||
selectAll
|
||||
}};
|
||||
|
||||
RegisteredMenuItemEnabler selectWaveTracks{{
|
||||
WaveTracksExistFlag,
|
||||
TimeSelectedFlag | WaveTracksSelectedFlag | CutCopyAvailableFlag,
|
||||
canSelectAll,
|
||||
selectAll
|
||||
}};
|
||||
|
||||
#undef XXO
|
||||
#undef FN
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include "../CommonCommandFlags.h"
|
||||
#include "../Prefs.h"
|
||||
#include "../Project.h"
|
||||
#include "../commands/CommandContext.h"
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "../Experimental.h"
|
||||
|
||||
#include "../BatchCommands.h"
|
||||
#include "../CommonCommandFlags.h"
|
||||
#include "../FileNames.h"
|
||||
#include "../LabelTrack.h"
|
||||
#include "../MissingAliasFileDialog.h"
|
||||
@ -589,6 +590,7 @@ static CommandHandlerObject &findCommandHandler(AudacityProject &) {
|
||||
MenuTable::BaseItemPtr FileMenu( AudacityProject& )
|
||||
{
|
||||
using namespace MenuTable;
|
||||
using Options = CommandManager::Options;
|
||||
|
||||
return Menu( _("&File"),
|
||||
/*i18n-hint: "New" is an action (verb) to create a NEW project*/
|
||||
@ -683,7 +685,8 @@ MenuTable::BaseItemPtr FileMenu( AudacityProject& )
|
||||
// Enable Export Selection commands only when there's a selection.
|
||||
Command( wxT("ExportSel"), XXO("Expo&rt Selected Audio..."),
|
||||
FN(OnExportSelection),
|
||||
AudioIONotBusyFlag | TimeSelectedFlag | WaveTracksSelectedFlag ),
|
||||
AudioIONotBusyFlag | TimeSelectedFlag | WaveTracksSelectedFlag,
|
||||
Options{}.UseStrictFlags() ),
|
||||
|
||||
Command( wxT("ExportLabels"), XXO("Export &Labels..."),
|
||||
FN(OnExportLabels),
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "../AllThemeResources.h"
|
||||
#include "../AudacityLogger.h"
|
||||
#include "../AudioIOBase.h"
|
||||
#include "../CommonCommandFlags.h"
|
||||
#include "../CrashReport.h"
|
||||
#include "../Dependencies.h"
|
||||
#include "../FileNames.h"
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "../AudioIOBase.h"
|
||||
#include "../Clipboard.h"
|
||||
#include "../CommonCommandFlags.h"
|
||||
#include "../LabelTrack.h"
|
||||
#include "../Menus.h"
|
||||
#include "../Prefs.h"
|
||||
@ -586,7 +587,7 @@ MenuTable::BaseItemPtr LabelEditMenus( AudacityProject & )
|
||||
|
||||
static const auto checkOff = Options{}.CheckState( false );
|
||||
|
||||
constexpr auto NotBusyLabelsAndWaveFlags =
|
||||
static const auto NotBusyLabelsAndWaveFlags =
|
||||
AudioIONotBusyFlag |
|
||||
LabelsSelectedFlag | WaveTracksExistFlag | TimeSelectedFlag;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "../Audacity.h"
|
||||
|
||||
#include "../CommonCommandFlags.h"
|
||||
#include "../Menus.h"
|
||||
#include "../Prefs.h"
|
||||
#include "../Project.h"
|
||||
@ -580,7 +581,7 @@ MenuTable::BaseItemPtr ExtraGlobalCommands( AudacityProject & )
|
||||
MenuTable::BaseItemPtr ExtraFocusMenu( AudacityProject & )
|
||||
{
|
||||
using namespace MenuTable;
|
||||
constexpr auto FocusedTracksFlags = TracksExistFlag | TrackPanelHasFocus;
|
||||
static const auto FocusedTracksFlags = TracksExistFlag | TrackPanelHasFocus;
|
||||
|
||||
return Menu( _("F&ocus"),
|
||||
Command( wxT("PrevFrame"),
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "../AudioIO.h"
|
||||
#include "../BatchProcessDialog.h"
|
||||
#include "../Benchmark.h"
|
||||
#include "../CommonCommandFlags.h"
|
||||
#include "../FreqWindow.h"
|
||||
#include "../Menus.h"
|
||||
#include "../MissingAliasFileDialog.h"
|
||||
@ -923,6 +924,13 @@ MenuTable::BaseItemPtr GenerateMenu( AudacityProject & )
|
||||
);
|
||||
}
|
||||
|
||||
const ReservedCommandFlag
|
||||
IsRealtimeNotActiveFlag{
|
||||
[](const AudacityProject &){
|
||||
return !EffectManager::Get().RealtimeIsActive();
|
||||
}
|
||||
}; //lll
|
||||
|
||||
MenuTable::BaseItemPtr EffectMenu( AudacityProject &project )
|
||||
{
|
||||
using namespace MenuTable;
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "../AdornedRulerPanel.h"
|
||||
#include "../AudioIO.h"
|
||||
#include "../CommonCommandFlags.h"
|
||||
#include "../FreqWindow.h"
|
||||
#include "../Menus.h" // for PrefsListener
|
||||
#include "../Prefs.h"
|
||||
@ -513,7 +514,7 @@ void SelectAllIfNone( AudacityProject &project )
|
||||
{
|
||||
auto &viewInfo = ViewInfo::Get( project );
|
||||
auto flags = MenuManager::Get( project ).GetUpdateFlags();
|
||||
if(!(flags & TracksSelectedFlag) ||
|
||||
if((flags & TracksSelectedFlag).none() ||
|
||||
viewInfo.selectedRegion.isPoint())
|
||||
DoSelectAllAudio( project );
|
||||
}
|
||||
@ -1332,7 +1333,7 @@ MenuTable::BaseItemPtr CursorMenu( AudacityProject & )
|
||||
{
|
||||
using namespace MenuTable;
|
||||
using Options = CommandManager::Options;
|
||||
constexpr auto CanStopFlags = AudioIONotBusyFlag | CanStopAudioStreamFlag;
|
||||
static const auto CanStopFlags = AudioIONotBusyFlag | CanStopAudioStreamFlag;
|
||||
|
||||
// JKC: ANSWER-ME: How is 'cursor to' different to 'Skip To' and how is it
|
||||
// useful?
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "../Audacity.h"
|
||||
#include "../Experimental.h"
|
||||
|
||||
#include "../CommonCommandFlags.h"
|
||||
#include "../LabelTrack.h"
|
||||
#include "../Menus.h"
|
||||
#include "../MissingAliasFileDialog.h"
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "../AdornedRulerPanel.h"
|
||||
#include "../AudioIO.h"
|
||||
#include "../CommonCommandFlags.h"
|
||||
#include "../DeviceManager.h"
|
||||
#include "../LabelTrack.h"
|
||||
#include "../Menus.h"
|
||||
@ -208,8 +209,7 @@ namespace TransportActions {
|
||||
// Stop playing or recording, if paused.
|
||||
void StopIfPaused( AudacityProject &project )
|
||||
{
|
||||
auto flags = MenuManager::Get( project ).GetUpdateFlags();
|
||||
if( flags & PausedFlag )
|
||||
if( AudioIOBase::Get()->IsPaused() )
|
||||
DoStop( project );
|
||||
}
|
||||
|
||||
@ -1076,7 +1076,7 @@ MenuTable::BaseItemPtr TransportMenu( AudacityProject &project )
|
||||
static const auto checkOff = Options{}.CheckState( false );
|
||||
static const auto checkOn = Options{}.CheckState( true );
|
||||
|
||||
constexpr auto CanStopFlags = AudioIONotBusyFlag | CanStopAudioStreamFlag;
|
||||
static const auto CanStopFlags = AudioIONotBusyFlag | CanStopAudioStreamFlag;
|
||||
|
||||
/* i18n-hint: 'Transport' is the name given to the set of controls that
|
||||
play, record, pause etc. */
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "../Audacity.h"
|
||||
#include "../Experimental.h"
|
||||
|
||||
#include "../CommonCommandFlags.h"
|
||||
#include "../HistoryWindow.h"
|
||||
#include "../LyricsWindow.h"
|
||||
#include "../Menus.h"
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#ifdef __WXMAC__
|
||||
|
||||
#include "../CommonCommandFlags.h"
|
||||
#include "../Menus.h"
|
||||
#include "../Project.h"
|
||||
#include "../commands/CommandContext.h"
|
||||
|
@ -60,6 +60,7 @@
|
||||
#include "../AdornedRulerPanel.h"
|
||||
#include "../AllThemeResources.h"
|
||||
#include "../AudioIO.h"
|
||||
#include "../CommonCommandFlags.h"
|
||||
#include "../ImageManipulation.h"
|
||||
#include "../Menus.h"
|
||||
#include "../Prefs.h"
|
||||
@ -824,7 +825,7 @@ void ControlToolBar::OnStop(wxCommandEvent & WXUNUSED(evt))
|
||||
}
|
||||
}
|
||||
|
||||
bool ControlToolBar::CanStopAudioStream()
|
||||
bool ControlToolBar::CanStopAudioStream() const
|
||||
{
|
||||
auto gAudioIO = AudioIO::Get();
|
||||
return (!gAudioIO->IsStreamActive() ||
|
||||
@ -1082,7 +1083,6 @@ bool ControlToolBar::DoRecord(AudacityProject &project,
|
||||
// NB: The call may have the side effect of changing flags.
|
||||
bool allowed = MenuManager::Get(project).TryToMakeActionAllowed(
|
||||
flags,
|
||||
AudioIONotBusyFlag | CanStopAudioStreamFlag,
|
||||
AudioIONotBusyFlag | CanStopAudioStreamFlag);
|
||||
|
||||
if (!allowed)
|
||||
@ -1563,3 +1563,10 @@ static RegisteredToolbarFactory factory{ TransportBarID,
|
||||
[]( AudacityProject &project ){
|
||||
return ToolBar::Holder{ safenew ControlToolBar{ project } }; }
|
||||
};
|
||||
|
||||
const ReservedCommandFlag
|
||||
CanStopAudioStreamFlag{
|
||||
[](const AudacityProject &project){
|
||||
return ControlToolBar::Get( project ).CanStopAudioStream();
|
||||
}
|
||||
};
|
||||
|
@ -99,7 +99,7 @@ class ControlToolBar final : public ToolBar {
|
||||
bool IsRecordDown() const;
|
||||
|
||||
// A project is only allowed to stop an audio stream that it owns.
|
||||
bool CanStopAudioStream ();
|
||||
bool CanStopAudioStream () const;
|
||||
|
||||
// Play currently selected region, or if nothing selected,
|
||||
// play from current cursor.
|
||||
@ -210,5 +210,10 @@ class ControlToolBar final : public ToolBar {
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
#include "../commands/CommandFlag.h"
|
||||
|
||||
extern const ReservedCommandFlag
|
||||
CanStopAudioStreamFlag;
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -49,6 +49,7 @@
|
||||
#endif
|
||||
|
||||
#include "../AllThemeResources.h"
|
||||
#include "../BatchCommands.h"
|
||||
#include "../ImageManipulation.h"
|
||||
#include "../Menus.h"
|
||||
#include "../Prefs.h"
|
||||
@ -299,7 +300,8 @@ void EditToolBar::OnButton(wxCommandEvent &event)
|
||||
|
||||
auto flags = MenuManager::Get(*p).GetUpdateFlags();
|
||||
const CommandContext context( *p );
|
||||
cm.HandleTextualCommand(EditToolbarButtonList[id].commandName, context, flags, NoFlagsSpecified);
|
||||
MacroCommands::HandleTextualCommand( cm,
|
||||
EditToolbarButtonList[id].commandName, context, flags, false);
|
||||
}
|
||||
|
||||
static RegisteredToolbarFactory factory{ EditBarID,
|
||||
|
@ -57,10 +57,9 @@
|
||||
#include "../ImageManipulation.h"
|
||||
#include "../Prefs.h"
|
||||
#include "../Project.h"
|
||||
#include "../ProjectWindow.h"
|
||||
#include "../widgets/AButton.h"
|
||||
#include "../widgets/ASlider.h"
|
||||
#include "../widgets/Meter.h"
|
||||
#include "../widgets/MeterPanelBase.h"
|
||||
#include "../widgets/Grabber.h"
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
@ -73,7 +72,7 @@
|
||||
//
|
||||
ToolFrame::ToolFrame
|
||||
( AudacityProject *parent, ToolManager *manager, ToolBar *bar, wxPoint pos )
|
||||
: wxFrame( ProjectWindow::Find( parent ),
|
||||
: wxFrame( FindProjectFrame( parent ),
|
||||
bar->GetId(),
|
||||
wxEmptyString,
|
||||
pos,
|
||||
@ -312,10 +311,26 @@ BEGIN_EVENT_TABLE( ToolManager, wxEvtHandler )
|
||||
EVT_TIMER( wxID_ANY, ToolManager::OnTimer )
|
||||
END_EVENT_TABLE()
|
||||
|
||||
static ToolManager::GetTopPanelHook &getTopPanelHook()
|
||||
{
|
||||
static ToolManager::GetTopPanelHook theHook;
|
||||
return theHook;
|
||||
}
|
||||
|
||||
auto ToolManager::SetGetTopPanelHook( const GetTopPanelHook &hook )
|
||||
-> GetTopPanelHook
|
||||
{
|
||||
auto &theHook = getTopPanelHook();
|
||||
auto result = theHook;
|
||||
theHook = hook;
|
||||
return result;
|
||||
}
|
||||
|
||||
static const AudacityProject::AttachedObjects::RegisteredFactory key{
|
||||
[]( AudacityProject &parent ){
|
||||
auto &window = ProjectWindow::Get( parent );
|
||||
return std::make_shared< ToolManager >( &parent, window.GetTopPanel() ); }
|
||||
auto &window = GetProjectFrame( parent );
|
||||
return std::make_shared< ToolManager >(
|
||||
&parent, getTopPanelHook()( window ) ); }
|
||||
};
|
||||
|
||||
ToolManager &ToolManager::Get( AudacityProject &project )
|
||||
@ -334,7 +349,10 @@ const ToolManager &ToolManager::Get( const AudacityProject &project )
|
||||
ToolManager::ToolManager( AudacityProject *parent, wxWindow *topDockParent )
|
||||
: wxEvtHandler()
|
||||
{
|
||||
auto &window = ProjectWindow::Get( *parent );
|
||||
if ( !topDockParent )
|
||||
THROW_INCONSISTENCY_EXCEPTION;
|
||||
|
||||
auto &window = GetProjectFrame( *parent );
|
||||
wxPoint pt[ 3 ];
|
||||
|
||||
#if defined(__WXMAC__)
|
||||
@ -653,7 +671,7 @@ int ToolManager::FilterEvent(wxEvent &event)
|
||||
if ( window &&
|
||||
!dynamic_cast<Grabber*>( window ) &&
|
||||
!dynamic_cast<ToolFrame*>( window ) &&
|
||||
top == ProjectWindow::Find( mParent ) )
|
||||
top == FindProjectFrame( mParent ) )
|
||||
// Note this is a dangle-proof wxWindowRef:
|
||||
mLastFocus = window;
|
||||
}
|
||||
@ -1022,6 +1040,11 @@ ToolDock *ToolManager::GetTopDock()
|
||||
return mTopDock;
|
||||
}
|
||||
|
||||
const ToolDock *ToolManager::GetTopDock() const
|
||||
{
|
||||
return mTopDock;
|
||||
}
|
||||
|
||||
//
|
||||
// Return a pointer to the bottom dock
|
||||
//
|
||||
@ -1030,6 +1053,11 @@ ToolDock *ToolManager::GetBotDock()
|
||||
return mBotDock;
|
||||
}
|
||||
|
||||
const ToolDock *ToolManager::GetBotDock() const
|
||||
{
|
||||
return mBotDock;
|
||||
}
|
||||
|
||||
//
|
||||
// Queues an EVT_TOOLBAR_UPDATED command event to notify any
|
||||
// interest parties of an updated toolbar or dock layout
|
||||
@ -1517,7 +1545,7 @@ bool ToolManager::RestoreFocus()
|
||||
if (mLastFocus) {
|
||||
auto temp1 = AButton::TemporarilyAllowFocus();
|
||||
auto temp2 = ASlider::TemporarilyAllowFocus();
|
||||
auto temp3 = MeterPanel::TemporarilyAllowFocus();
|
||||
auto temp3 = MeterPanelBase::TemporarilyAllowFocus();
|
||||
mLastFocus->SetFocus();
|
||||
return true;
|
||||
}
|
||||
|
@ -13,6 +13,8 @@
|
||||
#ifndef __AUDACITY_TOOLMANAGER__
|
||||
#define __AUDACITY_TOOLMANAGER__
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <wx/defs.h>
|
||||
#include <wx/eventfilter.h> // to inherit
|
||||
#include <wx/frame.h> // to inherit
|
||||
@ -48,6 +50,9 @@ class ToolManager final
|
||||
{
|
||||
|
||||
public:
|
||||
// a hook function to break dependency of ToolManager on ProjectWindow
|
||||
using GetTopPanelHook = std::function< wxWindow*( wxWindow& ) >;
|
||||
static GetTopPanelHook SetGetTopPanelHook( const GetTopPanelHook& );
|
||||
|
||||
static ToolManager &Get( AudacityProject &project );
|
||||
static const ToolManager &Get( const AudacityProject &project );
|
||||
@ -68,7 +73,9 @@ class ToolManager final
|
||||
ToolBar *GetToolBar( int type ) const;
|
||||
|
||||
ToolDock *GetTopDock();
|
||||
const ToolDock *GetTopDock() const;
|
||||
ToolDock *GetBotDock();
|
||||
const ToolDock *GetBotDock() const;
|
||||
|
||||
void Reset();
|
||||
void Destroy();
|
||||
|
@ -17,6 +17,7 @@ Paul Licameli split from TrackPanel.cpp
|
||||
|
||||
#include "../../AdornedRulerPanel.h"
|
||||
#include "../../AudioIO.h"
|
||||
#include "../../CommonCommandFlags.h"
|
||||
#include "../../Menus.h"
|
||||
#include "../../Project.h"
|
||||
#include "../../ProjectAudioIO.h"
|
||||
|
@ -268,7 +268,7 @@ enum {
|
||||
OnPreferencesID
|
||||
};
|
||||
|
||||
BEGIN_EVENT_TABLE(MeterPanel, wxPanelWrapper)
|
||||
BEGIN_EVENT_TABLE(MeterPanel, MeterPanelBase)
|
||||
EVT_TIMER(OnMeterUpdateID, MeterPanel::OnMeterUpdate)
|
||||
EVT_MOUSE_EVENTS(MeterPanel::OnMouse)
|
||||
EVT_CONTEXT_MENU(MeterPanel::OnContext)
|
||||
@ -2123,13 +2123,6 @@ wxString MeterPanel::Key(const wxString & key) const
|
||||
return wxT("/Meter/Output/") + key;
|
||||
}
|
||||
|
||||
bool MeterPanel::s_AcceptsFocus{ false };
|
||||
|
||||
auto MeterPanel::TemporarilyAllowFocus() -> TempAllowFocus {
|
||||
s_AcceptsFocus = true;
|
||||
return TempAllowFocus{ &s_AcceptsFocus };
|
||||
}
|
||||
|
||||
// This compensates for a but in wxWidgets 3.0.2 for mac:
|
||||
// Couldn't set focus from keyboard when AcceptsFocus returns false;
|
||||
// this bypasses that limitation
|
||||
|
@ -117,9 +117,6 @@ class MeterPanel final : public MeterPanelBase, private PrefsListener
|
||||
Style style = HorizontalStereo,
|
||||
float fDecayRate = 60.0f);
|
||||
|
||||
bool AcceptsFocus() const override { return s_AcceptsFocus; }
|
||||
bool AcceptsFocusFromKeyboard() const override { return true; }
|
||||
|
||||
void SetFocusFromKbd() override;
|
||||
|
||||
void Clear() override;
|
||||
@ -192,13 +189,6 @@ class MeterPanel final : public MeterPanelBase, private PrefsListener
|
||||
void UpdatePrefs() override;
|
||||
void UpdateSelectedPrefs( int ) override;
|
||||
|
||||
static bool s_AcceptsFocus;
|
||||
struct Resetter { void operator () (bool *p) const { if(p) *p = false; } };
|
||||
using TempAllowFocus = std::unique_ptr<bool, Resetter>;
|
||||
|
||||
public:
|
||||
static TempAllowFocus TemporarilyAllowFocus();
|
||||
|
||||
private:
|
||||
//
|
||||
// Event handlers
|
||||
|
@ -13,3 +13,10 @@ Paul Licameli split from Meter.cpp
|
||||
MeterPanelBase::~MeterPanelBase()
|
||||
{
|
||||
}
|
||||
|
||||
bool MeterPanelBase::s_AcceptsFocus{ false };
|
||||
|
||||
auto MeterPanelBase::TemporarilyAllowFocus() -> TempAllowFocus {
|
||||
s_AcceptsFocus = true;
|
||||
return TempAllowFocus{ &s_AcceptsFocus };
|
||||
}
|
||||
|
@ -26,7 +26,17 @@ public:
|
||||
int numFrames, float *sampleData) = 0;
|
||||
virtual bool IsMeterDisabled() const = 0;
|
||||
virtual float GetMaxPeak() const = 0;
|
||||
|
||||
bool AcceptsFocus() const override { return s_AcceptsFocus; }
|
||||
bool AcceptsFocusFromKeyboard() const override { return true; }
|
||||
|
||||
private:
|
||||
static bool s_AcceptsFocus;
|
||||
struct Resetter { void operator () (bool *p) const { if(p) *p = false; } };
|
||||
using TempAllowFocus = std::unique_ptr<bool, Resetter>;
|
||||
|
||||
public:
|
||||
static TempAllowFocus TemporarilyAllowFocus();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -140,6 +140,7 @@
|
||||
<ClCompile Include="..\..\..\src\blockfile\NotYetAvailableException.cpp" />
|
||||
<ClCompile Include="..\..\..\src\CellularPanel.cpp" />
|
||||
<ClCompile Include="..\..\..\src\Clipboard.cpp" />
|
||||
<ClCompile Include="..\..\..\src\CommonCommandFlags.cpp" />
|
||||
<ClCompile Include="..\..\..\src\CrashReport.cpp" />
|
||||
<ClCompile Include="..\..\..\src\commands\AudacityCommand.cpp" />
|
||||
<ClCompile Include="..\..\..\src\commands\CommandContext.cpp" />
|
||||
@ -522,6 +523,7 @@
|
||||
<ClInclude Include="..\..\..\src\Clipboard.h" />
|
||||
<ClInclude Include="..\..\..\src\ClientData.h" />
|
||||
<ClInclude Include="..\..\..\src\ClientDataHelpers.h" />
|
||||
<ClInclude Include="..\..\..\src\CommonCommandFlags.h" />
|
||||
<ClInclude Include="..\..\..\src\CrashReport.h" />
|
||||
<ClInclude Include="..\..\..\src\commands\AudacityCommand.h" />
|
||||
<ClInclude Include="..\..\..\src\commands\CommandContext.h" />
|
||||
|
@ -1148,6 +1148,9 @@
|
||||
<ClCompile Include="..\..\..\src\Clipboard.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\CommonCommandFlags.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\CrashReport.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
@ -2314,6 +2317,9 @@
|
||||
<ClInclude Include="..\..\..\src\ClientDataHelpers.h">
|
||||
<Filter>src</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\CommonCommandFlags.h">
|
||||
<Filter>src</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\CrashReport.h">
|
||||
<Filter>src</Filter>
|
||||
</ClInclude>
|
||||
|
Loading…
x
Reference in New Issue
Block a user