1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-24 16:20:05 +02:00

Auto-Select off by default.

I've implemented three states for what to do if no selection:
0 - Grey out (no longer used)
1 - Auto-select
2 - Give the warning message and try again.
This commit is contained in:
James Crook 2017-06-09 19:11:05 +01:00
parent 0d899b0163
commit adc7312954
10 changed files with 188 additions and 166 deletions

View File

@ -2184,7 +2184,7 @@ void AudacityProject::UpdateMenus(bool checkActive)
//ANSWER: Because flags2 is used in the menu enable/disable. //ANSWER: Because flags2 is used in the menu enable/disable.
//The effect still needs flags to determine whether it will need //The effect still needs flags to determine whether it will need
//to actually do the 'select all' to make the command valid. //to actually do the 'select all' to make the command valid.
if (mSelectAllOnNone) if (mWhatIfNoSelection != 0)
{ {
if ((flags & TracksExistFlag)) if ((flags & TracksExistFlag))
{ {
@ -2215,7 +2215,8 @@ void AudacityProject::UpdateMenus(bool checkActive)
// With select-all-on-none, some items that we don't want enabled may have // With select-all-on-none, some items that we don't want enabled may have
// been enabled, since we changed the flags. Here we manually disable them. // been enabled, since we changed the flags. Here we manually disable them.
if (mSelectAllOnNone) // 0 is grey out, 1 is Autoselect, 2 is Give warnings.
if (mWhatIfNoSelection != 0)
{ {
if (!(flags & TimeSelectedFlag) | !(flags & TracksSelectedFlag)) if (!(flags & TimeSelectedFlag) | !(flags & TracksSelectedFlag))
{ {

View File

@ -39,17 +39,16 @@ void ModifyAllProjectToolbarMenus();
CommandFlag GetFocusedFrame(); CommandFlag GetFocusedFrame();
public:
// If checkActive, do not do complete flags testing on an // If checkActive, do not do complete flags testing on an
// inactive project as it is needlessly expensive. // inactive project as it is needlessly expensive.
CommandFlag GetUpdateFlags(bool checkActive = false); CommandFlag GetUpdateFlags(bool checkActive = false);
double NearestZeroCrossing(double t0);
public:
//Adds label and returns index of label in labeltrack. //Adds label and returns index of label in labeltrack.
int DoAddLabel(const SelectedRegion& region, bool preserveFocus = false); int DoAddLabel(const SelectedRegion& region, bool preserveFocus = false);
private: private:
double NearestZeroCrossing(double t0);
// Selecting a tool from the keyboard // Selecting a tool from the keyboard

View File

@ -1284,7 +1284,16 @@ void AudacityProject::UpdatePrefsVariables()
#else #else
gPrefs->Read(wxT("/GUI/Help"), &mHelpPref, wxT("Local") ); gPrefs->Read(wxT("/GUI/Help"), &mHelpPref, wxT("Local") );
#endif #endif
gPrefs->Read(wxT("/GUI/SelectAllOnNone"), &mSelectAllOnNone, true); bool bSelectAllIfNone;
gPrefs->Read(wxT("/GUI/SelectAllOnNone"), &bSelectAllIfNone, false);
// 0 is grey out, 1 is Autoselect, 2 is Give warnings.
#ifdef EXPERIMENTAL_DA
// DA warns or greys out.
mWhatIfNoSelection = bSelectAllIfNone ? 2 : 0;
#else
// Audacity autoselects or warns.
mWhatIfNoSelection = bSelectAllIfNone ? 1 : 2;
#endif
mStopIfWasPaused = true; // not configurable for now, but could be later. mStopIfWasPaused = true; // not configurable for now, but could be later.
gPrefs->Read(wxT("/GUI/ShowSplashScreen"), &mShowSplashScreen, true); gPrefs->Read(wxT("/GUI/ShowSplashScreen"), &mShowSplashScreen, true);
gPrefs->Read(wxT("/GUI/Solo"), &mSoloPref, wxT("Simple")); gPrefs->Read(wxT("/GUI/Solo"), &mSoloPref, wxT("Simple"));
@ -2272,6 +2281,19 @@ void AudacityProject::DoScroll()
} }
} }
bool AudacityProject::ReportIfActionNotAllowed
( const wxString & Name, CommandFlag & flags, CommandFlag flagsRqd, CommandFlag mask )
{
bool bAllowed = TryToMakeActionAllowed( flags, flagsRqd, mask );
if( bAllowed )
return true;
CommandManager* cm = GetCommandManager();
if (!cm) return false;
cm->TellUserWhyDisallowed( Name, flags & mask, flagsRqd & mask);
return false;
}
/// Determines if flags for command are compatible with current state. /// Determines if flags for command are compatible with current state.
/// If not, then try some recovery action to make it so. /// If not, then try some recovery action to make it so.
/// @return whether compatible or not after any actions taken. /// @return whether compatible or not after any actions taken.
@ -2300,12 +2322,14 @@ bool AudacityProject::TryToMakeActionAllowed
return true; return true;
} }
//We can only make the action allowed if we select audio when no selection.
// IF not set up to select all audio when none, THEN return with failure.
if( mWhatIfNoSelection != 1 )
return false;
// Why is action still not allowed? // Why is action still not allowed?
// 0's wherever a required flag is missing (or is don't care) // 0's wherever a required flag is missing (or is don't care)
MissingFlags = (flags & ~flagsRqd) & mask; MissingFlags = (flags & ~flagsRqd) & mask;
// IF not set up to select all audio in that case, THEN return with failure.
if( !mSelectAllOnNone )
return false;
// IF selecting all audio won't do any good, THEN return with failure. // IF selecting all audio won't do any good, THEN return with failure.
if( !(flags & WaveTracksExistFlag) ) if( !(flags & WaveTracksExistFlag) )

View File

@ -541,6 +541,8 @@ public:
void OnAudioIONewBlockFiles(const AutoSaveFile & blockFileLog) override; void OnAudioIONewBlockFiles(const AutoSaveFile & blockFileLog) override;
// Command Handling // Command Handling
bool ReportIfActionNotAllowed
( const wxString & Name, CommandFlag & flags, CommandFlag flagsRqd, CommandFlag mask );
bool TryToMakeActionAllowed bool TryToMakeActionAllowed
( CommandFlag & flags, CommandFlag flagsRqd, CommandFlag mask ); ( CommandFlag & flags, CommandFlag flagsRqd, CommandFlag mask );
@ -688,7 +690,8 @@ private:
bool mShowId3Dialog{ true }; //lda bool mShowId3Dialog{ true }; //lda
bool mEmptyCanBeDirty; bool mEmptyCanBeDirty;
bool mSelectAllOnNone; // 0 is grey out, 1 is Autoselect, 2 is Give warnings.
int mWhatIfNoSelection;
bool mStopIfWasPaused; bool mStopIfWasPaused;
bool mIsSyncLocked; bool mIsSyncLocked;

View File

@ -93,6 +93,8 @@ CommandManager. It holds the callback for one command.
#include "Keyboard.h" #include "Keyboard.h"
#include "../PluginManager.h" #include "../PluginManager.h"
#include "../effects/EffectManager.h" #include "../effects/EffectManager.h"
#include "../widgets/LinkingHtmlWindow.h"
#include "../widgets/ErrorDialog.h"
// On wxGTK, there may be many many many plugins, but the menus don't automatically // On wxGTK, there may be many many many plugins, but the menus don't automatically
// allow for scrolling, so we build sub-menus. If the menu gets longer than // allow for scrolling, so we build sub-menus. If the menu gets longer than
@ -1139,19 +1141,39 @@ void CommandManager::SetKeyFromIndex(int i, const wxString &key)
entry->key = KeyStringNormalize(key); entry->key = KeyStringNormalize(key);
} }
void CommandManager::TellUserWhyDisallowed( CommandFlag flagsGot, CommandMask flagsRequired ) void CommandManager::TellUserWhyDisallowed( const wxString & Name, CommandFlag flagsGot, CommandMask flagsRequired )
{ {
// The default string for 'reason' is a catch all. I hope it won't ever be seen // The default string for 'reason' is a catch all. I hope it won't ever be seen
// and that we will get something more specific. // and that we will get something more specific.
wxString reason = _("There was a problem with your last action. If you think\nthis is a bug, please tell us exactly where it occurred."); wxString reason = _("There was a problem with your last action. If you think\nthis is a bug, please tell us exactly where it occurred.");
// The default title string is 'Disallowed'.
wxString title = _("Disallowed");
wxString help_url ="";
auto missingFlags = flagsRequired & (~flagsGot ); auto missingFlags = flagsRequired & (~flagsGot );
if( missingFlags & AudioIONotBusyFlag ) if( missingFlags & AudioIONotBusyFlag )
reason = _("You can only do this when playing and recording are\nstopped. (Pausing is not sufficient.)"); reason = _("You can only do this when playing and recording are\nstopped. (Pausing is not sufficient.)");
else if( missingFlags & StereoRequiredFlag ) else if( missingFlags & StereoRequiredFlag )
reason = _("You must first select some stereo audio to perform this\naction. (You cannot use this with mono.)"); reason = _("You must first select some stereo audio to perform this\naction. (You cannot use this with mono.)");
else if( missingFlags & TimeSelectedFlag ) // In reporting the issue with cut or copy, we don't tell the user they could also select some text in a label.
reason = _("You must first select some audio to perform this action."); else if(( missingFlags & TimeSelectedFlag ) || (missingFlags &CutCopyAvailableFlag )){
title = _("No Audio Selected");
#ifdef EXPERIMENTAL_DA
// i18n-hint: %s will be replaced by the name of an action, such as Normalize, Cut, Fade.
reason = wxString::Format( _("You must first select some audio for '%s' to act on.\n\nCtrl + A selects all audio."), Name );
#else
#ifdef __WXMAC__
// i18n-hint: %s will be replaced by the name of an action, such as Normalize, Cut, Fade.
reason = wxString::Format( _("Select the audio for %s to use (for example, Cmd + A to Select All) then try again.\n\n"
"Click the Help button to learn more about selection methods."), Name );
#else
// i18n-hint: %s will be replaced by the name of an action, such as Normalize, Cut, Fade.
reason = wxString::Format( _("Select the audio for %s to use (for example, Ctrl + A to Select All) then try again.\n\n"
"Click the Help button to learn more about selection methods."), Name );
#endif
#endif
help_url = "http://alphamanual.audacityteam.org/man/Selecting_Audio_-_the_basics";
}
else if( missingFlags & WaveTracksSelectedFlag) else if( missingFlags & WaveTracksSelectedFlag)
reason = _("You must first select some audio to perform this action.\n(Selecting other kinds of track won't work.)"); reason = _("You must first select some audio to perform this action.\n(Selecting other kinds of track won't work.)");
// If the only thing wrong was no tracks, we do nothing and don't report a problem // If the only thing wrong was no tracks, we do nothing and don't report a problem
@ -1164,7 +1186,30 @@ void CommandManager::TellUserWhyDisallowed( CommandFlag flagsGot, CommandMask fl
else if( missingFlags == TrackPanelHasFocus ) else if( missingFlags == TrackPanelHasFocus )
return; return;
wxMessageBox(reason, _("Disallowed"), wxICON_WARNING | wxOK );
#if 0
// Does not have the warning icon...
ShowErrorDialog(
NULL,
title,
reason,
help_url,
false);
#endif
// JKC: I tried building a custom error dialog with the warning icon, and a
// help button linking to our html (without closing).
// In the end I decided it was easier (more portable across different
// OS's) to use the stock one.
int result = ::wxMessageBox(reason, title, wxICON_WARNING | wxOK |
(help_url.IsEmpty() ? 0 : wxHELP) );
// if they click help, we fetch that help, and pop the dialog (without a
// help button) up again.
if( result == wxHELP ){
wxHtmlLinkInfo link( help_url );
OpenInDefaultBrowser(link);
::wxMessageBox(reason, title, wxICON_WARNING | wxOK );
}
} }
/// ///
@ -1285,14 +1330,14 @@ bool CommandManager::HandleCommandEntry(const CommandListEntry * entry,
if( !proj ) if( !proj )
return false; return false;
wxString NiceName = entry->label;
NiceName.Replace("&", "");// remove &
NiceName.Replace(".","");// remove ...
// NB: The call may have the side effect of changing flags. // NB: The call may have the side effect of changing flags.
bool allowed = proj->TryToMakeActionAllowed( flags, entry->flags, combinedMask ); bool allowed = proj->ReportIfActionNotAllowed(
NiceName, flags, entry->flags, combinedMask );
if (!allowed) if (!allowed)
{
TellUserWhyDisallowed(
flags & combinedMask, entry->flags & combinedMask);
return false; return false;
}
} }
(*(entry->callback))(entry->index, evt); (*(entry->callback))(entry->index, evt);
@ -1314,7 +1359,7 @@ bool CommandManager::HandleMenuID(int id, CommandFlag flags, CommandMask mask)
/// HandleTextualCommand() allows us a limitted version of script/batch /// HandleTextualCommand() allows us a limitted version of script/batch
/// behavior, since we can get from a string command name to the actual /// behavior, since we can get from a string command name to the actual
/// code to run. /// code to run.
bool CommandManager::HandleTextualCommand(wxString & Str, CommandFlag flags, CommandMask mask) bool CommandManager::HandleTextualCommand(const wxString & Str, CommandFlag flags, CommandMask mask)
{ {
if( Str.IsEmpty() ) if( Str.IsEmpty() )
return false; return false;

View File

@ -225,7 +225,7 @@ class AUDACITY_DLL_API CommandManager final : public XMLTagHandler
// Lyrics and MixerTrackCluster classes use it. // Lyrics and MixerTrackCluster classes use it.
bool FilterKeyEvent(AudacityProject *project, const wxKeyEvent & evt, bool permit = false); bool FilterKeyEvent(AudacityProject *project, const wxKeyEvent & evt, bool permit = false);
bool HandleMenuID(int id, CommandFlag flags, CommandMask mask); bool HandleMenuID(int id, CommandFlag flags, CommandMask mask);
bool HandleTextualCommand(wxString & Str, CommandFlag flags, CommandMask mask); bool HandleTextualCommand(const wxString & Str, CommandFlag flags, CommandMask mask);
// //
// Accessing // Accessing
@ -259,6 +259,7 @@ class AUDACITY_DLL_API CommandManager final : public XMLTagHandler
// //
void WriteXML(XMLWriter &xmlFile) const /* not override */; void WriteXML(XMLWriter &xmlFile) const /* not override */;
void TellUserWhyDisallowed(const wxString & Name, CommandFlag flagsGot, CommandFlag flagsRequired);
protected: protected:
@ -288,7 +289,6 @@ protected:
// //
bool HandleCommandEntry(const CommandListEntry * entry, CommandFlag flags, CommandMask mask, const wxEvent * evt = NULL); bool HandleCommandEntry(const CommandListEntry * entry, CommandFlag flags, CommandMask mask, const wxEvent * evt = NULL);
void TellUserWhyDisallowed(CommandFlag flagsGot, CommandFlag flagsRequired);
// //
// Modifying // Modifying

View File

@ -3171,14 +3171,13 @@ void EffectUIHost::OnApply(wxCommandEvent & evt)
if (!mIsBatch && mEffect->GetType() != EffectTypeGenerate && mProject->mViewInfo.selectedRegion.isPoint()) if (!mIsBatch && mEffect->GetType() != EffectTypeGenerate && mProject->mViewInfo.selectedRegion.isPoint())
{ {
auto flags = AlwaysEnabledFlag; auto flags = AlwaysEnabledFlag;
bool allowed = mProject->TryToMakeActionAllowed(flags, bool allowed = mProject->ReportIfActionNotAllowed(
WaveTracksSelectedFlag | TimeSelectedFlag, mEffect->GetName(),
WaveTracksSelectedFlag | TimeSelectedFlag); flags,
WaveTracksSelectedFlag | TimeSelectedFlag,
WaveTracksSelectedFlag | TimeSelectedFlag);
if (!allowed) if (!allowed)
{
wxMessageBox(_("You must select audio in the project window."));
return; return;
}
} }
if (!mClient->ValidateUI()) if (!mClient->ValidateUI())

View File

@ -62,7 +62,7 @@ void TracksBehaviorsPrefs::PopulateOrExchange(ShuttleGui & S)
{ {
S.TieCheckBox(_("A&uto-select audio for editing"), S.TieCheckBox(_("A&uto-select audio for editing"),
wxT("/GUI/SelectAllOnNone"), wxT("/GUI/SelectAllOnNone"),
true); false);
/* i18n-hint: Cut-lines are lines that can expand to show the cut audio.*/ /* i18n-hint: Cut-lines are lines that can expand to show the cut audio.*/
S.TieCheckBox(_("Enable cut &lines"), S.TieCheckBox(_("Enable cut &lines"),
wxT("/GUI/EnableCutLines"), wxT("/GUI/EnableCutLines"),

View File

@ -198,150 +198,94 @@ void EditToolBar::UpdatePrefs()
void EditToolBar::RegenerateTooltips() void EditToolBar::RegenerateTooltips()
{ {
#if wxUSE_TOOLTIPS ForAllButtons( ETBActTooltips );
static const struct Entry {
int tool;
wxString commandName;
wxString untranslatedLabel;
} table[] = {
{ ETBCutID, wxT("Cut"), XO("Cut") },
{ ETBCopyID, wxT("Copy"), XO("Copy") },
{ ETBPasteID, wxT("Paste"), XO("Paste") },
{ ETBTrimID, wxT("Trim"), XO("Trim Audio") },
{ ETBSilenceID, wxT("Silence"), XO("Silence Audio") },
{ ETBUndoID, wxT("Undo"), XO("Undo") },
{ ETBRedoID, wxT("Redo"), XO("Redo") },
#ifdef OPTION_SYNC_LOCK_BUTTON
{ ETBSyncLockID, wxT("SyncLock"), XO("Sync-Lock Tracks") },
#endif
{ ETBZoomInID, wxT("ZoomIn"), XO("Zoom In") },
{ ETBZoomOutID, wxT("ZoomOut"), XO("Zoom Out") },
{ ETBZoomSelID, wxT("ZoomSel"), XO("Fit Selection") },
{ ETBZoomFitID, wxT("FitInWindow"), XO("Fit Project") },
#if defined(EXPERIMENTAL_EFFECTS_RACK)
{ ETBEffectsID, wxT(""), XO("Open Effects Rack") },
#endif
};
std::vector<wxString> commands;
for (const auto &entry : table) {
commands.clear();
commands.push_back(wxGetTranslation(entry.untranslatedLabel));
commands.push_back(entry.commandName);
ToolBar::SetButtonToolTip(*mButtons[entry.tool], commands);
}
#endif
}
void EditToolBar::OnButton(wxCommandEvent &event)
{
AudacityProject *p = GetActiveProject();
if (!p) return;
int id = event.GetId();
// FIXME: Some "SelectAllIfNone()" do not work as expected
// due to bugs elsewhere (see: AudacityProject::UpdateMenus() )
// Be sure the pop-up happens even if there are exceptions
// except for buttons which toggle.
auto cleanup = finally( [&] { mButtons[id]->InteractionOver();}
);
switch (id) {
case ETBCutID:
p->SelectAllIfNone();
p->OnCut();
break;
case ETBCopyID:
p->SelectAllIfNone();
p->OnCopy();
break;
case ETBPasteID:
p->OnPaste();
break;
case ETBTrimID:
p->SelectAllIfNone();
p->OnTrim();
break;
case ETBSilenceID:
p->SelectAllIfNone();
p->OnSilence();
break;
case ETBUndoID:
p->OnUndo();
break;
case ETBRedoID:
p->OnRedo();
break;
#ifdef OPTION_SYNC_LOCK_BUTTON
case ETBSyncLockID:
p->OnSyncLock();
break;
#endif
case ETBZoomInID:
p->OnZoomIn();
break;
case ETBZoomOutID:
p->OnZoomOut();
break;
#if 0 // Disabled for version 1.2.0 because we have many other zoomers.
case ETBZoomToggleID:
p->OnZoomToggle();
break;
#endif
case ETBZoomSelID:
p->OnZoomSel();
break;
case ETBZoomFitID:
p->OnZoomFit();
break;
#if defined(EXPERIMENTAL_EFFECTS_RACK)
case ETBEffectsID:
EffectManager::Get().ShowRack();
break;
#endif
}
} }
void EditToolBar::EnableDisableButtons() void EditToolBar::EnableDisableButtons()
{ {
ForAllButtons( ETBActEnableDisable );
}
static const struct Entry {
int tool;
wxString commandName;
wxString untranslatedLabel;
} EditToolbarButtonList[] = {
{ ETBCutID, wxT("Cut"), XO("Cut") },
{ ETBCopyID, wxT("Copy"), XO("Copy") },
{ ETBPasteID, wxT("Paste"), XO("Paste") },
{ ETBTrimID, wxT("Trim"), XO("Trim audio outside selection") },
{ ETBSilenceID, wxT("Silence"), XO("Silence audio selection") },
{ ETBUndoID, wxT("Undo"), XO("Undo") },
{ ETBRedoID, wxT("Redo"), XO("Redo") },
#ifdef OPTION_SYNC_LOCK_BUTTON
{ ETBSyncLockID, wxT("SyncLock"), XO("Sync-Lock Tracks") },
#endif
{ ETBZoomInID, wxT("ZoomIn"), XO("Zoom In") },
{ ETBZoomOutID, wxT("ZoomOut"), XO("Zoom Out") },
{ ETBZoomSelID, wxT("ZoomSel"), XO("Fit selection in window") },
{ ETBZoomFitID, wxT("FitInWindow"), XO("Fit project in window") },
#if defined(EXPERIMENTAL_EFFECTS_RACK)
{ ETBEffectsID, wxT(""), XO("Open Effects Rack") },
#endif
};
void EditToolBar::ForAllButtons(int Action)
{
AudacityProject *p;
CommandManager* cm;
if( Action & ETBActEnableDisable ){
p = GetActiveProject();
if (!p) return;
cm = p->GetCommandManager();
if (!cm) return;
#ifdef OPTION_SYNC_LOCK_BUTTON
bool bSyncLockTracks;
gPrefs->Read(wxT("/GUI/SyncLockTracks"), &bSyncLockTracks, false);
if (bSyncLockTracks)
mButtons[ETBSyncLockID]->PushDown();
else
mButtons[ETBSyncLockID]->PopUp();
#endif
}
std::vector<wxString> commands;
for (const auto &entry : EditToolbarButtonList) {
#if wxUSE_TOOLTIPS
if( Action & ETBActTooltips ){
commands.clear();
commands.push_back(wxGetTranslation(entry.untranslatedLabel));
commands.push_back(entry.commandName);
ToolBar::SetButtonToolTip(*mButtons[entry.tool], commands);
}
#endif
if( Action & ETBActEnableDisable ){
mButtons[entry.tool]->SetEnabled(cm->GetEnabled(entry.commandName));
}
}
}
void EditToolBar::OnButton(wxCommandEvent &event)
{
int id = event.GetId();
// Be sure the pop-up happens even if there are exceptions, except for buttons which toggle.
auto cleanup = finally( [&] { mButtons[id]->InteractionOver();});
AudacityProject *p = GetActiveProject(); AudacityProject *p = GetActiveProject();
if (!p) return; if (!p) return;
CommandManager* cm = p->GetCommandManager(); CommandManager* cm = p->GetCommandManager();
if (!cm) return; if (!cm) return;
mButtons[ETBCutID]->SetEnabled(cm->GetEnabled("Cut")); auto flags = p->GetUpdateFlags();
mButtons[ETBCopyID]->SetEnabled(cm->GetEnabled("Copy")); cm->HandleTextualCommand(EditToolbarButtonList[id].commandName, flags, NoFlagsSpecifed);
mButtons[ETBTrimID]->SetEnabled(cm->GetEnabled("Trim"));
mButtons[ETBSilenceID]->SetEnabled(cm->GetEnabled("Silence"));
mButtons[ETBUndoID]->SetEnabled(cm->GetEnabled("Undo"));
mButtons[ETBRedoID]->SetEnabled(cm->GetEnabled("Redo"));
mButtons[ETBZoomInID]->SetEnabled(cm->GetEnabled("ZoomIn"));
mButtons[ETBZoomOutID]->SetEnabled(cm->GetEnabled("ZoomOut"));
#if 0 // Disabled for version 1.2.0 since it doesn't work quite right...
mButtons[ETBZoomToggleID]->SetEnabled(true);
#endif
mButtons[ETBZoomSelID]->SetEnabled(cm->GetEnabled("ZoomSel"));
mButtons[ETBZoomFitID]->SetEnabled(cm->GetEnabled("FitInWindow"));
mButtons[ETBPasteID]->SetEnabled(cm->GetEnabled("Paste"));
#ifdef OPTION_SYNC_LOCK_BUTTON
bool bSyncLockTracks;
gPrefs->Read(wxT("/GUI/SyncLockTracks"), &bSyncLockTracks, false);
if (bSyncLockTracks)
mButtons[ETBSyncLockID]->PushDown();
else
mButtons[ETBSyncLockID]->PopUp();
#endif
} }

View File

@ -63,6 +63,12 @@ enum {
ETBNumButtons ETBNumButtons
}; };
// flags so 1,2,4,8 etc.
enum {
ETBActTooltips = 1,
ETBActEnableDisable = 2,
};
class EditToolBar final : public ToolBar { class EditToolBar final : public ToolBar {
public: public:
@ -89,6 +95,7 @@ class EditToolBar final : public ToolBar {
void MakeButtons(); void MakeButtons();
void RegenerateTooltips() override; void RegenerateTooltips() override;
void ForAllButtons(int Action);
AButton *mButtons[ETBNumButtons]; AButton *mButtons[ETBNumButtons];