mirror of
https://github.com/cookiengineer/audacity
synced 2025-08-04 22:29:27 +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:
parent
9a4c18255e
commit
76996bf0cd
142
src/Menus.cpp
142
src/Menus.cpp
@ -814,6 +814,55 @@ 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 );
|
||||
}
|
||||
|
||||
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
|
||||
// get multiple effect preview working
|
||||
void MenuManager::UpdateMenus( bool checkActive )
|
||||
@ -827,6 +876,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.
|
||||
@ -834,33 +889,15 @@ 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).any() )
|
||||
{
|
||||
flags2 |= TracksSelectedFlag;
|
||||
if ( (flags & WaveTracksExistFlag).any() )
|
||||
{
|
||||
flags2 |= TimeSelectedFlag
|
||||
| WaveTracksSelectedFlag
|
||||
| CutCopyAvailableFlag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( mStopIfWasPaused )
|
||||
{
|
||||
if( (flags & PausedFlag).any() ){
|
||||
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 );
|
||||
|
||||
// With select-all-on-none, some items that we don't want enabled may have
|
||||
@ -908,7 +945,6 @@ bool MenuManager::ReportIfActionNotAllowed(
|
||||
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.
|
||||
@ -921,42 +957,24 @@ bool MenuManager::TryToMakeActionAllowed(
|
||||
if( flags.none() )
|
||||
flags = GetUpdateFlags();
|
||||
|
||||
bAllowed = ((flags & flagsRqd) == flagsRqd);
|
||||
if( bAllowed )
|
||||
return true;
|
||||
|
||||
// Why is action not allowed?
|
||||
// 1's wherever a required flag is missing.
|
||||
auto MissingFlags = (~flags & flagsRqd);
|
||||
|
||||
if( mStopIfWasPaused && (MissingFlags & AudioIONotBusyFlag ).any() ){
|
||||
TransportActions::StopIfPaused( project );
|
||||
// Hope this will now reflect stopped audio.
|
||||
flags = GetUpdateFlags();
|
||||
bAllowed = ((flags & flagsRqd) == flagsRqd);
|
||||
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).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;
|
||||
return (flags & flagsRqd) == flagsRqd;
|
||||
}
|
||||
|
@ -91,6 +91,7 @@ private:
|
||||
|
||||
AudacityProject &mProject;
|
||||
|
||||
public:
|
||||
// 0 is grey out, 1 is Autoselect, 2 is Give warnings.
|
||||
int mWhatIfNoSelection;
|
||||
bool mStopIfWasPaused;
|
||||
|
@ -94,4 +94,26 @@ extern const ReservedCommandFlag
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user