1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-19 17:40:15 +02:00

Fix part-translated identifiers for Align cmds; new string pair class

This commit is contained in:
Paul Licameli 2018-03-15 20:34:17 -04:00
commit cfd9bd3331
19 changed files with 143 additions and 117 deletions

View File

@ -128,7 +128,7 @@ void MacroCommandDialog::PopulateCommandList()
long ii = 0; long ii = 0;
for ( const auto &entry : mCatalog ) for ( const auto &entry : mCatalog )
// insert the user-facing string // insert the user-facing string
mChoices->InsertItem( ii++, entry.friendly /* .Translation() */ ); mChoices->InsertItem( ii++, entry.name.Translated() );
} }
void MacroCommandDialog::ValidateChoices() void MacroCommandDialog::ValidateChoices()
@ -162,18 +162,19 @@ void MacroCommandDialog::OnItemSelected(wxListEvent &event)
const auto &command = mCatalog[ event.GetIndex() ]; const auto &command = mCatalog[ event.GetIndex() ];
EffectManager & em = EffectManager::Get(); EffectManager & em = EffectManager::Get();
PluginID ID = em.GetEffectByIdentifier( command.internal ); PluginID ID = em.GetEffectByIdentifier( command.name.Internal() );
// If ID is empty, then the effect wasn't found, in which case, the user must have // If ID is empty, then the effect wasn't found, in which case, the user must have
// selected one of the "special" commands. // selected one of the "special" commands.
mEditParams->Enable(!ID.IsEmpty()); mEditParams->Enable(!ID.IsEmpty());
mUsePreset->Enable(em.HasPresets(ID)); mUsePreset->Enable(em.HasPresets(ID));
if ( command.friendly == mCommand->GetValue() ) if ( command.name.Translated() == mCommand->GetValue() )
// This uses the assumption of uniqueness of translated names!
return; return;
mCommand->SetValue(command.friendly); mCommand->SetValue(command.name.Translated());
mInternalCommandName = command.internal; mInternalCommandName = command.name.Internal();
wxString params = MacroCommands::GetCurrentParamsFor(mInternalCommandName); wxString params = MacroCommands::GetCurrentParamsFor(mInternalCommandName);
if (params.IsEmpty()) if (params.IsEmpty())
@ -221,8 +222,8 @@ void MacroCommandDialog::SetCommandAndParams(const wxString &Command, const wxSt
// -- AVOID THIS! // -- AVOID THIS!
mCommand->SetValue( Command ); mCommand->SetValue( Command );
else { else {
mCommand->SetValue( iter->friendly /* .Translation() */ ); mCommand->SetValue( iter->name.Translated() );
mDetails->SetValue( iter->internal + "\r\n" + iter->category ); mDetails->SetValue( iter->name.Internal() + "\r\n" + iter->category );
mChoices->SetItemState(iter - mCatalog.begin(), mChoices->SetItemState(iter - mCatalog.begin(),
wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED); wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);

View File

@ -289,8 +289,7 @@ MacroCommandsCatalog::MacroCommandsCatalog( const AudacityProject *project )
Entries commands; Entries commands;
for( const auto &command : SpecialCommands ) for( const auto &command : SpecialCommands )
commands.push_back( { commands.push_back( {
GetCustomTranslation( command.first ), { command.second, GetCustomTranslation( command.first ) },
command.second,
_("Special Command") _("Special Command")
} ); } );
@ -305,8 +304,7 @@ MacroCommandsCatalog::MacroCommandsCatalog( const AudacityProject *project )
auto command = em.GetCommandIdentifier(plug->GetID()); auto command = em.GetCommandIdentifier(plug->GetID());
if (!command.IsEmpty()) if (!command.IsEmpty())
commands.push_back( { commands.push_back( {
plug->GetTranslatedName(), { command, plug->GetTranslatedName() },
command,
plug->GetPluginType() == PluginTypeEffect ? plug->GetPluginType() == PluginTypeEffect ?
_("Effect") : _("Menu Command (With Parameters)") _("Effect") : _("Menu Command (With Parameters)")
} ); } );
@ -350,8 +348,10 @@ MacroCommandsCatalog::MacroCommandsCatalog( const AudacityProject *project )
commands.push_back( commands.push_back(
{ {
label, // User readable name {
mNames[i], // Internal name. mNames[i], // Internal name.
label // User readable name
},
_("Menu Command (No Parameters)") _("Menu Command (No Parameters)")
} }
); );
@ -363,12 +363,14 @@ MacroCommandsCatalog::MacroCommandsCatalog( const AudacityProject *project )
// I'm not sure, but at least I can sort stably for a better defined result, // 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. // keeping specials before effects and menu items, and lastly commands.
auto less = auto less =
[](const Entry &a, const Entry &b) { return a.friendly < b.friendly; }; [](const Entry &a, const Entry &b)
{ return a.name.Translated() < b.name.Translated(); };
std::stable_sort(commands.begin(), commands.end(), less); std::stable_sort(commands.begin(), commands.end(), less);
// Now uniquify by friendly name // Now uniquify by friendly name
auto equal = auto equal =
[](const Entry &a, const Entry &b) { return a.friendly == b.friendly; }; [](const Entry &a, const Entry &b)
{ return a.name.Translated() == b.name.Translated(); };
std::unique_copy( std::unique_copy(
commands.begin(), commands.end(), std::back_inserter(mCommands), equal); commands.begin(), commands.end(), std::back_inserter(mCommands), equal);
} }
@ -378,9 +380,10 @@ auto MacroCommandsCatalog::ByFriendlyName( const wxString &friendlyName ) const
-> Entries::const_iterator -> Entries::const_iterator
{ {
const auto less = [](const Entry &entryA, const Entry &entryB) const auto less = [](const Entry &entryA, const Entry &entryB)
{ return entryA.friendly < entryB.friendly; }; { return entryA.name.Translated() < entryB.name.Translated(); };
auto range = std::equal_range( auto range = std::equal_range(
begin(), end(), Entry{ friendlyName, {}, {} }, less); begin(), end(), Entry{ { {}, friendlyName }, {} }, less
);
if (range.first != range.second) { if (range.first != range.second) {
wxASSERT_MSG( range.first + 1 == range.second, wxASSERT_MSG( range.first + 1 == range.second,
"Non-unique user-visible command name" ); "Non-unique user-visible command name" );
@ -396,7 +399,8 @@ auto MacroCommandsCatalog::ByCommandId( const wxString &commandId ) const
{ {
// Maybe this too should have a uniqueness check? // Maybe this too should have a uniqueness check?
return std::find_if( begin(), end(), return std::find_if( begin(), end(),
[&](const Entry &entry){ return entry.internal == commandId; }); [&](const Entry &entry)
{ return entry.name.Internal() == commandId; });
} }
@ -839,7 +843,7 @@ bool MacroCommands::ApplyMacro(
auto iter = catalog.ByCommandId(command); auto iter = catalog.ByCommandId(command);
auto friendly = (iter == catalog.end()) auto friendly = (iter == catalog.end())
? command // Expose internal name to user, in default of a better one! ? command // Expose internal name to user, in default of a better one!
: iter->friendly; : iter->name.Translated();
if (!ApplyCommandInBatchMode(friendly, command, mParamsMacro[i]) || mAbort) if (!ApplyCommandInBatchMode(friendly, command, mParamsMacro[i]) || mAbort)
break; break;
} }

View File

@ -25,8 +25,7 @@ class MacroCommandsCatalog {
public: public:
// A triple of user-visible name, internal string identifier and type/help string. // A triple of user-visible name, internal string identifier and type/help string.
struct Entry { struct Entry {
wxString friendly; TranslatedInternalString name;
wxString internal;
wxString category; wxString category;
}; };
using Entries = std::vector<Entry>; using Entries = std::vector<Entry>;

View File

@ -686,7 +686,7 @@ void MacrosWindow::AddItem(const wxString &Action, const wxString &Params)
{ {
auto entry = mCatalog.ByCommandId(Action); auto entry = mCatalog.ByCommandId(Action);
auto friendlyName = entry != mCatalog.end() auto friendlyName = entry != mCatalog.end()
? entry->friendly /* .Translation() */ ? entry->name.Translated()
: :
// Expose an internal name to the user in default of any friendly name // Expose an internal name to the user in default of any friendly name
// -- AVOID THIS! // -- AVOID THIS!

View File

@ -184,4 +184,36 @@ inline wxArrayString LocalizedStrings(const wxArrayString &strings)
return LocalizedStrings( &strings[0], strings.size() ); return LocalizedStrings( &strings[0], strings.size() );
} }
// This object pairs an internal string, maybe empty, with a translated string.
// Any internal string may be written to configuration or other files and,
// for compatibility, should not vary between Audacity versions.
// The translated string may be shown to users and may vary with locale, and
// Audacity version if it is decided to use a different user-visible message.
// Sometimes the translated string is derived from a msgid identical
// to the internal string. The translated string is not meant to persist.
class TranslatedInternalString
{
public:
TranslatedInternalString() = default;
// One-argument constructor from a msgid
explicit TranslatedInternalString( const wxString &internal )
: mInternal{ internal }, mTranslated{ GetCustomTranslation( internal ) }
{}
// Two-argument version, when translated does not derive from internal
TranslatedInternalString( const wxString &internal,
const wxString &translated )
: mInternal{ internal }, mTranslated{ translated }
{}
const wxString &Internal() const { return mInternal; }
const wxString &Translated() const { return mTranslated; }
private:
wxString mInternal;
wxString mTranslated;
};
#endif #endif

View File

@ -1020,17 +1020,19 @@ void AudacityProject::CreateMenusAndCommands()
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
wxArrayString alignLabelsNoSync; const TranslatedInternalString alignLabelsNoSync[] = {
alignLabelsNoSync.Add(_("&Align End to End")); { wxT("EndToEnd"), _("&Align End to End") },
alignLabelsNoSync.Add(_("Align &Together")); { wxT("Together"), _("Align &Together") },
};
wxArrayString alignLabels; const TranslatedInternalString alignLabels[] = {
alignLabels.Add(_("Start to &Zero")); { wxT("StartToZero"), _("Start to &Zero") },
alignLabels.Add(_("Start to &Cursor/Selection Start")); { wxT("StartToSelStart"), _("Start to &Cursor/Selection Start") },
alignLabels.Add(_("Start to Selection &End")); { wxT("StartToSelEnd"), _("Start to Selection &End") },
alignLabels.Add(_("End to Cu&rsor/Selection Start")); { wxT("EndToSelStart"), _("End to Cu&rsor/Selection Start") },
alignLabels.Add(_("End to Selection En&d")); { wxT("EndToSelEnd"), _("End to Selection En&d") },
mAlignLabelsCount = alignLabels.GetCount(); };
mAlignLabelsCount = sizeof(alignLabels) / sizeof(alignLabels[0]);
// Calling c->SetCommandFlags() after AddItemList for "Align" and "AlignMove" // Calling c->SetCommandFlags() after AddItemList for "Align" and "AlignMove"
// does not correctly set flags for submenus, so do it this way. // does not correctly set flags for submenus, so do it this way.
@ -1040,9 +1042,9 @@ void AudacityProject::CreateMenusAndCommands()
c->BeginSubMenu(_("&Align Tracks")); c->BeginSubMenu(_("&Align Tracks"));
//c->BeginSubMenu(_("Just Move Tracks")); //c->BeginSubMenu(_("Just Move Tracks"));
c->AddItemList(wxT("Align"), alignLabelsNoSync, FN(OnAlignNoSync)); c->AddItemList(wxT("Align"), alignLabelsNoSync, 2u, FN(OnAlignNoSync));
c->AddSeparator(); c->AddSeparator();
c->AddItemList(wxT("Align"), alignLabels, FN(OnAlign)); c->AddItemList(wxT("Align"), alignLabels, mAlignLabelsCount, FN(OnAlign));
c->AddSeparator(); c->AddSeparator();
c->AddCheck(wxT("MoveSelectionWithTracks"), _("&Move Selection with Tracks (on/off)"), c->AddCheck(wxT("MoveSelectionWithTracks"), _("&Move Selection with Tracks (on/off)"),
FN(OnMoveSelectionWithTracks), FN(OnMoveSelectionWithTracks),
@ -1054,7 +1056,7 @@ void AudacityProject::CreateMenusAndCommands()
// TODO: Can these labels be made clearer? Do we need this sub-menu at all? // TODO: Can these labels be made clearer? Do we need this sub-menu at all?
c->BeginSubMenu(_("Move Sele&ction and Tracks")); c->BeginSubMenu(_("Move Sele&ction and Tracks"));
c->AddItemList(wxT("AlignMove"), alignLabels, FN(OnAlignMoveSel)); c->AddItemList(wxT("AlignMove"), alignLabels, mAlignLabelsCount, FN(OnAlignMoveSel));
c->SetCommandFlags(wxT("AlignMove"), c->SetCommandFlags(wxT("AlignMove"),
AudioIONotBusyFlag | TracksSelectedFlag, AudioIONotBusyFlag | TracksSelectedFlag,
AudioIONotBusyFlag | TracksSelectedFlag); AudioIONotBusyFlag | TracksSelectedFlag);

View File

@ -57,7 +57,7 @@ bool BatchEvalCommand::Apply(const CommandContext & context)
auto iter = catalog.ByCommandId(cmdName); auto iter = catalog.ByCommandId(cmdName);
const wxString &friendly = (iter == catalog.end()) const wxString &friendly = (iter == catalog.end())
? cmdName // Expose internal name to user, in default of a better one! ? cmdName // Expose internal name to user, in default of a better one!
: iter->friendly; : iter->name.Translated();
// Create a Batch that will have just one command in it... // Create a Batch that will have just one command in it...
MacroCommands Batch; MacroCommands Batch;

View File

@ -760,7 +760,7 @@ void CommandManager::InsertItem(const wxString & name,
} }
} }
CommandListEntry *entry = NewIdentifier(name, label_in, menu, finder, callback, false, 0, 0, false); CommandListEntry *entry = NewIdentifier(name, label_in, menu, finder, callback, {}, 0, 0, false);
int ID = entry->id; int ID = entry->id;
wxString label = GetLabel(entry); wxString label = GetLabel(entry);
@ -828,7 +828,7 @@ void CommandManager::AddItem(const wxChar *name,
cookedParameter = parameter; cookedParameter = parameter;
CommandListEntry *entry = CommandListEntry *entry =
NewIdentifier(name, label_in, accel, CurrentMenu(), finder, callback, NewIdentifier(name, label_in, accel, CurrentMenu(), finder, callback,
false, 0, 0, bIsEffect, cookedParameter); {}, 0, 0, bIsEffect, cookedParameter);
int ID = entry->id; int ID = entry->id;
wxString label = GetLabelWithDisabledAccel(entry); wxString label = GetLabelWithDisabledAccel(entry);
@ -855,18 +855,19 @@ void CommandManager::AddItem(const wxChar *name,
/// When you call Enable on this command name, it will enable or disable /// When you call Enable on this command name, it will enable or disable
/// all of the items at once. /// all of the items at once.
void CommandManager::AddItemList(const wxString & name, void CommandManager::AddItemList(const wxString & name,
const wxArrayString & labels, const TranslatedInternalString items[],
size_t nItems,
CommandHandlerFinder finder, CommandHandlerFinder finder,
CommandFunctorPointer callback, CommandFunctorPointer callback,
bool bIsEffect) bool bIsEffect)
{ {
for (size_t i = 0, cnt = labels.GetCount(); i < cnt; i++) { for (size_t i = 0, cnt = nItems; i < cnt; i++) {
CommandListEntry *entry = NewIdentifier(name, CommandListEntry *entry = NewIdentifier(name,
labels[i], items[i].Translated(),
CurrentMenu(), CurrentMenu(),
finder, finder,
callback, callback,
true, items[i].Internal(),
i, i,
cnt, cnt,
bIsEffect); bIsEffect);
@ -896,7 +897,7 @@ void CommandManager::AddCommand(const wxChar *name,
CommandFlag flags, CommandFlag flags,
CommandMask mask) CommandMask mask)
{ {
NewIdentifier(name, label_in, accel, NULL, finder, callback, false, 0, 0, false, {}); NewIdentifier(name, label_in, accel, NULL, finder, callback, {}, 0, 0, false, {});
if (flags != NoFlagsSpecifed || mask != NoFlagsSpecifed) { if (flags != NoFlagsSpecifed || mask != NoFlagsSpecifed) {
SetCommandFlags(name, flags, mask); SetCommandFlags(name, flags, mask);
@ -911,7 +912,7 @@ void CommandManager::AddGlobalCommand(const wxChar *name,
{ {
CommandListEntry *entry = CommandListEntry *entry =
NewIdentifier(name, label_in, accel, NULL, finder, callback, NewIdentifier(name, label_in, accel, NULL, finder, callback,
false, 0, 0, false, {}); {}, 0, 0, false, {});
entry->enabled = false; entry->enabled = false;
entry->isGlobal = true; entry->isGlobal = true;
@ -947,7 +948,7 @@ CommandListEntry *CommandManager::NewIdentifier(const wxString & name,
wxMenu *menu, wxMenu *menu,
CommandHandlerFinder finder, CommandHandlerFinder finder,
CommandFunctorPointer callback, CommandFunctorPointer callback,
bool multi, const wxString &nameSuffix,
int index, int index,
int count, int count,
bool bIsEffect) bool bIsEffect)
@ -958,7 +959,7 @@ CommandListEntry *CommandManager::NewIdentifier(const wxString & name,
menu, menu,
finder, finder,
callback, callback,
multi, nameSuffix,
index, index,
count, count,
bIsEffect, bIsEffect,
@ -971,12 +972,13 @@ CommandListEntry *CommandManager::NewIdentifier(const wxString & nameIn,
wxMenu *menu, wxMenu *menu,
CommandHandlerFinder finder, CommandHandlerFinder finder,
CommandFunctorPointer callback, CommandFunctorPointer callback,
bool multi, const wxString &nameSuffix,
int index, int index,
int count, int count,
bool bIsEffect, bool bIsEffect,
const CommandParameter &parameter) const CommandParameter &parameter)
{ {
const bool multi = !nameSuffix.empty();
wxString name = nameIn; wxString name = nameIn;
// If we have the identifier already, reuse it. // If we have the identifier already, reuse it.
@ -1001,7 +1003,7 @@ CommandListEntry *CommandManager::NewIdentifier(const wxString & nameIn,
// This feature is not used for built-in effects. // This feature is not used for built-in effects.
if (multi) { if (multi) {
// The name needs to be clean for use by automation. // The name needs to be clean for use by automation.
wxString cleanedName = wxString::Format(wxT("%s_%s"), name, label); wxString cleanedName = wxString::Format(wxT("%s_%s"), name, nameSuffix);
cleanedName.Replace( "/", "" ); cleanedName.Replace( "/", "" );
cleanedName.Replace( "&", "" ); cleanedName.Replace( "&", "" );
cleanedName.Replace( " ", "" ); cleanedName.Replace( " ", "" );
@ -1353,7 +1355,7 @@ void CommandManager::TellUserWhyDisallowed( const wxString & Name, CommandFlag f
} }
wxString CommandManager::DescribeCommandsAndShortcuts wxString CommandManager::DescribeCommandsAndShortcuts
(const LocalizedCommandNameVector &commands) const (const TranslatedInternalString commands[], size_t nCommands) const
{ {
wxString mark; wxString mark;
// This depends on the language setting and may change in-session after // This depends on the language setting and may change in-session after
@ -1364,15 +1366,16 @@ wxString CommandManager::DescribeCommandsAndShortcuts
static const wxString &separatorFormat = wxT("%s / %s"); static const wxString &separatorFormat = wxT("%s / %s");
wxString result; wxString result;
for (const auto &pair : commands) { for (size_t ii = 0; ii < nCommands; ++ii) {
const auto &pair = commands[ii];
// If RTL, then the control character forces right-to-left sequencing of // If RTL, then the control character forces right-to-left sequencing of
// "/" -separated command names, and puts any "(...)" shortcuts to the // "/" -separated command names, and puts any "(...)" shortcuts to the
// left, consistently with accelerators in menus (assuming matching // left, consistently with accelerators in menus (assuming matching
// operating system prefernces for language), even if the command name // operating system prefernces for language), even if the command name
// was missing from the translation file and defaulted to the English. // was missing from the translation file and defaulted to the English.
auto piece = wxString::Format(wxT("%s%s"), mark, pair.first); auto piece = wxString::Format(wxT("%s%s"), mark, pair.Translated());
wxString name{ pair.second }; wxString name{ pair.Internal() };
if (!name.empty()) { if (!name.empty()) {
auto keyStr = GetKeyFromName(name); auto keyStr = GetKeyFromName(name);
if (!keyStr.empty()){ if (!keyStr.empty()){

View File

@ -33,6 +33,7 @@
#endif #endif
using CommandParameter = wxString; using CommandParameter = wxString;
class TranslatedInternalString;
struct MenuBarListEntry struct MenuBarListEntry
{ {
@ -161,7 +162,8 @@ class AUDACITY_DLL_API CommandManager final : public XMLTagHandler
int checkmark = -1); int checkmark = -1);
void AddItemList(const wxString & name, void AddItemList(const wxString & name,
const wxArrayString & labels, const TranslatedInternalString items[],
size_t nItems,
CommandHandlerFinder finder, CommandHandlerFinder finder,
CommandFunctorPointer callback, CommandFunctorPointer callback,
bool bIsEffect = false); bool bIsEffect = false);
@ -313,14 +315,11 @@ class AUDACITY_DLL_API CommandManager final : public XMLTagHandler
/// ///
/// Formatting summaries that include shortcut keys /// Formatting summaries that include shortcut keys
/// ///
using LocalizedCommandName = std::pair<wxString, const wxChar*>;
using LocalizedCommandNameVector = std::vector<LocalizedCommandName>;
wxString DescribeCommandsAndShortcuts wxString DescribeCommandsAndShortcuts
(// An array of paired user-visible strings, and (
// non-user-visible command names. If a shortcut key is defined // If a shortcut key is defined for the command, then it is appended,
// for the command, then it is appended, parenthesized, after the // parenthesized, after the translated name.
// user-visible string. const TranslatedInternalString commands[], size_t nCommands) const;
const LocalizedCommandNameVector &commands) const;
// Sorted list of the shortcut keys to be exluded from the standard defaults // Sorted list of the shortcut keys to be exluded from the standard defaults
static const std::vector<NormalizedKeyString> &ExcludedList(); static const std::vector<NormalizedKeyString> &ExcludedList();
@ -337,7 +336,7 @@ protected:
wxMenu *menu, wxMenu *menu,
CommandHandlerFinder finder, CommandHandlerFinder finder,
CommandFunctorPointer callback, CommandFunctorPointer callback,
bool multi, const wxString &nameSuffix,
int index, int index,
int count, int count,
bool bIsEffect); bool bIsEffect);
@ -347,7 +346,7 @@ protected:
wxMenu *menu, wxMenu *menu,
CommandHandlerFinder finder, CommandHandlerFinder finder,
CommandFunctorPointer callback, CommandFunctorPointer callback,
bool multi, const wxString &nameSuffix,
int index, int index,
int count, int count,
bool bIsEffect, bool bIsEffect,

View File

@ -249,27 +249,27 @@ void ControlToolBar::RegenerateTooltips()
name = wxT("CursProjectStart"); name = wxT("CursProjectStart");
break; break;
} }
LocalizedCommandNameVector commands( 1u, { pCtrl->GetLabel(), name } ); std::vector<TranslatedInternalString> commands(
1u, { name, pCtrl->GetLabel() } );
// Some have a second // Some have a second
switch (iWinID) switch (iWinID)
{ {
case ID_PLAY_BUTTON: case ID_PLAY_BUTTON:
// With shift // With shift
commands.push_back( commands.push_back( { wxT("PlayLooped"), _("Loop Play") } );
LocalizedCommandName( _("Loop Play"), wxT("PlayLooped") ) );
break; break;
case ID_RECORD_BUTTON: case ID_RECORD_BUTTON:
// With shift // With shift
{ bool bPreferNewTrack; { bool bPreferNewTrack;
gPrefs->Read("/GUI/PreferNewTrackRecord",&bPreferNewTrack, false); gPrefs->Read("/GUI/PreferNewTrackRecord",&bPreferNewTrack, false);
// For the shortcut tooltip. // For the shortcut tooltip.
commands.push_back( LocalizedCommandName( commands.push_back( {
wxT("Record2ndChoice"),
!bPreferNewTrack !bPreferNewTrack
? _("Record New Track") ? _("Record New Track")
: _("Append Record"), : _("Append Record")
wxT("Record2ndChoice") } );
));
} }
break; break;
case ID_PAUSE_BUTTON: case ID_PAUSE_BUTTON:
@ -278,16 +278,16 @@ void ControlToolBar::RegenerateTooltips()
break; break;
case ID_FF_BUTTON: case ID_FF_BUTTON:
// With shift // With shift
commands.push_back( LocalizedCommandName( commands.push_back( {
_("Select to End"), wxT("SelEnd") ) ); wxT("SelEnd"), _("Select to End") } );
break; break;
case ID_REW_BUTTON: case ID_REW_BUTTON:
// With shift // With shift
commands.push_back( LocalizedCommandName( commands.push_back( {
_("Select to Start"), wxT("SelStart") ) ); wxT("SelStart"), _("Select to Start") } );
break; break;
} }
ToolBar::SetButtonToolTip(*pCtrl, commands); ToolBar::SetButtonToolTip(*pCtrl, commands.data(), commands.size());
} }
#endif #endif
} }

View File

@ -277,10 +277,9 @@ void EditToolBar::ForAllButtons(int Action)
for (const auto &entry : EditToolbarButtonList) { for (const auto &entry : EditToolbarButtonList) {
#if wxUSE_TOOLTIPS #if wxUSE_TOOLTIPS
if( Action & ETBActTooltips ){ if( Action & ETBActTooltips ){
LocalizedCommandNameVector commands( 1u, TranslatedInternalString command{
{ wxGetTranslation(entry.untranslatedLabel), entry.commandName } entry.commandName, wxGetTranslation(entry.untranslatedLabel) };
); ToolBar::SetButtonToolTip( *mButtons[entry.tool], &command, 1u );
ToolBar::SetButtonToolTip(*mButtons[entry.tool], commands);
} }
#endif #endif
if (cm) { if (cm) {

View File

@ -136,10 +136,10 @@ void ScrubbingToolBar::RegenerateTooltips()
{ {
#if wxUSE_TOOLTIPS #if wxUSE_TOOLTIPS
auto fn = [&] auto fn = [&]
(AButton &button, const wxString &label, const wxString &command) (AButton &button, const wxString &label, const wxString &cmd)
{ {
LocalizedCommandNameVector commands( 1u, { label, command } ); TranslatedInternalString command{ cmd, label };
ToolBar::SetButtonToolTip(button, commands); ToolBar::SetButtonToolTip( button, &command, 1u );
}; };
auto project = GetActiveProject(); auto project = GetActiveProject();

View File

@ -825,7 +825,7 @@ void ToolBar::MakeAlternateImages(AButton &button, int idx,
} }
void ToolBar::SetButtonToolTip void ToolBar::SetButtonToolTip
(AButton &button, const LocalizedCommandNameVector &commands) (AButton &button, const TranslatedInternalString commands[], size_t nCommands)
{ {
wxString result; wxString result;
const auto project = GetActiveProject(); const auto project = GetActiveProject();
@ -833,7 +833,7 @@ void ToolBar::SetButtonToolTip
project ? project->GetCommandManager() : nullptr; project ? project->GetCommandManager() : nullptr;
if (commandManager) if (commandManager)
result = result =
commandManager->DescribeCommandsAndShortcuts(commands); commandManager->DescribeCommandsAndShortcuts(commands, nCommands);
button.SetToolTip(result); button.SetToolTip(result);
} }

View File

@ -156,16 +156,12 @@ class ToolBar /* not final */ : public wxPanelWrapper
teBmps eDisabled, teBmps eDisabled,
wxSize size); wxSize size);
using LocalizedCommandName = std::pair<wxString, const wxChar*>;
using LocalizedCommandNameVector = std::vector<LocalizedCommandName>;
static static
void SetButtonToolTip void SetButtonToolTip
(AButton &button, (AButton &button,
// An array of paired user-visible strings, and // If a shortcut key is defined for the command, then it is appended,
// non-user-visible command names. If a shortcut key is defined // parenthesized, after the translated name.
// for the command, then it is appended, parenthesized, after the const TranslatedInternalString commands[], size_t nCommands);
// user-visible string.
const LocalizedCommandNameVector &commands);
protected: protected:
void SetButton(bool down, AButton *button); void SetButton(bool down, AButton *button);

View File

@ -138,9 +138,9 @@ void ToolsToolBar::RegenerateTooltips()
}; };
for (const auto &entry : table) { for (const auto &entry : table) {
LocalizedCommandNameVector commands( 1u, TranslatedInternalString command{
{ wxGetTranslation(entry.untranslatedLabel), entry.commandName } ); entry.commandName, wxGetTranslation(entry.untranslatedLabel) };
ToolBar::SetButtonToolTip(*mTool[entry.tool], commands); ToolBar::SetButtonToolTip( *mTool[entry.tool], &command, 1u );
} }
#endif #endif

View File

@ -312,16 +312,12 @@ void TranscriptionToolBar::RegenerateTooltips()
}, },
}; };
LocalizedCommandNameVector commands;
for (const auto &entry : table) { for (const auto &entry : table) {
commands.clear(); TranslatedInternalString commands[] = {
commands.push_back( LocalizedCommandName( { entry.commandName, wxGetTranslation(entry.untranslatedLabel) },
wxGetTranslation(entry.untranslatedLabel), entry.commandName { entry.commandName2, wxGetTranslation(entry.untranslatedLabel2) },
) ); };
commands.push_back( LocalizedCommandName( ToolBar::SetButtonToolTip( *mButtons[entry.tool], commands, 2u );
wxGetTranslation(entry.untranslatedLabel2), entry.commandName2
) );
ToolBar::SetButtonToolTip(*mButtons[entry.tool], commands);
} }

View File

@ -48,9 +48,8 @@ wxString MuteButtonHandle::Tip(const wxMouseState &) const
return name; return name;
auto commandManager = project->GetCommandManager(); auto commandManager = project->GetCommandManager();
CommandManager::LocalizedCommandNameVector commands( 1u, TranslatedInternalString command{ wxT("TrackMute"), name };
{ name, wxT("TrackMute") } ); return commandManager->DescribeCommandsAndShortcuts(&command, 1u);
return commandManager->DescribeCommandsAndShortcuts(commands);
} }
UIHandlePtr MuteButtonHandle::HitTest UIHandlePtr MuteButtonHandle::HitTest
@ -105,9 +104,8 @@ wxString SoloButtonHandle::Tip(const wxMouseState &) const
return name; return name;
auto commandManager = project->GetCommandManager(); auto commandManager = project->GetCommandManager();
CommandManager::LocalizedCommandNameVector commands( 1u, TranslatedInternalString command{ wxT("TrackSolo"), name };
{ name, wxT("TrackSolo") } ); return commandManager->DescribeCommandsAndShortcuts( &command, 1u );
return commandManager->DescribeCommandsAndShortcuts(commands);
} }
UIHandlePtr SoloButtonHandle::HitTest UIHandlePtr SoloButtonHandle::HitTest

View File

@ -115,9 +115,8 @@ wxString CloseButtonHandle::Tip(const wxMouseState &) const
return name; return name;
auto commandManager = project->GetCommandManager(); auto commandManager = project->GetCommandManager();
CommandManager::LocalizedCommandNameVector commands( 1u, TranslatedInternalString command{ wxT("TrackClose"), name };
{ name, wxT("TrackClose") } ); return commandManager->DescribeCommandsAndShortcuts( &command, 1u );
return commandManager->DescribeCommandsAndShortcuts(commands);
} }
UIHandlePtr CloseButtonHandle::HitTest UIHandlePtr CloseButtonHandle::HitTest
@ -175,9 +174,8 @@ wxString MenuButtonHandle::Tip(const wxMouseState &) const
return name; return name;
auto commandManager = project->GetCommandManager(); auto commandManager = project->GetCommandManager();
CommandManager::LocalizedCommandNameVector commands( 1u, TranslatedInternalString command{ wxT("TrackMenu"), name };
{ name, wxT("TrackMenu") } ); return commandManager->DescribeCommandsAndShortcuts( &command, 1u );
return commandManager->DescribeCommandsAndShortcuts(commands);
} }
UIHandlePtr MenuButtonHandle::HitTest UIHandlePtr MenuButtonHandle::HitTest

View File

@ -2897,9 +2897,8 @@ void AdornedRulerPanel::UpdateButtonStates()
{ {
auto common = [this] auto common = [this]
(AButton &button, const wxString &commandName, const wxString &label) { (AButton &button, const wxString &commandName, const wxString &label) {
CommandManager::LocalizedCommandNameVector commands( 1u, TranslatedInternalString command{ commandName, label };
{ label, commandName } ); ToolBar::SetButtonToolTip( button, &command, 1u );
ToolBar::SetButtonToolTip(button, commands);
button.SetLabel(button.GetToolTipText()); button.SetLabel(button.GetToolTipText());
button.UpdateStatus(); button.UpdateStatus();