mirror of
https://github.com/cookiengineer/audacity
synced 2025-10-24 07:13:48 +02:00
TryToMakeActionAllowed is also table driven...
... and also the logic for relaxing the conditions for enabling the menu items
This commit is contained in:
142
src/Menus.cpp
142
src/Menus.cpp
@@ -814,6 +814,55 @@ void MenuManager::ModifyToolbarMenus(AudacityProject &project)
|
|||||||
commandManager.Check(wxT("TypeToCreateLabel"), active);
|
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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
RegisteredMenuItemEnabler stopIfPaused{{
|
||||||
|
PausedFlag,
|
||||||
|
AudioIONotBusyFlag,
|
||||||
|
[]( const AudacityProject &project ){
|
||||||
|
return MenuManager::Get( project ).mStopIfWasPaused; },
|
||||||
|
[]( AudacityProject &project, CommandFlag ){
|
||||||
|
if ( MenuManager::Get( project ).mStopIfWasPaused )
|
||||||
|
TransportActions::StopIfPaused( project );
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
||||||
|
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
|
||||||
|
}};
|
||||||
|
|
||||||
// checkActive is a temporary hack that should be removed as soon as we
|
// checkActive is a temporary hack that should be removed as soon as we
|
||||||
// get multiple effect preview working
|
// get multiple effect preview working
|
||||||
void MenuManager::UpdateMenus( bool checkActive )
|
void MenuManager::UpdateMenus( bool checkActive )
|
||||||
@@ -827,6 +876,12 @@ void MenuManager::UpdateMenus( bool checkActive )
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
auto flags = GetUpdateFlags(checkActive);
|
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;
|
auto flags2 = flags;
|
||||||
|
|
||||||
// We can enable some extra items if we have select-all-on-none.
|
// We can enable some extra items if we have select-all-on-none.
|
||||||
@@ -834,33 +889,15 @@ void MenuManager::UpdateMenus( bool checkActive )
|
|||||||
//ANSWER: Because flags2 is used in the menu enable/disable.
|
//ANSWER: Because flags2 is used in the menu enable/disable.
|
||||||
//The effect still needs flags to determine whether it will need
|
//The effect still needs flags to determine whether it will need
|
||||||
//to actually do the 'select all' to make the command valid.
|
//to actually do the 'select all' to make the command valid.
|
||||||
if (mWhatIfNoSelection != 0)
|
|
||||||
{
|
|
||||||
if ( (flags & TracksExistFlag).any() )
|
|
||||||
{
|
|
||||||
flags2 |= TracksSelectedFlag;
|
|
||||||
if ( (flags & WaveTracksExistFlag).any() )
|
|
||||||
{
|
|
||||||
flags2 |= TimeSelectedFlag
|
|
||||||
| WaveTracksSelectedFlag
|
|
||||||
| CutCopyAvailableFlag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( mStopIfWasPaused )
|
for ( const auto &enabler : Enablers() ) {
|
||||||
{
|
if (
|
||||||
if( (flags & PausedFlag).any() ){
|
enabler.applicable( project ) &&
|
||||||
flags2 |= AudioIONotBusyFlag;
|
(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 );
|
auto &commandManager = CommandManager::Get( project );
|
||||||
|
|
||||||
// With select-all-on-none, some items that we don't want enabled may have
|
// With select-all-on-none, some items that we don't want enabled may have
|
||||||
@@ -908,7 +945,6 @@ bool MenuManager::ReportIfActionNotAllowed(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Determines if flags for command are compatible with current state.
|
/// Determines if flags for command are compatible with current state.
|
||||||
/// If not, then try some recovery action to make it so.
|
/// If not, then try some recovery action to make it so.
|
||||||
/// @return whether compatible or not after any actions taken.
|
/// @return whether compatible or not after any actions taken.
|
||||||
@@ -921,42 +957,24 @@ bool MenuManager::TryToMakeActionAllowed(
|
|||||||
if( flags.none() )
|
if( flags.none() )
|
||||||
flags = GetUpdateFlags();
|
flags = GetUpdateFlags();
|
||||||
|
|
||||||
bAllowed = ((flags & flagsRqd) == flagsRqd);
|
// Visit the table of recovery actions
|
||||||
if( bAllowed )
|
auto &enablers = Enablers();
|
||||||
return true;
|
auto iter = enablers.begin(), end = enablers.end();
|
||||||
|
while ((flags & flagsRqd) != flagsRqd && iter != end) {
|
||||||
// Why is action not allowed?
|
const auto &enabler = *iter;
|
||||||
// 1's wherever a required flag is missing.
|
auto MissingFlags = (~flags & flagsRqd);
|
||||||
auto MissingFlags = (~flags & flagsRqd);
|
if (
|
||||||
|
// Do we have the right precondition?
|
||||||
if( mStopIfWasPaused && (MissingFlags & AudioIONotBusyFlag ).any() ){
|
(flags & enabler.actualFlags) == enabler.actualFlags
|
||||||
TransportActions::StopIfPaused( project );
|
&&
|
||||||
// Hope this will now reflect stopped audio.
|
// Can we get the condition we need?
|
||||||
flags = GetUpdateFlags();
|
(MissingFlags & enabler.possibleFlags) == MissingFlags
|
||||||
bAllowed = ((flags & flagsRqd) == flagsRqd);
|
) {
|
||||||
if( bAllowed )
|
// Then try the function
|
||||||
return true;
|
enabler.tryEnable( project, flagsRqd );
|
||||||
|
flags = GetUpdateFlags();
|
||||||
|
}
|
||||||
|
++iter;
|
||||||
}
|
}
|
||||||
|
return (flags & flagsRqd) == flagsRqd;
|
||||||
//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).any() )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// IF selecting all audio won't do any good, THEN return with failure.
|
|
||||||
if( (flags & WaveTracksExistFlag).none() )
|
|
||||||
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 & flagsRqd) == flagsRqd);
|
|
||||||
return bAllowed;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ private:
|
|||||||
|
|
||||||
AudacityProject &mProject;
|
AudacityProject &mProject;
|
||||||
|
|
||||||
|
public:
|
||||||
// 0 is grey out, 1 is Autoselect, 2 is Give warnings.
|
// 0 is grey out, 1 is Autoselect, 2 is Give warnings.
|
||||||
int mWhatIfNoSelection;
|
int mWhatIfNoSelection;
|
||||||
bool mStopIfWasPaused;
|
bool mStopIfWasPaused;
|
||||||
|
|||||||
@@ -94,4 +94,26 @@ extern const ReservedCommandFlag
|
|||||||
NoAutoSelect // jkc
|
NoAutoSelect // jkc
|
||||||
;
|
;
|
||||||
|
|
||||||
|
// 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
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user