mirror of
https://github.com/cookiengineer/audacity
synced 2025-08-07 23:51:14 +02:00
Cleanup of Menus.* after moving most things out of them
This commit is contained in:
commit
7c7aab1648
@ -722,16 +722,16 @@ bool MacroCommands::ApplyEffectCommand(
|
||||
// and apply the effect...
|
||||
res = PluginActions::DoAudacityCommand(ID,
|
||||
Context,
|
||||
MenuCommandHandler::OnEffectFlags::kConfigured |
|
||||
MenuCommandHandler::OnEffectFlags::kSkipState |
|
||||
MenuCommandHandler::OnEffectFlags::kDontRepeatLast);
|
||||
PluginActions::kConfigured |
|
||||
PluginActions::kSkipState |
|
||||
PluginActions::kDontRepeatLast);
|
||||
else
|
||||
// and apply the effect...
|
||||
res = PluginActions::DoEffect(ID,
|
||||
Context,
|
||||
MenuCommandHandler::OnEffectFlags::kConfigured |
|
||||
MenuCommandHandler::OnEffectFlags::kSkipState |
|
||||
MenuCommandHandler::OnEffectFlags::kDontRepeatLast);
|
||||
PluginActions::kConfigured |
|
||||
PluginActions::kSkipState |
|
||||
PluginActions::kDontRepeatLast);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
321
src/Menus.cpp
321
src/Menus.cpp
@ -11,17 +11,7 @@
|
||||
*******************************************************************//**
|
||||
|
||||
\file Menus.cpp
|
||||
\brief Functions that provide most of the menu actions.
|
||||
|
||||
This file implements the method that creates the menu bar, plus
|
||||
most of the methods that get called when you select an item
|
||||
from a menu.
|
||||
|
||||
*//****************************************************************//**
|
||||
|
||||
\class MenuCommandHandler
|
||||
\brief MenuCommandHandler contains many command handlers for individual
|
||||
menu items.
|
||||
\brief Functions for building toobar menus and enabling and disabling items
|
||||
|
||||
*//****************************************************************//**
|
||||
|
||||
@ -37,75 +27,25 @@ menu items.
|
||||
|
||||
#include "Audacity.h"
|
||||
#include "Menus.h"
|
||||
#include "commands/CommandManager.h"
|
||||
#include "commands/CommandContext.h"
|
||||
|
||||
#include <cfloat>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
#include <wx/defs.h>
|
||||
#include <wx/docview.h>
|
||||
#include <wx/filedlg.h>
|
||||
#include <wx/textfile.h>
|
||||
#include <wx/textdlg.h>
|
||||
#include <wx/progdlg.h>
|
||||
#include <wx/scrolbar.h>
|
||||
#include <wx/ffile.h>
|
||||
#include <wx/statusbr.h>
|
||||
#include <wx/utils.h>
|
||||
|
||||
#include "TrackPanel.h"
|
||||
#include "widgets/Ruler.h"
|
||||
|
||||
#include "effects/EffectManager.h"
|
||||
|
||||
#include "AudacityApp.h"
|
||||
#include "AudioIO.h"
|
||||
#include "float_cast.h"
|
||||
#include "LabelTrack.h"
|
||||
#include "import/ImportRaw.h"
|
||||
#include "prefs/PrefsDialog.h"
|
||||
#include "prefs/PlaybackPrefs.h"
|
||||
#include "LyricsWindow.h"
|
||||
#include "MixerBoard.h"
|
||||
#include "Project.h"
|
||||
#include "Internat.h"
|
||||
#include "FileFormats.h"
|
||||
#include "ModuleManager.h"
|
||||
#include "Prefs.h"
|
||||
#ifdef USE_MIDI
|
||||
#include "NoteTrack.h"
|
||||
#endif // USE_MIDI
|
||||
#include "ondemand/ODManager.h"
|
||||
|
||||
#include "prefs/BatchPrefs.h"
|
||||
|
||||
#include "toolbars/ToolManager.h"
|
||||
#include "toolbars/ControlToolBar.h"
|
||||
#include "toolbars/EditToolBar.h"
|
||||
|
||||
#include "tracks/ui/SelectHandle.h"
|
||||
|
||||
#include "widgets/LinkingHtmlWindow.h"
|
||||
|
||||
#include "Experimental.h"
|
||||
#include "PlatformCompatibility.h"
|
||||
|
||||
#include "Prefs.h"
|
||||
#include "Project.h"
|
||||
#include "TrackPanel.h"
|
||||
#include "UndoManager.h"
|
||||
#include "WaveTrack.h"
|
||||
|
||||
#include "commands/CommandManager.h"
|
||||
#include "prefs/TracksPrefs.h"
|
||||
|
||||
#include "widgets/ErrorDialog.h"
|
||||
#include "./commands/AudacityCommand.h"
|
||||
|
||||
static const AudacityProject::RegisteredAttachedObjectFactory factory{ []{
|
||||
return std::make_unique< MenuCommandHandler >();
|
||||
} };
|
||||
#include "toolbars/ControlToolBar.h"
|
||||
#include "toolbars/ToolManager.h"
|
||||
#include "widgets/Ruler.h"
|
||||
|
||||
PrefsListener::~PrefsListener()
|
||||
{
|
||||
@ -115,34 +55,17 @@ void PrefsListener::UpdatePrefs()
|
||||
{
|
||||
}
|
||||
|
||||
MenuCommandHandler &GetMenuCommandHandler(AudacityProject &project)
|
||||
{
|
||||
return static_cast<MenuCommandHandler&>(
|
||||
project.GetAttachedObject( factory ) );
|
||||
}
|
||||
|
||||
MenuManager &GetMenuManager(AudacityProject &project)
|
||||
{ return *project.mMenuManager; }
|
||||
|
||||
MenuCommandHandler::MenuCommandHandler()
|
||||
MenuCreator::MenuCreator()
|
||||
{
|
||||
}
|
||||
|
||||
MenuCommandHandler::~MenuCommandHandler()
|
||||
{
|
||||
}
|
||||
|
||||
MenuCreator::MenuCreator(){
|
||||
}
|
||||
|
||||
MenuCreator::~MenuCreator()
|
||||
{
|
||||
}
|
||||
|
||||
void MenuCommandHandler::UpdatePrefs()
|
||||
{
|
||||
}
|
||||
|
||||
void MenuManager::UpdatePrefs()
|
||||
{
|
||||
bool bSelectAllIfNone;
|
||||
@ -311,14 +234,6 @@ void VisitItem( AudacityProject &project, MenuTable::BaseItem *pItem )
|
||||
/// changes in configured preferences - for example changes in key-bindings
|
||||
/// affect the short-cut key legend that appears beside each command,
|
||||
|
||||
// To supply the "finder" argument in AddItem calls
|
||||
static CommandHandlerObject &findMenuCommandHandler(AudacityProject &project)
|
||||
{ return GetMenuCommandHandler( project ); }
|
||||
|
||||
#define FN(X) findMenuCommandHandler, \
|
||||
static_cast<CommandFunctorPointer>(& MenuCommandHandler :: X)
|
||||
#define XXO(X) _(X), wxString{X}.Contains("...")
|
||||
|
||||
MenuTable::BaseItemPtr FileMenu( AudacityProject& );
|
||||
|
||||
MenuTable::BaseItemPtr EditMenu( AudacityProject& );
|
||||
@ -382,9 +297,6 @@ void MenuCreator::CreateMenusAndCommands(AudacityProject &project)
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef XXO
|
||||
#undef FN
|
||||
|
||||
// TODO: This surely belongs in CommandManager?
|
||||
void MenuManager::ModifyUndoMenuItems(AudacityProject &project)
|
||||
{
|
||||
@ -447,10 +359,6 @@ void MenuCreator::RebuildMenuBar(AudacityProject &project)
|
||||
ModuleManager::Get().Dispatch(MenusRebuilt);
|
||||
}
|
||||
|
||||
void AudacityProject::RebuildOtherMenus()
|
||||
{
|
||||
}
|
||||
|
||||
CommandFlag MenuManager::GetFocusedFrame(AudacityProject &project)
|
||||
{
|
||||
wxWindow *w = wxWindow::FindFocus();
|
||||
@ -647,32 +555,6 @@ CommandFlag MenuManager::GetUpdateFlags
|
||||
return flags;
|
||||
}
|
||||
|
||||
namespace SelectActions {
|
||||
void DoSelectSomething(AudacityProject &project);
|
||||
}
|
||||
|
||||
// Select the full time range, if no
|
||||
// time range is selected.
|
||||
void AudacityProject::SelectAllIfNone()
|
||||
{
|
||||
auto flags = GetMenuManager(*this).GetUpdateFlags(*this);
|
||||
if(!(flags & TracksSelectedFlag) ||
|
||||
(mViewInfo.selectedRegion.isPoint()))
|
||||
SelectActions::DoSelectSomething(*this);
|
||||
}
|
||||
|
||||
namespace TransportActions {
|
||||
void DoStop( AudacityProject & );
|
||||
}
|
||||
|
||||
// Stop playing or recording, if paused.
|
||||
void AudacityProject::StopIfPaused()
|
||||
{
|
||||
auto flags = GetMenuManager(*this).GetUpdateFlags(*this);
|
||||
if( flags & PausedFlag )
|
||||
TransportActions::DoStop(*this);
|
||||
}
|
||||
|
||||
void MenuManager::ModifyAllProjectToolbarMenus()
|
||||
{
|
||||
AProjectArray::iterator i;
|
||||
@ -837,85 +719,11 @@ void MenuManager::UpdateMenus(AudacityProject &project, bool checkActive)
|
||||
MenuManager::ModifyToolbarMenus(project);
|
||||
}
|
||||
|
||||
//sort based on flags. see Project.h for sort flags
|
||||
void AudacityProject::SortTracks(int flags)
|
||||
{
|
||||
auto GetTime = [](const Track *t) {
|
||||
return t->TypeSwitch< double >(
|
||||
[&](const WaveTrack* w) {
|
||||
auto stime = w->GetEndTime();
|
||||
|
||||
int ndx;
|
||||
for (ndx = 0; ndx < w->GetNumClips(); ndx++) {
|
||||
const auto c = w->GetClipByIndex(ndx);
|
||||
if (c->GetNumSamples() == 0)
|
||||
continue;
|
||||
stime = std::min(stime, c->GetStartTime());
|
||||
}
|
||||
return stime;
|
||||
},
|
||||
[&](const LabelTrack* l) {
|
||||
return l->GetStartTime();
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
size_t ndx = 0;
|
||||
// This one place outside of TrackList where we must use undisguised
|
||||
// std::list iterators! Avoid this elsewhere!
|
||||
std::vector<TrackNodePointer> arr;
|
||||
arr.reserve(mTracks->size());
|
||||
|
||||
// First find the permutation.
|
||||
// This routine, very unusually, deals with the underlying stl list
|
||||
// iterators, not with TrackIter! Dangerous!
|
||||
for (auto iter = mTracks->ListOfTracks::begin(),
|
||||
end = mTracks->ListOfTracks::end(); iter != end; ++iter) {
|
||||
const auto &track = *iter;
|
||||
if ( !track->IsLeader() )
|
||||
// keep channels contiguous
|
||||
ndx++;
|
||||
else {
|
||||
auto size = arr.size();
|
||||
for (ndx = 0; ndx < size;) {
|
||||
Track &arrTrack = **arr[ndx].first;
|
||||
auto channels = TrackList::Channels(&arrTrack);
|
||||
if(flags & kAudacitySortByName) {
|
||||
//do case insensitive sort - cmpNoCase returns less than zero if the string is 'less than' its argument
|
||||
//also if we have case insensitive equality, then we need to sort by case as well
|
||||
//We sort 'b' before 'B' accordingly. We uncharacteristically use greater than for the case sensitive
|
||||
//compare because 'b' is greater than 'B' in ascii.
|
||||
auto cmpValue = track->GetName().CmpNoCase(arrTrack.GetName());
|
||||
if ( cmpValue < 0 ||
|
||||
( 0 == cmpValue &&
|
||||
track->GetName().CompareTo(arrTrack.GetName()) > 0 ) )
|
||||
break;
|
||||
}
|
||||
//sort by time otherwise
|
||||
else if(flags & kAudacitySortByTime) {
|
||||
auto time1 = TrackList::Channels(track.get()).min( GetTime );
|
||||
|
||||
//get candidate's (from sorted array) time
|
||||
auto time2 = channels.min( GetTime );
|
||||
|
||||
if (time1 < time2)
|
||||
break;
|
||||
}
|
||||
ndx += channels.size();
|
||||
}
|
||||
}
|
||||
arr.insert(arr.begin() + ndx, TrackNodePointer{iter, mTracks.get()});
|
||||
}
|
||||
|
||||
// Now apply the permutation
|
||||
mTracks->Permute(arr);
|
||||
}
|
||||
|
||||
/// The following method moves to the previous track
|
||||
/// selecting and unselecting depending if you are on the start of a
|
||||
/// block or not.
|
||||
|
||||
void MenuCommandHandler::RebuildAllMenuBars()
|
||||
void MenuCreator::RebuildAllMenuBars()
|
||||
{
|
||||
for( size_t i = 0; i < gAudacityProjects.size(); i++ ) {
|
||||
AudacityProject *p = gAudacityProjects[i].get();
|
||||
@ -933,112 +741,3 @@ void MenuCommandHandler::RebuildAllMenuBars()
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void AudacityProject::SelectNone()
|
||||
{
|
||||
for (auto t : GetTracks()->Any())
|
||||
t->SetSelected(false);
|
||||
|
||||
mTrackPanel->Refresh(false);
|
||||
if (mMixerBoard)
|
||||
mMixerBoard->Refresh(false);
|
||||
}
|
||||
|
||||
//
|
||||
// View Menu
|
||||
//
|
||||
|
||||
double AudacityProject::GetScreenEndTime() const
|
||||
{
|
||||
return mTrackPanel->GetScreenEndTime();
|
||||
}
|
||||
|
||||
void AudacityProject::ZoomInByFactor( double ZoomFactor )
|
||||
{
|
||||
// LLL: Handling positioning differently when audio is
|
||||
// actively playing. Don't do this if paused.
|
||||
if ((gAudioIO->IsStreamActive(GetAudioIOToken()) != 0) && !gAudioIO->IsPaused()){
|
||||
ZoomBy(ZoomFactor);
|
||||
mTrackPanel->ScrollIntoView(gAudioIO->GetStreamTime());
|
||||
mTrackPanel->Refresh(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// DMM: Here's my attempt to get logical zooming behavior
|
||||
// when there's a selection that's currently at least
|
||||
// partially on-screen
|
||||
|
||||
const double endTime = GetScreenEndTime();
|
||||
const double duration = endTime - mViewInfo.h;
|
||||
|
||||
bool selectionIsOnscreen =
|
||||
(mViewInfo.selectedRegion.t0() < endTime) &&
|
||||
(mViewInfo.selectedRegion.t1() >= mViewInfo.h);
|
||||
|
||||
bool selectionFillsScreen =
|
||||
(mViewInfo.selectedRegion.t0() < mViewInfo.h) &&
|
||||
(mViewInfo.selectedRegion.t1() > endTime);
|
||||
|
||||
if (selectionIsOnscreen && !selectionFillsScreen) {
|
||||
// Start with the center of the selection
|
||||
double selCenter = (mViewInfo.selectedRegion.t0() +
|
||||
mViewInfo.selectedRegion.t1()) / 2;
|
||||
|
||||
// If the selection center is off-screen, pick the
|
||||
// center of the part that is on-screen.
|
||||
if (selCenter < mViewInfo.h)
|
||||
selCenter = mViewInfo.h +
|
||||
(mViewInfo.selectedRegion.t1() - mViewInfo.h) / 2;
|
||||
if (selCenter > endTime)
|
||||
selCenter = endTime -
|
||||
(endTime - mViewInfo.selectedRegion.t0()) / 2;
|
||||
|
||||
// Zoom in
|
||||
ZoomBy(ZoomFactor);
|
||||
const double newDuration = GetScreenEndTime() - mViewInfo.h;
|
||||
|
||||
// Recenter on selCenter
|
||||
TP_ScrollWindow(selCenter - newDuration / 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
double origLeft = mViewInfo.h;
|
||||
double origWidth = duration;
|
||||
ZoomBy(ZoomFactor);
|
||||
|
||||
const double newDuration = GetScreenEndTime() - mViewInfo.h;
|
||||
double newh = origLeft + (origWidth - newDuration) / 2;
|
||||
|
||||
// MM: Commented this out because it was confusing users
|
||||
/*
|
||||
// make sure that the *right-hand* end of the selection is
|
||||
// no further *left* than 1/3 of the way across the screen
|
||||
if (mViewInfo.selectedRegion.t1() < newh + mViewInfo.screen / 3)
|
||||
newh = mViewInfo.selectedRegion.t1() - mViewInfo.screen / 3;
|
||||
|
||||
// make sure that the *left-hand* end of the selection is
|
||||
// no further *right* than 2/3 of the way across the screen
|
||||
if (mViewInfo.selectedRegion.t0() > newh + mViewInfo.screen * 2 / 3)
|
||||
newh = mViewInfo.selectedRegion.t0() - mViewInfo.screen * 2 / 3;
|
||||
*/
|
||||
|
||||
TP_ScrollWindow(newh);
|
||||
}
|
||||
|
||||
|
||||
void AudacityProject::ZoomOutByFactor( double ZoomFactor )
|
||||
{
|
||||
//Zoom() may change these, so record original values:
|
||||
const double origLeft = mViewInfo.h;
|
||||
const double origWidth = GetScreenEndTime() - origLeft;
|
||||
|
||||
ZoomBy(ZoomFactor);
|
||||
const double newWidth = GetScreenEndTime() - mViewInfo.h;
|
||||
|
||||
const double newh = origLeft + (origWidth - newWidth) / 2;
|
||||
// newh = (newh > 0) ? newh : 0;
|
||||
TP_ScrollWindow(newh);
|
||||
}
|
||||
|
||||
//
|
||||
|
69
src/Menus.h
69
src/Menus.h
@ -12,11 +12,7 @@
|
||||
|
||||
#include "Experimental.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <wx/event.h>
|
||||
#include "SelectedRegion.h"
|
||||
#include "commands/CommandFunctors.h"
|
||||
#include <wx/arrstr.h>
|
||||
|
||||
class AudacityProject;
|
||||
class CommandContext;
|
||||
@ -42,36 +38,6 @@ public:
|
||||
virtual void UpdatePrefs(); // default is no-op
|
||||
};
|
||||
|
||||
struct MenuCommandHandler final
|
||||
: public CommandHandlerObject // MUST be the first base class!
|
||||
, public PrefsListener
|
||||
{
|
||||
MenuCommandHandler();
|
||||
~MenuCommandHandler();
|
||||
|
||||
public:
|
||||
|
||||
// Effect Menu
|
||||
|
||||
struct OnEffectFlags
|
||||
{
|
||||
|
||||
// No flags specified
|
||||
static const int kNone = 0x00;
|
||||
// Flag used to disable prompting for configuration parameteres.
|
||||
static const int kConfigured = 0x01;
|
||||
// Flag used to disable saving the state after processing.
|
||||
static const int kSkipState = 0x02;
|
||||
// Flag used to disable "Repeat Last Effect"
|
||||
static const int kDontRepeatLast = 0x04;
|
||||
};
|
||||
|
||||
static void RebuildAllMenuBars();
|
||||
|
||||
public:
|
||||
void UpdatePrefs() override;
|
||||
};
|
||||
|
||||
class MenuCreator
|
||||
{
|
||||
public:
|
||||
@ -80,6 +46,8 @@ public:
|
||||
void CreateMenusAndCommands(AudacityProject &project);
|
||||
void RebuildMenuBar(AudacityProject &project);
|
||||
|
||||
static void RebuildAllMenuBars();
|
||||
|
||||
public:
|
||||
CommandFlag mLastFlags;
|
||||
|
||||
@ -101,16 +69,18 @@ public:
|
||||
|
||||
// If checkActive, do not do complete flags testing on an
|
||||
// inactive project as it is needlessly expensive.
|
||||
CommandFlag GetUpdateFlags(AudacityProject &project, bool checkActive = false);
|
||||
CommandFlag GetUpdateFlags(
|
||||
AudacityProject &project, bool checkActive = false);
|
||||
void UpdatePrefs();
|
||||
|
||||
// Command Handling
|
||||
bool ReportIfActionNotAllowed
|
||||
( AudacityProject &project,
|
||||
const wxString & Name, CommandFlag & flags, CommandFlag flagsRqd, CommandFlag mask );
|
||||
bool TryToMakeActionAllowed
|
||||
( AudacityProject &project,
|
||||
CommandFlag & flags, CommandFlag flagsRqd, CommandFlag mask );
|
||||
bool ReportIfActionNotAllowed(
|
||||
AudacityProject &project,
|
||||
const wxString & Name, CommandFlag & flags, CommandFlag flagsRqd,
|
||||
CommandFlag mask );
|
||||
bool TryToMakeActionAllowed(
|
||||
AudacityProject &project,
|
||||
CommandFlag & flags, CommandFlag flagsRqd, CommandFlag mask );
|
||||
|
||||
|
||||
private:
|
||||
@ -122,10 +92,10 @@ private:
|
||||
};
|
||||
|
||||
|
||||
MenuCommandHandler &GetMenuCommandHandler(AudacityProject &project);
|
||||
MenuManager &GetMenuManager(AudacityProject &project);
|
||||
|
||||
// Exported helper functions from various menu handling source files
|
||||
|
||||
namespace FileActions {
|
||||
AudacityProject *DoImportMIDI(
|
||||
AudacityProject *pProject, const wxString &fileName );
|
||||
@ -173,6 +143,16 @@ void DoRemoveTracks( AudacityProject & );
|
||||
}
|
||||
|
||||
namespace PluginActions {
|
||||
enum : unsigned {
|
||||
// No flags specified
|
||||
kNone = 0x00,
|
||||
// Flag used to disable prompting for configuration parameteres.
|
||||
kConfigured = 0x01,
|
||||
// Flag used to disable saving the state after processing.
|
||||
kSkipState = 0x02,
|
||||
// Flag used to disable "Repeat Last Effect"
|
||||
kDontRepeatLast = 0x04,
|
||||
};
|
||||
bool DoEffect(
|
||||
const PluginID & ID, const CommandContext & context, unsigned flags );
|
||||
bool DoAudacityCommand(
|
||||
@ -185,6 +165,3 @@ void DoShowLog( AudacityProject& );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
125
src/Project.cpp
125
src/Project.cpp
@ -3124,7 +3124,7 @@ void AudacityProject::OpenFile(const wxString &fileNameArg, bool addtohistory)
|
||||
#ifdef EXPERIMENTAL_DRAG_DROP_PLUG_INS
|
||||
// Is it a plug-in?
|
||||
if (PluginManager::Get().DropFile(fileName)) {
|
||||
MenuCommandHandler::RebuildAllMenuBars();
|
||||
MenuCreator::RebuildAllMenuBars();
|
||||
}
|
||||
else
|
||||
// No, so import.
|
||||
@ -4419,7 +4419,7 @@ bool AudacityProject::Import(const wxString &fileName, WaveTrackArray* pTrackArr
|
||||
PluginActions::DoEffect(
|
||||
EffectManager::Get().GetEffectByIdentifier(wxT("Normalize")),
|
||||
context,
|
||||
MenuCommandHandler::OnEffectFlags::kConfigured);
|
||||
PluginActions::kConfigured);
|
||||
}
|
||||
|
||||
// This is a no-fail:
|
||||
@ -6245,3 +6245,124 @@ ContrastDialog *AudacityProject::GetContrastDialog(bool create)
|
||||
|
||||
return mContrastDialog.get();
|
||||
}
|
||||
|
||||
double AudacityProject::GetScreenEndTime() const
|
||||
{
|
||||
return mTrackPanel->GetScreenEndTime();
|
||||
}
|
||||
|
||||
void AudacityProject::SelectNone()
|
||||
{
|
||||
for (auto t : GetTracks()->Any())
|
||||
t->SetSelected(false);
|
||||
|
||||
mTrackPanel->Refresh(false);
|
||||
if (mMixerBoard)
|
||||
mMixerBoard->Refresh(false);
|
||||
}
|
||||
|
||||
void AudacityProject::ZoomInByFactor( double ZoomFactor )
|
||||
{
|
||||
// LLL: Handling positioning differently when audio is
|
||||
// actively playing. Don't do this if paused.
|
||||
if ((gAudioIO->IsStreamActive(GetAudioIOToken()) != 0) &&
|
||||
!gAudioIO->IsPaused()){
|
||||
ZoomBy(ZoomFactor);
|
||||
mTrackPanel->ScrollIntoView(gAudioIO->GetStreamTime());
|
||||
mTrackPanel->Refresh(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// DMM: Here's my attempt to get logical zooming behavior
|
||||
// when there's a selection that's currently at least
|
||||
// partially on-screen
|
||||
|
||||
const double endTime = GetScreenEndTime();
|
||||
const double duration = endTime - mViewInfo.h;
|
||||
|
||||
bool selectionIsOnscreen =
|
||||
(mViewInfo.selectedRegion.t0() < endTime) &&
|
||||
(mViewInfo.selectedRegion.t1() >= mViewInfo.h);
|
||||
|
||||
bool selectionFillsScreen =
|
||||
(mViewInfo.selectedRegion.t0() < mViewInfo.h) &&
|
||||
(mViewInfo.selectedRegion.t1() > endTime);
|
||||
|
||||
if (selectionIsOnscreen && !selectionFillsScreen) {
|
||||
// Start with the center of the selection
|
||||
double selCenter = (mViewInfo.selectedRegion.t0() +
|
||||
mViewInfo.selectedRegion.t1()) / 2;
|
||||
|
||||
// If the selection center is off-screen, pick the
|
||||
// center of the part that is on-screen.
|
||||
if (selCenter < mViewInfo.h)
|
||||
selCenter = mViewInfo.h +
|
||||
(mViewInfo.selectedRegion.t1() - mViewInfo.h) / 2;
|
||||
if (selCenter > endTime)
|
||||
selCenter = endTime -
|
||||
(endTime - mViewInfo.selectedRegion.t0()) / 2;
|
||||
|
||||
// Zoom in
|
||||
ZoomBy(ZoomFactor);
|
||||
const double newDuration = GetScreenEndTime() - mViewInfo.h;
|
||||
|
||||
// Recenter on selCenter
|
||||
TP_ScrollWindow(selCenter - newDuration / 2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
double origLeft = mViewInfo.h;
|
||||
double origWidth = duration;
|
||||
ZoomBy(ZoomFactor);
|
||||
|
||||
const double newDuration = GetScreenEndTime() - mViewInfo.h;
|
||||
double newh = origLeft + (origWidth - newDuration) / 2;
|
||||
|
||||
// MM: Commented this out because it was confusing users
|
||||
/*
|
||||
// make sure that the *right-hand* end of the selection is
|
||||
// no further *left* than 1/3 of the way across the screen
|
||||
if (mViewInfo.selectedRegion.t1() < newh + mViewInfo.screen / 3)
|
||||
newh = mViewInfo.selectedRegion.t1() - mViewInfo.screen / 3;
|
||||
|
||||
// make sure that the *left-hand* end of the selection is
|
||||
// no further *right* than 2/3 of the way across the screen
|
||||
if (mViewInfo.selectedRegion.t0() > newh + mViewInfo.screen * 2 / 3)
|
||||
newh = mViewInfo.selectedRegion.t0() - mViewInfo.screen * 2 / 3;
|
||||
*/
|
||||
|
||||
TP_ScrollWindow(newh);
|
||||
}
|
||||
|
||||
void AudacityProject::ZoomOutByFactor( double ZoomFactor )
|
||||
{
|
||||
//Zoom() may change these, so record original values:
|
||||
const double origLeft = mViewInfo.h;
|
||||
const double origWidth = GetScreenEndTime() - origLeft;
|
||||
|
||||
ZoomBy(ZoomFactor);
|
||||
const double newWidth = GetScreenEndTime() - mViewInfo.h;
|
||||
|
||||
const double newh = origLeft + (origWidth - newWidth) / 2;
|
||||
// newh = (newh > 0) ? newh : 0;
|
||||
TP_ScrollWindow(newh);
|
||||
}
|
||||
|
||||
// Select the full time range, if no
|
||||
// time range is selected.
|
||||
void AudacityProject::SelectAllIfNone()
|
||||
{
|
||||
auto flags = GetMenuManager(*this).GetUpdateFlags(*this);
|
||||
if(!(flags & TracksSelectedFlag) ||
|
||||
(mViewInfo.selectedRegion.isPoint()))
|
||||
SelectActions::DoSelectSomething(*this);
|
||||
}
|
||||
|
||||
// Stop playing or recording, if paused.
|
||||
void AudacityProject::StopIfPaused()
|
||||
{
|
||||
auto flags = GetMenuManager(*this).GetUpdateFlags(*this);
|
||||
if( flags & PausedFlag )
|
||||
TransportActions::DoStop(*this);
|
||||
}
|
||||
|
@ -169,7 +169,6 @@ class WaveTrack;
|
||||
#include "./commands/CommandFlag.h"
|
||||
#include "../include/audacity/EffectInterface.h"
|
||||
|
||||
struct MenuCommandHandler;
|
||||
class MenuManager;
|
||||
|
||||
class PrefsListener;
|
||||
@ -375,7 +374,6 @@ public:
|
||||
static void CaptureKeyboard(wxWindow *handler);
|
||||
static void ReleaseKeyboard(wxWindow *handler);
|
||||
|
||||
void RebuildOtherMenus();
|
||||
void MayStartMonitoring();
|
||||
|
||||
|
||||
@ -831,7 +829,6 @@ private:
|
||||
std::unique_ptr<MenuManager> mMenuManager;
|
||||
|
||||
public:
|
||||
friend MenuCommandHandler &GetMenuCommandHandler(AudacityProject &project);
|
||||
friend MenuManager &GetMenuManager(AudacityProject &project);
|
||||
|
||||
class PlaybackScroller final : public wxEvtHandler
|
||||
|
@ -1536,7 +1536,7 @@ bool CommandManager::HandleMenuID(int id, CommandFlag flags, CommandMask mask)
|
||||
factories.push_back(&keyConfigPrefsFactory);
|
||||
GlobalPrefsDialog dialog(GetActiveProject(), factories);
|
||||
dialog.ShowModal();
|
||||
MenuCommandHandler::RebuildAllMenuBars();
|
||||
MenuCreator::RebuildAllMenuBars();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@ -1589,7 +1589,7 @@ bool CommandManager::HandleTextualCommand(const wxString & Str, const CommandCon
|
||||
{
|
||||
return PluginActions::DoEffect(
|
||||
plug->GetID(), context,
|
||||
MenuCommandHandler::OnEffectFlags::kConfigured);
|
||||
PluginActions::kConfigured);
|
||||
}
|
||||
plug = pm.GetNextPlugin(PluginTypeEffect);
|
||||
}
|
||||
|
@ -769,7 +769,7 @@ bool Effect::Apply()
|
||||
//
|
||||
// It should callback to the EffectManager to kick off the processing
|
||||
return PluginActions::DoEffect(GetID(), context,
|
||||
MenuCommandHandler::OnEffectFlags::kConfigured);
|
||||
PluginActions::kConfigured);
|
||||
}
|
||||
|
||||
void Effect::Preview()
|
||||
|
@ -307,7 +307,7 @@ void EffectRack::OnApply(wxCommandEvent & WXUNUSED(evt))
|
||||
{
|
||||
if (!PluginActions::DoEffect(mEffects[i]->GetID(),
|
||||
*project,
|
||||
AudacityProject::OnEffectFlags::kConfigured))
|
||||
PluginActions::kConfigured))
|
||||
// If any effect fails (or throws), then stop.
|
||||
return;
|
||||
}
|
||||
|
@ -178,7 +178,6 @@ void DoReloadPreferences( AudacityProject &project )
|
||||
AudacityProject *p = gAudacityProjects[i].get();
|
||||
|
||||
GetMenuManager(*p).RebuildMenuBar(*p);
|
||||
p->RebuildOtherMenus();
|
||||
// TODO: The comment below suggests this workaround is obsolete.
|
||||
#if defined(__WXGTK__)
|
||||
// Workaround for:
|
||||
@ -1030,7 +1029,6 @@ void OnPreferences(const CommandContext &context)
|
||||
AudacityProject *p = gAudacityProjects[i].get();
|
||||
|
||||
GetMenuManager(*p).RebuildMenuBar(*p);
|
||||
p->RebuildOtherMenus();
|
||||
// TODO: The comment below suggests this workaround is obsolete.
|
||||
#if defined(__WXGTK__)
|
||||
// Workaround for:
|
||||
|
@ -23,7 +23,7 @@ void DoManagePluginsMenu
|
||||
(AudacityProject &project, EffectType type)
|
||||
{
|
||||
if (PluginManager::Get().ShowManager(&project, type))
|
||||
MenuCommandHandler::RebuildAllMenuBars();
|
||||
MenuCreator::RebuildAllMenuBars();
|
||||
}
|
||||
|
||||
bool CompareEffectsByName(const PluginDescriptor *a, const PluginDescriptor *b)
|
||||
@ -404,7 +404,7 @@ bool DoEffect(
|
||||
// Make sure there's no activity since the effect is about to be applied
|
||||
// to the project's tracks. Mainly for Apply during RTP, but also used
|
||||
// for batch commands
|
||||
if (flags & MenuCommandHandler::OnEffectFlags::kConfigured)
|
||||
if (flags & kConfigured)
|
||||
{
|
||||
TransportActions::DoStop(project);
|
||||
project.SelectAllIfNone();
|
||||
@ -443,22 +443,22 @@ bool DoEffect(
|
||||
|
||||
success = em.DoEffect(ID, &project, rate,
|
||||
tracks, trackFactory, &selectedRegion,
|
||||
(flags & MenuCommandHandler::OnEffectFlags::kConfigured) == 0);
|
||||
(flags & kConfigured) == 0);
|
||||
|
||||
if (!success)
|
||||
return false;
|
||||
|
||||
if (em.GetSkipStateFlag())
|
||||
flags = flags | MenuCommandHandler::OnEffectFlags::kSkipState;
|
||||
flags = flags | kSkipState;
|
||||
|
||||
if (!(flags & MenuCommandHandler::OnEffectFlags::kSkipState))
|
||||
if (!(flags & kSkipState))
|
||||
{
|
||||
wxString shortDesc = em.GetCommandName(ID);
|
||||
wxString longDesc = em.GetCommandDescription(ID);
|
||||
project.PushState(longDesc, shortDesc);
|
||||
}
|
||||
|
||||
if (!(flags & MenuCommandHandler::OnEffectFlags::kDontRepeatLast))
|
||||
if (!(flags & kDontRepeatLast))
|
||||
{
|
||||
// Only remember a successful effect, don't remember insert,
|
||||
// or analyze effects.
|
||||
@ -515,7 +515,7 @@ bool DoAudacityCommand(
|
||||
if (!plug)
|
||||
return false;
|
||||
|
||||
if (flags & MenuCommandHandler::OnEffectFlags::kConfigured)
|
||||
if (flags & kConfigured)
|
||||
{
|
||||
TransportActions::DoStop(project);
|
||||
// SelectAllIfNone();
|
||||
@ -525,7 +525,7 @@ bool DoAudacityCommand(
|
||||
bool success = em.DoAudacityCommand(ID,
|
||||
context,
|
||||
&project,
|
||||
(flags & MenuCommandHandler::OnEffectFlags::kConfigured) == 0);
|
||||
(flags & kConfigured) == 0);
|
||||
|
||||
if (!success)
|
||||
return false;
|
||||
@ -571,8 +571,7 @@ void OnRepeatLastEffect(const CommandContext &context)
|
||||
auto lastEffect = GetMenuManager(context.project).mLastEffect;
|
||||
if (!lastEffect.IsEmpty())
|
||||
{
|
||||
DoEffect(lastEffect,
|
||||
context, MenuCommandHandler::OnEffectFlags::kConfigured);
|
||||
DoEffect( lastEffect, context, kConfigured );
|
||||
}
|
||||
}
|
||||
|
||||
@ -682,8 +681,7 @@ void OnAudacityCommand(const CommandContext & ctx)
|
||||
wxLogDebug( "Command was: %s", ctx.parameter);
|
||||
// Not configured, so prompt user.
|
||||
DoAudacityCommand(EffectManager::Get().GetEffectByIdentifier(ctx.parameter),
|
||||
ctx,
|
||||
MenuCommandHandler::OnEffectFlags::kNone);
|
||||
ctx, kNone);
|
||||
}
|
||||
|
||||
}; // struct Handler
|
||||
|
@ -427,6 +427,84 @@ long mixer_process(void *mixer, float **buffer, long n)
|
||||
|
||||
#endif // EXPERIMENTAL_SCOREALIGN
|
||||
|
||||
//sort based on flags. see Project.h for sort flags
|
||||
void DoSortTracks( AudacityProject &project, int flags )
|
||||
{
|
||||
auto GetTime = [](const Track *t) {
|
||||
return t->TypeSwitch< double >(
|
||||
[&](const WaveTrack* w) {
|
||||
auto stime = w->GetEndTime();
|
||||
|
||||
int ndx;
|
||||
for (ndx = 0; ndx < w->GetNumClips(); ndx++) {
|
||||
const auto c = w->GetClipByIndex(ndx);
|
||||
if (c->GetNumSamples() == 0)
|
||||
continue;
|
||||
stime = std::min(stime, c->GetStartTime());
|
||||
}
|
||||
return stime;
|
||||
},
|
||||
[&](const LabelTrack* l) {
|
||||
return l->GetStartTime();
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
size_t ndx = 0;
|
||||
// This one place outside of TrackList where we must use undisguised
|
||||
// std::list iterators! Avoid this elsewhere!
|
||||
std::vector<TrackNodePointer> arr;
|
||||
auto pTracks = project.GetTracks();
|
||||
arr.reserve(pTracks->size());
|
||||
|
||||
// First find the permutation.
|
||||
// This routine, very unusually, deals with the underlying stl list
|
||||
// iterators, not with TrackIter! Dangerous!
|
||||
for (auto iter = pTracks->ListOfTracks::begin(),
|
||||
end = pTracks->ListOfTracks::end(); iter != end; ++iter) {
|
||||
const auto &track = *iter;
|
||||
if ( !track->IsLeader() )
|
||||
// keep channels contiguous
|
||||
ndx++;
|
||||
else {
|
||||
auto size = arr.size();
|
||||
for (ndx = 0; ndx < size;) {
|
||||
Track &arrTrack = **arr[ndx].first;
|
||||
auto channels = TrackList::Channels(&arrTrack);
|
||||
if(flags & kAudacitySortByName) {
|
||||
//do case insensitive sort - cmpNoCase returns less than zero if
|
||||
// the string is 'less than' its argument
|
||||
//also if we have case insensitive equality, then we need to sort
|
||||
// by case as well
|
||||
//We sort 'b' before 'B' accordingly. We uncharacteristically
|
||||
// use greater than for the case sensitive
|
||||
//compare because 'b' is greater than 'B' in ascii.
|
||||
auto cmpValue = track->GetName().CmpNoCase(arrTrack.GetName());
|
||||
if ( cmpValue < 0 ||
|
||||
( 0 == cmpValue &&
|
||||
track->GetName().CompareTo(arrTrack.GetName()) > 0 ) )
|
||||
break;
|
||||
}
|
||||
//sort by time otherwise
|
||||
else if(flags & kAudacitySortByTime) {
|
||||
auto time1 = TrackList::Channels(track.get()).min( GetTime );
|
||||
|
||||
//get candidate's (from sorted array) time
|
||||
auto time2 = channels.min( GetTime );
|
||||
|
||||
if (time1 < time2)
|
||||
break;
|
||||
}
|
||||
ndx += channels.size();
|
||||
}
|
||||
}
|
||||
arr.insert(arr.begin() + ndx, TrackNodePointer{iter, pTracks});
|
||||
}
|
||||
|
||||
// Now apply the permutation
|
||||
pTracks->Permute(arr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace TrackActions {
|
||||
@ -638,7 +716,7 @@ void OnStereoToMono(const CommandContext &context)
|
||||
PluginActions::DoEffect(
|
||||
EffectManager::Get().GetEffectByIdentifier(wxT("StereoToMono")),
|
||||
context,
|
||||
MenuCommandHandler::OnEffectFlags::kConfigured);
|
||||
PluginActions::kConfigured);
|
||||
}
|
||||
|
||||
void OnMixAndRender(const CommandContext &context)
|
||||
@ -989,7 +1067,7 @@ void OnScoreAlign(const CommandContext &context)
|
||||
void OnSortTime(const CommandContext &context)
|
||||
{
|
||||
auto &project = context.project;
|
||||
project.SortTracks(kAudacitySortByTime);
|
||||
DoSortTracks(project, kAudacitySortByTime);
|
||||
|
||||
project.PushState(_("Tracks sorted by time"), _("Sort by Time"));
|
||||
|
||||
@ -1000,7 +1078,7 @@ void OnSortTime(const CommandContext &context)
|
||||
void OnSortName(const CommandContext &context)
|
||||
{
|
||||
auto &project = context.project;
|
||||
project.SortTracks(kAudacitySortByName);
|
||||
DoSortTracks(project, kAudacitySortByName);
|
||||
|
||||
project.PushState(_("Tracks sorted by name"), _("Sort by Name"));
|
||||
|
||||
|
@ -223,7 +223,7 @@ void OnShowExtraMenus(const CommandContext &context)
|
||||
gPrefs->Write(wxT("/GUI/ShowExtraMenus"), checked);
|
||||
gPrefs->Flush();
|
||||
commandManager->Check(wxT("ShowExtraMenus"), checked);
|
||||
MenuCommandHandler::RebuildAllMenuBars();
|
||||
MenuCreator::RebuildAllMenuBars();
|
||||
}
|
||||
|
||||
void OnShowClipping(const CommandContext &context)
|
||||
|
@ -798,7 +798,7 @@ void WaveTrackMenuTable::OnSpectrogramSettings(wxCommandEvent &)
|
||||
//Bug 1725 Toolbar was left greyed out.
|
||||
//This solution is overkill, but does fix the problem and is what the
|
||||
//prefs dialog normally does.
|
||||
MenuCommandHandler::RebuildAllMenuBars();
|
||||
MenuCreator::RebuildAllMenuBars();
|
||||
mpData->result = RefreshCode::RefreshAll;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user