1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-08-01 08:29:27 +02:00

Revert changes for Bug 1119 made by Paul.

These changes were made too close to release and are considered too dangerous for 2.4.0.
We will use the changes Leland provided.  We can review these proposed changes by Paul after 2.4.0 is released.
This commit is contained in:
James Crook 2020-04-21 17:45:16 +01:00
parent c3d0d0370b
commit 018a8681ef
8 changed files with 152 additions and 106 deletions

View File

@ -109,6 +109,10 @@ It handles initialization and termination by subclassing wxApp.
#include "tracks/ui/Scrubbing.h"
#include "widgets/FileHistory.h"
#if defined(__WXMAC__)
#include "menus/WindowMenus.h"
#endif
#ifdef EXPERIMENTAL_EASY_CHANGE_KEY_BINDINGS
#include "prefs/KeyConfigPrefs.h"
#endif
@ -885,6 +889,11 @@ BEGIN_EVENT_TABLE(AudacityApp, wxApp)
EVT_MENU_RANGE(FileHistory::ID_RECENT_FIRST, FileHistory::ID_RECENT_LAST,
AudacityApp::OnMRUFile)
#if defined(__WXMAC__)
// Window menu event handlers.
EVT_MENU_RANGE(WindowActions::ID_BASE, WindowActions::ID_LAST, AudacityApp::OnWindow)
#endif
// Handle AppCommandEvents (usually from a script)
EVT_APP_COMMAND(wxID_ANY, AudacityApp::OnReceiveCommand)
@ -978,6 +987,35 @@ void AudacityApp::OnMRUFile(wxCommandEvent& event) {
history.RemoveFileFromHistory(n);
}
#if defined(__WXMAC__)
// Handles switching projects when an item in the Window menu is selected
void AudacityApp::OnWindow(wxCommandEvent& event)
{
// Get the project's number
int projectNumber = event.GetId() - WindowActions::ID_BASE;
// Search for it
for (auto project : AllProjects{})
{
if (project->GetProjectNumber() == projectNumber)
{
// Make it the active project
SetActiveProject(project.get());
// And ensure it's visible
wxFrame *frame = project->GetFrame();
if (frame->IsIconized())
{
frame->Restore();
}
frame->Raise();
break;
}
}
}
#endif
void AudacityApp::OnTimer(wxTimerEvent& WXUNUSED(event))
{
// Filenames are queued when Audacity receives a few of the

View File

@ -69,6 +69,10 @@ class AudacityApp final : public wxApp {
// A wrapper of the above that does not throw
bool SafeMRUOpen(const wxString &fileName);
#if defined(__WXMAC__)
void OnWindow(wxCommandEvent &event);
#endif
void OnReceiveCommand(AppCommandEvent &event);
void OnKeyDown(wxKeyEvent &event);

View File

@ -15,11 +15,14 @@
#include "KeyboardCapture.h"
#include "ondemand/ODTaskThread.h"
#if defined(__WXMAC__)
#include "menus/WindowMenus.h"
#endif
#include <wx/display.h>
#include <wx/frame.h>
wxDEFINE_EVENT(EVT_TRACK_PANEL_TIMER, wxCommandEvent);
wxDEFINE_EVENT(EVT_PROJECT_ACTIVATION, wxCommandEvent);
size_t AllProjects::size() const
{
@ -112,9 +115,13 @@ void SetActiveProject(AudacityProject * project)
if ( gActiveProject != project ) {
gActiveProject = project;
KeyboardCapture::Capture( nullptr );
wxTheApp->QueueEvent( safenew wxCommandEvent{ EVT_PROJECT_ACTIVATION } );
}
wxTheApp->SetTopWindow( FindProjectFrame( project ) );
#if defined(__WXMAC__)
// Refresh the Window menu
WindowActions::Refresh();
#endif
}
AudacityProject::AudacityProject()

View File

@ -93,11 +93,6 @@ using AttachedWindows = ClientData::Site<
wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API,
EVT_TRACK_PANEL_TIMER, wxCommandEvent);
// This event is emitted by the application object when there is a change
// in the activated project
wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API,
EVT_PROJECT_ACTIVATION, wxCommandEvent);
///\brief The top-level handle to an Audacity project. It serves as a source
/// of events that other objects can bind to, and a container of associated
/// sub-objects that it treats opaquely. It stores a filename and a status

View File

@ -24,7 +24,9 @@ Paul Licameli split from AudacityProject.cpp
#include "widgets/AudacityMessageBox.h"
#include "widgets/NumericTextCtrl.h"
wxDEFINE_EVENT(EVT_PROJECT_TITLE_CHANGE, wxCommandEvent);
#if defined(__WXMAC__)
#include "menus/WindowMenus.h"
#endif
static void RefreshAllTitles(bool bShowProjectNumbers )
{
@ -132,13 +134,13 @@ void ProjectFileIO::SetProjectTitle( int number)
name += _("(Recovered)");
}
if ( name != window.GetTitle() ) {
window.SetTitle( name );
window.SetName(name); // to make the nvda screen reader read the correct title
window.SetTitle( name );
window.SetName(name); // to make the nvda screen reader read the correct title
project.QueueEvent(
safenew wxCommandEvent{ EVT_PROJECT_TITLE_CHANGE } );
}
#if defined(__WXMAC__)
// Refresh the Window menu
WindowActions::Refresh();
#endif
}
// Most of this string was duplicated 3 places. Made the warning consistent in this global.

View File

@ -96,9 +96,4 @@ public:
size_t UnnamedCount;
};
// This event is emitted by the project when there is a change
// in its title
wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API,
EVT_PROJECT_TITLE_CHANGE, wxCommandEvent);
#endif

View File

@ -7,14 +7,16 @@
#ifdef __WXMAC__
#include "WindowMenus.h"
#include "../CommonCommandFlags.h"
#include "../Menus.h"
#include "../Project.h"
#include "../ProjectFileIO.h"
#include "../commands/CommandContext.h"
#include <wx/frame.h>
#include <wx/menu.h>
#include <wx/menuitem.h>
#undef USE_COCOA
@ -53,69 +55,74 @@ void DoMacMinimize(AudacityProject *project)
}
}
std::vector< wxWindowID > sReservedIds;
std::vector< std::weak_ptr< AudacityProject > > sProjects;
void RebuildMenu(wxCommandEvent &evt)
{
// Let other listeners hear it too
evt.Skip();
// This is a big hammer.
// Really we just need to recreate just the Window menu.
// This causes the checkmark to be put in the right place for the
// currently active project
MenuCreator::RebuildAllMenuBars();
}
wxWindowID ReservedID(
size_t index, const std::shared_ptr< AudacityProject > &pProject )
{
if ( sReservedIds.empty() ) {
// Do this once only per session, and don't worry about unbinding
wxTheApp->Bind( EVT_PROJECT_ACTIVATION, RebuildMenu );
wxTheApp->Bind( EVT_PROJECT_TITLE_CHANGE, RebuildMenu );
}
while ( sReservedIds.size() <= index )
sReservedIds.emplace_back( wxIdManager::ReserveId() );
if ( sProjects.size() < sReservedIds.size() )
sProjects.resize( sReservedIds.size() );
sProjects[ index ] = pProject;
return sReservedIds[ index ];
}
void OnWindow( wxCommandEvent &evt )
{
const auto begin = sReservedIds.begin(), end = sReservedIds.end(),
iter = std::find( begin, end, evt.GetId() );
size_t index = iter - begin;
if ( index < sProjects.size() ) {
auto pProject = sProjects[ index ].lock();
if ( pProject ) {
// Make it the active project
SetActiveProject(pProject.get());
// And ensure it's visible
wxFrame *frame = pProject->GetFrame();
if (frame->IsIconized())
{
frame->Restore();
}
frame->Raise();
}
}
}
} // namespace
/// Namespace for functions for window management (mac only?)
namespace WindowActions {
// exported helper functions
// none
// Refreshes the Window menu in all projects
void Refresh()
{
// Must do it in all projects
for (auto thisProject : AllProjects{})
{
// Need the projects frame, but this should always be successful
wxFrame *frame = thisProject->GetFrame();
wxASSERT(frame != NULL);
if (!frame)
{
continue;
}
// This can happen if we are called before the menubar is set in the frame
wxMenuBar *bar = frame->GetMenuBar();
if (!bar)
{
continue;
}
// Should always find the Window menu
int pos = bar->FindMenu(wxT("Window"));
wxASSERT(pos != wxNOT_FOUND);
if (pos == wxNOT_FOUND)
{
continue;
}
// We can not get the menu proper
wxMenu *menu = bar->GetMenu(pos);
// Remove all existing window items
for (auto item : menu->GetMenuItems())
{
if (item->GetId() >= WindowActions::ID_BASE)
{
menu->Destroy(item);
}
}
// Add all projects to this project's Window menu
for (auto project : AllProjects{})
{
int itemId = WindowActions::ID_BASE + project->GetProjectNumber();
wxString itemName = project->GetFrame()->GetTitle();
bool isActive = (GetActiveProject() == project.get());
// This should never really happen, but a menu item must have a name
if (itemName.empty())
{
itemName = _("<untitled>");
}
// Add it to the menu and check it if it's the active project
wxMenuItem *item = menu->Append(itemId, itemName);
item->SetCheckable(true);
item->Check(isActive);
}
}
}
// Menu handler functions
@ -180,9 +187,9 @@ namespace {
using namespace MenuTable;
BaseItemSharedPtr WindowMenu()
{
//////////////////////////////////////////////////////////////////////////
// poor imitation of the Mac Windows Menu
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// poor imitation of the Mac Windows Menu
//////////////////////////////////////////////////////////////////////////
static BaseItemSharedPtr menu{
( FinderScope{ findCommandHandler },
Menu( wxT("Window"), XO("&Window"),
@ -208,34 +215,10 @@ BaseItemSharedPtr WindowMenu()
Special( wxT("PopulateWindowsStep"),
[](AudacityProject &, wxMenu &theMenu)
{
// Undo previous bindings
for ( auto id : sReservedIds )
wxTheApp->Unbind( wxEVT_MENU, OnWindow, id );
// Add all projects to this project's Window menu
size_t ii = 0;
for (auto project : AllProjects{})
{
int itemId = ReservedID( ii++, project );
wxString itemName = project->GetFrame()->GetTitle();
bool isActive = (GetActiveProject() == project.get());
// This should never really happen, but a menu item must have a name
if (itemName.empty())
{
itemName = _("<untitled>");
}
// Add it to the menu and check it if it's the active project
wxMenuItem *item = theMenu.Append(itemId, itemName);
item->SetCheckable(true);
item->Check(isActive);
// Bind the callback
wxTheApp->Bind( wxEVT_MENU, OnWindow, itemId );
}
// Should something be done here???
} )
)
) ) };
return menu;
}

22
src/menus/WindowMenus.h Normal file
View File

@ -0,0 +1,22 @@
#include "../Audacity.h"
#include "../commands/CommandManager.h"
#ifdef __WXMAC__
/// Namespace for functions for window management (mac only?)
namespace WindowActions {
// Range of assigned menu IDs
static const wxWindowID ID_BASE = 30000;
static const wxWindowID ID_LAST = 30999;
// Exported helper functions
void Refresh();
};
#else
// Not WXMAC.
#endif