Define MacroCommandsCatalog to associate friendly and internal names...
... friendly names are still English only. Not yet localized, but ought to be.
This commit is contained in:
parent
9d73effe09
commit
ffadd64a56
|
@ -62,6 +62,7 @@ MacroCommandDialog::MacroCommandDialog(wxWindow * parent, wxWindowID id):
|
|||
wxDialogWrapper(parent, id, _("Select Command"),
|
||||
wxDefaultPosition, wxDefaultSize,
|
||||
wxCAPTION | wxRESIZE_BORDER)
|
||||
, mCatalog( GetActiveProject() )
|
||||
{
|
||||
SetLabel(_("Select Command")); // Provide visual label
|
||||
SetName(_("Select Command")); // Provide audible label
|
||||
|
@ -123,12 +124,11 @@ void MacroCommandDialog::PopulateOrExchange(ShuttleGui &S)
|
|||
|
||||
void MacroCommandDialog::PopulateCommandList()
|
||||
{
|
||||
mCommandNames = MacroCommands::GetAllCommands();
|
||||
|
||||
mChoices->DeleteAllItems();
|
||||
for (size_t ii = 0, size = mCommandNames.size(); ii < size; ++ii)
|
||||
long ii = 0;
|
||||
for ( const auto &entry : mCatalog )
|
||||
// insert the user-facing string
|
||||
mChoices->InsertItem( ii, std::get<0>( mCommandNames[ii] ) );
|
||||
mChoices->InsertItem( ii++, entry.friendly /* .Translation() */ );
|
||||
}
|
||||
|
||||
void MacroCommandDialog::ValidateChoices()
|
||||
|
@ -159,21 +159,21 @@ void MacroCommandDialog::OnHelp(wxCommandEvent & WXUNUSED(event))
|
|||
|
||||
void MacroCommandDialog::OnItemSelected(wxListEvent &event)
|
||||
{
|
||||
const auto &command = mCommandNames[ event.GetIndex() ];
|
||||
const auto &command = mCatalog[ event.GetIndex() ];
|
||||
|
||||
EffectManager & em = EffectManager::Get();
|
||||
PluginID ID = em.GetEffectByIdentifier( std::get<1>( command ));
|
||||
PluginID ID = em.GetEffectByIdentifier( command.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.IsEmpty());
|
||||
mUsePreset->Enable(em.HasPresets(ID));
|
||||
|
||||
if (std::get<0>( command ) == mCommand->GetValue())
|
||||
if ( command.friendly == mCommand->GetValue() )
|
||||
return;
|
||||
|
||||
mCommand->SetValue(std::get<0> (command));
|
||||
mInternalCommandName = std::get<1>( command );
|
||||
mCommand->SetValue(command.friendly);
|
||||
mInternalCommandName = command.internal;
|
||||
|
||||
wxString params = MacroCommands::GetCurrentParamsFor(mInternalCommandName);
|
||||
if (params.IsEmpty())
|
||||
|
@ -183,7 +183,7 @@ void MacroCommandDialog::OnItemSelected(wxListEvent &event)
|
|||
|
||||
// Cryptic command and category.
|
||||
// Later we can put help information there, perhaps.
|
||||
mDetails->SetValue( mInternalCommandName + "\r\n" + std::get<2>(command) );
|
||||
mDetails->SetValue( mInternalCommandName + "\r\n" + command.category );
|
||||
mParameters->SetValue(params);
|
||||
}
|
||||
|
||||
|
@ -211,19 +211,20 @@ void MacroCommandDialog::OnUsePreset(wxCommandEvent & WXUNUSED(event))
|
|||
|
||||
void MacroCommandDialog::SetCommandAndParams(const wxString &Command, const wxString &Params)
|
||||
{
|
||||
auto item = make_iterator_range(mCommandNames).index_if(
|
||||
[&](const CommandName &name){ return Command == std::get<1>( name); }
|
||||
);
|
||||
auto iter = mCatalog.ByCommandId( Command );
|
||||
|
||||
mParameters->SetValue( Params );
|
||||
|
||||
mInternalCommandName = Command;
|
||||
if (item < 0)
|
||||
if (iter == mCatalog.end())
|
||||
// Expose an internal name to the user in default of any friendly name
|
||||
// -- AVOID THIS!
|
||||
mCommand->SetValue( Command );
|
||||
else {
|
||||
mCommand->SetValue( std::get<0>( mCommandNames[item]) );
|
||||
mDetails->SetValue( std::get<1>(mCommandNames[item]) + "\r\n" + std::get<2>(mCommandNames[item]) );
|
||||
mChoices->SetItemState(item, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
|
||||
mCommand->SetValue( iter->friendly /* .Translation() */ );
|
||||
mDetails->SetValue( iter->internal + "\r\n" + iter->category );
|
||||
mChoices->SetItemState(iter - mCatalog.begin(),
|
||||
wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
|
||||
|
||||
EffectManager & em = EffectManager::Get();
|
||||
PluginID ID = em.GetEffectByIdentifier(Command);
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#ifndef __AUDACITY_MACRO_COMMAND_DIALOG__
|
||||
#define __AUDACITY_MACRO_COMMAND_DIALOG__
|
||||
|
||||
#include "MemoryX.h"
|
||||
#include <wx/defs.h>
|
||||
#include <wx/string.h>
|
||||
|
||||
|
@ -26,6 +25,8 @@
|
|||
#include <wx/menuitem.h>
|
||||
#include <wx/checklst.h>
|
||||
|
||||
#include "BatchCommands.h"
|
||||
|
||||
class wxWindow;
|
||||
class wxCheckBox;
|
||||
class wxChoice;
|
||||
|
@ -70,9 +71,7 @@ class MacroCommandDialog final : public wxDialogWrapper {
|
|||
|
||||
wxString mInternalCommandName;
|
||||
|
||||
using CommandName = std::tuple<wxString, wxString,wxString>;
|
||||
using CommandNameVector = std::vector<CommandName>;
|
||||
CommandNameVector mCommandNames;
|
||||
const MacroCommandsCatalog mCatalog;
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
|
|
@ -274,19 +274,19 @@ bool MacroCommands::RenameMacro(const wxString & oldchain, const wxString & newc
|
|||
}
|
||||
|
||||
// Gets all commands that are valid for this mode.
|
||||
auto MacroCommands::GetAllCommands() -> CommandNameVector
|
||||
MacroCommandsCatalog::MacroCommandsCatalog( const AudacityProject *project )
|
||||
{
|
||||
CommandNameVector commands;
|
||||
|
||||
AudacityProject *project = GetActiveProject();
|
||||
if (!project)
|
||||
return commands;
|
||||
return;
|
||||
|
||||
// CLEANSPEECH remnant
|
||||
Entries commands;
|
||||
for( const auto &command : SpecialCommands )
|
||||
commands.push_back(
|
||||
CommandName( command.first, command.second, _("Special Command") )
|
||||
);
|
||||
commands.push_back( {
|
||||
command.first /* .Translation() */,
|
||||
command.second,
|
||||
_("Special Command")
|
||||
} );
|
||||
|
||||
// end CLEANSPEECH remnant
|
||||
|
||||
|
@ -298,72 +298,103 @@ auto MacroCommands::GetAllCommands() -> CommandNameVector
|
|||
{
|
||||
auto command = em.GetCommandIdentifier(plug->GetID());
|
||||
if (!command.IsEmpty())
|
||||
commands.push_back(
|
||||
CommandName(
|
||||
plug->GetUntranslatedName(), // plug->GetTranslatedName(),
|
||||
command,
|
||||
plug->GetPluginType() == PluginTypeEffect ?
|
||||
_("Effect") : _("Menu Command (With Parameters)")
|
||||
)
|
||||
);
|
||||
commands.push_back( {
|
||||
plug->GetUntranslatedName(), // plug->GetTranslatedName(),
|
||||
command,
|
||||
plug->GetPluginType() == PluginTypeEffect ?
|
||||
_("Effect") : _("Menu Command (With Parameters)")
|
||||
} );
|
||||
plug = pm.GetNextPlugin(PluginTypeEffect|PluginTypeAudacityCommand);
|
||||
}
|
||||
}
|
||||
|
||||
CommandManager * mManager = project->GetCommandManager();
|
||||
auto mManager = project->GetCommandManager();
|
||||
wxArrayString mLabels;
|
||||
wxArrayString mNames;
|
||||
mLabels.Clear();
|
||||
mNames.Clear();
|
||||
mManager->GetAllCommandLabels(mLabels, false);
|
||||
mManager->GetAllCommandNames(mNames, false);
|
||||
|
||||
const bool english = wxGetLocale()->GetCanonicalName().StartsWith(wxT("en"));
|
||||
|
||||
for(size_t i=0; i<mNames.GetCount(); i++) {
|
||||
wxString label = mLabels[i];
|
||||
if( !label.Contains( "..." ) ){
|
||||
label.Replace( "&", "" );
|
||||
wxString squashed = label;
|
||||
squashed.Replace( " ", "" );
|
||||
bool suffix;
|
||||
if (!english)
|
||||
suffix = true;
|
||||
else {
|
||||
// We'll disambiguate if the squashed name is short and shorter than the internal name.
|
||||
// Otherwise not.
|
||||
// This means we won't have repetitive items like "Cut (Cut)"
|
||||
// But we will show important disambiguation like "All (SelectAll)" and "By Date (SortByDate)"
|
||||
// Disambiguation is no longer essential as the details box will show it.
|
||||
// PRL: I think this reasoning applies only when locale is English.
|
||||
// For other locales, show the (CamelCaseCodeName) always. Or, never?
|
||||
wxString squashed = label;
|
||||
squashed.Replace( " ", "" );
|
||||
|
||||
// We'll disambiguate if the squashed name is short and shorter than the internal name.
|
||||
// Otherwise not.
|
||||
// This means we won't have repetitive items like "Cut (Cut)"
|
||||
// But we will show important disambiguation like "All (SelectAll)" and "By Date (SortByDate)"
|
||||
// Disambiguation is no longer essential as the details box will show it.
|
||||
if( squashed.Length() < wxMin( 18, mNames[i].Length()) )
|
||||
suffix = squashed.Length() < wxMin( 18, mNames[i].Length());
|
||||
}
|
||||
|
||||
if( suffix )
|
||||
label = label + " (" + mNames[i] + ")";
|
||||
|
||||
commands.push_back(
|
||||
CommandName(
|
||||
label, // User readable name
|
||||
commands.push_back(
|
||||
{
|
||||
label, // User readable name
|
||||
mNames[i], // Internal name.
|
||||
_("Menu Command (No Parameters)")
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort commands by their user-visible names.
|
||||
// PRL: What should happen if first members of pairs are not unique?
|
||||
// Sort stably?
|
||||
std::sort(
|
||||
commands.begin(), commands.end(),
|
||||
[](const CommandName &a, const CommandName &b)
|
||||
{ return std::get<0>(a) < std::get<0>(b); }
|
||||
);
|
||||
// PRL: What exactly should happen if first members of pairs are not unique?
|
||||
// I'm not sure, but at least I can sort stably for a better defined result,
|
||||
// keeping specials before effects and menu items, and lastly commands.
|
||||
auto less =
|
||||
[](const Entry &a, const Entry &b) { return a.friendly < b.friendly; };
|
||||
std::stable_sort(commands.begin(), commands.end(), less);
|
||||
|
||||
// JKC: Gave up on trying to use std::unique on this.
|
||||
CommandNameVector uniqueCommands;
|
||||
unsigned size = commands.size();
|
||||
wxString oldName = "";
|
||||
for( unsigned i = 0; i < size; ++i )
|
||||
{
|
||||
if( std::get<0>( commands[i] ) != oldName )
|
||||
uniqueCommands.push_back( commands[i] );
|
||||
oldName = std::get<0>( commands[i] );
|
||||
}
|
||||
return uniqueCommands;
|
||||
// Now uniquify by friendly name
|
||||
auto equal =
|
||||
[](const Entry &a, const Entry &b) { return a.friendly == b.friendly; };
|
||||
std::unique_copy(
|
||||
commands.begin(), commands.end(), std::back_inserter(mCommands), equal);
|
||||
}
|
||||
|
||||
// binary search
|
||||
auto MacroCommandsCatalog::ByFriendlyName( const wxString &friendlyName ) const
|
||||
-> Entries::const_iterator
|
||||
{
|
||||
const auto less = [&](const Entry &entryA, const Entry &entryB)
|
||||
{ return entryA.friendly < entryB.friendly; };
|
||||
auto range = std::equal_range(
|
||||
begin(), end(), Entry{ friendlyName }, less);
|
||||
if (range.first != range.second) {
|
||||
wxASSERT_MSG( range.first + 1 == range.second,
|
||||
"Non-unique user-visible command name" );
|
||||
return range.first;
|
||||
}
|
||||
else
|
||||
return end();
|
||||
}
|
||||
|
||||
// linear search
|
||||
auto MacroCommandsCatalog::ByCommandId( const wxString &commandId ) const
|
||||
-> Entries::const_iterator
|
||||
{
|
||||
// Maybe this too should have a uniqueness check?
|
||||
return std::find_if( begin(), end(),
|
||||
[&](const Entry &entry){ return entry.internal == commandId; });
|
||||
}
|
||||
|
||||
|
||||
|
||||
wxString MacroCommands::GetCurrentParamsFor(const wxString & command)
|
||||
{
|
||||
const PluginID & ID = EffectManager::Get().GetEffectByIdentifier(command);
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#ifndef __AUDACITY_BATCH_COMMANDS_DIALOG__
|
||||
#define __AUDACITY_BATCH_COMMANDS_DIALOG__
|
||||
|
||||
#include "MemoryX.h"
|
||||
#include <wx/defs.h>
|
||||
#include <wx/string.h>
|
||||
|
||||
|
@ -20,7 +19,37 @@
|
|||
|
||||
class Effect;
|
||||
class CommandContext;
|
||||
class AudacityProject;
|
||||
|
||||
class MacroCommandsCatalog {
|
||||
public:
|
||||
// A triple of user-visible name, internal string identifier and type/help string.
|
||||
struct Entry {
|
||||
wxString friendly;
|
||||
wxString internal;
|
||||
wxString category;
|
||||
};
|
||||
using Entries = std::vector<Entry>;
|
||||
|
||||
MacroCommandsCatalog( const AudacityProject *project );
|
||||
|
||||
// binary search
|
||||
Entries::const_iterator ByFriendlyName( const wxString &friendlyName ) const;
|
||||
// linear search
|
||||
Entries::const_iterator ByCommandId( const wxString &commandId ) const;
|
||||
|
||||
// Lookup by position as sorted by friendly name
|
||||
const Entry &operator[] ( size_t index ) const { return mCommands[index]; }
|
||||
|
||||
Entries::const_iterator begin() const { return mCommands.begin(); }
|
||||
Entries::const_iterator end() const { return mCommands.end(); }
|
||||
|
||||
private:
|
||||
// Sorted by friendly name
|
||||
Entries mCommands;
|
||||
};
|
||||
|
||||
// Stores information for one chain
|
||||
class MacroCommands final {
|
||||
public:
|
||||
// constructors and destructors
|
||||
|
@ -44,12 +73,6 @@ class MacroCommands final {
|
|||
static wxArrayString GetNames();
|
||||
static wxArrayString GetNamesOfDefaultMacros();
|
||||
|
||||
// A triple of user-visible name, internal string identifier and type/help string.
|
||||
using CommandName = std::tuple<wxString, wxString, wxString>;
|
||||
using CommandNameVector = std::vector<CommandName>;
|
||||
// Result is sorted by user-visible name
|
||||
static CommandNameVector GetAllCommands();
|
||||
|
||||
static wxString GetCurrentParamsFor(const wxString & command);
|
||||
static wxString PromptForParamsFor(const wxString & command, const wxString & params, wxWindow *parent);
|
||||
static wxString PromptForPresetFor(const wxString & command, const wxString & params, wxWindow *parent);
|
||||
|
|
|
@ -525,6 +525,7 @@ enum {
|
|||
/// Constructor
|
||||
MacrosWindow::MacrosWindow(wxWindow * parent, bool bExpanded):
|
||||
ApplyMacroDialog(parent, true)
|
||||
, mCatalog( GetActiveProject() )
|
||||
{
|
||||
mbExpanded = bExpanded;
|
||||
SetLabel(_("Manage Macros")); // Provide visual label
|
||||
|
@ -547,8 +548,6 @@ MacrosWindow::~MacrosWindow()
|
|||
/// Creates the dialog and its contents.
|
||||
void MacrosWindow::Populate()
|
||||
{
|
||||
mCommandNames = MacroCommands::GetAllCommands();
|
||||
|
||||
//------------------------- Main section --------------------
|
||||
ShuttleGui S(this, eIsCreating);
|
||||
PopulateOrExchange(S);
|
||||
|
@ -690,14 +689,13 @@ void MacrosWindow::PopulateList()
|
|||
/// Add one item into mList
|
||||
void MacrosWindow::AddItem(const wxString &Action, const wxString &Params)
|
||||
{
|
||||
// Translate internal command name to a friendly form
|
||||
auto item = make_iterator_range(mCommandNames).index_if(
|
||||
[&](const CommandName &name){ return Action == std::get<1>(name); }
|
||||
);
|
||||
auto friendlyName = item >= 0
|
||||
? // wxGetTranslation
|
||||
std::get<0>( mCommandNames[item] )
|
||||
: Action;
|
||||
auto entry = mCatalog.ByCommandId(Action);
|
||||
auto friendlyName = entry != mCatalog.end()
|
||||
? entry->friendly /* .Translation() */
|
||||
:
|
||||
// Expose an internal name to the user in default of any friendly name
|
||||
// -- AVOID THIS!
|
||||
Action;
|
||||
|
||||
int i = mList->GetItemCount();
|
||||
|
||||
|
|
|
@ -142,9 +142,7 @@ private:
|
|||
int mSelectedCommand;
|
||||
bool mChanged;
|
||||
|
||||
using CommandName = std::tuple<wxString, wxString,wxString>;
|
||||
using CommandNameVector = std::vector<CommandName>;
|
||||
CommandNameVector mCommandNames;
|
||||
const MacroCommandsCatalog mCatalog;
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
|
|
@ -1650,7 +1650,7 @@ void CommandManager::GetCategories(wxArrayString &cats)
|
|||
}
|
||||
|
||||
void CommandManager::GetAllCommandNames(wxArrayString &names,
|
||||
bool includeMultis)
|
||||
bool includeMultis) const
|
||||
{
|
||||
for(const auto &entry : mCommandList) {
|
||||
if ( entry->isEffect )
|
||||
|
@ -1663,7 +1663,7 @@ void CommandManager::GetAllCommandNames(wxArrayString &names,
|
|||
}
|
||||
|
||||
void CommandManager::GetAllCommandLabels(wxArrayString &names,
|
||||
bool includeMultis)
|
||||
bool includeMultis) const
|
||||
{
|
||||
for(const auto &entry : mCommandList) {
|
||||
// This is fetching commands from the menus, for use as batch commands.
|
||||
|
|
|
@ -278,8 +278,8 @@ class AUDACITY_DLL_API CommandManager final : public XMLTagHandler
|
|||
//
|
||||
|
||||
void GetCategories(wxArrayString &cats);
|
||||
void GetAllCommandNames(wxArrayString &names, bool includeMultis);
|
||||
void GetAllCommandLabels(wxArrayString &labels, bool includeMultis);
|
||||
void GetAllCommandNames(wxArrayString &names, bool includeMultis) const;
|
||||
void GetAllCommandLabels(wxArrayString &labels, bool includeMultis) const;
|
||||
void GetAllCommandData(
|
||||
wxArrayString &names,
|
||||
std::vector<NormalizedKeyString> &keys,
|
||||
|
|
Loading…
Reference in New Issue