27#include <wx/listbox.h>
29#include <wx/listbook.h>
31#include <wx/treebook.h>
32#include <wx/treectrl.h>
37#include "../ShuttleGui.h"
38#include "../commands/CommandManager.h"
42#include "../widgets/HelpSystem.h"
44#if wxUSE_ACCESSIBILITY
45#include "../widgets/WindowAccessible.h"
49#if wxUSE_ACCESSIBILITY
60 template<
typename Result,
typename Fn >
64 std::vector< wxTreeItemId > stack;
65 stack.push_back( ctrl.GetRootItem() );
66 unsigned position = 0;
67 while ( !stack.empty() ) {
68 auto itemId = stack.back();
69 auto pair =
fn( itemId, position );
73 wxTreeItemIdValue cookie;
74 auto childId = ctrl.GetFirstChild( itemId, cookie );
76 stack.push_back( childId );
78 auto &
id = stack.back();
79 if ( !!(
id = ctrl.GetNextSibling(
id ) ) )
81 }
while ( stack.pop_back(), !stack.empty() );
88 unsigned FindItemPosition(
const wxTreeCtrl &ctrl, wxTreeItemId
id )
93 return VisitItems<unsigned>( ctrl,
94 [=]( wxTreeItemId itemId,
unsigned position ){
95 return std::make_pair( itemId ==
id, position ); } );
98 wxTreeItemId FindItem(
const wxTreeCtrl &ctrl,
int nn )
101 return VisitItems<wxTreeItemId>( ctrl,
102 [=]( wxTreeItemId itemId,
unsigned position ){
103 return std::make_pair( nn == position, itemId ); } );
108class TreeCtrlAx final
112 TreeCtrlAx(wxTreeCtrl * ctrl);
113 virtual ~ TreeCtrlAx();
115 wxAccStatus GetChild(
int childId, wxAccessible** child)
override;
117 wxAccStatus GetChildCount(
int* childCount)
override;
119 wxAccStatus GetDefaultAction(
int childId, wxString *actionName)
override;
122 wxAccStatus GetDescription(
int childId, wxString *description)
override;
128 wxAccStatus GetFocus(
int *childId, wxAccessible **child)
override;
131 wxAccStatus GetHelpText(
int childId, wxString *helpText)
override;
135 wxAccStatus GetKeyboardShortcut(
int childId, wxString *shortcut)
override;
139 wxAccStatus GetLocation(wxRect& rect,
int elementId)
override;
142 wxAccStatus GetName(
int childId, wxString *
name)
override;
145 wxAccStatus GetRole(
int childId, wxAccRole *role)
override;
159 wxAccStatus GetState(
int childId,
long* state)
override;
163 wxAccStatus GetValue(
int childId, wxString* strValue)
override;
169 wxAccStatus Select(
int childId, wxAccSelectionFlags selectFlags)
override;
172 wxTreeCtrl *GetCtrl() {
return static_cast<wxTreeCtrl*
>( GetWindow() ); }
175TreeCtrlAx::TreeCtrlAx( wxTreeCtrl *ctrl )
180TreeCtrlAx::~TreeCtrlAx() =
default;
182wxAccStatus TreeCtrlAx::GetChild(
int childId, wxAccessible** child )
184 if( childId == wxACC_SELF )
196wxAccStatus TreeCtrlAx::GetChildCount(
int* childCount)
198 auto ctrl = GetCtrl();
202 *childCount = ctrl->GetCount();
206wxAccStatus TreeCtrlAx::GetDefaultAction(
int WXUNUSED(childId), wxString* actionName)
214wxAccStatus TreeCtrlAx::GetDescription(
int WXUNUSED(childId), wxString *description )
216 description->clear();
224wxAccStatus TreeCtrlAx::GetFocus(
int *childId, wxAccessible **child )
226 auto ctrl = GetCtrl();
230 auto item = ctrl->GetFocusedItem();
231 auto id = FindItemPosition( *ctrl, item );
238wxAccStatus TreeCtrlAx::GetHelpText(
int WXUNUSED(childId), wxString *helpText )
247wxAccStatus TreeCtrlAx::GetKeyboardShortcut(
int WXUNUSED(childId), wxString *shortcut )
254wxAccStatus TreeCtrlAx::GetLocation( wxRect& rect,
int elementId )
256 auto ctrl = GetCtrl();
260 if (elementId == wxACC_SELF)
261 rect = ctrl->GetRect();
263 auto item = FindItem( *ctrl, elementId );
264 if ( !( item && ctrl->GetBoundingRect( item, rect ) ) )
265 return wxACC_INVALID_ARG;
267 rect.SetPosition( ctrl->GetParent()->ClientToScreen( rect.GetPosition() ) );
271wxAccStatus TreeCtrlAx::GetName(
int childId, wxString*
name)
273 if ( childId == wxACC_SELF )
274 return WindowAccessible::GetName( childId,
name );
276 auto ctrl = GetCtrl();
280 auto item = FindItem( *ctrl, childId );
282 *
name = ctrl->GetItemText( item );
286 return wxACC_INVALID_ARG;
290wxAccStatus TreeCtrlAx::GetRole(
int childId, wxAccRole* role )
295 childId == wxACC_SELF ? wxROLE_SYSTEM_PANE : wxROLE_SYSTEM_STATICTEXT;
300wxAccStatus TreeCtrlAx::GetState(
int childId,
long* state)
302 auto ctrl = GetCtrl();
306 *state = wxACC_STATE_SYSTEM_FOCUSABLE | wxACC_STATE_SYSTEM_SELECTABLE;
308 if ( childId != wxACC_SELF ) {
309 auto item = FindItem( *ctrl, childId );
311 if( item == ctrl->GetFocusedItem() )
312 *state |= wxACC_STATE_SYSTEM_FOCUSED;
314 if( item == ctrl->GetSelection() )
315 *state |= wxACC_STATE_SYSTEM_SELECTED;
324wxAccStatus TreeCtrlAx::GetValue(
int childId, wxString* strValue)
326 *strValue = wxString{};
337wxAccStatus TreeCtrlAx::Select(
int childId, wxAccSelectionFlags selectFlags)
339 auto ctrl = GetCtrl();
343 if (childId != wxACC_SELF) {
345 GetChildCount( &childCount );
346 if (childId > childCount)
349 auto item = FindItem( *ctrl, childId );
351 if (selectFlags == wxACC_SEL_TAKEFOCUS)
352 ctrl->SetFocusedItem( item );
353 else if (selectFlags == wxACC_SEL_TAKESELECTION)
354 ctrl->SelectItem( item );
356 return wxACC_NOT_IMPLEMENTED;
361 return wxACC_NOT_IMPLEMENTED;
381 wxTreebookExt( wxWindow *parent,
384 , mTitlePrefix(titlePrefix)
387 int ChangeSelection(
size_t n)
override;
388 int SetSelection(
size_t n)
override;
393int wxTreebookExt::ChangeSelection(
size_t n) {
394 int i = wxTreebook::ChangeSelection(n);
395 wxString Temp = GetPageText( n );
396 static_cast<wxDialog*
>(GetParent())->SetTitle( Temp );
397 static_cast<wxDialog*
>(GetParent())->SetName( Temp );
401int wxTreebookExt::SetSelection(
size_t n)
403 int i = wxTreebook::SetSelection(n);
404 auto Temp = mTitlePrefix.Translation() +
wxT(
" ") + GetPageText( n );
405 static_cast<wxDialog*
>(GetParent())->SetTitle( Temp );
406 static_cast<wxDialog*
>(GetParent())->SetName( Temp );
411 wxWindow *
const helpButton = wxWindow::FindWindowById(wxID_HELP, GetParent());
412 wxWindow *
const previewButton = wxWindow::FindWindowById(wxID_PREVIEW, GetParent());
417#if defined(__WXMAC__)
420 entries[0].Set(wxACCEL_NORMAL, (
int) WXK_F1, wxID_HELP);
422 wxAcceleratorTable accel(1,
entries);
423 this->SetAcceleratorTable(accel);
426 this->SetAcceleratorTable(wxNullAcceleratorTable);
429 const bool changed = helpButton->Show(showHelp);
431 GetParent()->Layout();
435 const bool changed = previewButton->Show(showPreview);
437 GetParent()->Layout();
450 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
451, mFactories(factories)
452, mTitlePrefix(titlePrefix)
454 wxASSERT(factories.size() > 0);
455 const bool uniquePage = (factories.size() == 1);
456 SetLayoutDirection(wxLayout_LeftToRight);
460 S.StartVerticalLay(
true);
462 wxASSERT(factories.size() > 0);
465#if wxUSE_ACCESSIBILITY
472 S.StartHorizontalLay(wxALIGN_LEFT | wxEXPAND,
true);
479 typedef std::pair<int, int> IntPair;
480 std::vector<IntPair> stack;
482 for (
auto it = factories.begin(),
end = factories.end();
483 it !=
end; ++it, ++iPage)
485 const auto &node = *it;
486 const auto &
factory = node.factory;
492 IntPair &top = *stack.rbegin();
493 mCategories->InsertSubPage(top.first, w, w->GetName(),
false, 0);
494 if (--top.second == 0) {
500 if (node.nChildren > 0)
501 stack.push_back(IntPair(iPage, node.nChildren));
505 S.EndHorizontalLay();
513 const auto &node = factories[0];
514 const auto &
factory = node.factory;
516 wxWindow * uniquePageWindow =
S.Prop(1)
521#if defined(__WXMAC__)
524 entries[0].Set(wxACCEL_NORMAL, (
int) WXK_F1, wxID_HELP);
526 wxAcceleratorTable accel(1,
entries);
527 uniquePageWindow->SetAcceleratorTable(accel);
535 wxWindow *
const previewButton =
536 wxWindow::FindWindowById(wxID_PREVIEW, GetParent());
537 previewButton->Show(
false);
540#if defined(__WXGTK__)
548 wxSize sz = GetSize();
554 for (
auto it = factories.begin(),
end = factories.end();
555 it !=
end; ++it, ++iPage)
566 wxRect screenRect(wxGetClientDisplayRect());
567 wxASSERT_MSG(sz.x <= screenRect.width && sz.y <= screenRect.height,
wxT(
"Preferences dialog exceeds max size"));
569 sz.DecTo(screenRect.GetSize());
572 int prefWidth, prefHeight;
573 gPrefs->Read(
wxT(
"/Prefs/Width"), &prefWidth, sz.x);
574 gPrefs->Read(
wxT(
"/Prefs/Height"), &prefHeight, wxMax(480,sz.y));
576 wxSize prefSize = wxSize(prefWidth, prefHeight);
577 prefSize.DecTo(screenRect.GetSize());
579 InvalidateBestSize();
588 mTransaction = std::make_unique< SettingTransaction >();
604 if (selected < 0 ||
size_t(selected) >=
mCategories->GetPageCount())
615 return wxDialogWrapper::ShowModal();
623 for (
size_t i = 0; i <
mCategories->GetPageCount(); i++) {
632 wxSize sz = GetSize();
633 gPrefs->Write(
wxT(
"/Prefs/Width"), sz.x);
634 gPrefs->Write(
wxT(
"/Prefs/Height"), sz.y);
667 for (
size_t i = 0; i <
mCategories->GetPageCount(); i++) {
682 if(event.GetKeyCode() == WXK_RETURN)
694 for (
size_t i = 0; i <
mCategories->GetPageCount(); i++) {
698 if (!panel->Validate()) {
715 for (
int i = (
int)
mCategories->GetPageCount()-1; i>= 0; i--) {
728 wxSize sz = GetSize();
729 gPrefs->Write(
wxT(
"/Prefs/Width"), sz.x);
730 gPrefs->Write(
wxT(
"/Prefs/Height"), sz.y);
752 if (gAudioIO->IsMonitoring())
754 gAudioIO->StopStream();
755 while (gAudioIO->IsBusy()) {
756 using namespace std::chrono;
757 std::this_thread::sleep_for(100ms);
760 gAudioIO->HandleDeviceChange();
786 for (
size_t i = 0; i < n; i++) {
811 :
PrefsDialog(parent, pProject,
XO(
"Preferences:"), factories)
821 long prefscat =
gPrefs->Read(
wxT(
"/Prefs/PrefsCategory"), 0L);
838 it !=
end; ++it, ++iPage)
867#if defined(__WXGTK__)
875 wxRect r = window.GetRect();
876 window.SetSize(wxSize(1,1));
877 window.SetSize(r.GetSize());
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
const TranslatableString name
void DoReloadPreferences(AudacityProject &project)
static ProjectFileIORegistry::AttributeReaderEntries entries
AUDACITY_DLL_API wxFrame & GetProjectFrame(AudacityProject &project)
Get the top-level window associated with the project (as a wxFrame only, when you do not need to use ...
accessors for certain important windows associated with each project
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
static AudioIOBase * Get()
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
GlobalPrefsDialog(wxWindow *parent, AudacityProject *pProject, PrefsPanel::Factories &factories=PrefsPanel::DefaultFactories())
virtual ~GlobalPrefsDialog()
void SavePreferredPage() override
long GetPreferredPage() override
static void ShowHelp(wxWindow *parent, const FilePath &localFileName, const URLString &remoteURL, bool bModal=false, bool alwaysDefaultBrowser=false)
Dialog that shows the current PrefsPanel in a tabbed divider.
void OnPreview(wxCommandEvent &e)
void ShuttleAll(ShuttleGui &S)
void RecordExpansionState()
void OnHelp(wxCommandEvent &e)
int GetSelectedPage() const
const TranslatableString mTitlePrefix
PrefsPanel * GetCurrentPanel()
void OnTreeKeyDown(wxTreeEvent &e)
void OnCancel(wxCommandEvent &e)
virtual void SavePreferredPage()=0
std::unique_ptr< SettingTransaction > mTransaction
PrefsDialog(wxWindow *parent, AudacityProject *pProject, const TranslatableString &titlePrefix=XO("Preferences:"), PrefsPanel::Factories &factories=PrefsPanel::DefaultFactories())
virtual long GetPreferredPage()=0
void OnOK(wxCommandEvent &e)
void SelectPageByName(const wxString &pageName)
PrefsPanel::Factories & mFactories
static void Broadcast(int id=0)
Call this static function to notify all PrefsListener objects.
Base class for a panel in the PrefsDialog. Classes derived from this class include BatchPrefs,...
virtual ManualPageID HelpPageName()
If not empty string, the Help button is added below the panel.
virtual bool ShowsPreviewButton()
virtual void PopulateOrExchange(ShuttleGui &WXUNUSED(S))
std::vector< PrefsPanel::PrefsNode > Factories
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Holds a msgid for the translation catalog; may also bind format arguments.
TranslatableString & Join(TranslatableString arg, const wxString &separator={}) &
Append another translatable string.
An alternative to using wxWindowAccessible, which in wxWidgets 3.1.1 contained GetParent() which was ...
void SetTitle(const TranslatableString &title)
A wxTreebook is a class like wxNotebook, but not yet supported by wxWidgets 2.6.3.
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
void VisitItems(Registry::Visitor &visitor, CollectedItems &collection, Path &path, GroupItem *pGroup, const GroupItem *pToMerge, const OrderingHint &hint, bool &doFlush)
static RegisteredToolbarFactory factory
static void ReinitializeAll()