Skip to content

Commit

Permalink
Lift wxWidgets-specific logic out of CommandManager with new virtuals
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul-Licameli committed Oct 25, 2023
1 parent 126aaf3 commit fca64ec
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 169 deletions.
97 changes: 97 additions & 0 deletions src/MenuCreator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,16 @@ struct MenuItemVisitor final : CommandManager::Populator

void DoVisit(const SingleItem &item, const Path&) final;
void DoSeparator() final;

private:
void BeginMenu(const TranslatableString & tName) final;
void EndMenu() final;
void BeginMainMenu(const TranslatableString & tName);
void EndMainMenu();
void BeginSubMenu(const TranslatableString & tName);
void EndSubMenu();
void BeginOccultCommands() final;
void EndOccultCommands() final;
};

MenuItemVisitor::CommandListEntryEx::~CommandListEntryEx() = default;
Expand Down Expand Up @@ -292,6 +302,93 @@ MenuItemVisitor::MenuItemVisitor(AudacityProject &proj)
}

MenuItemVisitor::~MenuItemVisitor() = default;

void MenuItemVisitor::BeginMenu(const TranslatableString & tName)
{
if ( mCurrentMenu )
return BeginSubMenu( tName );
else
return BeginMainMenu( tName );
}

/// This attaches a menu, if it's main, to the menubar
// and in all cases ends the menu
void MenuItemVisitor::EndMenu()
{
if ( mSubMenuList.empty() )
EndMainMenu();
else
EndSubMenu();
}

void MenuItemVisitor::BeginMainMenu(const TranslatableString & tName)
{
uCurrentMenu = std::make_unique<wxMenu>();
mCurrentMenu = uCurrentMenu.get();
mCurrentMenuName = tName;
}

/// This attaches a menu to the menubar and ends the menu
void MenuItemVisitor::EndMainMenu()
{
// Add the menu to the menubar after all menu items have been
// added to the menu to allow OSX to rearrange special menu
// items like Preferences, About, and Quit.
wxASSERT(uCurrentMenu);
CurrentMenuBar()->Append(
uCurrentMenu.release(), mCurrentMenuName.Translation());
mCurrentMenu = nullptr;
mCurrentMenuName = CommandManager::COMMAND;
}

/// This starts a new submenu, and names it according to
/// the function's argument.
void MenuItemVisitor::BeginSubMenu(const TranslatableString & tName)
{
mSubMenuList.emplace_back( tName );
mbSeparatorAllowed = false;
}

/// This function is called after the final item of a SUBmenu is added.
/// Submenu items are added just like regular menu items; they just happen
/// after BeginSubMenu() is called but before EndSubMenu() is called.
void MenuItemVisitor::EndSubMenu()
{
//Save the submenu's information
SubMenuListEntry tmpSubMenu{ std::move( mSubMenuList.back() ) };

//Pop off the NEW submenu so CurrentMenu returns the parent of the submenu
mSubMenuList.pop_back();

//Add the submenu to the current menu
auto name = tmpSubMenu.name.Translation();
CurrentMenu()->Append(0, name, tmpSubMenu.menu.release(),
name /* help string */ );
mbSeparatorAllowed = true;
}

void MenuItemVisitor::BeginOccultCommands()
{
// To do: perhaps allow occult item switching at lower levels of the
// menu tree.
wxASSERT( !CurrentMenu() );

// Make a temporary menu bar collecting items added after.
// This bar will be discarded but other side effects on the command
// manager persist.
mTempMenuBar = AddMenuBar(wxT("ext-menu"));
}

void MenuItemVisitor::EndOccultCommands()
{
auto iter = mMenuBarList.end();
if ( iter != mMenuBarList.begin() )
mMenuBarList.erase( --iter );
else
wxASSERT( false );
mTempMenuBar.reset();
}

}

void MenuCreator::CreateMenusAndCommands()
Expand Down
167 changes: 14 additions & 153 deletions src/commands/CommandManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,31 +45,11 @@ CommandManager. It holds the callback for one command.
*//****************************************************************//**
\class MenuBarListEntry
\brief MenuBarListEntry is a structure used by CommandManager.
*//****************************************************************//**
\class SubMenuListEntry
\brief SubMenuListEntry is a structure used by CommandManager.
*//****************************************************************//**
\class CommandListEntry
\brief CommandListEntry is a structure used by CommandManager.
*//****************************************************************//**
\class MenuBarList
\brief List of MenuBarListEntry.
*//****************************************************************//**
\class SubMenuList
\brief List of SubMenuListEntry.
*//****************************************************************//**
\class CommandList
\brief List of CommandListEntry.
Expand Down Expand Up @@ -108,25 +88,6 @@ const TranslatableString CommandManager::COMMAND = XO("Command");

CommandManager::CommandListEntry::~CommandListEntry() = default;

struct MenuBarListEntry
{
MenuBarListEntry(const wxString &name_, wxMenuBar *menubar_);
~MenuBarListEntry();

wxString name;
wxWeakRef<wxMenuBar> menubar; // This structure does not assume memory ownership!
};

struct SubMenuListEntry
{
SubMenuListEntry( const TranslatableString &name_ );
SubMenuListEntry( SubMenuListEntry&& ) = default;
~SubMenuListEntry();

TranslatableString name;
std::unique_ptr<wxMenu> menu;
};

MenuBarListEntry::MenuBarListEntry(const wxString &name_, wxMenuBar *menubar_)
: name(name_), menubar(menubar_)
{
Expand Down Expand Up @@ -316,8 +277,10 @@ void CommandManager::Populator::DoBeginGroup(
dynamic_cast<const ConditionalGroupItem*>(pItem)
) {
const auto flag = (*pConditionalGroup)();
if (!flag)
if (!flag) {
bMakingOccultCommands = true;
BeginOccultCommands();
}
// to avoid repeated call of condition predicate in EndGroup():
mFlags.push_back(flag);
}
Expand All @@ -328,6 +291,10 @@ void CommandManager::Populator::DoBeginGroup(
wxASSERT( false );
}

void CommandManager::Populator::BeginMenu(const TranslatableString &)
{
}

void CommandManager::Populator::DoEndGroup(
const Registry::GroupItemBase &item, const Path&)
{
Expand All @@ -341,8 +308,10 @@ void CommandManager::Populator::DoEndGroup(
dynamic_cast<const ConditionalGroupItem*>(pItem)
) {
const bool flag = mFlags.back();
if (!flag)
if (!flag) {
EndOccultCommands();
bMakingOccultCommands = false;
}
mFlags.pop_back();
}
else if (const auto pGroup = dynamic_cast<const MenuSection*>(pItem)) {
Expand All @@ -351,6 +320,10 @@ void CommandManager::Populator::DoEndGroup(
wxASSERT( false );
}

void CommandManager::Populator::EndMenu()
{
}

void CommandManager::Populator::DoVisit(
const Registry::SingleItem &item, const Path &path)
{
Expand Down Expand Up @@ -431,106 +404,6 @@ wxMenuBar * CommandManager::Populator::CurrentMenuBar() const
return mMenuBarList.back().menubar;
}

///
/// Typically used to switch back and forth
/// between adding to a hidden menu bar and
/// adding to one that is visible
///
void CommandManager::Populator::PopMenuBar()
{
auto iter = mMenuBarList.end();
if ( iter != mMenuBarList.begin() )
mMenuBarList.erase( --iter );
else
wxASSERT( false );
}


///
/// This starts a NEW menu
///
wxMenu *CommandManager::Populator::BeginMenu(const TranslatableString & tName)
{
if ( mCurrentMenu )
return BeginSubMenu( tName );
else
return BeginMainMenu( tName );
}


///
/// This attaches a menu, if it's main, to the menubar
// and in all cases ends the menu
///
void CommandManager::Populator::EndMenu()
{
if ( mSubMenuList.empty() )
EndMainMenu();
else
EndSubMenu();
}


///
/// This starts a NEW menu
///
wxMenu *CommandManager::Populator::BeginMainMenu(const TranslatableString & tName)
{
uCurrentMenu = std::make_unique<wxMenu>();
mCurrentMenu = uCurrentMenu.get();
mCurrentMenuName = tName;
return mCurrentMenu;
}


///
/// This attaches a menu to the menubar and ends the menu
///
void CommandManager::Populator::EndMainMenu()
{
// Add the menu to the menubar after all menu items have been
// added to the menu to allow OSX to rearrange special menu
// items like Preferences, About, and Quit.
wxASSERT(uCurrentMenu);
CurrentMenuBar()->Append(
uCurrentMenu.release(), mCurrentMenuName.Translation());
mCurrentMenu = nullptr;
mCurrentMenuName = COMMAND;
}


///
/// This starts a NEW submenu, and names it according to
/// the function's argument.
wxMenu* CommandManager::Populator::BeginSubMenu(const TranslatableString & tName)
{
mSubMenuList.emplace_back( tName );
mbSeparatorAllowed = false;
return mSubMenuList.back().menu.get();
}


///
/// This function is called after the final item of a SUBmenu is added.
/// Submenu items are added just like regular menu items; they just happen
/// after BeginSubMenu() is called but before EndSubMenu() is called.
void CommandManager::Populator::EndSubMenu()
{
//Save the submenu's information
SubMenuListEntry tmpSubMenu{ std::move( mSubMenuList.back() ) };

//Pop off the NEW submenu so CurrentMenu returns the parent of the submenu
mSubMenuList.pop_back();

//Add the submenu to the current menu
auto name = tmpSubMenu.name.Translation();
CurrentMenu()->Append(0, name, tmpSubMenu.menu.release(),
name /* help string */ );
mbSeparatorAllowed = true;
}


///
/// This returns the 'Current' Submenu, which is the one at the
/// end of the mSubMenuList (or NULL, if it doesn't exist).
wxMenu * CommandManager::Populator::CurrentSubMenu() const
Expand Down Expand Up @@ -1432,22 +1305,10 @@ void CommandManager::WriteXML(XMLWriter &xmlFile) const

void CommandManager::Populator::BeginOccultCommands()
{
// To do: perhaps allow occult item switching at lower levels of the
// menu tree.
wxASSERT( !CurrentMenu() );

// Make a temporary menu bar collecting items added after.
// This bar will be discarded but other side effects on the command
// manager persist.
mTempMenuBar = AddMenuBar(wxT("ext-menu"));
bMakingOccultCommands = true;
}

void CommandManager::Populator::EndOccultCommands()
{
PopMenuBar();
bMakingOccultCommands = false;
mTempMenuBar.reset();
}

void CommandManager::SetCommandFlags(const CommandID &name,
Expand Down
Loading

0 comments on commit fca64ec

Please sign in to comment.