Audacity  2.3.1
Menus.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  Menus.cpp
6 
7  Dominic Mazzoni
8  Brian Gunlogson
9  et al.
10 
11 *******************************************************************//****************************************************************//****************************************************************//*******************************************************************/
27 
28 #include "Audacity.h"
29 #include "Menus.h"
30 
31 #include "AdornedRulerPanel.h"
32 #include "AudacityApp.h"
33 #include "AudioIO.h"
34 #include "LabelTrack.h"
35 #include "LyricsWindow.h"
36 #include "ModuleManager.h"
37 #ifdef USE_MIDI
38 #include "NoteTrack.h"
39 #endif // USE_MIDI
40 #include "Prefs.h"
41 #include "Project.h"
42 #include "TrackPanel.h"
43 #include "UndoManager.h"
44 #include "WaveTrack.h"
46 #include "prefs/TracksPrefs.h"
48 #include "toolbars/ToolManager.h"
49 
51 {
52 }
53 
55 {
56 }
57 
59 { return *project.mMenuManager; }
60 
62 {
63 }
64 
66 {
67 }
68 
70 {
71  bool bSelectAllIfNone;
72  gPrefs->Read(wxT("/GUI/SelectAllOnNone"), &bSelectAllIfNone, false);
73  // 0 is grey out, 1 is Autoselect, 2 is Give warnings.
74 #ifdef EXPERIMENTAL_DA
75  // DA warns or greys out.
76  mWhatIfNoSelection = bSelectAllIfNone ? 2 : 0;
77 #else
78  // Audacity autoselects or warns.
79  mWhatIfNoSelection = bSelectAllIfNone ? 1 : 2;
80 #endif
81  mStopIfWasPaused = true; // not configurable for now, but could be later.
82 }
83 
85 namespace MenuTable {
86 
88 
90 
92 : items{ std::move( items_ ) }
93 {
94 }
96 {
97  items.push_back( std::move( ptr ) );
98 }
100 
101 MenuItem::MenuItem( const wxString &title_, BaseItemPtrs &&items_ )
102 : GroupItem{ std::move( items_ ) }, title{ title_ }
103 {
104  wxASSERT( !title.empty() );
105 }
107 
109  Condition condition_, BaseItemPtrs &&items_ )
110 : GroupItem{ std::move( items_ ) }, condition{ condition_ }
111 {
112 }
114 
116 
117 CommandItem::CommandItem(const wxString &name_,
118  const wxString &label_in_,
119  bool hasDialog_,
120  CommandHandlerFinder finder_,
121  CommandFunctorPointer callback_,
122  CommandFlag flags_,
123  const CommandManager::Options &options_)
124 : name{ name_ }, label_in{ label_in_ }, hasDialog{ hasDialog_ }
125 , finder{ finder_ }, callback{ callback_ }
126 , flags{ flags_ }, options{ options_ }
127 {}
129 
131  const ComponentInterfaceSymbol items_[],
132  size_t nItems_,
133  CommandHandlerFinder finder_,
134  CommandFunctorPointer callback_,
135  CommandFlag flags_,
136  bool isEffect_)
137 : name{ name_ }, items{ items_, items_ + nItems_ }
138 , finder{ finder_ }, callback{ callback_ }
139 , flags{ flags_ }, isEffect{ isEffect_ }
140 {}
142 
144 
145 }
146 
147 namespace {
148 
149 void VisitItem( AudacityProject &project, MenuTable::BaseItem *pItem );
150 
151 void VisitItems(
152  AudacityProject &project, const MenuTable::BaseItemPtrs &items )
153 {
154  for ( auto &pSubItem : items )
155  VisitItem( project, pSubItem.get() );
156 }
157 
158 void VisitItem( AudacityProject &project, MenuTable::BaseItem *pItem )
159 {
160  if (!pItem)
161  return;
162 
163  auto &manager = *project.GetCommandManager();
164 
165  using namespace MenuTable;
166  if (const auto pComputed =
167  dynamic_cast<ComputedItem*>( pItem )) {
168  // TODO maybe? memo-ize the results of the function, but that requires
169  // invalidating the memo at the right times
170  auto result = pComputed->factory( project );
171  if (result)
172  // recursion
173  VisitItem( project, result.get() );
174  }
175  else
176  if (const auto pCommand =
177  dynamic_cast<CommandItem*>( pItem )) {
178  manager.AddItem(
179  pCommand->name, pCommand->label_in, pCommand->hasDialog,
180  pCommand->finder, pCommand->callback,
181  pCommand->flags, pCommand->options
182  );
183  }
184  else
185  if (const auto pCommandList =
186  dynamic_cast<CommandGroupItem*>( pItem ) ) {
187  manager.AddItemList(pCommandList->name,
188  pCommandList->items.data(), pCommandList->items.size(),
189  pCommandList->finder, pCommandList->callback,
190  pCommandList->flags, pCommandList->isEffect);
191  }
192  else
193  if (const auto pMenu =
194  dynamic_cast<MenuItem*>( pItem )) {
195  manager.BeginMenu( pMenu->title );
196  // recursion
197  VisitItems( project, pMenu->items );
198  manager.EndMenu();
199  }
200  else
201  if (const auto pConditionalGroup =
202  dynamic_cast<ConditionalGroupItem*>( pItem )) {
203  const auto flag = pConditionalGroup->condition();
204  if (!flag)
205  manager.BeginOccultCommands();
206  // recursion
207  VisitItems( project, pConditionalGroup->items );
208  if (!flag)
209  manager.EndOccultCommands();
210  }
211  else
212  if (const auto pGroup =
213  dynamic_cast<GroupItem*>( pItem )) {
214  // recursion
215  VisitItems( project, pGroup->items );
216  }
217  else
218  if (dynamic_cast<SeparatorItem*>( pItem )) {
219  manager.AddSeparator();
220  }
221  else
222  if (const auto pSpecial =
223  dynamic_cast<SpecialItem*>( pItem )) {
224  const auto pCurrentMenu = manager.CurrentMenu();
225  wxASSERT( pCurrentMenu );
226  pSpecial->fn( project, *pCurrentMenu );
227  }
228  else
229  wxASSERT( false );
230 }
231 
232 }
233 
237 
239 
241 
243 
245 
247 
249 
254 
256 
258 
260 
261 // Table of menu factories.
262 // TODO: devise a registration system instead.
263 static const auto menuTree = MenuTable::Items(
264  FileMenu
265  , EditMenu
266  , SelectMenu
267  , ViewMenu
268  , TransportMenu
269  , TracksMenu
270  , GenerateMenu
271  , EffectMenu
272  , AnalyzeMenu
273  , ToolsMenu
274  , WindowMenu
275  , ExtraMenu
276  , HelpMenu
277 );
278 
280 {
281  CommandManager *c = project.GetCommandManager();
282 
283  // The list of defaults to exclude depends on
284  // preference wxT("/GUI/Shortcuts/FullDefaults"), which may have changed.
285  c->SetMaxList();
286 
287  auto menubar = c->AddMenuBar(wxT("appmenu"));
288  wxASSERT(menubar);
289 
290  VisitItem( project, menuTree.get() );
291 
292  project.SetMenuBar(menubar.release());
293 
295 
296 #if defined(__WXDEBUG__)
297 // c->CheckDups();
298 #endif
299 }
300 
301 // TODO: This surely belongs in CommandManager?
303 {
304  wxString desc;
305  auto &undoManager = *project.GetUndoManager();
306  auto &commandManager = *project.GetCommandManager();
307  int cur = undoManager.GetCurrentState();
308 
309  if (undoManager.UndoAvailable()) {
310  undoManager.GetShortDescription(cur, &desc);
311  commandManager.Modify(wxT("Undo"),
312  wxString::Format(_("&Undo %s"),
313  desc));
314  commandManager.Enable(wxT("Undo"), project.UndoAvailable());
315  }
316  else {
317  commandManager.Modify(wxT("Undo"),
318  _("&Undo"));
319  }
320 
321  if (undoManager.RedoAvailable()) {
322  undoManager.GetShortDescription(cur+1, &desc);
323  commandManager.Modify(wxT("Redo"),
324  wxString::Format(_("&Redo %s"),
325  desc));
326  commandManager.Enable(wxT("Redo"), project.RedoAvailable());
327  }
328  else {
329  commandManager.Modify(wxT("Redo"),
330  _("&Redo"));
331  commandManager.Enable(wxT("Redo"), false);
332  }
333 }
334 
336 {
337  // On OSX, we can't rebuild the menus while a modal dialog is being shown
338  // since the enabled state for menus like Quit and Preference gets out of
339  // sync with wxWidgets idea of what it should be.
340 #if defined(__WXMAC__) && defined(__WXDEBUG__)
341  {
342  wxDialog *dlg =
343  wxDynamicCast(wxGetTopLevelParent(wxWindow::FindFocus()), wxDialog);
344  wxASSERT((!dlg || !dlg->IsModal()));
345  }
346 #endif
347 
348  // Delete the menus, since we will soon recreate them.
349  // Rather oddly, the menus don't vanish as a result of doing this.
350  {
351  std::unique_ptr<wxMenuBar> menuBar{ project.GetMenuBar() };
352  project.DetachMenuBar();
353  // menuBar gets deleted here
354  }
355 
356  project.GetCommandManager()->PurgeData();
357 
358  CreateMenusAndCommands(project);
359 
361 }
362 
364 {
365  wxWindow *w = wxWindow::FindFocus();
366 
367  while (w && project.GetToolManager() && project.GetTrackPanel()) {
368  if (w == project.GetToolManager()->GetTopDock()) {
369  return TopDockHasFocus;
370  }
371 
372  if (w == project.GetRulerPanel())
373  return RulerHasFocus;
374 
375  if (w == project.GetTrackPanel()) {
376  return TrackPanelHasFocus;
377  }
378  // LIE if Lyrics window has focus.
379  // we want to act as if TrackPanel has focus.
380  if (w == project.GetLyricsWindow()) {
381  return TrackPanelHasFocus;
382  }
383  if (w == project.GetToolManager()->GetBotDock()) {
384  return BotDockHasFocus;
385  }
386 
387  w = w->GetParent();
388  }
389 
390  return AlwaysEnabledFlag;
391 }
392 
394 (AudacityProject &project, bool checkActive)
395 {
396  // This method determines all of the flags that determine whether
397  // certain menu items and commands should be enabled or disabled,
398  // and returns them in a bitfield. Note that if none of the flags
399  // have changed, it's not necessary to even check for updates.
400  auto flags = AlwaysEnabledFlag;
401  // static variable, used to remember flags for next time.
402  static auto lastFlags = flags;
403 
404  if (auto focus = wxWindow::FindFocus()) {
405  while (focus && focus->GetParent())
406  focus = focus->GetParent();
407  if (focus && !static_cast<wxTopLevelWindow*>(focus)->IsIconized())
408  flags |= NotMinimizedFlag;
409  }
410 
411  // quick 'short-circuit' return.
412  if ( checkActive && !project.IsActive() ){
413  // short cirucit return should preserve flags that have not been calculated.
414  flags = (lastFlags & ~NotMinimizedFlag) | flags;
415  lastFlags = flags;
416  return flags;
417  }
418 
420  flags |= AudioIONotBusyFlag;
421  else
422  flags |= AudioIOBusyFlag;
423 
424  if( gAudioIO->IsPaused() )
425  flags |= PausedFlag;
426  else
427  flags |= NotPausedFlag;
428 
429  auto &viewInfo = project.GetViewInfo();
430  const auto &selectedRegion = viewInfo.selectedRegion;
431 
432  if (!selectedRegion.isPoint())
433  flags |= TimeSelectedFlag;
434 
435  auto tracks = project.GetTracks();
436  auto trackRange = tracks->Any();
437  if ( trackRange )
438  flags |= TracksExistFlag;
439  trackRange.Visit(
440  [&](LabelTrack *lt) {
441  flags |= LabelTracksExistFlag;
442 
443  if (lt->GetSelected()) {
444  flags |= TracksSelectedFlag;
445  for (int i = 0; i < lt->GetNumLabels(); i++) {
446  const LabelStruct *ls = lt->GetLabel(i);
447  if (ls->getT0() >= selectedRegion.t0() &&
448  ls->getT1() <= selectedRegion.t1()) {
449  flags |= LabelsSelectedFlag;
450  break;
451  }
452  }
453  }
454 
455  if (lt->IsTextSelected()) {
456  flags |= CutCopyAvailableFlag;
457  }
458  },
459  [&](WaveTrack *t) {
460  flags |= WaveTracksExistFlag;
461  flags |= PlayableTracksExistFlag;
462  if (t->GetSelected()) {
463  flags |= TracksSelectedFlag;
464  // TODO: more-than-two-channels
465  if (TrackList::Channels(t).size() > 1) {
466  flags |= StereoRequiredFlag;
467  }
468  flags |= WaveTracksSelectedFlag;
469  flags |= AudioTracksSelectedFlag;
470  }
471  if( t->GetEndTime() > t->GetStartTime() )
472  flags |= HasWaveDataFlag;
473  }
474 #if defined(USE_MIDI)
475  ,
476  [&](NoteTrack *nt) {
477  flags |= NoteTracksExistFlag;
478 #ifdef EXPERIMENTAL_MIDI_OUT
479  flags |= PlayableTracksExistFlag;
480 #endif
481 
482  if (nt->GetSelected()) {
483  flags |= TracksSelectedFlag;
484  flags |= NoteTracksSelectedFlag;
485  flags |= AudioTracksSelectedFlag; // even if not EXPERIMENTAL_MIDI_OUT
486  }
487  }
488 #endif
489  );
490 
492  flags |= ClipboardFlag;
493 
494  auto &undoManager = *project.GetUndoManager();
495 
496  if (undoManager.UnsavedChanges() || !project.IsProjectSaved())
497  flags |= UnsavedChangesFlag;
498 
499  if (!mLastEffect.IsEmpty())
500  flags |= HasLastEffectFlag;
501 
502  if (project.UndoAvailable())
503  flags |= UndoAvailableFlag;
504 
505  if (project.RedoAvailable())
506  flags |= RedoAvailableFlag;
507 
508  if (project.ZoomInAvailable() && (flags & TracksExistFlag))
509  flags |= ZoomInAvailableFlag;
510 
511  if (project.ZoomOutAvailable() && (flags & TracksExistFlag))
512  flags |= ZoomOutAvailableFlag;
513 
514  // TextClipFlag is currently unused (Jan 2017, 2.1.3 alpha)
515  // and LabelTrack::IsTextClipSupported() is quite slow on Linux,
516  // so disable for now (See bug 1575).
517  // if ((flags & LabelTracksExistFlag) && LabelTrack::IsTextClipSupported())
518  // flags |= TextClipFlag;
519 
520  flags |= GetFocusedFrame(project);
521 
522  double start, end;
523  project.GetPlayRegion(&start, &end);
524  if (project.IsPlayRegionLocked())
525  flags |= PlayRegionLockedFlag;
526  else if (start != end)
527  flags |= PlayRegionNotLockedFlag;
528 
529  if (flags & AudioIONotBusyFlag) {
530  if (flags & TimeSelectedFlag) {
531  if (flags & TracksSelectedFlag) {
532  flags |= CutCopyAvailableFlag;
533  }
534  }
535  }
536 
537  if (wxGetApp().GetRecentFiles()->GetCount() > 0)
538  flags |= HaveRecentFiles;
539 
540  if (project.IsSyncLocked())
541  flags |= IsSyncLockedFlag;
542  else
543  flags |= IsNotSyncLockedFlag;
544 
546  flags |= IsRealtimeNotActiveFlag;
547 
548  if (!project.IsCapturing())
549  flags |= CaptureNotBusyFlag;
550 
551  ControlToolBar *bar = project.GetControlToolBar();
552  if (bar->ControlToolBar::CanStopAudioStream())
553  flags |= CanStopAudioStreamFlag;
554 
555  lastFlags = flags;
556  return flags;
557 }
558 
560 {
561  AProjectArray::iterator i;
562  for (i = gAudacityProjects.begin(); i != gAudacityProjects.end(); ++i) {
563  auto &project = **i;
564  GetMenuManager(project).ModifyToolbarMenus(project);
565  }
566 }
567 
569 {
570  // Refreshes can occur during shutdown and the toolmanager may already
571  // be deleted, so protect against it.
572  auto toolManager = project.GetToolManager();
573  if (!toolManager) {
574  return;
575  }
576 
577  auto &commandManager = *project.GetCommandManager();
578 
579  commandManager.Check(wxT("ShowScrubbingTB"),
580  toolManager->IsVisible(ScrubbingBarID));
581  commandManager.Check(wxT("ShowDeviceTB"),
582  toolManager->IsVisible(DeviceBarID));
583  commandManager.Check(wxT("ShowEditTB"),
584  toolManager->IsVisible(EditBarID));
585  commandManager.Check(wxT("ShowMeterTB"),
586  toolManager->IsVisible(MeterBarID));
587  commandManager.Check(wxT("ShowRecordMeterTB"),
588  toolManager->IsVisible(RecordMeterBarID));
589  commandManager.Check(wxT("ShowPlayMeterTB"),
590  toolManager->IsVisible(PlayMeterBarID));
591  commandManager.Check(wxT("ShowMixerTB"),
592  toolManager->IsVisible(MixerBarID));
593  commandManager.Check(wxT("ShowSelectionTB"),
594  toolManager->IsVisible(SelectionBarID));
595 #ifdef EXPERIMENTAL_SPECTRAL_EDITING
596  commandManager.Check(wxT("ShowSpectralSelectionTB"),
597  toolManager->IsVisible(SpectralSelectionBarID));
598 #endif
599  commandManager.Check(wxT("ShowToolsTB"),
600  toolManager->IsVisible(ToolsBarID));
601  commandManager.Check(wxT("ShowTranscriptionTB"),
602  toolManager->IsVisible(TranscriptionBarID));
603  commandManager.Check(wxT("ShowTransportTB"),
604  toolManager->IsVisible(TransportBarID));
605 
606  // Now, go through each toolbar, and call EnableDisableButtons()
607  for (int i = 0; i < ToolBarCount; i++) {
608  toolManager->GetToolBar(i)->EnableDisableButtons();
609  }
610 
611  // These don't really belong here, but it's easier and especially so for
612  // the Edit toolbar and the sync-lock menu item.
613  bool active;
614  gPrefs->Read(wxT("/AudioIO/SoundActivatedRecord"),&active, false);
615  commandManager.Check(wxT("SoundActivation"), active);
616 #ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
617  gPrefs->Read(wxT("/AudioIO/AutomatedInputLevelAdjustment"),&active, false);
618  commandManager.Check(wxT("AutomatedInputLevelAdjustmentOnOff"), active);
619 #endif
620 
622  commandManager.Check(wxT("PinnedHead"), active);
623 
624 #ifdef EXPERIMENTAL_DA
625  gPrefs->Read(wxT("/AudioIO/Duplex"),&active, false);
626 #else
627  gPrefs->Read(wxT("/AudioIO/Duplex"),&active, true);
628 #endif
629  commandManager.Check(wxT("Overdub"), active);
630  gPrefs->Read(wxT("/AudioIO/SWPlaythrough"),&active, false);
631  commandManager.Check(wxT("SWPlaythrough"), active);
632  gPrefs->Read(wxT("/GUI/SyncLockTracks"), &active, false);
633  project.SetSyncLock(active);
634  commandManager.Check(wxT("SyncLock"), active);
635  gPrefs->Read(wxT("/GUI/TypeToCreateLabel"),&active, true);
636  commandManager.Check(wxT("TypeToCreateLabel"), active);
637 }
638 
639 // checkActive is a temporary hack that should be removed as soon as we
640 // get multiple effect preview working
641 void MenuManager::UpdateMenus(AudacityProject &project, bool checkActive)
642 {
643  //ANSWER-ME: Why UpdateMenus only does active project?
644  //JKC: Is this test fixing a bug when multiple projects are open?
645  //so that menu states work even when different in different projects?
646  if (&project != GetActiveProject())
647  return;
648 
649  auto flags = GetMenuManager(project).GetUpdateFlags(project, checkActive);
650  auto flags2 = flags;
651 
652  // We can enable some extra items if we have select-all-on-none.
653  //EXPLAIN-ME: Why is this here rather than in GetUpdateFlags()?
654  //ANSWER: Because flags2 is used in the menu enable/disable.
655  //The effect still needs flags to determine whether it will need
656  //to actually do the 'select all' to make the command valid.
657  if (mWhatIfNoSelection != 0)
658  {
659  if ((flags & TracksExistFlag))
660  {
661  flags2 |= TracksSelectedFlag;
662  if ((flags & WaveTracksExistFlag))
663  {
664  flags2 |= TimeSelectedFlag
667  }
668  }
669  }
670 
671  if( mStopIfWasPaused )
672  {
673  if( flags & PausedFlag ){
674  flags2 |= AudioIONotBusyFlag;
675  }
676  }
677 
678  // Return from this function if nothing's changed since
679  // the last time we were here.
680  if (flags == mLastFlags)
681  return;
682  mLastFlags = flags;
683 
684  auto &commandManager = *project.GetCommandManager();
685 
686  commandManager.EnableUsingFlags(flags2 , NoFlagsSpecified);
687 
688  // With select-all-on-none, some items that we don't want enabled may have
689  // been enabled, since we changed the flags. Here we manually disable them.
690  // 0 is grey out, 1 is Autoselect, 2 is Give warnings.
691  if (mWhatIfNoSelection != 0)
692  {
693  if (!(flags & TimeSelectedFlag) | !(flags & TracksSelectedFlag))
694  {
695  commandManager.Enable(wxT("SplitCut"), false);
696  commandManager.Enable(wxT("SplitDelete"), false);
697  }
698  if (!(flags & WaveTracksSelectedFlag))
699  {
700  commandManager.Enable(wxT("Split"), false);
701  }
702  if (!(flags & TimeSelectedFlag) | !(flags & WaveTracksSelectedFlag))
703  {
704  commandManager.Enable(wxT("ExportSel"), false);
705  commandManager.Enable(wxT("SplitNew"), false);
706  }
707  if (!(flags & TimeSelectedFlag) | !(flags & AudioTracksSelectedFlag))
708  {
709  commandManager.Enable(wxT("Trim"), false);
710  }
711  }
712 
713 #if 0
714  if (flags & CutCopyAvailableFlag) {
715  GetCommandManager()->Enable(wxT("Copy"), true);
716  GetCommandManager()->Enable(wxT("Cut"), true);
717  }
718 #endif
719 
721 }
722 
726 
728 {
729  for( size_t i = 0; i < gAudacityProjects.size(); i++ ) {
730  AudacityProject *p = gAudacityProjects[i].get();
731 
733 #if defined(__WXGTK__)
734  // Workaround for:
735  //
736  // http://bugzilla.audacityteam.org/show_bug.cgi?id=458
737  //
738  // This workaround should be removed when Audacity updates to wxWidgets 3.x which has a fix.
739  wxRect r = p->GetRect();
740  p->SetSize(wxSize(1,1));
741  p->SetSize(r.GetSize());
742 #endif
743  }
744 }
745 
747 ( AudacityProject &project,
748  const wxString & Name, CommandFlag & flags, CommandFlag flagsRqd, CommandFlag mask )
749 {
750  bool bAllowed = TryToMakeActionAllowed( project, flags, flagsRqd, mask );
751  if( bAllowed )
752  return true;
753  CommandManager* cm = project.GetCommandManager();
754  if (!cm) return false;
755  cm->TellUserWhyDisallowed( Name, flags & mask, flagsRqd & mask);
756  return false;
757 }
758 
759 
764 ( AudacityProject &project,
765  CommandFlag & flags, CommandFlag flagsRqd, CommandFlag mask )
766 {
767  bool bAllowed;
768 
769  if( !flags )
770  flags = GetMenuManager(project).GetUpdateFlags(project);
771 
772  bAllowed = ((flags & mask) == (flagsRqd & mask));
773  if( bAllowed )
774  return true;
775 
776  // Why is action not allowed?
777  // 1's wherever a required flag is missing.
778  auto MissingFlags = (~flags & flagsRqd) & mask;
779 
780  if( mStopIfWasPaused && (MissingFlags & AudioIONotBusyFlag ) ){
781  project.StopIfPaused();
782  // Hope this will now reflect stopped audio.
783  flags = GetMenuManager(project).GetUpdateFlags(project);
784  bAllowed = ((flags & mask) == (flagsRqd & mask));
785  if( bAllowed )
786  return true;
787  }
788 
789  //We can only make the action allowed if we select audio when no selection.
790  // IF not set up to select all audio when none, THEN return with failure.
791  if( mWhatIfNoSelection != 1 )
792  return false;
793 
794  // Some effects disallow autoselection.
795  if( flagsRqd & NoAutoSelect )
796  return false;
797 
798  // Why is action still not allowed?
799  // 0's wherever a required flag is missing (or is don't care)
800  MissingFlags = (flags & ~flagsRqd) & mask;
801 
802  // IF selecting all audio won't do any good, THEN return with failure.
803  if( !(flags & WaveTracksExistFlag) )
804  return false;
805  // returns if mask wants a zero in some flag and that's not present.
806  // logic seems a bit peculiar and worth revisiting.
807  if( (MissingFlags & ~( TimeSelectedFlag | WaveTracksSelectedFlag)) )
808  return false;
809 
810  // This was 'OnSelectAll'. Changing it to DoSelectSomething means if
811  // selecting all tracks is enough, we just do that.
813  flags = GetMenuManager(project).GetUpdateFlags(project);
814  bAllowed = ((flags & mask) == (flagsRqd & mask));
815  return bAllowed;
816 }
~CommandGroupItem() override
Definition: Menus.cpp:141
bool ReportIfActionNotAllowed(AudacityProject &project, const wxString &Name, CommandFlag &flags, CommandFlag flagsRqd, CommandFlag mask)
Definition: Menus.cpp:747
~SeparatorItem() override
Definition: Menus.cpp:115
bool IsTextSelected()
Definition: LabelTrack.cpp:984
ToolDock * GetTopDock()
bool IsCapturing() const
Definition: Project.h:763
std::unique_ptr< MenuManager > mMenuManager
Definition: Project.h:793
void SetSyncLock(bool flag)
Definition: Project.cpp:5306
A ToolBar that has the main Transport buttons.
AudacityPrefs * gPrefs
Definition: Prefs.cpp:73
~ComputedItem() override
Definition: Menus.cpp:89
bool ZoomInAvailable() const
Definition: Project.h:217
SelectedRegion selectedRegion
Definition: ViewInfo.h:162
std::unique_ptr< BaseItem > BaseItemPtr
static ModuleManager & Get()
bool RedoAvailable()
Definition: Project.cpp:4604
bool GetSelected() const
Definition: Track.h:381
BaseItemPtr Items(Args &&...args)
const wxChar * desc
Definition: ExportPCM.cpp:58
int mWhatIfNoSelection
Definition: Menus.h:90
AProjectArray gAudacityProjects
Definition: Project.cpp:306
std::unique_ptr< wxMenuBar > AddMenuBar(const wxString &sMenu)
void UpdateMenus(AudacityProject &project, bool checkActive=true)
Definition: Menus.cpp:641
MenuTable::BaseItemPtr ToolsMenu(AudacityProject &)
void EnableUsingFlags(CommandFlag flags, CommandMask mask)
MenuTable::BaseItemPtr AnalyzeMenu(AudacityProject &)
auto Any() -> TrackIterRange< TrackType >
Definition: Track.h:1246
ConditionalGroupItem(Condition condition_, BaseItemPtrs &&items_)
Definition: Menus.cpp:108
int GetAudioIOToken() const
Definition: Project.cpp:1522
MenuManager handles updates to menu state.
Definition: Menus.h:58
MenuTable::BaseItemPtr FileMenu(AudacityProject &)
Definition: FileMenus.cpp:560
bool IsAudioTokenActive(int token) const
Returns true if the stream is active, or even if audio I/O is busy cleaning up its data or writing to...
Definition: AudioIO.cpp:2768
CommandManager * GetCommandManager()
Definition: Project.h:362
MenuTable::BaseItemPtr TracksMenu(AudacityProject &)
int GetNumLabels() const
void DoSelectSomething(AudacityProject &project)
CommandFlag GetUpdateFlags(AudacityProject &project, bool checkActive=false)
Definition: Menus.cpp:394
~GroupItem() override
Definition: Menus.cpp:99
MenuTable::BaseItemPtr ExtraMenu(AudacityProject &)
Definition: ExtraMenus.cpp:192
MenuTable::BaseItemPtr TransportMenu(AudacityProject &)
MenuTable::BaseItemPtr EditMenu(AudacityProject &)
Definition: EditMenus.cpp:1076
bool IsActive() override
Definition: Project.cpp:2438
int Dispatch(ModuleDispatchTypes type)
LyricsWindow * GetLyricsWindow(bool create=false)
Definition: Project.cpp:5572
void(CommandHandlerObject::*)(const CommandContext &context) CommandFunctorPointer
A LabelTrack is a Track that holds labels (LabelStruct).
Definition: LabelTrack.h:113
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional...
MenuTable::BaseItemPtr SelectMenu(AudacityProject &)
GroupItem(BaseItemPtrs &&items_)
Definition: Menus.cpp:91
AudacityProject provides the main window, with tools and tracks contained within it.
Definition: Project.h:174
A LabelStruct holds information for ONE label in a LabelTrack.
Definition: LabelTrack.h:44
MenuItem(const wxString &title_, BaseItemPtrs &&items_)
Definition: Menus.cpp:101
virtual ~PrefsListener()
Definition: Menus.cpp:50
MenuCreator()
Definition: Menus.cpp:61
CommandFlag GetFocusedFrame(AudacityProject &project)
Definition: Menus.cpp:363
void Check(const wxString &name, bool checked)
static void RebuildAllMenuBars()
Definition: Menus.cpp:727
std::vector< BaseItemPtr > BaseItemPtrs
void Modify(const wxString &name, const wxString &newLabel)
Changes the label text of a menu item.
MenuTable::BaseItemPtr EffectMenu(AudacityProject &)
AdornedRulerPanel * GetRulerPanel()
Definition: Project.cpp:1517
const LabelStruct * GetLabel(int index) const
static double msClipT0
Definition: Project.h:623
static double msClipT1
Definition: Project.h:624
A Track that contains audio waveform data.
Definition: WaveTrack.h:60
ToolManager * GetToolManager()
Definition: Project.h:685
CommandManager implements a system for organizing all user-callable commands.
void RebuildMenuBar(AudacityProject &project)
Definition: Menus.cpp:335
std::function< bool() > Condition
bool TryToMakeActionAllowed(AudacityProject &project, CommandFlag &flags, CommandFlag flagsRqd, CommandFlag mask)
Definition: Menus.cpp:764
~MenuItem() override
Definition: Menus.cpp:106
void UpdatePrefs()
Definition: Menus.cpp:69
CommandGroupItem(const wxString &name_, const ComponentInterfaceSymbol items_[], size_t nItems_, CommandHandlerFinder finder_, CommandFunctorPointer callback_, CommandFlag flags_, bool isEffect_)
Definition: Menus.cpp:130
bool ZoomOutAvailable() const
Definition: Project.h:218
MenuManager & GetMenuManager(AudacityProject &project)
Definition: Menus.cpp:58
static EffectManager & Get()
~MenuCreator()
Definition: Menus.cpp:65
static void ModifyUndoMenuItems(AudacityProject &project)
Definition: Menus.cpp:302
void CreateMenusAndCommands(AudacityProject &project)
Definition: Menus.cpp:279
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
CommandFlag
Definition: CommandFlag.h:16
AudioIO * gAudioIO
Definition: AudioIO.cpp:491
ControlToolBar * GetControlToolBar()
Definition: Project.cpp:4810
FileHistory * GetRecentFiles()
Definition: AudacityApp.h:159
const wxChar * name
Definition: Distortion.cpp:94
bool IsSyncLocked()
Definition: Project.cpp:5297
double getT1() const
Definition: LabelTrack.h:62
MenuTable::BaseItemPtr ViewMenu(AudacityProject &)
Definition: ViewMenus.cpp:392
UndoManager * GetUndoManager()
Definition: Project.h:212
void AddItem(const wxChar *name, const wxChar *label_in, bool hasDialog, CommandHandlerFinder finder, CommandFunctorPointer callback, CommandFlag flags, const Options &options={})
AUDACITY_DLL_API AudacityProject * GetActiveProject()
Definition: Project.cpp:311
static bool GetPinnedHeadPreference()
MenuTable::BaseItemPtr WindowMenu(AudacityProject &)
bool mStopIfWasPaused
Definition: Menus.h:91
virtual void UpdatePrefs()
Definition: Menus.cpp:54
~CommandItem() override
Definition: Menus.cpp:128
void StopIfPaused()
Definition: Project.cpp:5742
MenuTable::BaseItemPtr GenerateMenu(AudacityProject &)
~SpecialItem() override
Definition: Menus.cpp:143
bool IsPaused() const
Find out if playback / recording is currently paused.
Definition: AudioIO.cpp:2709
bool IsProjectSaved()
Definition: Project.cpp:5371
TrackPanel * GetTrackPanel()
Definition: Project.h:324
static void ModifyAllProjectToolbarMenus()
Definition: Menus.cpp:559
bool UndoAvailable()
Definition: Project.cpp:4597
ToolDock * GetBotDock()
AudacityApp & wxGetApp()
CommandHandlerObject &(*)(AudacityProject &) CommandHandlerFinder
TrackList * GetTracks()
Definition: Project.h:209
double getT0() const
Definition: LabelTrack.h:61
void GetPlayRegion(double *playRegionStart, double *playRegionEnd)
Definition: Project.cpp:5087
bool IsPlayRegionLocked()
Definition: Project.h:228
const ViewInfo & GetViewInfo() const
Definition: Project.h:224
static void ModifyToolbarMenus(AudacityProject &project)
Definition: Menus.cpp:568
MenuTable::BaseItemPtr HelpMenu(AudacityProject &)
Definition: HelpMenus.cpp:235
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1356
void TellUserWhyDisallowed(const wxString &Name, CommandFlag flagsGot, CommandFlag flagsRequired)
CommandItem(const wxString &name_, const wxString &label_in_, bool hasDialog_, CommandHandlerFinder finder_, CommandFunctorPointer callback_, CommandFlag flags_, const CommandManager::Options &options_)
Definition: Menus.cpp:117
bool RealtimeIsActive()
virtual ~BaseItem()
Definition: Menus.cpp:87
CommandFlag mLastFlags
Definition: Menus.h:52
size_t GetCount()
Definition: FileHistory.cpp:97
static const auto menuTree
Definition: Menus.cpp:263
A Track that is used for Midi notes. (Somewhat old code).
Definition: NoteTrack.h:66
void AppendOne(BaseItemPtr &&ptr)
Definition: Menus.cpp:95