Audacity 3.2.0
ShuttleGui.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 ShuttleGui.cpp
6
7 James Crook
8
9 Audacity is free software.
10 This file is licensed under the wxWidgets license, see License.txt
11
12**********************************************************************//***************************************************************//***************************************************************//***************************************************************//******************************************************************/
94
95
96#include "ShuttleGui.h"
97
98
99
100#include "MemoryX.h"
101#include "Prefs.h"
102#include "ShuttlePrefs.h"
103#include "Theme.h"
104
105#include <wx/setup.h> // for wxUSE_* macros
106#include <wx/wx.h>
107#include <wx/wxprec.h>
108#include <wx/grid.h>
109#include <wx/listctrl.h>
110#include <wx/notebook.h>
111#include <wx/simplebook.h>
112#include <wx/treectrl.h>
113#include <wx/spinctrl.h>
114#include <wx/stattext.h>
115#include <wx/bmpbuttn.h>
116#include <wx/wrapsizer.h>
117
118#include "ReadOnlyText.h"
119#include "wxPanelWrapper.h"
120#include "wxTextCtrlWrapper.h"
121#include "AllThemeResources.h"
122
123#if wxUSE_ACCESSIBILITY
124#include "WindowAccessible.h"
125#endif
126
128 wxWindow * pParent, teShuttleMode ShuttleMode, bool vertical, wxSize minSize )
129 : mpDlg{ pParent }
130{
131 wxASSERT( (pParent != NULL ) || ( ShuttleMode != eIsCreating));
132 mpbOptionalFlag = nullptr;
133 mpParent = pParent;
134 mShuttleMode = ShuttleMode;
135 Init( vertical, minSize );
136}
137
139{
140}
141
142void ShuttleGuiBase::Init(bool vertical, wxSize minSize)
143{
144 mpShuttle = NULL;
145 mpSizer = NULL;
146 mpWind = NULL;
147 mpSubSizer = NULL;
148
150 mRadioCount = -1;
151
152 miBorder = 5;
153 miProp=0;
155 miSizerProp=0;
156 mSizerDepth=-1;
157
158 ResetId();
159
161
163 return;
164
165 mpSizer = mpParent->GetSizer();
166
167#if 0
168 if( mpSizer == NULL )
169 {
170 wxWindow * pGrandParent = mpParent->GetParent();
171 if( pGrandParent )
172 {
173 mpSizer = pGrandParent->GetSizer();
174 }
175 }
176#endif
177
178 if( !mpSizer )
179 {
180 mpParent->SetSizer(
181 mpSizer = safenew wxBoxSizer(vertical ? wxVERTICAL : wxHORIZONTAL));
182 }
183 PushSizer();
184 mpSizer->SetMinSize(minSize);
185}
186
188{
189 miIdSetByUser = -1;
190 miId = -1;
191 miIdNext = 3000;
192}
193
194
195int ShuttleGuiBase::GetBorder() const noexcept
196{
197 return miBorder;
198}
199
202{
204 return;
205 wxFlexGridSizer *pSizer = wxDynamicCast(mpSizer, wxFlexGridSizer);
206 wxASSERT( pSizer );
207 pSizer->AddGrowableCol( i, 1 );
208}
209
212{
214 return;
215 wxFlexGridSizer *pSizer = wxDynamicCast(mpSizer, wxFlexGridSizer);
216 wxASSERT( pSizer );
217 pSizer->AddGrowableRow( i, 1 );
218}
219
220
221//---- Add Functions.
222
224{
225 // If creating, will be handled by an AddPrompt.
227 return;
228 //wxLogDebug( "Optionality: [%s] Id:%i (%i)", Prompt.c_str(), miId, miIdSetByUser ) ;
229 if( mpbOptionalFlag ){
230 bool * pVar = mpbOptionalFlag;
231 mpbOptionalFlag = nullptr;
232 TieCheckBox( Prompt, *pVar);
233 }
234}
235
237void ShuttleGuiBase::AddPrompt(const TranslatableString &Prompt, int wrapWidth)
238{
240 return;
241 //wxLogDebug( "Prompt: [%s] Id:%i (%i)", Prompt.c_str(), miId, miIdSetByUser ) ;
242 if( mpbOptionalFlag ){
243 bool * pVar = mpbOptionalFlag;
244 mpbOptionalFlag = nullptr;
245 TieCheckBox( {}, *pVar);
246 //return;
247 }
248 if( Prompt.empty() )
249 return;
250 miProp=1;
251 const auto translated = Prompt.Translation();
252 auto text = safenew wxStaticText(GetParent(), -1, translated, wxDefaultPosition, wxDefaultSize,
253 GetStyle( wxALIGN_RIGHT ));
254 mpWind = text;
255 if (wrapWidth > 0)
256 text->Wrap(wrapWidth);
257 mpWind->SetName(wxStripMenuCodes(translated)); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
258 UpdateSizersCore( false, wxALL | wxALIGN_CENTRE_VERTICAL, true );
259}
260
262void ShuttleGuiBase::AddUnits(const TranslatableString &Prompt, int wrapWidth)
263{
264 if( Prompt.empty() )
265 return;
267 return;
268 miProp = 1;
269 const auto translated = Prompt.Translation();
270 auto text = safenew wxStaticText(GetParent(), -1, translated, wxDefaultPosition, wxDefaultSize,
271 GetStyle( wxALIGN_LEFT ));
272 mpWind = text;
273 if (wrapWidth > 0)
274 text->Wrap(wrapWidth);
275 mpWind->SetName(translated); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
276 UpdateSizersCore( false, wxALL | wxALIGN_CENTRE_VERTICAL );
277}
278
280void ShuttleGuiBase::AddTitle(const TranslatableString &Prompt, int wrapWidth)
281{
282 if( Prompt.empty() )
283 return;
285 return;
286 const auto translated = Prompt.Translation();
287 auto text = safenew wxStaticText(GetParent(), -1, translated, wxDefaultPosition, wxDefaultSize,
288 GetStyle( wxALIGN_CENTRE ));
289 mpWind = text;
290 if (wrapWidth > 0)
291 text->Wrap(wrapWidth);
292 mpWind->SetName(translated); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
293 UpdateSizers();
294}
295
298wxWindow* ShuttleGuiBase::AddWindow(wxWindow* pWindow, int PositionFlags)
299{
301 return pWindow;
302 mpWind = pWindow;
303 SetProportions( 0 );
304 UpdateSizersCore(false, PositionFlags | wxALL);
305 return pWindow;
306}
307
308wxCheckBox * ShuttleGuiBase::AddCheckBox( const TranslatableString &Prompt, bool Selected)
309{
310 HandleOptionality( Prompt );
311 auto realPrompt = Prompt.Translation();
312 if( mpbOptionalFlag )
313 {
314 AddPrompt( {} );
315 //realPrompt = wxT("");
316 }
317
318 UseUpId();
320 return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxCheckBox);
321 wxCheckBox * pCheckBox;
322 miProp=0;
323 mpWind = pCheckBox = safenew wxCheckBox(GetParent(), miId, realPrompt, wxDefaultPosition, wxDefaultSize,
324 GetStyle( 0 ));
325 pCheckBox->SetValue(Selected);
326 if (realPrompt.empty()) {
327 // NVDA 2018.3 does not read controls which are buttons, check boxes or radio buttons which have
328 // an accessibility name which is empty. Bug 1980.
329#if wxUSE_ACCESSIBILITY
330 // so that name can be set on a standard control
331 pCheckBox->SetAccessible(safenew WindowAccessible(pCheckBox));
332#endif
333 pCheckBox->SetName(wxT("\a")); // non-empty string which screen readers do not read
334 }
335 UpdateSizers();
336 return pCheckBox;
337}
338
342wxCheckBox * ShuttleGuiBase::AddCheckBoxOnRight( const TranslatableString &Prompt, bool Selected)
343{
344 HandleOptionality( Prompt );
345 AddPrompt( Prompt );
346 UseUpId();
348 return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxCheckBox);
349 wxCheckBox * pCheckBox;
350 miProp=0;
351 mpWind = pCheckBox = safenew wxCheckBox(GetParent(), miId, wxT(""), wxDefaultPosition, wxDefaultSize,
352 GetStyle( 0 ));
353 pCheckBox->SetValue(Selected);
354 pCheckBox->SetName(Prompt.Stripped().Translation());
355 UpdateSizers();
356 return pCheckBox;
357}
358
360 const TranslatableString &Text, int PositionFlags, bool setDefault)
361{
362 UseUpId();
364 return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxButton);
365 wxButton * pBtn;
366 const auto translated = Text.Translation();
367 mpWind = pBtn = safenew wxButton(GetParent(), miId,
368 translated, wxDefaultPosition, wxDefaultSize,
369 GetStyle( 0 ) );
370 mpWind->SetName(wxStripMenuCodes(translated));
371 miProp=0;
372 UpdateSizersCore(false, PositionFlags | wxALL);
373 if (setDefault)
374 pBtn->SetDefault();
375 return pBtn;
376}
377
379 const wxBitmap &Bitmap, int PositionFlags, bool setDefault)
380{
381 UseUpId();
383 return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxBitmapButton);
384 wxBitmapButton * pBtn;
385 mpWind = pBtn = safenew wxBitmapButton(GetParent(), miId, Bitmap,
386 wxDefaultPosition, wxDefaultSize, GetStyle( wxBU_AUTODRAW ) );
387 pBtn->SetBackgroundColour(
388 wxColour( 246,246,243));
389// wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
390 miProp=0;
391 UpdateSizersCore(false, PositionFlags | wxALL);
392 if (setDefault)
393 pBtn->SetDefault();
394 return pBtn;
395}
396
398 const TranslatableStrings &choices, int Selected )
399{
400 HandleOptionality( Prompt );
401 AddPrompt( Prompt );
402 UseUpId();
404 return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxChoice);
405 wxChoice * pChoice;
406 miProp=0;
407
408 mpWind = pChoice = safenew wxChoice(
409 GetParent(),
410 miId,
411 wxDefaultPosition,
412 wxDefaultSize,
413 transform_container<wxArrayString>(
414 choices, std::mem_fn( &TranslatableString::StrippedTranslation ) ),
415 GetStyle( 0 ) );
416
417 pChoice->SetMinSize( { 180, -1 } );// Use -1 for 'default size' - Platform specific.
418#ifdef __WXMAC__
419#if wxUSE_ACCESSIBILITY
420 // so that name can be set on a standard control
421 mpWind->SetAccessible(safenew WindowAccessible(mpWind));
422#endif
423#endif
424 pChoice->SetName(Prompt.Stripped().Translation());
425 if ( Selected >= 0 && Selected < (int)choices.size() )
426 pChoice->SetSelection( Selected );
427
428 UpdateSizers();
429 return pChoice;
430}
431
433 const TranslatableStrings &choices, const TranslatableString &Selected )
434{
435 return AddChoice(
436 Prompt, choices, make_iterator_range( choices ).index( Selected ) );
437}
438
440 const TranslatableString &Str, bool bCenter, int wrapWidth)
441{
442 const auto translated = Str.Translation();
443 UseUpId();
445 return;
446 auto text = safenew wxStaticText(GetParent(),
447 miId, translated, wxDefaultPosition, wxDefaultSize,
448 GetStyle( wxALIGN_LEFT ));
449 mpWind = text;
450 if ( wrapWidth > 0 )
451 text->Wrap( wrapWidth );
452 mpWind->SetName(wxStripMenuCodes(translated)); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
453 if( bCenter )
454 {
455 miProp=1;
457 }
458 else
459 UpdateSizers();
460}
461
463 const TranslatableString &Str,
464 bool bCenter, int PositionFlags, int wrapWidth )
465{
466 const auto translated = Str.Translation();
467 UseUpId();
469 return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxStaticText);
470
471 wxStaticText *pStatic;
472 auto text = pStatic = safenew wxStaticText(GetParent(), miId, translated,
473 wxDefaultPosition, wxDefaultSize,
474 GetStyle( wxALIGN_LEFT ));
475 mpWind = text;
476 if ( wrapWidth > 0 )
477 text->Wrap( wrapWidth );
478 mpWind->SetName(wxStripMenuCodes(translated)); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
479 if( bCenter )
480 {
481 miProp=1;
482 if( PositionFlags )
483 UpdateSizersCore( false, PositionFlags );
484 else
486 }
487 else
488 if( PositionFlags )
489 UpdateSizersCore( false, PositionFlags );
490 else
491 UpdateSizers();
492 return pStatic;
493}
494
496 const TranslatableString &Caption, const wxString &Value)
497{
498 const auto translated = Caption.Translation();
499 auto style = GetStyle( wxBORDER_NONE );
500 HandleOptionality( Caption );
501 mItem.miStyle = wxALIGN_CENTER_VERTICAL;
502 AddPrompt( Caption );
503 UseUpId();
505 return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), ReadOnlyText);
506 ReadOnlyText * pReadOnlyText;
507 miProp=0;
508
509 mpWind = pReadOnlyText = safenew ReadOnlyText(GetParent(), miId, Value,
510 wxDefaultPosition, wxDefaultSize, GetStyle( style ));
511 mpWind->SetName(wxStripMenuCodes(translated));
512 UpdateSizers();
513 return pReadOnlyText;
514}
515
517 const TranslatableString &Prompt,
518 const wxString &Selected, const wxArrayStringEx & choices )
519{
520 const auto translated = Prompt.Translation();
521 HandleOptionality( Prompt );
522 AddPrompt( Prompt );
523 UseUpId();
525 return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxComboBox);
526 wxComboBox * pCombo;
527 miProp=0;
528
529 int n = choices.size();
530 if( n>50 ) n=50;
531 int i;
532 wxString Choices[50];
533 for(i=0;i<n;i++)
534 {
535 Choices[i] = choices[i];
536 }
537
538 mpWind = pCombo = safenew wxComboBox(GetParent(), miId, Selected, wxDefaultPosition, wxDefaultSize,
539 n, Choices, GetStyle( 0 ));
540 mpWind->SetName(wxStripMenuCodes(translated));
541
542 UpdateSizers();
543 return pCombo;
544}
545
546
548 const TranslatableString &Prompt, int style, int selector, int initValue)
549{
550 const auto translated = Prompt.Translation();
553 UseUpId();
555 return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxRadioButton);
556 wxRadioButton * pRad;
557 mpWind = pRad = safenew wxRadioButton(GetParent(), miId, translated,
558 wxDefaultPosition, wxDefaultSize, GetStyle( style ) );
559 mpWind->SetName(wxStripMenuCodes(translated));
560 if ( style )
561 pRad->SetValue( true );
562 UpdateSizers();
563 pRad->SetValue( selector == initValue );
564 return pRad;
565}
566
568 const TranslatableString &Prompt, int selector, int initValue)
569{
570 return DoAddRadioButton( Prompt, wxRB_GROUP, selector, initValue );
571}
572
574 const TranslatableString &Prompt, int selector, int initValue)
575{
576 return DoAddRadioButton( Prompt, 0, selector, initValue );
577}
578
579#ifdef __WXMAC__
581{
582 // bypassing the override in wxCompositeWindow<wxSliderBase> which ends up
583 // doing nothing
584 return wxSliderBase::SetFocus();
585}
586#endif
587
589 const TranslatableString &Prompt, int pos, int Max, int Min)
590{
591 HandleOptionality( Prompt );
592 AddPrompt( Prompt );
593 UseUpId();
595 return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxSlider);
596 wxSlider * pSlider;
598 pos, Min, Max,
599 wxDefaultPosition,
600 // Bug2289: On Linux at least, sliders like to be constructed with the
601 // proper size, not reassigned size later
602 ( ( mItem.mWindowSize == wxSize{} ) ? wxDefaultSize : mItem.mWindowSize ),
603 GetStyle( wxSL_HORIZONTAL | wxSL_LABELS | wxSL_AUTOTICKS )
604 );
605#if wxUSE_ACCESSIBILITY
606 // so that name can be set on a standard control
607 mpWind->SetAccessible(safenew WindowAccessible(mpWind));
608#endif
609 mpWind->SetName(wxStripMenuCodes(Prompt.Translation()));
610 miProp=1;
611 UpdateSizers();
612 return pSlider;
613}
614
616 const TranslatableString &Prompt, int Value, int Max, int Min)
617{
618 const auto translated = Prompt.Translation();
619 HandleOptionality( Prompt );
620 AddPrompt( Prompt );
621 UseUpId();
623 return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxSpinCtrl);
624 wxSpinCtrl * pSpinCtrl;
625 mpWind = pSpinCtrl = safenew wxSpinCtrl(GetParent(), miId,
626 wxEmptyString,
627 wxDefaultPosition, wxDefaultSize,
628 GetStyle( wxSP_VERTICAL | wxSP_ARROW_KEYS ),
629 Min, Max, Value
630 );
631 mpWind->SetName(wxStripMenuCodes(translated));
632 miProp=1;
633 UpdateSizers();
634 return pSpinCtrl;
635}
636
638 const TranslatableString &Caption, const wxString &Value, const int nChars)
639{
640 const auto translated = Caption.Translation();
641 HandleOptionality( Caption );
642 AddPrompt( Caption );
643 UseUpId();
645 return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxTextCtrl);
646 wxTextCtrl * pTextCtrl;
647 wxSize Size(wxDefaultSize);
648 if( nChars > 0 )
649 {
650 int width;
651 mpDlg->GetTextExtent( wxT("9"), &width, nullptr );
652 Size.SetWidth( nChars * width );
653 }
654 miProp=0;
655
656#ifdef EXPERIMENTAL_RIGHT_ALIGNED_TEXTBOXES
657 long flags = wxTE_RIGHT;
658#else
659 long flags = wxTE_LEFT;
660#endif
661
662 mpWind = pTextCtrl = safenew wxTextCtrlWrapper(GetParent(), miId, Value,
663 wxDefaultPosition, Size, GetStyle( flags ));
664#if wxUSE_ACCESSIBILITY
665 // so that name can be set on a standard control
666 mpWind->SetAccessible(safenew WindowAccessible(mpWind));
667#endif
668 mpWind->SetName(wxStripMenuCodes(translated));
669 UpdateSizers();
670 return pTextCtrl;
671}
672
674 const TranslatableString &Caption, const wxString &Value, const int nChars)
675{
676 const auto translated = Caption.Translation();
677 HandleOptionality( Caption );
678 AddPrompt( Caption );
679 UseUpId();
681 return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxTextCtrl);
682 wxTextCtrl * pTextCtrl;
683 wxSize Size(wxDefaultSize);
684 if( nChars > 0 )
685 {
686 Size.SetWidth( nChars *5 );
687 }
688 miProp=0;
689
690#ifdef EXPERIMENTAL_RIGHT_ALIGNED_TEXTBOXES
691 long flags = wxTE_RIGHT;
692#else
693 long flags = wxTE_LEFT;
694#endif
695
696 wxTextValidator Validator(wxFILTER_NUMERIC);
697 mpWind = pTextCtrl = safenew wxTextCtrl(GetParent(), miId, Value,
698 wxDefaultPosition, Size, GetStyle( flags ),
699 Validator // It's OK to pass this. It will be cloned.
700 );
701#if wxUSE_ACCESSIBILITY
702 // so that name can be set on a standard control
703 mpWind->SetAccessible(safenew WindowAccessible(mpWind));
704#endif
705 mpWind->SetName(wxStripMenuCodes(translated));
706 UpdateSizers();
707 return pTextCtrl;
708}
709
711wxTextCtrl * ShuttleGuiBase::AddTextWindow(const wxString &Value)
712{
713 UseUpId();
715 return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxTextCtrl);
716 wxTextCtrl * pTextCtrl;
717 SetProportions( 1 );
718 mpWind = pTextCtrl = safenew wxTextCtrl(GetParent(), miId, Value,
719 wxDefaultPosition, wxDefaultSize, GetStyle( wxTE_MULTILINE ));
720#if wxUSE_ACCESSIBILITY
721 // so that name can be set on a standard control
722 mpWind->SetAccessible(safenew WindowAccessible(mpWind));
723#endif
724 UpdateSizers();
725 // Start off at start of window...
726 pTextCtrl->SetInsertionPoint( 0 );
727 pTextCtrl->ShowPosition( 0 );
728 return pTextCtrl;
729}
730
733 const TranslatableString &Prompt, const TranslatableString &Value)
734{
735 HandleOptionality( Prompt );
736 AddPrompt( Prompt );
737 UseUpId();
739 return;
740// return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wx);
741 miProp=0;
742 UpdateSizers();
743 miProp=0;
744 const auto translatedValue = Value.Translation();
745 mpWind = safenew wxStaticText(GetParent(), miId,
746 translatedValue, wxDefaultPosition, wxDefaultSize,
747 GetStyle( 0 ));
748 mpWind->SetName(translatedValue); // fix for bug 577 (NVDA/Narrator screen readers do not read static text in dialogs)
749 UpdateSizers();
750}
751
753{
754 UseUpId();
756 return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxListBox);
757 wxListBox * pListBox;
758 SetProportions( 1 );
759 mpWind = pListBox = safenew wxListBox(GetParent(), miId,
760 wxDefaultPosition, wxDefaultSize, choices, GetStyle(0));
761 pListBox->SetMinSize( wxSize( 120,150 ));
762 UpdateSizers();
763 return pListBox;
764}
765
766
768{
769 UseUpId();
771 return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxGrid);
772 wxGrid * pGrid;
773 SetProportions( 1 );
774 mpWind = pGrid = safenew wxGrid(GetParent(), miId, wxDefaultPosition,
775 wxDefaultSize, GetStyle( wxWANTS_CHARS ));
776 pGrid->SetMinSize( wxSize( 120, 150 ));
777 UpdateSizers();
778 return pGrid;
779}
780
782 std::initializer_list<const ListControlColumn> columns,
783 long listControlStyles
784)
785{
786 UseUpId();
788 return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxListCtrl);
789 wxListCtrl * pListCtrl;
790 SetProportions( 1 );
791 mpWind = pListCtrl = safenew wxListCtrl(GetParent(), miId,
792 wxDefaultPosition, wxDefaultSize, GetStyle( wxLC_ICON ));
793 pListCtrl->SetMinSize( wxSize( 120,150 ));
794 UpdateSizers();
795
796 DoInsertListColumns( pListCtrl, listControlStyles, columns );
797
798 return pListCtrl;
799}
800
802 std::initializer_list<const ListControlColumn> columns,
803 long listControlStyles
804)
805{
806 UseUpId();
808 return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxListCtrl);
809 wxListCtrl * pListCtrl;
810 SetProportions( 1 );
811 mpWind = pListCtrl = safenew wxListCtrl(GetParent(), miId,
812 wxDefaultPosition, wxSize(230,120),//wxDefaultSize,
813 GetStyle( wxLC_REPORT | wxLC_HRULES | wxLC_VRULES | wxSUNKEN_BORDER ));
814// pListCtrl->SetMinSize( wxSize( 120,150 ));
815 UpdateSizers();
816
817 DoInsertListColumns( pListCtrl, listControlStyles, columns );
818
819 return pListCtrl;
820}
821
823 wxListCtrl *pListCtrl,
824 long listControlStyles,
825 std::initializer_list<const ListControlColumn> columns )
826{
827 // Old comment from HistoryWindow.cpp follows
828 // -- is it still correct for wxWidgets 3?
829
830 // Do this BEFORE inserting the columns. On the Mac at least, the
831 // columns are deleted and later InsertItem()s will cause Audacity to crash.
832 for ( auto style = 1l; style <= listControlStyles; style <<= 1 )
833 if ( (style & listControlStyles) )
834 pListCtrl->SetSingleStyle(style, true);
835
836 long iCol = 0;
837 bool dummyColumn =
838 columns.size() > 0 && begin(columns)->format == wxLIST_FORMAT_RIGHT;
839
840 //A dummy first column, which is then deleted, is a workaround -
841 // under Windows the first column can't be right aligned.
842 if (dummyColumn)
843 pListCtrl->InsertColumn( iCol++, wxString{} );
844
845 for (auto &column : columns)
846 pListCtrl->InsertColumn(
847 iCol++, column.heading.Translation(), column.format, column.width );
848
849 if (dummyColumn)
850 pListCtrl->DeleteColumn( 0 );
851}
852
854{
855 UseUpId();
857 return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxTreeCtrl);
858 wxTreeCtrl * pTreeCtrl;
859 SetProportions( 1 );
860 mpWind = pTreeCtrl = safenew wxTreeCtrl(GetParent(), miId, wxDefaultPosition, wxDefaultSize,
861 GetStyle( wxTR_HAS_BUTTONS ));
862 pTreeCtrl->SetMinSize( wxSize( 120,650 ));
863 UpdateSizers();
864 return pTreeCtrl;
865}
866
867void ShuttleGuiBase::AddIcon(wxBitmap *pBmp)
868{
869 UseUpId();
871// return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wx);
872 return;
873 wxBitmapButton * pBtn;
874 mpWind = pBtn = safenew wxBitmapButton(GetParent(), miId, *pBmp,
875 wxDefaultPosition, wxDefaultSize, GetStyle( wxBU_AUTODRAW ) );
876 pBtn->SetWindowStyle( wxBORDER_NONE );
877 pBtn->SetCanFocus(false);
879}
880
882{
883 miPropSetByUser = iProp;
884 return *this;
885}
886
892wxStaticBox * ShuttleGuiBase::StartStatic(const TranslatableString &Str, int iProp)
893{
894 UseUpId();
896 return NULL;
897 auto translated = Str.Translation();
898 wxStaticBox * pBox = safenew wxStaticBoxWrapper(
899 GetParent(), miId, translated );
900 pBox->SetLabel( translated );
901 if (Str.empty()) {
902 // NVDA 2018.3 or later does not read the controls in a group box which has
903 // an accessibility name which is empty. Bug 2169.
904#if wxUSE_ACCESSIBILITY
905 // so that name can be set on a standard control
906 pBox->SetAccessible(safenew WindowAccessible(pBox));
907#endif
908 pBox->SetName(wxT("\a")); // non-empty string which screen readers do not read
909 }
910 else
911 pBox->SetName( wxStripMenuCodes( translated ) );
912 mpSubSizer = std::make_unique<wxStaticBoxSizer>(
913 pBox,
914 wxVERTICAL );
915 miSizerProp = iProp;
916 UpdateSizers();
917 mpParent = pBox;
918 return pBox;
919}
920
922{
924 return;
925 PopSizer();
926 mpParent = mpParent->GetParent();
927}
928
937wxScrolledWindow * ShuttleGuiBase::StartScroller(int iStyle)
938{
939 UseUpId();
941 return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxScrolledWindow);
942
943 wxScrolledWindow * pScroller;
944 mpWind = pScroller = safenew wxScrolledWindow(GetParent(), miId, wxDefaultPosition, wxDefaultSize,
945 GetStyle( wxSUNKEN_BORDER ) );
946 pScroller->SetScrollRate( 20,20 );
947
948 // This fools NVDA into not saying "Panel" when the dialog gets focus
949 pScroller->SetName(wxT("\a"));
950 pScroller->SetLabel(wxT("\a"));
951
952 SetProportions( 1 );
953 if( iStyle==2 )
954 {
956 }
957 else
958 {
959 // mpWind->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_MENUBAR));
960 UpdateSizers(); // adds window in to current sizer.
961 }
962
963 // create a sizer within the window...
964 mpParent = pScroller;
965 pScroller->SetSizer(mpSizer = safenew wxBoxSizer(wxVERTICAL));
966 PushSizer();
967 return pScroller;
968}
969
971{
973 return;
974 wxSize ScrollSize = mpSizer->GetMinSize();
975 int yMin = ScrollSize.y+4;
976 int xMin = ScrollSize.x+4;
977 if( yMin > 400)
978 {
979 yMin = 400;
980 xMin+=50;// extra space for vertical scrollbar.
981 }
982
983 mpParent->SetMinSize( wxSize(xMin, yMin) );
984
985 PopSizer();
986 mpParent = mpParent->GetParent();
987}
988
989wxPanel * ShuttleGuiBase::StartPanel(int iStyle)
990{
991 UseUpId();
993 return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxPanel);
994 wxPanel * pPanel;
995 mpWind = pPanel = safenew wxPanelWrapper( GetParent(), miId, wxDefaultPosition, wxDefaultSize,
996 GetStyle( wxNO_BORDER ));
997
998 if( iStyle != 0 )
999 {
1000 mpWind->SetBackgroundColour(
1001 iStyle==1
1002 ? wxColour( 190,200,230) :
1003 wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)
1004 );
1005 }
1006 SetProportions(0);
1007 miBorder=2;
1008 UpdateSizers(); // adds window in to current sizer.
1009
1010 // create a sizer within the window...
1011 mpParent = pPanel;
1012 pPanel->SetSizer(mpSizer = safenew wxBoxSizer(wxVERTICAL));
1013 PushSizer();
1014 return pPanel;
1015}
1016
1018{
1019 if( mShuttleMode != eIsCreating )
1020 return;
1021 PopSizer();
1022 mpParent = mpParent->GetParent();
1023}
1024
1026{
1027 UseUpId();
1028 if( mShuttleMode != eIsCreating )
1029 return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxNotebook);
1030 wxNotebook * pNotebook;
1031 mpWind = pNotebook = safenew wxNotebook(GetParent(),
1032 miId, wxDefaultPosition, wxDefaultSize, GetStyle( 0 ));
1033 SetProportions( 1 );
1034 UpdateSizers();
1035 mpParent = pNotebook;
1036 return pNotebook;
1037}
1038
1040{
1041 //PopSizer();
1042 mpParent = mpParent->GetParent();
1043}
1044
1045
1047{
1048 UseUpId();
1049 if( mShuttleMode != eIsCreating )
1050 return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxSimplebook);
1051 wxSimplebook * pNotebook;
1052 mpWind = pNotebook = safenew wxSimplebook(GetParent(),
1053 miId, wxDefaultPosition, wxDefaultSize, GetStyle( 0 ));
1054 SetProportions( 1 );
1055 UpdateSizers();
1056 mpParent = pNotebook;
1057 return pNotebook;
1058}
1059
1061{
1062 //PopSizer();
1063 mpParent = mpParent->GetParent();
1064}
1065
1066
1068 const TranslatableString & Name )
1069{
1070 if( mShuttleMode != eIsCreating )
1071 return NULL;
1072// return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wx);
1073 auto pNotebook = static_cast< wxBookCtrlBase* >( mpParent );
1075 const auto translated = Name.Translation();
1076 pPage->SetName(translated);
1077
1078 pNotebook->AddPage(
1079 pPage,
1080 translated);
1081
1082 SetProportions( 1 );
1083 mpParent = pPage;
1084 pPage->SetSizer(mpSizer = safenew wxBoxSizer(wxVERTICAL));
1085 PushSizer();
1086 // UpdateSizers();
1087 return pPage;
1088}
1089
1091{
1092 if( mShuttleMode != eIsCreating )
1093 return;
1094 PopSizer();
1095 mpParent = mpParent->GetParent();
1096}
1097
1098// Doxygen description is at the start of the file
1099// this is a wxPanel with erase background disabled.
1100class InvisiblePanel final : public wxPanelWrapper
1101{
1102public:
1104 wxWindow* parent,
1105 wxWindowID id = -1,
1106 const wxPoint& pos = wxDefaultPosition,
1107 const wxSize& size = wxDefaultSize,
1108 long style = wxTAB_TRAVERSAL ) :
1109 wxPanelWrapper( parent, id, pos, size, style )
1110 {
1111 };
1113 void OnPaint( wxPaintEvent &event );
1114 void OnErase(wxEraseEvent &/*evt*/){;};
1115 DECLARE_EVENT_TABLE()
1116};
1117
1118
1119BEGIN_EVENT_TABLE(InvisiblePanel, wxPanelWrapper)
1120// EVT_PAINT(InvisiblePanel::OnPaint)
1121 EVT_ERASE_BACKGROUND( InvisiblePanel::OnErase)
1123
1124void InvisiblePanel::OnPaint( wxPaintEvent & WXUNUSED(event))
1125{
1126 // Don't repaint my background.
1127 wxPaintDC dc(this);
1128 // event.Skip(); // swallow the paint event.
1129}
1130
1132{
1133 UseUpId();
1134 if( mShuttleMode != eIsCreating )
1135 return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxPanel);
1136 wxPanel * pPanel;
1137 mpWind = pPanel = safenew wxPanelWrapper(GetParent(), miId, wxDefaultPosition, wxDefaultSize,
1138 wxNO_BORDER);
1139
1140 mpWind->SetBackgroundColour(
1141 wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)
1142 );
1143 SetProportions( 1 );
1144 miBorder = border;
1145 UpdateSizers(); // adds window in to current sizer.
1146
1147 // create a sizer within the window...
1148 mpParent = pPanel;
1149 pPanel->SetSizer(mpSizer = safenew wxBoxSizer(wxVERTICAL));
1150 PushSizer();
1151 return pPanel;
1152}
1153
1155{
1156 EndPanel();
1157}
1158
1159
1166void ShuttleGuiBase::StartHorizontalLay( int PositionFlags, int iProp)
1167{
1168 if( mShuttleMode != eIsCreating )
1169 return;
1170 miSizerProp=iProp;
1171 mpSubSizer = std::make_unique<wxBoxSizer>( wxHORIZONTAL );
1172 // PRL: wxALL has no effect because UpdateSizersCore ignores border
1173 UpdateSizersCore( false, PositionFlags | wxALL );
1174}
1175
1177{
1178 if( mShuttleMode != eIsCreating )
1179 return;
1180 PopSizer();
1181}
1182
1184{
1185 if( mShuttleMode != eIsCreating )
1186 return;
1187 miSizerProp=iProp;
1188 mpSubSizer = std::make_unique<wxBoxSizer>( wxVERTICAL );
1189 UpdateSizers();
1190}
1191
1192void ShuttleGuiBase::StartVerticalLay(int PositionFlags, int iProp)
1193{
1194 if( mShuttleMode != eIsCreating )
1195 return;
1196 miSizerProp=iProp;
1197 mpSubSizer = std::make_unique<wxBoxSizer>( wxVERTICAL );
1198 // PRL: wxALL has no effect because UpdateSizersCore ignores border
1199 UpdateSizersCore( false, PositionFlags | wxALL );
1200}
1201
1203{
1204 if( mShuttleMode != eIsCreating )
1205 return;
1206 PopSizer();
1207}
1208
1209void ShuttleGuiBase::StartWrapLay(int PositionFlags, int iProp)
1210{
1212 return;
1213
1214 miSizerProp = iProp;
1215 mpSubSizer = std::make_unique<wxWrapSizer>(wxHORIZONTAL, 0);
1216
1217 UpdateSizersCore(false, PositionFlags | wxALL);
1218}
1219
1221{
1223 return;
1224
1225 PopSizer();
1226}
1227
1228void ShuttleGuiBase::StartMultiColumn(int nCols, int PositionFlags)
1229{
1230 if( mShuttleMode != eIsCreating )
1231 return;
1232 mpSubSizer = std::make_unique<wxFlexGridSizer>( nCols );
1233 // PRL: wxALL has no effect because UpdateSizersCore ignores border
1234 UpdateSizersCore( false, PositionFlags | wxALL );
1235}
1236
1238{
1239 if( mShuttleMode != eIsCreating )
1240 return;
1241 PopSizer();
1242}
1243
1246void ShuttleGuiBase::DoDataShuttle( const wxString &Name, WrappedType & WrappedRef )
1247{
1248 wxASSERT( mpShuttle );
1249 mpShuttle->TransferWrappedType( Name, WrappedRef );
1250}
1251
1252//-----------------------------------------------------------------------//
1253
1254// We now have a group of tie functions which are generic in the type
1255// they bind to (i.e. WrappedType).
1256// The type specific versions are much shorter and are later
1257// in this file.
1258wxCheckBox * ShuttleGuiBase::DoTieCheckBox(const TranslatableString &Prompt, WrappedType & WrappedRef)
1259{
1260 HandleOptionality( Prompt );
1261 // The Add function does a UseUpId(), so don't do it here in that case.
1262 if( mShuttleMode == eIsCreating )
1263 return AddCheckBox( Prompt, WrappedRef.ReadAsString() == wxT("true"));
1264
1265 UseUpId();
1266
1267 wxWindow * pWnd = wxWindow::FindWindowById( miId, mpDlg);
1268 wxCheckBox * pCheckBox = wxDynamicCast(pWnd, wxCheckBox);
1269
1270 switch( mShuttleMode )
1271 {
1272 // IF setting internal storage from the controls.
1273 case eIsGettingMetadata:
1274 break;
1276 {
1277 wxASSERT( pCheckBox );
1278 WrappedRef.WriteToAsBool( pCheckBox->GetValue() );
1279 }
1280 break;
1281 case eIsSettingToDialog:
1282 {
1283 wxASSERT( pCheckBox );
1284 pCheckBox->SetValue( WrappedRef.ReadAsBool() );
1285 }
1286 break;
1287 default:
1288 wxASSERT( false );
1289 break;
1290 }
1291 return pCheckBox;
1292}
1293
1295{
1296 HandleOptionality( Prompt );
1297 // The Add function does a UseUpId(), so don't do it here in that case.
1298 if( mShuttleMode == eIsCreating )
1299 return AddCheckBoxOnRight( Prompt, WrappedRef.ReadAsString() == wxT("true"));
1300
1301 UseUpId();
1302
1303 wxWindow * pWnd = wxWindow::FindWindowById( miId, mpDlg);
1304 wxCheckBox * pCheckBox = wxDynamicCast(pWnd, wxCheckBox);
1305
1306 switch( mShuttleMode )
1307 {
1308 // IF setting internal storage from the controls.
1309 case eIsGettingMetadata:
1310 break;
1312 {
1313 wxASSERT( pCheckBox );
1314 WrappedRef.WriteToAsBool( pCheckBox->GetValue() );
1315 }
1316 break;
1317 case eIsSettingToDialog:
1318 {
1319 wxASSERT( pCheckBox );
1320 pCheckBox->SetValue( WrappedRef.ReadAsBool() );
1321 }
1322 break;
1323 default:
1324 wxASSERT( false );
1325 break;
1326 }
1327 return pCheckBox;
1328}
1329
1331 const TranslatableString &Prompt,
1332 WrappedType & WrappedRef, const int max, const int min )
1333{
1334 HandleOptionality( Prompt );
1335 // The Add function does a UseUpId(), so don't do it here in that case.
1336 if( mShuttleMode == eIsCreating )
1337 return AddSpinCtrl( Prompt, WrappedRef.ReadAsInt(), max, min );
1338
1339 UseUpId();
1340 wxSpinCtrl * pSpinCtrl=NULL;
1341
1342 wxWindow * pWnd = wxWindow::FindWindowById( miId, mpDlg);
1343 pSpinCtrl = wxDynamicCast(pWnd, wxSpinCtrl);
1344
1345 switch( mShuttleMode )
1346 {
1347 // IF setting internal storage from the controls.
1348 case eIsGettingMetadata:
1349 break;
1351 {
1352 wxASSERT( pSpinCtrl );
1353 WrappedRef.WriteToAsInt( pSpinCtrl->GetValue() );
1354 }
1355 break;
1356 case eIsSettingToDialog:
1357 {
1358 wxASSERT( pSpinCtrl );
1359 pSpinCtrl->SetValue( WrappedRef.ReadAsInt() );
1360 }
1361 break;
1362 default:
1363 wxASSERT( false );
1364 break;
1365 }
1366 return pSpinCtrl;
1367}
1368
1370 const TranslatableString &Prompt, WrappedType & WrappedRef, const int nChars)
1371{
1372 HandleOptionality( Prompt );
1373 // The Add function does a UseUpId(), so don't do it here in that case.
1374 if( mShuttleMode == eIsCreating )
1375 return AddTextBox( Prompt, WrappedRef.ReadAsString(), nChars );
1376
1377 UseUpId();
1378 wxTextCtrl * pTextBox=NULL;
1379
1380 wxWindow * pWnd = wxWindow::FindWindowById( miId, mpDlg);
1381 pTextBox = wxDynamicCast(pWnd, wxTextCtrl);
1382
1383 switch( mShuttleMode )
1384 {
1385 // IF setting internal storage from the controls.
1386 case eIsGettingMetadata:
1387 break;
1389 {
1390 wxASSERT( pTextBox );
1391 WrappedRef.WriteToAsString( pTextBox->GetValue() );
1392 }
1393 break;
1394 case eIsSettingToDialog:
1395 {
1396 wxASSERT( pTextBox );
1397 pTextBox->SetValue( WrappedRef.ReadAsString() );
1398 }
1399 break;
1400 default:
1401 wxASSERT( false );
1402 break;
1403 }
1404 return pTextBox;
1405}
1406
1408 const TranslatableString &Prompt, WrappedType & WrappedRef, const int nChars)
1409{
1410 HandleOptionality( Prompt );
1411 // The Add function does a UseUpId(), so don't do it here in that case.
1412 if( mShuttleMode == eIsCreating )
1413 return AddNumericTextBox( Prompt, WrappedRef.ReadAsString(), nChars );
1414
1415 UseUpId();
1416 wxTextCtrl * pTextBox=NULL;
1417
1418 wxWindow * pWnd = wxWindow::FindWindowById( miId, mpDlg);
1419 pTextBox = wxDynamicCast(pWnd, wxTextCtrl);
1420
1421 switch( mShuttleMode )
1422 {
1423 // IF setting internal storage from the controls.
1424 case eIsGettingMetadata:
1425 break;
1427 {
1428 wxASSERT( pTextBox );
1429 WrappedRef.WriteToAsString( pTextBox->GetValue() );
1430 }
1431 break;
1432 case eIsSettingToDialog:
1433 {
1434 wxASSERT( pTextBox );
1435 pTextBox->SetValue( WrappedRef.ReadAsString() );
1436 }
1437 break;
1438 default:
1439 wxASSERT( false );
1440 break;
1441 }
1442 return pTextBox;
1443}
1444
1446 const TranslatableString &Prompt,
1447 WrappedType & WrappedRef, const int max, int min )
1448{
1449 HandleOptionality( Prompt );
1450 // The Add function does a UseUpId(), so don't do it here in that case.
1451 if( mShuttleMode != eIsCreating )
1452 UseUpId();
1453 wxSlider * pSlider=NULL;
1454 switch( mShuttleMode )
1455 {
1456 case eIsCreating:
1457 {
1458 pSlider = AddSlider( Prompt, WrappedRef.ReadAsInt(), max, min );
1459 }
1460 break;
1461 // IF setting internal storage from the controls.
1462 case eIsGettingMetadata:
1463 break;
1465 {
1466 wxWindow * pWnd = wxWindow::FindWindowById( miId, mpDlg);
1467 pSlider = wxDynamicCast(pWnd, wxSlider);
1468 wxASSERT( pSlider );
1469 WrappedRef.WriteToAsInt( pSlider->GetValue() );
1470 }
1471 break;
1472 case eIsSettingToDialog:
1473 {
1474 wxWindow * pWnd = wxWindow::FindWindowById( miId, mpDlg);
1475 pSlider = wxDynamicCast(pWnd, wxSlider);
1476 wxASSERT( pSlider );
1477 pSlider->SetValue( WrappedRef.ReadAsInt() );
1478 }
1479 break;
1480 default:
1481 wxASSERT( false );
1482 break;
1483 }
1484 return pSlider;
1485}
1486
1487
1489 const TranslatableString &Prompt,
1490 int &Selected,
1491 const TranslatableStrings &choices )
1492{
1493 HandleOptionality( Prompt );
1494
1495 // The Add function does a UseUpId(), so don't do it here in that case.
1496 if( mShuttleMode != eIsCreating )
1497 UseUpId();
1498
1499 wxChoice * pChoice=NULL;
1500 switch( mShuttleMode )
1501 {
1502 case eIsCreating:
1503 {
1504 pChoice = AddChoice( Prompt, choices, Selected );
1505 ShuttleGui::SetMinSize(pChoice, choices);
1506 }
1507 break;
1508 // IF setting internal storage from the controls.
1509 case eIsGettingMetadata:
1510 break;
1512 {
1513 wxWindow * pWnd = wxWindow::FindWindowById( miId, mpDlg);
1514 pChoice = wxDynamicCast(pWnd, wxChoice);
1515 wxASSERT( pChoice );
1516 Selected = pChoice->GetSelection();
1517 }
1518 break;
1519 case eIsSettingToDialog:
1520 {
1521 wxWindow * pWnd = wxWindow::FindWindowById( miId, mpDlg);
1522 pChoice = wxDynamicCast(pWnd, wxChoice);
1523 wxASSERT( pChoice );
1524 pChoice->SetSelection( Selected );
1525 }
1526 break;
1527 default:
1528 wxASSERT( false );
1529 break;
1530 }
1531 return pChoice;
1532}
1533
1536{
1537 wxASSERT( mRadioCount >= 0); // Did you remember to use StartRadioButtonGroup() ?
1538
1539 EnumValueSymbol symbol;
1540 if (mRadioCount >= 0 && mRadioCount < (int)mRadioSymbols.size() )
1541 symbol = mRadioSymbols[ mRadioCount ];
1542
1543 // In what follows, WrappedRef is used in read only mode, but we
1544 // don't have a 'read-only' version, so we copy to deal with the constness.
1545 auto Temp = symbol.Internal();
1546 wxASSERT( !Temp.empty() ); // More buttons than values?
1547
1548 WrappedType WrappedRef( Temp );
1549
1550 mRadioCount++;
1551
1552 UseUpId();
1553 wxRadioButton * pRadioButton = NULL;
1554
1555 switch( mShuttleMode )
1556 {
1557 case eIsCreating:
1558 {
1559 const auto &Prompt = symbol.Translation();
1560
1561 mpWind = pRadioButton = safenew wxRadioButton(GetParent(), miId, Prompt,
1562 wxDefaultPosition, wxDefaultSize,
1563 (mRadioCount==1)?wxRB_GROUP:0);
1564
1565 wxASSERT( WrappedRef.IsString() );
1566 wxASSERT( mRadioValue->IsString() );
1567 const bool value =
1568 (WrappedRef.ReadAsString() == mRadioValue->ReadAsString() );
1569 pRadioButton->SetValue( value );
1570
1571 pRadioButton->SetName(wxStripMenuCodes(Prompt));
1572 UpdateSizers();
1573 }
1574 break;
1575 case eIsGettingMetadata:
1576 break;
1578 {
1579 wxWindow * pWnd = wxWindow::FindWindowById( miId, mpDlg);
1580 pRadioButton = wxDynamicCast(pWnd, wxRadioButton);
1581 wxASSERT( pRadioButton );
1582 if( pRadioButton->GetValue() )
1583 mRadioValue->WriteToAsString( WrappedRef.ReadAsString() );
1584 }
1585 break;
1586 default:
1587 wxASSERT( false );
1588 break;
1589 }
1590 return pRadioButton;
1591}
1592
1595{
1596 mRadioSymbols = Setting.GetSymbols();
1597
1598 // Configure the generic type mechanism to use OUR string.
1599 mRadioValueString = Setting.Default().Internal();
1600 mRadioValue.emplace( mRadioValueString );
1601
1602 // Now actually start the radio button group.
1603 mRadioSettingName = Setting.Key();
1604 mRadioCount = 0;
1605 if( mShuttleMode == eIsCreating )
1607}
1608
1612{
1613 // too few buttons?
1614 wxASSERT( mRadioCount == mRadioSymbols.size() );
1615
1618 mRadioValue.reset();// Clear it out...
1619 mRadioSettingName = wxT("");
1620 mRadioCount = -1; // So we detect a problem.
1621 mRadioSymbols = {};
1622}
1623
1624//-----------------------------------------------------------------------//
1625//-- Now we are into type specific Tie() functions.
1626//-- These are all 'one-step' tie functions.
1627
1628wxCheckBox * ShuttleGuiBase::TieCheckBox(const TranslatableString &Prompt, bool &Var)
1629{
1630 WrappedType WrappedRef( Var );
1631 return DoTieCheckBox( Prompt, WrappedRef );
1632}
1633
1634// See comment in AddCheckBoxOnRight() for why we have this variant.
1635wxCheckBox * ShuttleGuiBase::TieCheckBoxOnRight(const TranslatableString &Prompt, bool &Var)
1636{
1637 // Only does anything different if it's creating.
1638 WrappedType WrappedRef( Var );
1639 if( mShuttleMode == eIsCreating )
1640 return AddCheckBoxOnRight( Prompt, WrappedRef.ReadAsString() == wxT("true") );
1641 return DoTieCheckBox( Prompt, WrappedRef );
1642}
1643
1645 const TranslatableString &Prompt, int &Value, const int max, const int min )
1646{
1647 WrappedType WrappedRef(Value);
1648 return DoTieSpinCtrl( Prompt, WrappedRef, max, min );
1649}
1650
1652 const TranslatableString &Prompt, wxString &Selected, const int nChars)
1653{
1654 WrappedType WrappedRef(Selected);
1655 return DoTieTextBox( Prompt, WrappedRef, nChars );
1656}
1657
1659 const TranslatableString &Prompt, int &Selected, const int nChars)
1660{
1661 WrappedType WrappedRef( Selected );
1662 return DoTieTextBox( Prompt, WrappedRef, nChars );
1663}
1664
1666 const TranslatableString &Prompt, double &Value, const int nChars)
1667{
1668 WrappedType WrappedRef( Value );
1669 return DoTieTextBox( Prompt, WrappedRef, nChars );
1670}
1671
1673 const TranslatableString &Prompt, int &Value, const int nChars)
1674{
1675 WrappedType WrappedRef( Value );
1676 return DoTieNumericTextBox( Prompt, WrappedRef, nChars );
1677}
1678
1680 const TranslatableString &Prompt, double &Value, const int nChars)
1681{
1682 WrappedType WrappedRef( Value );
1683 return DoTieNumericTextBox( Prompt, WrappedRef, nChars );
1684}
1685
1687 const TranslatableString &Prompt, int &pos, const int max, const int min )
1688{
1689 WrappedType WrappedRef( pos );
1690 return DoTieSlider( Prompt, WrappedRef, max, min );
1691}
1692
1694 const TranslatableString &Prompt,
1695 double &pos, const double max, const double min )
1696{
1697 WrappedType WrappedRef( pos );
1698 return DoTieSlider( Prompt, WrappedRef, max, min );
1699}
1700
1702 const TranslatableString &Prompt,
1703 float &pos, const float fMin, const float fMax)
1704{
1705 const float RoundFix=0.0000001f;
1706 int iVal=(pos-fMin+RoundFix)*100.0/(fMax-fMin);
1707 wxSlider * pWnd = TieSlider( Prompt, iVal, 100 );
1708 pos = iVal*(fMax-fMin)*0.01+fMin;
1709 return pWnd;
1710}
1711
1713 const TranslatableString &Prompt,
1714 float &pos, const float fMin, const float fMax)
1715{
1716 int iVal=(pos-fMin)*100.0/(fMax-fMin);
1717// if( mShuttleMode == eIsCreating )
1718// {
1719// return AddVSlider( Prompt, iVal, 100 );
1720// }
1721 wxSlider * pWnd = TieSlider( Prompt, iVal, 100 );
1722 pos = iVal*(fMax-fMin)*0.01+fMin;
1723 return pWnd;
1724}
1725
1727 const TranslatableString &Prompt,
1728 TranslatableString &Selected,
1729 const TranslatableStrings &choices )
1730{
1731 int Index = make_iterator_range( choices ).index( Selected );
1732 auto result = TieChoice( Prompt, Index, choices );
1733 if ( Index >= 0 && Index < choices.size() )
1734 Selected = choices[ Index ];
1735 else
1736 Selected = {};
1737 return result;
1738}
1739
1740//-----------------------------------------------------------------------//
1741
1742// ShuttleGui utility functions to look things up in a list.
1743// If not present, we use the configured default index value.
1744
1745//-----------------------------------------------------------------------//
1746
1748int ShuttleGuiBase::TranslateToIndex( const wxString &Value, const wxArrayStringEx &Choices )
1749{
1750 int n = make_iterator_range( Choices ).index( Value );
1751 if( n == wxNOT_FOUND )
1754 return n;
1755}
1756
1758wxString ShuttleGuiBase::TranslateFromIndex( const int nIn, const wxArrayStringEx &Choices )
1759{
1760 int n = nIn;
1761 if( n== wxNOT_FOUND )
1764 if( n < (int)Choices.size() )
1765 {
1766 return Choices[n];
1767 }
1768 return wxT("");
1769}
1770
1771//-----------------------------------------------------------------------//
1772
1773
1774// ShuttleGui code uses the model that you read into program variables
1775// and write out from program variables.
1776
1777// In programs like Audacity which don't use internal program variables
1778// you have to do both steps in one go, using variants of the standard
1779// 'Tie' functions which call the underlying Tie functions twice.
1780
1781//----------------------------------------------------------------------//
1782
1783
1816bool ShuttleGuiBase::DoStep( int iStep )
1817{
1818 // Get value and create
1819 if( mShuttleMode == eIsCreating )
1820 {
1821 return (iStep==1) || (iStep==2);
1822 }
1823 // Like creating, get the value and set.
1825 {
1826 return (iStep==1) || (iStep==2);
1827 }
1829 {
1830 return (iStep==2) || (iStep==3);
1831 }
1833 return iStep ==2;
1834 wxASSERT( false );
1835 return false;
1836}
1837
1838
1842 const TranslatableString &Prompt,
1843 const BoolSetting &Setting)
1844{
1845 wxCheckBox * pCheck=NULL;
1846
1847 auto Value = Setting.GetDefault();
1848 WrappedType WrappedRef( Value );
1849 if( DoStep(1) ) DoDataShuttle( Setting.GetPath(), WrappedRef );
1850 if( DoStep(2) ) pCheck = DoTieCheckBox( Prompt, WrappedRef );
1851 if( DoStep(3) ) DoDataShuttle( Setting.GetPath(), WrappedRef );
1852
1853 return pCheck;
1854}
1855
1859 const TranslatableString &Prompt,
1860 const BoolSetting & Setting)
1861{
1862 wxCheckBox * pCheck=NULL;
1863
1864 auto Value = Setting.GetDefault();
1865 WrappedType WrappedRef( Value );
1866 if( DoStep(1) ) DoDataShuttle( Setting.GetPath(), WrappedRef );
1867 if( DoStep(2) ) pCheck = DoTieCheckBoxOnRight( Prompt, WrappedRef );
1868 if( DoStep(3) ) DoDataShuttle( Setting.GetPath(), WrappedRef );
1869
1870 return pCheck;
1871}
1872
1876 const TranslatableString &Prompt,
1877 const IntSetting & Setting,
1878 const int max,
1879 const int min)
1880{
1881 wxSlider * pSlider=NULL;
1882
1883 auto Value = Setting.GetDefault();
1884 WrappedType WrappedRef( Value );
1885 if( DoStep(1) ) DoDataShuttle( Setting.GetPath(), WrappedRef );
1886 if( DoStep(2) ) pSlider = DoTieSlider( Prompt, WrappedRef, max, min );
1887 if( DoStep(3) ) DoDataShuttle( Setting.GetPath(), WrappedRef );
1888
1889 return pSlider;
1890}
1891
1895 const TranslatableString &Prompt,
1896 const IntSetting &Setting,
1897 const int max,
1898 const int min)
1899{
1900 wxSpinCtrl * pSpinCtrl=NULL;
1901
1902 auto Value = Setting.GetDefault();
1903 WrappedType WrappedRef( Value );
1904 if( DoStep(1) ) DoDataShuttle( Setting.GetPath(), WrappedRef );
1905 if( DoStep(2) ) pSpinCtrl = DoTieSpinCtrl( Prompt, WrappedRef, max, min );
1906 if( DoStep(3) ) DoDataShuttle( Setting.GetPath(), WrappedRef );
1907
1908 return pSpinCtrl;
1909}
1910
1914 const TranslatableString & Prompt,
1915 const StringSetting & Setting,
1916 const int nChars)
1917{
1918 wxTextCtrl * pText=(wxTextCtrl*)NULL;
1919
1920 auto Value = Setting.GetDefault();
1921 WrappedType WrappedRef( Value );
1922 if( DoStep(1) ) DoDataShuttle( Setting.GetPath(), WrappedRef );
1923 if( DoStep(2) ) pText = DoTieTextBox( Prompt, WrappedRef, nChars );
1924 if( DoStep(3) ) DoDataShuttle( Setting.GetPath(), WrappedRef );
1925 return pText;
1926}
1927
1932 const TranslatableString & Prompt,
1933 const IntSetting &Setting,
1934 const int nChars)
1935{
1936 wxTextCtrl * pText=(wxTextCtrl*)NULL;
1937
1938 auto Value = Setting.GetDefault();
1939 WrappedType WrappedRef( Value );
1940 if( DoStep(1) ) DoDataShuttle( Setting.GetPath(), WrappedRef );
1941 if( DoStep(2) ) pText = DoTieNumericTextBox( Prompt, WrappedRef, nChars );
1942 if( DoStep(3) ) DoDataShuttle( Setting.GetPath(), WrappedRef );
1943 return pText;
1944}
1945
1950 const TranslatableString & Prompt,
1951 const DoubleSetting & Setting,
1952 const int nChars)
1953{
1954 wxTextCtrl * pText=(wxTextCtrl*)NULL;
1955
1956 auto Value = Setting.GetDefault();
1957 WrappedType WrappedRef( Value );
1958 if( DoStep(1) ) DoDataShuttle( Setting.GetPath(), WrappedRef );
1959 if( DoStep(2) ) pText = DoTieNumericTextBox( Prompt, WrappedRef, nChars );
1960 if( DoStep(3) ) DoDataShuttle( Setting.GetPath(), WrappedRef );
1961 return pText;
1962}
1963
1971 ChoiceSetting &choiceSetting)
1972{
1973 // Do this to force any needed migrations first
1974 choiceSetting.Read();
1975
1976 const auto &symbols = choiceSetting.GetSymbols();
1977 const auto &SettingName = choiceSetting.Key();
1978 const auto &Default = choiceSetting.Default().Internal();
1979 const auto &Choices = symbols.GetMsgids();
1980 const auto &InternalChoices = symbols.GetInternals();
1981
1982 wxChoice * pChoice=(wxChoice*)NULL;
1983
1984 int TempIndex=0;
1985// int TempIndex = TranslateToIndex( Default, InternalChoices );
1986 wxString TempStr = Default;
1987 WrappedType WrappedRef( TempStr );
1988 // Get from prefs does 1 and 2.
1989 // Put to prefs does 2 and 3.
1990 if( DoStep(1) ) DoDataShuttle( SettingName, WrappedRef ); // Get Index from Prefs.
1991 if( DoStep(1) ) TempIndex = TranslateToIndex( TempStr, InternalChoices ); // To an index
1992 if( DoStep(2) ) pChoice = TieChoice( Prompt, TempIndex, Choices );
1993 if( DoStep(3) ) TempStr = TranslateFromIndex( TempIndex, InternalChoices ); // To a string
1994 if( DoStep(3) ) choiceSetting.Write(TempStr); // Put into Prefs.
1995 return pChoice;
1996}
1997
2011 const TranslatableStrings & Choices,
2012 const std::vector<int> * pInternalChoices,
2013 int iNoMatchSelector)
2014{
2015 auto fn = [](int arg){ return wxString::Format( "%d", arg ); };
2016
2017 wxArrayStringEx InternalChoices;
2018 if ( pInternalChoices )
2019 InternalChoices =
2020 transform_container<wxArrayStringEx>(*pInternalChoices, fn);
2021 else
2022 for ( int ii = 0; ii < (int)Choices.size(); ++ii )
2023 InternalChoices.push_back( fn( ii ) );
2024
2025 const auto Default = Setting.GetDefault();
2026
2027 miNoMatchSelector = iNoMatchSelector;
2028
2029 long defaultIndex;
2030 if ( pInternalChoices )
2031 defaultIndex = make_iterator_range( *pInternalChoices ).index( Default );
2032 else
2033 defaultIndex = Default;
2034 if ( defaultIndex < 0 || defaultIndex >= (int)Choices.size() )
2035 defaultIndex = -1;
2036
2037 ChoiceSetting choiceSetting{
2038 Setting,
2039 {
2040 ByColumns,
2041 Choices,
2042 InternalChoices,
2043 },
2044 defaultIndex
2045 };
2046
2047 return ShuttleGuiBase::TieChoice(Prompt, choiceSetting);
2048}
2049
2050//------------------------------------------------------------------//
2051
2052// We're now into ShuttleGuiBase sizer and misc functions.
2053
2061{
2062 if( miIdSetByUser > 0)
2063 {
2065 miIdSetByUser = -1;
2066 return;
2067 }
2068 miId = miIdNext++;
2069}
2070
2072{
2073 if( miPropSetByUser >=0 )
2074 {
2076 miPropSetByUser =-1;
2077 return;
2078 }
2079 miProp = Default;
2080}
2081
2082
2084 wxWindow *pWind, wxWindow *pDlg )
2085{
2086 if ( step == 0 ) {
2087 // Do these steps before adding the window to the sizer
2088 if( item.mUseBestSize )
2089 pWind->SetMinSize( pWind->GetBestSize() );
2090 else if( item.mHasMinSize )
2091 pWind->SetMinSize( item.mMinSize );
2092
2093 if ( item.mWindowSize != wxSize{} )
2094 pWind->SetSize( item.mWindowSize );
2095 }
2096 else if ( step == 1) {
2097 // Apply certain other optional window attributes here
2098
2099 if ( item.mValidatorSetter )
2100 item.mValidatorSetter( pWind );
2101
2102 if ( !item.mToolTip.empty() )
2103 pWind->SetToolTip( item.mToolTip.Translation() );
2104
2105 if ( !item.mName.empty() ) {
2106 pWind->SetName( item.mName.Stripped().Translation() );
2107#ifndef __WXMAC__
2108 if (auto pButton = dynamic_cast< wxBitmapButton* >( pWind ))
2109 pButton->SetLabel( item.mName.Translation() );
2110#endif
2111 }
2112
2113 if ( !item.mNameSuffix.empty() )
2114 pWind->SetName(
2115 pWind->GetName() + " " + item.mNameSuffix.Translation() );
2116
2117 if (item.mFocused)
2118 pWind->SetFocus();
2119
2120 if (item.mDisabled)
2121 pWind->Enable( false );
2122
2123 for (auto &pair : item.mRootConnections)
2124 pWind->Connect( pair.first, pair.second, nullptr, pDlg );
2125 }
2126}
2127
2128
2129void ShuttleGuiBase::UpdateSizersCore(bool bPrepend, int Flags, bool prompt)
2130{
2131 if( mpWind && mpParent )
2132 {
2133 int useFlags = Flags;
2134
2135 if ( !prompt && mItem.mWindowPositionFlags )
2136 // override the given Flags
2137 useFlags = mItem.mWindowPositionFlags;
2138
2139 if (!prompt)
2140 ApplyItem( 0, mItem, mpWind, mpDlg );
2141
2142 if( mpSizer){
2143 if( bPrepend )
2144 {
2145 mpSizer->Prepend(mpWind, miProp, useFlags, miBorder);
2146 }
2147 else
2148 {
2149 mpSizer->Add(mpWind, miProp, useFlags, miBorder);
2150 }
2151 }
2152
2153 if (!prompt) {
2154 ApplyItem( 1, mItem, mpWind, mpDlg );
2155 // Reset to defaults
2156 mItem = {};
2157 }
2158 }
2159
2160 if( mpSubSizer && mpSizer )
2161 {
2162 // When adding sizers into sizers, don't add a border.
2163 // unless it's a static box sizer.
2164 wxSizer *const pSubSizer = mpSubSizer.get();
2165 if (wxDynamicCast(pSubSizer, wxStaticBoxSizer))
2166 {
2167 mpSizer->Add( mpSubSizer.release(), miSizerProp, Flags , miBorder);
2168 }
2169 else
2170 {
2171 mpSizer->Add( mpSubSizer.release(), miSizerProp, Flags ,0);//miBorder);
2172 }
2173 mpSizer = pSubSizer;
2174 PushSizer();
2175 }
2176
2177 mpWind = NULL;
2178 miProp = 0;
2179 miSizerProp =0;
2180}
2181
2182// Sizer is added into parent sizer, and will expand/shrink.
2184{ UpdateSizersCore( false, wxEXPAND | wxALL );}
2185
2186// Sizer is added into parent sizer, centred
2188{ UpdateSizersCore( false, wxALIGN_CENTRE | wxALL );}
2189
2190// Sizer is added into parent sizer, and will expand/shrink.
2191// added to start of sizer list.
2193{ UpdateSizersCore( true, wxEXPAND | wxALL );}
2194
2196{
2197 mSizerDepth--;
2198 wxASSERT( mSizerDepth >=0 );
2200}
2201
2203{
2204 mSizerDepth++;
2205 wxASSERT( mSizerDepth < nMaxNestedSizers );
2207}
2208
2210{
2211 if( mItem.miStyle )
2212 style = mItem.miStyle;
2213 mItem.miStyle = 0;
2214 return style;
2215}
2216
2217// A rarely used helper function that sets a pointer
2218// ONLY if the value it is to be set to is non NULL.
2219void SetIfCreated( wxChoice * &Var, wxChoice * Val )
2220{
2221 if( Val != NULL )
2222 Var = Val;
2223};
2224void SetIfCreated( wxTextCtrl * &Var, wxTextCtrl * Val )
2225{
2226 if( Val != NULL )
2227 Var = Val;
2228};
2229void SetIfCreated( wxStaticText *&Var, wxStaticText * Val )
2230{
2231 if( Val != NULL )
2232 Var = Val;
2233};
2234
2236 wxWindow * pParent, teShuttleMode ShuttleMode, bool vertical, wxSize minSize)
2237 : ShuttleGuiBase( pParent, ShuttleMode, vertical, minSize )
2238{
2239 if( ShuttleMode == eIsCreatingFromPrefs )
2240 {
2242 Init( vertical, minSize ); // Wasn't fully done in base constructor because it is only done when eIsCreating is set.
2243 }
2244 else if( ShuttleMode == eIsSavingToPrefs )
2245 {
2247 }
2248 else
2249 {
2250 return;
2251 }
2252
2253 mpShuttle = std::make_unique<ShuttlePrefs>();
2254 // In this case the client is the GUI, so if creating we do want to
2255 // store in the client.
2256 mpShuttle->mbStoreInClient = (mShuttleMode == eIsCreating );
2257};
2258
2260{
2261}
2262
2263// Now we have Audacity specific shuttle functions.
2265{
2266 miIdSetByUser = id;
2267 return *this;
2268}
2269
2271 mpbOptionalFlag = &bVar;
2272 return *this;
2273};
2274
2275
2276std::unique_ptr<wxSizer> CreateStdButtonSizer(wxWindow *parent, long buttons, wxWindow *extra)
2277{
2278 wxASSERT(parent != NULL); // To justify safenew
2279
2280 int margin;
2281 {
2282#if defined(__WXMAC__)
2283 margin = 12;
2284#elif defined(__WXGTK20__)
2285 margin = 12;
2286#elif defined(__WXMSW__)
2287 wxButton b(parent, 0, wxEmptyString);
2288 margin = b.ConvertDialogToPixels(wxSize(2, 0)).x;
2289#else
2290 wxButton b(parent, 0, wxEmptyString);
2291 margin = b->ConvertDialogToPixels(wxSize(4, 0)).x;
2292#endif
2293 }
2294
2295 wxButton *b = NULL;
2296 auto bs = std::make_unique<wxStdDialogButtonSizer>();
2297
2298 const auto makeButton =
2299 [parent]( wxWindowID id, const wxString label = {} ) {
2300 auto result = safenew wxButton( parent, id, label );
2301 result->SetName( result->GetLabel() );
2302 return result;
2303 };
2304
2305 if( buttons & eOkButton )
2306 {
2307 b = makeButton( wxID_OK );
2308 b->SetDefault();
2309 bs->AddButton( b );
2310 }
2311
2312 if( buttons & eCancelButton )
2313 {
2314 bs->AddButton( makeButton( wxID_CANCEL ) );
2315 }
2316
2317 if( buttons & eYesButton )
2318 {
2319 b = makeButton( wxID_YES );
2320 b->SetDefault();
2321 bs->AddButton( b );
2322 }
2323
2324 if( buttons & eNoButton )
2325 {
2326 bs->AddButton( makeButton( wxID_NO ) );
2327 }
2328
2329 if( buttons & eApplyButton )
2330 {
2331 b = makeButton( wxID_APPLY );
2332 b->SetDefault();
2333 bs->AddButton( b );
2334 }
2335
2336 if( buttons & eCloseButton )
2337 {
2338 bs->AddButton( makeButton( wxID_CANCEL, XO("&Close").Translation() ) );
2339 }
2340
2341#if defined(__WXMSW__)
2342 // See below for explanation
2343 if( buttons & eHelpButton )
2344 {
2345 // Replace standard Help button with smaller icon button.
2346 // bs->AddButton(safenew wxButton(parent, wxID_HELP));
2347 b = safenew wxBitmapButton(parent, wxID_HELP, theTheme.Bitmap( bmpHelpIcon ));
2348 b->SetToolTip( XO("Help").Translation() );
2349 b->SetLabel(XO("Help").Translation()); // for screen readers
2350 b->SetName( b->GetLabel() );
2351 bs->AddButton( b );
2352 }
2353#endif
2354
2355 if (buttons & ePreviewButton)
2356 {
2357 bs->Add( makeButton( ePreviewID, XO("&Preview").Translation() ),
2358 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, margin);
2359 }
2360 if (buttons & ePreviewDryButton)
2361 {
2362 bs->Add( makeButton( ePreviewDryID, XO("Dry Previe&w").Translation() ),
2363 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, margin);
2364 bs->Add( 20, 0 );
2365 }
2366
2367 if( buttons & eSettingsButton )
2368 {
2369 bs->Add( makeButton( eSettingsID, XO("&Settings").Translation() ),
2370 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, margin);
2371 bs->Add( 20, 0 );
2372 }
2373
2374 if( extra )
2375 {
2376 bs->Add( extra, 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, margin );
2377 bs->Add( 40, 0 );
2378 }
2379
2380 bs->AddStretchSpacer();
2381 bs->Realize();
2382
2383 size_t lastLastSpacer = 0;
2384 size_t lastSpacer = 0;
2385 wxSizerItemList & list = bs->GetChildren();
2386 for( size_t i = 0, cnt = list.size(); i < cnt; i++ )
2387 {
2388 if( list[i]->IsSpacer() )
2389 {
2390 lastSpacer = i;
2391 }
2392 else
2393 {
2394 lastLastSpacer = lastSpacer;
2395 }
2396 }
2397
2398 // Add any buttons that need to cuddle up to the right hand cluster
2399 if( buttons & eDebugButton )
2400 {
2401 b = makeButton( eDebugID, XO("Debu&g").Translation() );
2402 bs->Insert( ++lastLastSpacer, b, 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, margin );
2403 }
2404
2405#if !defined(__WXMSW__)
2406 // Bug #2432: Couldn't find GTK guidelines, but Mac HIGs state:
2407 //
2408 // View style Help button position
2409 // Dialog with dismissal buttons (like OK and Cancel). Lower-left corner, vertically aligned with the dismissal buttons.
2410 // Dialog without dismissal buttons. Lower-left or lower-right corner.
2411 // Preference window or pane. Lower-left or lower-right corner.
2412 //
2413 // So, we're gonna cheat a little and use the lower-right corner.
2414 if( buttons & eHelpButton )
2415 {
2416 // Replace standard Help button with smaller icon button.
2417 // bs->AddButton(safenew wxButton(parent, wxID_HELP));
2418 b = safenew wxBitmapButton(parent, wxID_HELP, theTheme.Bitmap( bmpHelpIcon ));
2419 b->SetToolTip( XO("Help").Translation() );
2420 b->SetLabel(XO("Help").Translation()); // for screen readers
2421 b->SetName( b->GetLabel() );
2422 bs->Add( b, 0, wxALIGN_CENTER );
2423 }
2424#endif
2425
2426
2427 auto s = std::make_unique<wxBoxSizer>( wxVERTICAL );
2428 s->Add( bs.release(), 1, wxEXPAND | wxALL, 7 );
2429 s->Add( 0, 3 ); // a little extra space
2430
2431 return std::unique_ptr<wxSizer>{ s.release() };
2432}
2433
2434void ShuttleGui::AddStandardButtons(long buttons, wxWindow *extra)
2435{
2436 if( mShuttleMode != eIsCreating )
2437 return;
2438
2439 StartVerticalLay( false );
2440
2441 miSizerProp = false;
2442 mpSubSizer = CreateStdButtonSizer( mpParent, buttons, extra );
2443 UpdateSizers();
2444 PopSizer();
2445
2447}
2448
2449wxSizerItem * ShuttleGui::AddSpace( int width, int height, int prop )
2450{
2451 if( mShuttleMode != eIsCreating )
2452 return NULL;
2453
2454// SetProportions(0);
2455 // return mpSizer->Add( width, height, miProp);
2456
2457 return mpSizer->Add( width, height, prop );
2458}
2459
2460void ShuttleGui::SetMinSize( wxWindow *window, const TranslatableStrings & items )
2461{
2462 SetMinSize( window,
2463 transform_container<wxArrayStringEx>(
2464 items, std::mem_fn( &TranslatableString::StrippedTranslation ) ) );
2465}
2466
2467void ShuttleGui::SetMinSize( wxWindow *window, const wxArrayStringEx & items )
2468{
2469 int maxw = 0;
2470
2471 for( size_t i = 0; i < items.size(); i++ )
2472 {
2473 int x;
2474 int y;
2475
2476 window->GetTextExtent(items[i], &x, &y );
2477 if( x > maxw )
2478 {
2479 maxw = x;
2480 }
2481 }
2482
2483 // Would be nice to know the sizes of the button and borders, but this is
2484 // the best we can do for now.
2485#if defined(__WXMAC__)
2486 maxw += 50;
2487#elif defined(__WXMSW__)
2488 maxw += 50;
2489#elif defined(__WXGTK__)
2490 maxw += 50;
2491#else
2492 maxw += 50;
2493#endif
2494
2495 window->SetMinSize( { maxw, -1 } );
2496}
2497
2498/*
2499void ShuttleGui::SetMinSize( wxWindow *window, const std::vector<int> & items )
2500{
2501 wxArrayStringEx strs;
2502
2503 for( size_t i = 0; i < items.size(); i++ )
2504 {
2505 strs.Add( wxString::Format( wxT("%d"), items[i] ) );
2506 }
2507
2508 SetMinSize( window, strs );
2509}
2510*/
2511
2513 const EnumValueSymbol strings[], size_t nStrings)
2514{
2515 return transform_range<TranslatableStrings>(
2516 strings, strings + nStrings,
2517 std::mem_fn( &EnumValueSymbol::Msgid )
2518 );
2519}
2520
2521TranslatableStrings Msgids( const std::vector<EnumValueSymbol> &strings )
2522{
2523 return Msgids( strings.data(), strings.size() );
2524}
wxT("CloseDown"))
END_EVENT_TABLE()
int min(int a, int b)
XO("Cut/Copy/Paste")
#define safenew
Definition: MemoryX.h:10
IteratorRange< Iterator > make_iterator_range(const Iterator &i1, const Iterator &i2)
Definition: MemoryX.h:448
ByColumns_t ByColumns
Definition: Prefs.cpp:474
std::unique_ptr< wxSizer > CreateStdButtonSizer(wxWindow *parent, long buttons, wxWindow *extra)
TranslatableStrings Msgids(const EnumValueSymbol strings[], size_t nStrings)
Convenience function often useful when adding choice controls.
void SetIfCreated(wxChoice *&Var, wxChoice *Val)
teShuttleMode
Definition: ShuttleGui.h:36
@ eIsSettingToDialog
Definition: ShuttleGui.h:39
@ eIsCreating
Definition: ShuttleGui.h:37
@ eIsCreatingFromPrefs
Definition: ShuttleGui.h:46
@ eIsSavingToPrefs
Definition: ShuttleGui.h:47
@ eIsGettingFromDialog
Definition: ShuttleGui.h:38
@ eIsGettingMetadata
Definition: ShuttleGui.h:40
@ ePreviewID
Definition: ShuttleGui.h:611
@ eDebugID
Definition: ShuttleGui.h:613
@ eSettingsID
Definition: ShuttleGui.h:614
@ ePreviewDryID
Definition: ShuttleGui.h:615
const int nMaxNestedSizers
Definition: ShuttleGui.h:33
wxWindow wxNotebookPage
Definition: ShuttleGui.h:60
@ eOkButton
Definition: ShuttleGui.h:594
@ eApplyButton
Definition: ShuttleGui.h:603
@ eYesButton
Definition: ShuttleGui.h:596
@ eCancelButton
Definition: ShuttleGui.h:595
@ ePreviewDryButton
Definition: ShuttleGui.h:602
@ eCloseButton
Definition: ShuttleGui.h:604
@ eHelpButton
Definition: ShuttleGui.h:598
@ eNoButton
Definition: ShuttleGui.h:597
@ ePreviewButton
Definition: ShuttleGui.h:599
@ eDebugButton
Definition: ShuttleGui.h:600
@ eSettingsButton
Definition: ShuttleGui.h:601
TranslatableString label
Definition: TagsEditor.cpp:164
THEME_API Theme theTheme
Definition: Theme.cpp:82
std::vector< TranslatableString > TranslatableStrings
int id
static const auto fn
This specialization of Setting for bool adds a Toggle method to negate the saved value.
Definition: Prefs.h:339
bool Write(const wxString &value)
Definition: Prefs.cpp:390
const wxString & Key() const
Definition: Prefs.h:432
wxString Read() const
Definition: Prefs.cpp:354
const EnumValueSymbols & GetSymbols() const
Definition: Prefs.h:434
const EnumValueSymbol & Default() const
Definition: Prefs.cpp:346
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
const wxString & Internal() const
const TranslatableString & Msgid() const
const wxString Translation() const
Specialization of Setting for double.
Definition: Prefs.h:356
Specialization of Setting for int.
Definition: Prefs.h:349
An InvisiblePanel is a panel which does not repaint its own background.
InvisiblePanel(wxWindow *parent, wxWindowID id=-1, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxTAB_TRAVERSAL)
void OnPaint(wxPaintEvent &event)
void OnErase(wxEraseEvent &)
const SettingPath & GetPath() const
Definition: Prefs.h:83
Definition: Prefs.h:173
const T & GetDefault() const
Definition: Prefs.h:192
Base class for shuttling data to and from a GUI.
Definition: ShuttleGui.h:240
wxSimplebook * StartSimplebook()
void EndVerticalLay()
wxStaticBox * StartStatic(const TranslatableString &Str, int iProp=0)
Definition: ShuttleGui.cpp:892
int GetBorder() const noexcept
Definition: ShuttleGui.cpp:195
wxNotebookPage * StartNotebookPage(const TranslatableString &Name)
long GetStyle(long Style)
wxCheckBox * AddCheckBoxOnRight(const TranslatableString &Prompt, bool Selected)
Definition: ShuttleGui.cpp:342
wxWindow *const mpDlg
Definition: ShuttleGui.h:525
void EndMultiColumn()
wxComboBox * AddCombo(const TranslatableString &Prompt, const wxString &Selected, const wxArrayStringEx &choices)
Definition: ShuttleGui.cpp:516
virtual wxTextCtrl * TieIntegerTextBox(const TranslatableString &Prompt, const IntSetting &Setting, const int nChars)
ShuttleGuiBase(wxWindow *pParent, teShuttleMode ShuttleMode, bool vertical, wxSize minSize)
Definition: ShuttleGui.cpp:127
void DoDataShuttle(const wxString &Name, WrappedType &WrappedRef)
void StartRadioButtonGroup(ChoiceSetting &Setting)
Call this before any TieRadioButton calls.
wxPanel * StartPanel(int iStyle=0)
Definition: ShuttleGui.cpp:989
void EndInvisiblePanel()
wxNotebook * StartNotebook()
wxString mRadioValueString
The index of this radio item. -1 for none.
Definition: ShuttleGui.h:572
wxSlider * TieVSlider(const TranslatableString &Prompt, float &pos, const float fMin, const float fMax)
wxCheckBox * AddCheckBox(const TranslatableString &Prompt, bool Selected)
Definition: ShuttleGui.cpp:308
wxChoice * TieChoice(const TranslatableString &Prompt, TranslatableString &Selected, const TranslatableStrings &choices)
wxPanel * StartInvisiblePanel(int border=0)
wxWindow * GetParent()
Definition: ShuttleGui.h:491
wxCheckBox * TieCheckBox(const TranslatableString &Prompt, bool &Var)
DialogDefinition::Item mItem
Definition: ShuttleGui.h:577
std::unique_ptr< ShuttlePrefs > mpShuttle
Definition: ShuttleGui.h:528
void UpdateSizersC()
void UpdateSizersAtStart()
void EndNotebookPage()
wxTextCtrl * AddTextBox(const TranslatableString &Caption, const wxString &Value, const int nChars)
Definition: ShuttleGui.cpp:637
static void ApplyItem(int step, const DialogDefinition::Item &item, wxWindow *pWind, wxWindow *pDlg)
wxTextCtrl * AddNumericTextBox(const TranslatableString &Caption, const wxString &Value, const int nChars)
Definition: ShuttleGui.cpp:673
void AddUnits(const TranslatableString &Prompt, int wrapWidth=0)
Left aligned text string.
Definition: ShuttleGui.cpp:262
int TranslateToIndex(const wxString &Value, const wxArrayStringEx &Choices)
String-to-Index.
virtual wxChoice * TieNumberAsChoice(const TranslatableString &Prompt, IntSetting &Setting, const TranslatableStrings &Choices, const std::vector< int > *pInternalChoices=nullptr, int iNoMatchSelector=0)
wxSpinCtrl * AddSpinCtrl(const TranslatableString &Prompt, int Value, int Max, int Min)
Definition: ShuttleGui.cpp:615
void EndSimplebook()
void SetStretchyRow(int i)
Used to modify an already placed FlexGridSizer to make a row stretchy.
Definition: ShuttleGui.cpp:211
void StartVerticalLay(int iProp=1)
std::vector< EnumValueSymbol > mRadioSymbols
Definition: ShuttleGui.h:568
ReadOnlyText * AddReadOnlyText(const TranslatableString &Caption, const wxString &Value)
Definition: ShuttleGui.cpp:495
wxButton * AddButton(const TranslatableString &Text, int PositionFlags=wxALIGN_CENTRE, bool setDefault=false)
Definition: ShuttleGui.cpp:359
void HandleOptionality(const TranslatableString &Prompt)
Definition: ShuttleGui.cpp:223
wxSlider * DoTieSlider(const TranslatableString &Prompt, WrappedType &WrappedRef, const int max, const int min=0)
virtual ~ShuttleGuiBase()
Definition: ShuttleGui.cpp:138
wxBitmapButton * AddBitmapButton(const wxBitmap &Bitmap, int PositionFlags=wxALIGN_CENTRE, bool setDefault=false)
Definition: ShuttleGui.cpp:378
wxListBox * AddListBox(const wxArrayStringEx &choices)
Definition: ShuttleGui.cpp:752
void EndHorizontalLay()
wxTextCtrl * AddTextWindow(const wxString &Value)
Multiline text box that grows.
Definition: ShuttleGui.cpp:711
void StartWrapLay(int PositionFlags=wxEXPAND, int iProp=0)
void Init(bool vertical, wxSize minSize)
Definition: ShuttleGui.cpp:142
wxSizer * mpSizer
Definition: ShuttleGui.h:549
void AddIcon(wxBitmap *pBmp)
Definition: ShuttleGui.cpp:867
wxTextCtrl * TieNumericTextBox(const TranslatableString &Prompt, int &Value, const int nChars=0)
wxTreeCtrl * AddTree()
Definition: ShuttleGui.cpp:853
wxCheckBox * DoTieCheckBoxOnRight(const TranslatableString &Prompt, WrappedType &WrappedRef)
wxCheckBox * TieCheckBoxOnRight(const TranslatableString &Prompt, bool &Var)
void EndRadioButtonGroup()
wxScrolledWindow * StartScroller(int iStyle=0)
Definition: ShuttleGui.cpp:937
wxRadioButton * AddRadioButton(const TranslatableString &Prompt, int selector=0, int initValue=0)
Definition: ShuttleGui.cpp:567
wxString TranslateFromIndex(const int nIn, const wxArrayStringEx &Choices)
Index-to-String.
wxGrid * AddGrid()
Definition: ShuttleGui.cpp:767
void StartHorizontalLay(int PositionFlags=wxALIGN_CENTRE, int iProp=1)
std::optional< WrappedType > mRadioValue
The setting controlled by a group.
Definition: ShuttleGui.h:570
wxSpinCtrl * TieSpinCtrl(const TranslatableString &Prompt, int &Value, const int max, const int min=0)
bool DoStep(int iStep)
wxString mRadioSettingName
Definition: ShuttleGui.h:569
ShuttleGuiBase & Prop(int iProp)
Definition: ShuttleGui.cpp:881
wxWindow * AddWindow(wxWindow *pWindow, int PositionFlags=wxALIGN_CENTRE)
Definition: ShuttleGui.cpp:298
wxCheckBox * DoTieCheckBox(const TranslatableString &Prompt, WrappedType &WrappedRef)
bool * mpbOptionalFlag
Definition: ShuttleGui.h:546
wxWindow * mpParent
Definition: ShuttleGui.h:550
void AddPrompt(const TranslatableString &Prompt, int wrapWidth=0)
Right aligned text string.
Definition: ShuttleGui.cpp:237
wxRadioButton * AddRadioButtonToGroup(const TranslatableString &Prompt, int selector=1, int initValue=0)
Definition: ShuttleGui.cpp:573
wxSpinCtrl * DoTieSpinCtrl(const TranslatableString &Prompt, WrappedType &WrappedRef, const int max, const int min=0)
wxSlider * AddSlider(const TranslatableString &Prompt, int pos, int Max, int Min=0)
Definition: ShuttleGui.cpp:588
void SetStretchyCol(int i)
Used to modify an already placed FlexGridSizer to make a column stretchy.
Definition: ShuttleGui.cpp:201
wxTextCtrl * TieTextBox(const TranslatableString &Caption, wxString &Value, const int nChars=0)
int mRadioCount
The wrapped value associated with the active radio button.
Definition: ShuttleGui.h:571
void UpdateSizersCore(bool bPrepend, int Flags, bool prompt=false)
void EndScroller()
Definition: ShuttleGui.cpp:970
wxChoice * AddChoice(const TranslatableString &Prompt, const TranslatableStrings &choices, int Selected=-1)
Definition: ShuttleGui.cpp:397
wxTextCtrl * DoTieNumericTextBox(const TranslatableString &Prompt, WrappedType &WrappedRef, const int nChars)
void StartMultiColumn(int nCols, int PositionFlags=wxALIGN_LEFT)
wxListCtrl * AddListControlReportMode(std::initializer_list< const ListControlColumn > columns={}, long listControlStyles=0)
Definition: ShuttleGui.cpp:801
wxSizer * pSizerStack[nMaxNestedSizers]
Definition: ShuttleGui.h:526
void AddConstTextBox(const TranslatableString &Caption, const TranslatableString &Value)
Single line text box of fixed size.
Definition: ShuttleGui.cpp:732
wxTextCtrl * DoTieTextBox(const TranslatableString &Prompt, WrappedType &WrappedRef, const int nChars)
wxListCtrl * AddListControl(std::initializer_list< const ListControlColumn > columns={}, long listControlStyles=0)
Definition: ShuttleGui.cpp:781
teShuttleMode mShuttleMode
Used in choices to determine which item to use on no match.
Definition: ShuttleGui.h:532
void AddFixedText(const TranslatableString &Str, bool bCenter=false, int wrapWidth=0)
Definition: ShuttleGui.cpp:439
void SetProportions(int Default)
wxSlider * TieSlider(const TranslatableString &Prompt, int &pos, const int max, const int min=0)
wxStaticText * AddVariableText(const TranslatableString &Str, bool bCenter=false, int PositionFlags=0, int wrapWidth=0)
Definition: ShuttleGui.cpp:462
void AddTitle(const TranslatableString &Prompt, int wrapWidth=0)
Centred text string.
Definition: ShuttleGui.cpp:280
wxRadioButton * TieRadioButton()
This function must be within a StartRadioButtonGroup - EndRadioButtonGroup pair.
wxWindow * mpWind
Definition: ShuttleGui.h:551
void DoInsertListColumns(wxListCtrl *pListCtrl, long listControlStyles, std::initializer_list< const ListControlColumn > columns)
Definition: ShuttleGui.cpp:822
wxRadioButton * DoAddRadioButton(const TranslatableString &Prompt, int style, int selector, int initValue)
Unwrapped string value.
Definition: ShuttleGui.cpp:547
int miNoMatchSelector
Definition: ShuttleGui.h:530
std::unique_ptr< wxSizer > mpSubSizer
Definition: ShuttleGui.h:548
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:625
ShuttleGui & Id(int id)
wxSizerItem * AddSpace(int width, int height, int prop=0)
ShuttleGui & Optional(bool &bVar)
~ShuttleGui(void)
void AddStandardButtons(long buttons=eOkButton|eCancelButton, wxWindow *extra=NULL)
ShuttleGui(wxWindow *pParent, teShuttleMode ShuttleMode, bool vertical=true, wxSize minSize={ 250, 100 })
static void SetMinSize(wxWindow *window, const TranslatableStrings &items)
Specialization of Setting for strings.
Definition: Prefs.h:363
wxBitmap & Bitmap(int iIndex)
Holds a msgid for the translation catalog; may also bind format arguments.
wxString StrippedTranslation() const
wxString Translation() const
TranslatableString Stripped(unsigned options=MenuCodes) const
non-mutating, constructs another TranslatableString object
A Validator is an object which checks whether a wxVariant satisfies a certain criterion....
Definition: Validators.h:53
An alternative to using wxWindowAccessible, which in wxWidgets 3.1.1 contained GetParent() which was ...
Used in type conversions, this wrapper for ints, strings, doubles and enums provides conversions betw...
Definition: WrappedType.h:28
bool ReadAsBool()
bool IsString()
Definition: WrappedType.cpp:34
void WriteToAsInt(const int InInt)
int ReadAsInt()
Definition: WrappedType.cpp:67
void WriteToAsBool(const bool InBool)
void WriteToAsString(const wxString &InStr)
wxString ReadAsString()
Definition: WrappedType.cpp:41
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
void SetFocus() override
Definition: ShuttleGui.cpp:580
void SetFocus(const WindowPlacement &focus)
Set the window that accepts keyboard input.
Definition: BasicUI.h:352
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:150
std::function< void(wxWindow *) > mValidatorSetter
Definition: ShuttleGui.h:214
std::vector< std::pair< wxEventType, wxObjectEventFunction > > mRootConnections
Definition: ShuttleGui.h:219
TranslatableString mToolTip
Definition: ShuttleGui.h:215
TranslatableString mName
Definition: ShuttleGui.h:216
TranslatableString mNameSuffix
Definition: ShuttleGui.h:217