Audacity 3.2.0
Public Member Functions | Protected Member Functions | Private Member Functions | Private Attributes | List of all members
PrefsDialog Class Referenceabstract

Dialog that shows the current PrefsPanel in a tabbed divider. More...

#include <PrefsDialog.h>

Inheritance diagram for PrefsDialog:
[legend]
Collaboration diagram for PrefsDialog:
[legend]

Public Member Functions

 PrefsDialog (wxWindow *parent, AudacityProject *pProject, const TranslatableString &titlePrefix=XO("Preferences:"), PrefsPanel::Factories &factories=PrefsPanel::DefaultFactories())
 
virtual ~PrefsDialog ()
 
int ShowModal () override
 
void ShuttleAll (ShuttleGui &S)
 
void OnCategoryChange (wxCommandEvent &e)
 
void OnOK (wxCommandEvent &e)
 
void OnCancel (wxCommandEvent &e)
 
void OnPreview (wxCommandEvent &e)
 
void OnHelp (wxCommandEvent &e)
 
void OnTreeKeyDown (wxTreeEvent &e)
 
void SelectPageByName (const wxString &pageName)
 
int GetSelectedPage () const
 
- Public Member Functions inherited from wxDialogWrapper
 wxDialogWrapper ()
 
 wxDialogWrapper (wxWindow *parent, wxWindowID id, const TranslatableString &title, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxDEFAULT_DIALOG_STYLE, const TranslatableString &name=XO("Dialog"))
 
bool Create (wxWindow *parent, wxWindowID id, const TranslatableString &title, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxDEFAULT_DIALOG_STYLE, const TranslatableString &name=XO("Dialog"))
 
void SetTitle (const TranslatableString &title)
 
void SetLabel (const TranslatableString &title)
 
void SetName (const TranslatableString &title)
 
void SetName ()
 
- Public Member Functions inherited from wxTabTraversalWrapper< wxDialog >
 wxTabTraversalWrapper (Args &&... args)
 
 wxTabTraversalWrapper (const wxTabTraversalWrapper &)=delete
 
 wxTabTraversalWrapper (wxTabTraversalWrapper &&)=delete
 
wxTabTraversalWrapperoperator= (const wxTabTraversalWrapper &)=delete
 
wxTabTraversalWrapperoperator= (wxTabTraversalWrapper &&)=delete
 

Protected Member Functions

virtual long GetPreferredPage ()=0
 
virtual void SavePreferredPage ()=0
 

Private Member Functions

void RecordExpansionState ()
 
PrefsPanelGetCurrentPanel ()
 

Private Attributes

wxTreebookmCategories {}
 
PrefsPanelmUniquePage {}
 
PrefsPanel::FactoriesmFactories
 
const TranslatableString mTitlePrefix
 
std::unique_ptr< SettingTransactionmTransaction
 

Detailed Description

Dialog that shows the current PrefsPanel in a tabbed divider.

Definition at line 34 of file PrefsDialog.h.

Constructor & Destructor Documentation

◆ PrefsDialog()

PrefsDialog::PrefsDialog ( wxWindow *  parent,
AudacityProject pProject,
const TranslatableString titlePrefix = XO("Preferences:"),
PrefsPanel::Factories factories = PrefsPanel::DefaultFactories() 
)

Definition at line 443 of file PrefsDialog.cpp.

447: wxDialogWrapper(parent, wxID_ANY, XO("Audacity Preferences"),
448 wxDefaultPosition,
449 wxDefaultSize,
450 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
451, mFactories(factories)
452, mTitlePrefix(titlePrefix)
453{
454 wxASSERT(factories.size() > 0);
455 const bool uniquePage = (factories.size() == 1);
456 SetLayoutDirection(wxLayout_LeftToRight);
457
458 ShuttleGui S(this, eIsCreating);
459
460 S.StartVerticalLay(true);
461 {
462 wxASSERT(factories.size() > 0);
463 if (!uniquePage) {
464 mCategories = safenew wxTreebookExt(S.GetParent(), wxID_ANY, mTitlePrefix);
465#if wxUSE_ACCESSIBILITY
466 // so that name can be set on a standard control
467 mCategories->GetTreeCtrl()->SetAccessible(
468 safenew TreeCtrlAx(mCategories->GetTreeCtrl()));
469#endif
470 // RJH: Prevent NVDA from reading "treeCtrl"
471 mCategories->GetTreeCtrl()->SetName(_("Category"));
472 S.StartHorizontalLay(wxALIGN_LEFT | wxEXPAND, true);
473 {
474 S.Prop(1)
475 .Position(wxEXPAND)
476 .AddWindow(mCategories);
477
478 {
479 typedef std::pair<int, int> IntPair;
480 std::vector<IntPair> stack;
481 int iPage = 0;
482 for (auto it = factories.begin(), end = factories.end();
483 it != end; ++it, ++iPage)
484 {
485 const auto &node = *it;
486 const auto &factory = node.factory;
487 wxWindow *const w = factory(mCategories, wxID_ANY, pProject);
488 if (stack.empty())
489 // Parameters are: AddPage(page, name, IsSelected, imageId).
490 mCategories->AddPage(w, w->GetName(), false, 0);
491 else {
492 IntPair &top = *stack.rbegin();
493 mCategories->InsertSubPage(top.first, w, w->GetName(), false, 0);
494 if (--top.second == 0) {
495 // Expand all nodes before the layout calculation
496 mCategories->ExpandNode(top.first, true);
497 stack.pop_back();
498 }
499 }
500 if (node.nChildren > 0)
501 stack.push_back(IntPair(iPage, node.nChildren));
502 }
503 }
504 }
505 S.EndHorizontalLay();
506 }
507 else {
508 // TODO: Look into getting rid of mUniquePage and instead
509 // adding into mCategories, so there is just one page in mCategories.
510 // And then hiding the treebook.
511
512 // Unique page, don't show the factory
513 const auto &node = factories[0];
514 const auto &factory = node.factory;
515 mUniquePage = factory(S.GetParent(), wxID_ANY, pProject);
516 wxWindow * uniquePageWindow = S.Prop(1)
517 .Position(wxEXPAND)
518 .AddWindow(mUniquePage);
519 // We're not in the wxTreebook, so add the accelerator here
520 wxAcceleratorEntry entries[1];
521#if defined(__WXMAC__)
522 // Is there a standard shortcut on Mac?
523#else
524 entries[0].Set(wxACCEL_NORMAL, (int) WXK_F1, wxID_HELP);
525#endif
526 wxAcceleratorTable accel(1, entries);
527 uniquePageWindow->SetAcceleratorTable(accel);
528 }
529 }
530 S.EndVerticalLay();
531
532 S.AddStandardButtons(eOkButton | eCancelButton | ePreviewButton | eHelpButton);
533
535 wxWindow *const previewButton =
536 wxWindow::FindWindowById(wxID_PREVIEW, GetParent());
537 previewButton->Show(false);
538 }
539
540#if defined(__WXGTK__)
541 if (mCategories)
542 mCategories->GetTreeCtrl()->EnsureVisible(mCategories->GetTreeCtrl()->GetRootItem());
543#endif
544
545// mCategories->SetMaxSize({ 790, 600 }); // 790 = 800 - (border * 2)
546 Layout();
547 Fit();
548 wxSize sz = GetSize();
549
550 // Collapse nodes only after layout so the tree is wide enough
551 if (mCategories)
552 {
553 int iPage = 0;
554 for (auto it = factories.begin(), end = factories.end();
555 it != end; ++it, ++iPage)
556 mCategories->ExpandNode(iPage, it->expanded);
557 }
558
559 // This ASSERT was originally used to limit us to 800 x 600.
560 // However, the range of screen sizes and dpi of modern (2018) displays
561 // makes pixel dimensions an inadequate measure of usability, so
562 // now we only ASSERT that preferences will fit in the client display
563 // rectangle of the developer / tester's monitor.
564 // Use scrollers when necessary to ensure that preference pages will
565 // be fully visible.
566 wxRect screenRect(wxGetClientDisplayRect());
567 wxASSERT_MSG(sz.x <= screenRect.width && sz.y <= screenRect.height, wxT("Preferences dialog exceeds max size"));
568
569 sz.DecTo(screenRect.GetSize());
570
571 if( !mUniquePage ){
572 int prefWidth, prefHeight;
573 gPrefs->Read(wxT("/Prefs/Width"), &prefWidth, sz.x);
574 gPrefs->Read(wxT("/Prefs/Height"), &prefHeight, wxMax(480,sz.y));
575
576 wxSize prefSize = wxSize(prefWidth, prefHeight);
577 prefSize.DecTo(screenRect.GetSize());
578 SetSize(prefSize);
579 InvalidateBestSize();
580 Layout();
581 }
582 SetMinSize(sz);
583
584 // Center after all that resizing, but make sure it doesn't end up
585 // off-screen
586 CentreOnParent();
587
588 mTransaction = std::make_unique< SettingTransaction >();
589}
wxT("CloseDown"))
XO("Cut/Copy/Paste")
#define _(s)
Definition: Internat.h:75
#define safenew
Definition: MemoryX.h:10
FileConfig * gPrefs
Definition: Prefs.cpp:70
static ProjectFileIORegistry::AttributeReaderEntries entries
@ eIsCreating
Definition: ShuttleGui.h:39
@ eOkButton
Definition: ShuttleGui.h:597
@ eCancelButton
Definition: ShuttleGui.h:598
@ eHelpButton
Definition: ShuttleGui.h:601
@ ePreviewButton
Definition: ShuttleGui.h:602
#define S(N)
Definition: ToChars.cpp:64
const TranslatableString mTitlePrefix
Definition: PrefsDialog.h:74
wxTreebook * mCategories
Definition: PrefsDialog.h:71
std::unique_ptr< SettingTransaction > mTransaction
Definition: PrefsDialog.h:76
PrefsPanel * mUniquePage
Definition: PrefsDialog.h:72
PrefsPanel::Factories & mFactories
Definition: PrefsDialog.h:73
virtual bool ShowsPreviewButton()
Definition: PrefsPanel.cpp:93
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:628
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:159
static RegisteredToolbarFactory factory

References _, eCancelButton, eHelpButton, eIsCreating, PackedArray::end(), entries, eOkButton, ePreviewButton, cloud::factory, gPrefs, mCategories, mTitlePrefix, mTransaction, mUniquePage, S, safenew, PrefsPanel::ShowsPreviewButton(), and wxT().

Referenced by anonymous_namespace{SpectrumView.cpp}::SpectrogramSettingsHandler::OnSpectrogramSettings().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ~PrefsDialog()

PrefsDialog::~PrefsDialog ( )
virtual

Definition at line 591 of file PrefsDialog.cpp.

592{
593}

Member Function Documentation

◆ GetCurrentPanel()

PrefsPanel * PrefsDialog::GetCurrentPanel ( )
private

Definition at line 641 of file PrefsDialog.cpp.

642{
643 if( mCategories)
644 return static_cast<PrefsPanel*>(mCategories->GetCurrentPage());
645 else
646 {
647 wxASSERT( mUniquePage );
648 return mUniquePage;
649 }
650}
Base class for a panel in the PrefsDialog. Classes derived from this class include BatchPrefs,...
Definition: PrefsPanel.h:51

References mCategories, and mUniquePage.

Referenced by OnHelp(), and OnPreview().

Here is the caller graph for this function:

◆ GetPreferredPage()

virtual long PrefsDialog::GetPreferredPage ( )
protectedpure virtual

Implemented in GlobalPrefsDialog, and anonymous_namespace{AudioSetupToolBar.cpp}::ViewDeviceSettingsDialog.

Referenced by anonymous_namespace{SpectrumView.cpp}::SpectrogramSettingsHandler::OnSpectrogramSettings(), and ShowModal().

Here is the caller graph for this function:

◆ GetSelectedPage()

int PrefsDialog::GetSelectedPage ( ) const

Definition at line 800 of file PrefsDialog.cpp.

801{
802 if (mCategories)
803 return mCategories->GetSelection();
804 else
805 return 0;
806}

References mCategories.

Referenced by GlobalPrefsDialog::SavePreferredPage().

Here is the caller graph for this function:

◆ OnCancel()

void PrefsDialog::OnCancel ( wxCommandEvent &  e)

Definition at line 618 of file PrefsDialog.cpp.

619{
621
622 if (mCategories) {
623 for (size_t i = 0; i < mCategories->GetPageCount(); i++) {
624 ((PrefsPanel *)mCategories->GetPage(i))->Cancel();
625 }
626 }
627 else
629
630 // Remember modified dialog size, even if cancelling.
631 if( !mUniquePage ){
632 wxSize sz = GetSize();
633 gPrefs->Write(wxT("/Prefs/Width"), sz.x);
634 gPrefs->Write(wxT("/Prefs/Height"), sz.y);
635 }
636 gPrefs->Flush();
637
638 EndModal(false);
639}
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
Definition: FileConfig.cpp:143
void RecordExpansionState()
virtual void Cancel()
Definition: PrefsPanel.cpp:89

References PrefsPanel::Cancel(), FileConfig::Flush(), gPrefs, mCategories, mUniquePage, RecordExpansionState(), and wxT().

Here is the call graph for this function:

◆ OnCategoryChange()

void PrefsDialog::OnCategoryChange ( wxCommandEvent &  e)

◆ OnHelp()

void PrefsDialog::OnHelp ( wxCommandEvent &  e)

Definition at line 657 of file PrefsDialog.cpp.

658{
659 const auto &page = GetCurrentPanel()->HelpPageName();
660 HelpSystem::ShowHelp(this, page, true);
661}
static void ShowHelp(wxWindow *parent, const FilePath &localFileName, const URLString &remoteURL, bool bModal=false, bool alwaysDefaultBrowser=false)
Definition: HelpSystem.cpp:234
PrefsPanel * GetCurrentPanel()
virtual ManualPageID HelpPageName()
If not empty string, the Help button is added below the panel.
Definition: PrefsPanel.cpp:98

References GetCurrentPanel(), PrefsPanel::HelpPageName(), and HelpSystem::ShowHelp().

Here is the call graph for this function:

◆ OnOK()

void PrefsDialog::OnOK ( wxCommandEvent &  e)

Definition at line 688 of file PrefsDialog.cpp.

689{
691
692 // Validate all pages first
693 if (mCategories) {
694 for (size_t i = 0; i < mCategories->GetPageCount(); i++) {
695 PrefsPanel *panel = (PrefsPanel *)mCategories->GetPage(i);
696
697 // The dialog doesn't end until all the input is valid
698 if (!panel->Validate()) {
699 mCategories->SetSelection(i);
700 return;
701 }
702 }
703 }
704 else {
705 if (!mUniquePage->Validate())
706 return;
707 }
708
709 // flush now so toolbars will know their position.
710 gPrefs->Flush();
711 if (mCategories) {
712 // Now apply the changes
713 // Reverse order - so Track Name is updated before language change
714 // A workaround for Bug 1661
715 for (int i = (int)mCategories->GetPageCount()-1; i>= 0; i--) {
716 PrefsPanel *panel = (PrefsPanel *)mCategories->GetPage(i);
717
718 panel->Preview();
719 panel->Commit();
720 }
721 }
722 else {
725 }
726
727 if( !mUniquePage ){
728 wxSize sz = GetSize();
729 gPrefs->Write(wxT("/Prefs/Width"), sz.x);
730 gPrefs->Write(wxT("/Prefs/Height"), sz.y);
731 }
732 gPrefs->Flush();
733
735
736#if USE_PORTMIXER
737 auto gAudioIO = AudioIOBase::Get();
738 if (gAudioIO) {
739 // We cannot have opened this dialog if gAudioIO->IsAudioTokenActive(),
740 // per the setting of AudioIONotBusyFlag and AudioIOBusyFlag in
741 // AudacityProject::GetUpdateFlags().
742 // However, we can have an invalid audio token (so IsAudioTokenActive()
743 // is false), but be monitoring.
744 // If monitoring, have to stop the stream, so HandleDeviceChange() can work.
745 // We could disable the Preferences command while monitoring, i.e.,
746 // set AudioIONotBusyFlag/AudioIOBusyFlag according to monitoring, as well.
747 // Instead allow it because unlike recording, for example, monitoring
748 // is not clearly something that should prohibit opening prefs.
749 // TODO: We *could* be smarter in this method and call HandleDeviceChange()
750 // only when the device choices actually changed. True of lots of prefs!
751 // As is, we always stop monitoring before handling the device change.
752 if (gAudioIO->IsMonitoring())
753 {
754 gAudioIO->StopStream();
755 while (gAudioIO->IsBusy()) {
756 using namespace std::chrono;
757 std::this_thread::sleep_for(100ms);
758 }
759 }
760 gAudioIO->HandleDeviceChange();
761 }
762#endif
763
764 // PRL: Is the following concern still valid, now that prefs update is
765 // handled instead by delayed event processing?
766
767 // LL: wxMac can't handle recreating the menus when this dialog is still active,
768 // so AudacityProject::UpdatePrefs() or any of the routines it calls must
769 // not cause MenuCreator::RebuildMenuBar() to be executed.
770
772
773 mTransaction->Commit();
774
775 if( IsModal() )
776 EndModal(true);
777 else
778 Destroy();
779}
static AudioIOBase * Get()
Definition: AudioIOBase.cpp:91
virtual void SavePreferredPage()=0
static void Broadcast(int id=0)
Call this static function to notify all PrefsListener objects.
Definition: Prefs.cpp:97
virtual bool Commit()=0
virtual void Preview()
Definition: PrefsPanel.h:101

References PrefsListener::Broadcast(), PrefsPanel::Commit(), FileConfig::Flush(), AudioIOBase::Get(), gPrefs, mCategories, mTransaction, mUniquePage, PrefsPanel::Preview(), RecordExpansionState(), SavePreferredPage(), and wxT().

Referenced by DoReloadPreferences(), and OnTreeKeyDown().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ OnPreview()

void PrefsDialog::OnPreview ( wxCommandEvent &  e)

Definition at line 652 of file PrefsDialog.cpp.

653{
655}

References GetCurrentPanel(), and PrefsPanel::Preview().

Here is the call graph for this function:

◆ OnTreeKeyDown()

void PrefsDialog::OnTreeKeyDown ( wxTreeEvent &  e)

Definition at line 680 of file PrefsDialog.cpp.

681{
682 if(event.GetKeyCode() == WXK_RETURN)
683 OnOK(event);
684 else
685 event.Skip(); // Ensure standard behavior when enter is not pressed
686}
void OnOK(wxCommandEvent &e)

References OnOK().

Here is the call graph for this function:

◆ RecordExpansionState()

void PrefsDialog::RecordExpansionState ( )
private

Definition at line 831 of file PrefsDialog.cpp.

832{
833 // Remember expansion state of the tree control
834 if (mCategories)
835 {
836 int iPage = 0;
837 for (auto it = mFactories.begin(), end = mFactories.end();
838 it != end; ++it, ++iPage)
839 it->expanded = mCategories->IsNodeExpanded(iPage);
840 }
841 else
842 mFactories[0].expanded = true;
843}

References PackedArray::end(), mCategories, and mFactories.

Referenced by OnCancel(), and OnOK().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SavePreferredPage()

virtual void PrefsDialog::SavePreferredPage ( )
protectedpure virtual

Implemented in GlobalPrefsDialog, and anonymous_namespace{AudioSetupToolBar.cpp}::ViewDeviceSettingsDialog.

Referenced by OnOK(), anonymous_namespace{SpectrumView.cpp}::SpectrogramSettingsHandler::OnSpectrogramSettings(), and SelectPageByName().

Here is the caller graph for this function:

◆ SelectPageByName()

void PrefsDialog::SelectPageByName ( const wxString &  pageName)

Definition at line 781 of file PrefsDialog.cpp.

782{
783 if (mCategories) {
784 size_t n = mCategories->GetPageCount();
785
786 for (size_t i = 0; i < n; i++) {
787 if (mCategories->GetPageText(i) == pageName) {
788 mCategories->SetSelection(i);
789 // This covers the case, when ShowModal is called
790 // after selecting the page.
791 // ShowModal will select the page previously used by
792 // user
794 return;
795 }
796 }
797 }
798}

References mCategories, and SavePreferredPage().

Referenced by NoUpdatesAvailableDialog::NoUpdatesAvailableDialog(), UnwritableLocationErrorDialog::UnwritableLocationErrorDialog(), and UpdateNoticeDialog::UpdateNoticeDialog().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ShowModal()

int PrefsDialog::ShowModal ( )
override

Definition at line 595 of file PrefsDialog.cpp.

596{
597 if (mCategories) {
598 /* long is signed, size_t is unsigned. On some platforms they are different
599 * lengths as well. So we must check that the stored category is both > 0
600 * and within the possible range of categories, making the first check on the
601 * _signed_ value to avoid issues when converting an unsigned one.
602 */
603 long selected = GetPreferredPage();
604 if (selected < 0 || size_t(selected) >= mCategories->GetPageCount())
605 selected = 0; // clamp to available range of tabs
606 mCategories->SetSelection(selected);
607 }
608 else {
609 auto Temp = mTitlePrefix;
610 Temp.Join( Verbatim( mUniquePage->GetLabel() ), wxT(" ") );
611 SetTitle(Temp);
612 SetName(Temp);
613 }
614
615 return wxDialogWrapper::ShowModal();
616}
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
virtual long GetPreferredPage()=0
TranslatableString & Join(TranslatableString arg, const wxString &separator={}) &
Append another translatable string.
void SetTitle(const TranslatableString &title)

References GetPreferredPage(), TranslatableString::Join(), mCategories, mTitlePrefix, mUniquePage, wxDialogWrapper::SetName(), wxDialogWrapper::SetTitle(), Verbatim(), and wxT().

Referenced by AudacityApp::InitPart2(), AudacityApp::InitTempDir(), NoUpdatesAvailableDialog::NoUpdatesAvailableDialog(), AudacityApp::OnMenuPreferences(), anonymous_namespace{EditMenus.cpp}::OnPreferences(), UnwritableLocationErrorDialog::UnwritableLocationErrorDialog(), and UpdateNoticeDialog::UpdateNoticeDialog().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ShuttleAll()

void PrefsDialog::ShuttleAll ( ShuttleGui S)

Definition at line 663 of file PrefsDialog.cpp.

664{
665 // Validate all pages first
666 if (mCategories) {
667 for (size_t i = 0; i < mCategories->GetPageCount(); i++) {
668 S.ResetId();
669 PrefsPanel *panel = (PrefsPanel *)mCategories->GetPage(i);
670 panel->PopulateOrExchange( S );
671 }
672 }
673 else
674 {
675 S.ResetId();
677 }
678}
virtual void PopulateOrExchange(ShuttleGui &WXUNUSED(S))
Definition: PrefsPanel.h:116

References mCategories, mUniquePage, PrefsPanel::PopulateOrExchange(), and S.

Referenced by GetInfoCommand::SendPreferences().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ mCategories

wxTreebook* PrefsDialog::mCategories {}
private

◆ mFactories

PrefsPanel::Factories& PrefsDialog::mFactories
private

Definition at line 73 of file PrefsDialog.h.

Referenced by RecordExpansionState().

◆ mTitlePrefix

const TranslatableString PrefsDialog::mTitlePrefix
private

Definition at line 74 of file PrefsDialog.h.

Referenced by PrefsDialog(), and ShowModal().

◆ mTransaction

std::unique_ptr< SettingTransaction > PrefsDialog::mTransaction
private

Definition at line 76 of file PrefsDialog.h.

Referenced by OnOK(), and PrefsDialog().

◆ mUniquePage

PrefsPanel* PrefsDialog::mUniquePage {}
private

Definition at line 72 of file PrefsDialog.h.

Referenced by GetCurrentPanel(), OnCancel(), OnOK(), PrefsDialog(), ShowModal(), and ShuttleAll().


The documentation for this class was generated from the following files: