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:
commit
cfd9bd3331
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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>;
|
||||||
|
@ -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!
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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 ¶meter)
|
const CommandParameter ¶meter)
|
||||||
{
|
{
|
||||||
|
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()){
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user