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