/********************************************************************** Audacity: A Digital Audio Editor BatchCommandDialog.cpp Dominic Mazzoni James Crook *******************************************************************//*! \class MacroCommandDialog \brief Provides a list of configurable commands for use with MacroCommands Provides a list of commands, mostly effects, which can be chained together in a simple linear sequence. Can configure parameters on each selected command. *//*******************************************************************/ #include "BatchCommandDialog.h" #ifdef __WXMSW__ #include #endif // #include #include #include #include #include #include #include #include #include #include #include #include #include #include "Project.h" #include "effects/EffectManager.h" #include "ShuttleGui.h" #include "widgets/HelpSystem.h" #define CommandsListID 7001 #define EditParamsButtonID 7002 #define UsePresetButtonID 7003 BEGIN_EVENT_TABLE(MacroCommandDialog, wxDialogWrapper) EVT_BUTTON(wxID_OK, MacroCommandDialog::OnOk) EVT_BUTTON(wxID_CANCEL, MacroCommandDialog::OnCancel) EVT_BUTTON(wxID_HELP, MacroCommandDialog::OnHelp) EVT_BUTTON(EditParamsButtonID, MacroCommandDialog::OnEditParams) EVT_BUTTON(UsePresetButtonID, MacroCommandDialog::OnUsePreset) EVT_LIST_ITEM_ACTIVATED(CommandsListID, MacroCommandDialog::OnItemSelected) EVT_LIST_ITEM_SELECTED(CommandsListID, MacroCommandDialog::OnItemSelected) END_EVENT_TABLE(); MacroCommandDialog::MacroCommandDialog( wxWindow * parent, wxWindowID id, AudacityProject &project): wxDialogWrapper(parent, id, XO("Select Command"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxRESIZE_BORDER) , mCatalog{ &project } { SetLabel(XO("Select Command")); // Provide visual label SetName(XO("Select Command")); // Provide audible label Populate(); } void MacroCommandDialog::Populate() { //------------------------- Main section -------------------- ShuttleGui S(this, eIsCreating); PopulateOrExchange(S); // ----------------------- End of main section -------------- } void MacroCommandDialog::PopulateOrExchange(ShuttleGui &S) { S.StartVerticalLay(true); { S.StartMultiColumn(4, wxEXPAND); { S.SetStretchyCol(1); mCommand = S.AddTextBox(XXO("&Command"), wxT(""), 20); mCommand->SetEditable(false); mEditParams = S.Id(EditParamsButtonID) .Disable() // disable button as box is empty .AddButton(XXO("&Edit Parameters")); mUsePreset = S.Id(UsePresetButtonID) .Disable() // disable button as box is empty .AddButton(XXO("&Use Preset")); } S.EndMultiColumn(); S.StartMultiColumn(2, wxEXPAND); { S.SetStretchyCol(1); mParameters = S.AddTextBox(XXO("&Parameters"), wxT(""), 0); mParameters->SetEditable(false); auto prompt = XXO("&Details"); S.Prop(0).AddPrompt(prompt); mDetails = S .Name( prompt ) .AddTextWindow( wxT("")); mDetails->SetEditable(false); } S.EndMultiColumn(); S.Prop(10).StartStatic(XO("Choose command"), true); { mChoices = S.Id(CommandsListID) .Style(wxSUNKEN_BORDER | wxLC_LIST | wxLC_SINGLE_SEL) .AddListControl(); } S.EndStatic(); } S.EndVerticalLay(); S.AddStandardButtons( eOkButton | eCancelButton | eHelpButton); PopulateCommandList(); if (mChoices->GetItemCount() > 0) { // set first item to be selected (and the focus when the // list first becomes the focus) mChoices->SetItemState(0, wxLIST_STATE_FOCUSED | wxLIST_STATE_SELECTED, wxLIST_STATE_FOCUSED | wxLIST_STATE_SELECTED); } SetMinSize(wxSize(780, 560)); Fit(); Center(); } void MacroCommandDialog::PopulateCommandList() { mChoices->DeleteAllItems(); long ii = 0; for ( const auto &entry : mCatalog ) // insert the user-facing string mChoices->InsertItem( ii++, entry.name.StrippedTranslation() ); } void MacroCommandDialog::ValidateChoices() { } void MacroCommandDialog::OnChoice(wxCommandEvent & WXUNUSED(event)) { } void MacroCommandDialog::OnOk(wxCommandEvent & WXUNUSED(event)) { mSelectedCommand = mInternalCommandName // .Strip(wxString::both) // PRL: used to do this, here only, // but ultimately mSelectedCommand is looked up in the catalog without // similar adjustment of whitespace in the comparison ; mSelectedParameters = mParameters->GetValue().Strip(wxString::trailing); EndModal(true); } void MacroCommandDialog::OnCancel(wxCommandEvent & WXUNUSED(event)) { EndModal(false); } void MacroCommandDialog::OnHelp(wxCommandEvent & WXUNUSED(event)) { const auto &page = GetHelpPageName(); HelpSystem::ShowHelp(this, page, true); } void MacroCommandDialog::OnItemSelected(wxListEvent &event) { const auto &command = mCatalog[ event.GetIndex() ]; EffectManager & em = EffectManager::Get(); PluginID ID = em.GetEffectByIdentifier( command.name.Internal() ); // If ID is empty, then the effect wasn't found, in which case, the user must have // selected one of the "special" commands. mEditParams->Enable(!ID.empty()); mUsePreset->Enable(em.HasPresets(ID)); auto value = command.name.StrippedTranslation(); if ( value == mCommand->GetValue() ) // This uses the assumption of uniqueness of translated names! return; mCommand->SetValue(value); mInternalCommandName = command.name.Internal(); wxString params = MacroCommands::GetCurrentParamsFor(mInternalCommandName); if (params.empty()) { params = em.GetDefaultPreset(ID); } // using GET to expose a CommandID to the user! // Cryptic command and category. // Later we can put help information there, perhaps. // Macro command details are one place that we do expose Identifier // to (more sophisticated) users mDetails->SetValue( mInternalCommandName.GET() + "\r\n" + command.category.Translation() ); mParameters->SetValue(params); } void MacroCommandDialog::OnEditParams(wxCommandEvent & WXUNUSED(event)) { auto command = mInternalCommandName; wxString params = mParameters->GetValue(); params = MacroCommands::PromptForParamsFor(command, params, *this).Trim(); mParameters->SetValue(params); mParameters->Refresh(); } void MacroCommandDialog::OnUsePreset(wxCommandEvent & WXUNUSED(event)) { auto command = mInternalCommandName; wxString params = mParameters->GetValue(); wxString preset = MacroCommands::PromptForPresetFor(command, params, this).Trim(); mParameters->SetValue(preset); mParameters->Refresh(); } void MacroCommandDialog::SetCommandAndParams(const CommandID &Command, const wxString &Params) { auto iter = mCatalog.ByCommandId( Command ); mParameters->SetValue( Params ); mInternalCommandName = Command; if (iter == mCatalog.end()) // uh oh, using GET to expose an internal name to the user! // in default of any better friendly name mCommand->SetValue( Command.GET() ); else { mCommand->SetValue( iter->name.StrippedTranslation() ); // using GET to expose a CommandID to the user! // Macro command details are one place that we do expose Identifier // to (more sophisticated) users mDetails->SetValue( iter->name.Internal() + "\r\n" + iter->category.Translation() ); mChoices->SetItemState(iter - mCatalog.begin(), wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED); EffectManager & em = EffectManager::Get(); PluginID ID = em.GetEffectByIdentifier(Command); // If ID is empty, then the effect wasn't found, in which case, the user must have // selected one of the "special" commands. mEditParams->Enable(!ID.empty()); mUsePreset->Enable(em.HasPresets(ID)); } }