/********************************************************************** Audacity: A Digital Audio Editor ShuttleGui.h James Crook Audacity is free software. This file is licensed under the wxWidgets license, see License.txt **********************************************************************/ #ifndef SHUTTLE_GUI #define SHUTTLE_GUI #include "Audacity.h" #include #include // to inherit #include "MemoryX.h" #include "WrappedType.h" // For ShuttleGuiGetDefinitions. #include "commands/CommandTargets.h" class ChoiceSetting; class wxArrayStringEx; const int nMaxNestedSizers = 20; enum teShuttleMode { eIsCreating, eIsGettingFromDialog, eIsSettingToDialog, eIsSavingViaShuttle, eIsGettingViaShuttle, eIsGettingMetadata, // Next two are only ever seen in constructor. // After that they revert to one of the modes above. // They are used to achieve 'two step' operation, // where we transfer between two shuttles in one go. eIsCreatingFromPrefs, eIsSavingToPrefs }; class wxListCtrl; class wxCheckBox; class wxChoice; class wxComboBox; class wxScrolledWindow; class wxStaticText; class wxTreeCtrl; class wxTextCtrl; class wxSlider; class wxNotebook; typedef wxWindow wxNotebookPage; // so far, any window can be a page class wxButton; class wxBitmapButton; class wxRadioButton; class wxBitmap; class wxPanel; class wxSizer; class wxSizerItem; class wxStaticBox; class wxMenuBar; class wxMenu; class wxSpinCtrl; class wxListBox; class wxGrid; class Shuttle; class WrappedType; #ifdef __WXMAC__ #include // to inherit class wxStaticBoxWrapper : public wxStaticBox // inherit to get access to m_container { public: template< typename... Args > wxStaticBoxWrapper( Args &&...args ) : wxStaticBox( std::forward(args)... ) { m_container.EnableSelfFocus(); } }; /// Fix a defect in TAB key navigation to sliders, known to happen in wxWidgets /// 3.1.1 and maybe in earlier versions class wxSliderWrapper : public wxSlider { public: using wxSlider::wxSlider; void SetFocus() override; }; #else using wxStaticBoxWrapper = wxStaticBox; using wxSliderWrapper = wxSlider; #endif class AUDACITY_DLL_API ShuttleGuiBase /* not final */ { public: ShuttleGuiBase(wxWindow * pParent,teShuttleMode ShuttleMode); virtual ~ShuttleGuiBase(); void Init(); void ResetId(); //-- Add functions. These only add a widget or 2. void HandleOptionality(const wxString &Prompt); void AddPrompt(const wxString &Prompt); void AddUnits(const wxString &Prompt); void AddTitle(const wxString &Prompt); wxWindow * AddWindow(wxWindow * pWindow, int Flags = wxALIGN_CENTRE | wxALL ); wxSlider * AddSlider(const wxString &Prompt, int pos, int Max, int Min = 0); wxSlider * AddVSlider(const wxString &Prompt, int pos, int Max); wxSpinCtrl * AddSpinCtrl(const wxString &Prompt, int Value, int Max, int Min); wxTreeCtrl * AddTree(); wxRadioButton * AddRadioButton( const wxString & Prompt ); wxRadioButton * AddRadioButtonToGroup( const wxString & Prompt); wxButton * AddButton( const wxString & Text, int PositionFlags = wxALIGN_CENTRE ); wxBitmapButton * AddBitmapButton(const wxBitmap &Bitmap, int PositionFlags = wxALIGN_CENTRE); wxStaticText * AddVariableText(const wxString &Str, bool bCenter = false, int PositionFlags = 0); wxTextCtrl * AddTextBox(const wxString &Caption, const wxString &Value, const int nChars); wxTextCtrl * AddNumericTextBox(const wxString &Caption, const wxString &Value, const int nChars); wxTextCtrl * AddTextWindow(const wxString &Value); wxListBox * AddListBox(const wxArrayStringEx &choices, long style = 0); wxListCtrl * AddListControl(); wxListCtrl * AddListControlReportMode(); wxGrid * AddGrid(); wxCheckBox * AddCheckBox( const wxString &Prompt, bool Selected); wxCheckBox * AddCheckBoxOnRight( const wxString &Prompt, bool Selected); wxComboBox * AddCombo( const wxString &Prompt, const wxString &Selected,const wxArrayStringEx & choices, long style = 0 ); wxChoice * AddChoice( const wxString &Prompt, const wxArrayStringEx &choices, int Selected = -1 ); wxMenuBar * AddMenuBar( ); wxMenu * AddMenu( const wxString & Title ); void AddIcon( wxBitmap * pBmp); void AddIconButton( const wxString & Command, const wxString & Params,wxBitmap * pBmp ); void AddFixedText( const wxString & Str, bool bCenter = false ); void AddConstTextBox( const wxString &Caption, const wxString & Value ); //-- Start and end functions. These are used for sizer, or other window containers // and create the appropriate widget. void StartHorizontalLay(int PositionFlags=wxALIGN_CENTRE, int iProp=1); void EndHorizontalLay(); void StartVerticalLay(int iProp=1); void StartVerticalLay(int PositionFlags, int iProp); void EndVerticalLay(); wxScrolledWindow * StartScroller(int iStyle=0); void EndScroller(); wxPanel * StartPanel(int iStyle=0); void EndPanel(); void StartMultiColumn(int nCols, int PositionFlags=wxALIGN_LEFT); void EndMultiColumn(); void StartTwoColumn() {StartMultiColumn(2);}; void EndTwoColumn() {EndMultiColumn();}; void StartThreeColumn(){StartMultiColumn(3);}; void EndThreeColumn(){EndMultiColumn();}; wxStaticBox * StartStatic( const wxString & Str, int iProp=0 ); void EndStatic(); wxNotebook * StartNotebook(); void EndNotebook(); wxNotebookPage * StartNotebookPage( const wxString & Name ); void StartNotebookPage( const wxString & Name, wxNotebookPage * pPage ); void EndNotebookPage(); wxPanel * StartInvisiblePanel(); void EndInvisiblePanel(); void StartRadioButtonGroup( const wxString & SettingName ); void EndRadioButtonGroup(); void StartRadioButtonGroup( const wxString & SettingName, const int iDefaultValue ); void StartRadioButtonGroup( const wxString & SettingName, const wxString &DefaultValue ); void DoDataShuttle( const wxString &Name, WrappedType & WrappedRef ); bool DoStep( int iStep ); int TranslateToIndex( const wxString &Value, const wxArrayStringEx &Choices ); wxString TranslateFromIndex( const int nIn, const wxArrayStringEx &Choices ); int TranslateToIndex( const int Value, const std::vector &Choices ); int TranslateFromIndex( const int nIn, const std::vector &Choices ); //-- Tie functions both add controls and also read/write to them. // The ones taking a 'WrappedType' are type-generic and are used by the type specific ones. wxTextCtrl * TieTextBox( const wxString &Prompt, WrappedType & WrappedRef, const int nChars); wxTextCtrl * TieTextBox( const wxString &Caption, wxString & Value, const int nChars=0); wxTextCtrl * TieTextBox( const wxString &Prompt, int &Selected, const int nChars=0); wxTextCtrl * TieTextBox( const wxString &Prompt, double &Value, const int nChars=0); wxTextCtrl * TieNumericTextBox( const wxString &Prompt, WrappedType & WrappedRef, const int nChars); wxTextCtrl * TieNumericTextBox( const wxString &Prompt, int &Value, const int nChars=0); wxTextCtrl * TieNumericTextBox( const wxString &Prompt, double &Value, const int nChars=0); wxCheckBox * TieCheckBox( const wxString &Prompt, WrappedType & WrappedRef ); wxCheckBox * TieCheckBox( const wxString &Prompt, bool & Var ); wxCheckBox * TieCheckBoxOnRight( const wxString & Prompt, WrappedType & WrappedRef ); wxCheckBox * TieCheckBoxOnRight( const wxString & Prompt, bool & Var ); wxChoice * TieChoice( const wxString &Prompt, WrappedType & WrappedRef, const wxArrayStringEx &choices ); wxChoice * TieChoice( const wxString &Prompt, wxString &Selected, const wxArrayStringEx &choices ); wxChoice * TieChoice( const wxString &Prompt, int &Selected, const wxArrayStringEx &choices ); wxSlider * TieSlider( const wxString &Prompt, WrappedType & WrappedRef, const int max, const int min = 0 ); wxSlider * TieSlider( const wxString &Prompt, int &pos, const int max, const int min = 0); wxSlider * TieSlider( const wxString &Prompt, double &pos, const double max, const double min = 0.0); wxSlider * TieSlider( const wxString &Prompt, float &pos, const float fMin, const float fMax); wxSlider * TieVSlider( const wxString &Prompt, float &pos, const float fMin, const float fMax); wxRadioButton * TieRadioButton( const wxString & Prompt, WrappedType &WrappedRef); wxRadioButton * TieRadioButton( const wxString &Prompt, const int iValue); wxRadioButton * TieRadioButton( const wxString &Prompt, const wxString &Value); wxSpinCtrl * TieSpinCtrl( const wxString &Prompt, WrappedType & WrappedRef, const int max, const int min = 0 ); wxSpinCtrl * TieSpinCtrl( const wxString &Prompt, int &Value, const int max, const int min = 0 ); //-- Variants of the standard Tie functions which do two step exchange in one go // Note that unlike the other Tie functions, ALL the arguments are const. // That's because the data is being exchanged between the dialog and mpShuttle // so it doesn't need an argument that is writeable. virtual wxCheckBox * TieCheckBox( const wxString &Prompt, const wxString &SettingName, const bool bDefault); virtual wxCheckBox * TieCheckBoxOnRight( const wxString &Prompt, const wxString &SettingName, const bool bDefault); // This one is defined in terms of the next and not virtual virtual wxChoice *TieChoice( const wxString &Prompt, ChoiceSetting &choiceSetting ); virtual wxChoice * TieChoice( const wxString &Prompt, const wxString &SettingName, const wxString &Default, const wxArrayStringEx &Choices, const wxArrayStringEx & InternalChoices ); // This overload of TieChoice should no longer be used in Preferences! // Some uses do remain in export settings dialogs. virtual wxChoice * TieChoice( const wxString &Prompt, const wxString &SettingName, const int Default, const wxArrayStringEx & Choices, const std::vector & InternalChoices ); // This overload presents what is really a numerical setting as a choice among // commonly used values, but the choice is not exhaustive because there is // also an associated control that allows entry of a user-specified value // that is arbitrary (within some bounds). // This behaves just like the previous for building dialogs, but the // behavior is different when the call is intercepted for purposes of // emitting scripting information about Preferences. virtual wxChoice * TieNumberAsChoice( const wxString &Prompt, const wxString &SettingName, const int Default, const wxArrayStringEx & Choices, const std::vector & InternalChoices ); virtual wxTextCtrl * TieTextBox( const wxString &Prompt, const wxString &SettingName, const wxString &Default, const int nChars); virtual wxTextCtrl * TieNumericTextBox( const wxString & Prompt, const wxString & SettingName, const double & Default, const int nChars); virtual wxSlider * TieSlider( const wxString & Prompt, const wxString & SettingName, const int iDefault, const int max, const int min = 0); virtual wxSpinCtrl * TieSpinCtrl( const wxString &Prompt, const wxString &SettingName, const int Value, const int max, const int min); //-- End of variants. void EnableCtrl( bool bEnable ); void SetSizeHints( int minX, int minY ); void SetBorder( int Border ) {miBorder = Border;}; void SetStyle( int Style ) {miStyle = Style;}; void SetNoMatchSelector( int iSelector ) {miNoMatchSelector = iSelector;}; void SetSizerProportion( int iProp ) {miSizerProp = iProp;}; void SetStretchyCol( int i ); void SetStretchyRow( int i ); //--Some Additions since June 2007 that don't fit in elsewhere... wxWindow * GetParent() { // This assertion justifies the use of safenew in many places where GetParent() // is used to construct a window wxASSERT(mpParent != NULL); return mpParent; } ShuttleGuiBase & Prop( int iProp ); void UseUpId(); wxSizer * GetSizer() {return mpSizer;} protected: void SetProportions( int Default ); void PushSizer(); void PopSizer(); void UpdateSizersCore( bool bPrepend, int Flags ); void UpdateSizers(); void UpdateSizersC(); void UpdateSizersAtStart(); long Style( long Style ); private: void SetSizeHints( const wxArrayStringEx & items ); public: static void SetSizeHints( wxWindow *window, const wxArrayStringEx & items ); protected: wxWindow * mpLastWind; wxWindow * mpDlg; wxSizer * pSizerStack[ nMaxNestedSizers ]; std::unique_ptr mpShuttle; /*! Controls source/destination of shuttled data. You can leave this NULL if you are shuttling to variables */ int miNoMatchSelector; //! Used in choices to determine which item to use on no match. teShuttleMode mShuttleMode; // These five are needed to handle radio button groups. wxString mSettingName; /// The setting controlled by a group. int mRadioCount; /// The index of this radio item. -1 for none. Maybe mRadioValue; /// The wrapped value associated with the active radio button. wxString mRadioValueString; /// Unwrapped string value. int mRadioValueInt; /// Unwrapped integer value. int miSizerProp; int mSizerDepth; int miBorder; long miStyle; int miProp; // See UseUpId() for explanation of these three. int miId; int miIdNext; int miIdSetByUser; // Proportion set by user rather than default. int miPropSetByUser; bool * mpbOptionalFlag; std::unique_ptr mpSubSizer; wxSizer * mpSizer; wxWindow * mpParent; wxWindow * mpWind; wxMenuBar * mpMenuBar; wxMenu * mpMenu; }; // A rarely used helper function that sets a pointer // ONLY if the value it is to be set to is non NULL. extern void SetIfCreated( wxChoice *&Var, wxChoice * Val ); extern void SetIfCreated( wxTextCtrl *&Var, wxTextCtrl * Val ); extern void SetIfCreated( wxStaticText *&Var, wxStaticText * Val ); class GuiWaveTrack; class AttachableScrollBar; class ViewInfo; #include // to get wxSB_HORIZONTAL // CreateStdButtonSizer defs...should probably move to widgets subdir enum { eOkButton = 0x0001, eCancelButton = 0x0002, eYesButton = 0x0004, eNoButton = 0x0008, eHelpButton = 0x0010, ePreviewButton = 0x0020, eDebugButton = 0x0040, eSettingsButton= 0x0080, ePreviewDryButton = 0x0100, eApplyButton = 0x0200, eCloseButton = 0x0400, }; enum { // ePreviewID = wxID_LOWEST - 1, // But there is a wxID_PREVIEW ePreviewID = wxID_PREVIEW, eDebugID = wxID_LOWEST - 2, eSettingsID = wxID_LOWEST - 3, ePreviewDryID = wxID_LOWEST - 4, eCloseID = wxID_CANCEL }; AUDACITY_DLL_API std::unique_ptr CreateStdButtonSizer( wxWindow *parent, long buttons = eOkButton | eCancelButton, wxWindow *extra = NULL ); // ShuttleGui extends ShuttleGuiBase with Audacity specific extensions. class AUDACITY_DLL_API ShuttleGui /* not final */ : public ShuttleGuiBase { public: ShuttleGui(wxWindow * pParent,teShuttleMode ShuttleMode); ~ShuttleGui(void); public: ShuttleGui & Optional( bool & bVar ); ShuttleGui & Id(int id ); // Prop() sets the proportion value, defined as in wxSizer::Add(). ShuttleGui & Prop( int iProp ){ ShuttleGuiBase::Prop(iProp); return *this;}; // Has to be here too, to return a ShuttleGui and not a ShuttleGuiBase. GuiWaveTrack * AddGuiWaveTrack( const wxString & Name); AttachableScrollBar * AddAttachableScrollBar( long style = wxSB_HORIZONTAL ); void AddStandardButtons( long buttons = eOkButton | eCancelButton, wxButton *extra = NULL ); wxSizerItem * AddSpace( int width, int height ); wxSizerItem * AddSpace( int size ) { return AddSpace( size, size ); }; teShuttleMode GetMode() { return mShuttleMode; }; }; /**************************************************************************//** \brief Shuttle that retrieves a JSON format definition of a command's parameters. ********************************************************************************/ class ShuttleGuiGetDefinition : public ShuttleGui, public CommandMessageTargetDecorator { public: ShuttleGuiGetDefinition(wxWindow * pParent,CommandMessageTarget & target ); virtual ~ShuttleGuiGetDefinition(); wxCheckBox * TieCheckBox( const wxString &Prompt, const wxString &SettingName, const bool bDefault) override; wxCheckBox * TieCheckBoxOnRight( const wxString &Prompt, const wxString &SettingName, const bool bDefault) override; wxChoice * TieChoice( const wxString &Prompt, const wxString &SettingName, const wxString &Default, const wxArrayStringEx &Choices, const wxArrayStringEx & InternalChoices ) override; // An assertion will be violated if this override is reached! wxChoice * TieChoice( const wxString &Prompt, const wxString &SettingName, const int Default, const wxArrayStringEx & Choices, const std::vector & InternalChoices) override; wxChoice * TieNumberAsChoice( const wxString &Prompt, const wxString &SettingName, const int Default, const wxArrayStringEx & Choices, const std::vector & InternalChoices) override; wxTextCtrl * TieTextBox( const wxString &Prompt, const wxString &SettingName, const wxString &Default, const int nChars) override; wxTextCtrl * TieNumericTextBox( const wxString & Prompt, const wxString & SettingName, const double & Default, const int nChars) override; wxSlider * TieSlider( const wxString & Prompt, const wxString & SettingName, const int iDefault, const int max, const int min = 0) override; wxSpinCtrl * TieSpinCtrl( const wxString &Prompt, const wxString &SettingName, const int Value, const int max, const int min) override; }; #endif