[go: up one dir, main page]

Skip to content

Commit

Permalink
Define Setting classes, bundling config path with settings value...
Browse files Browse the repository at this point in the history
... the intention being, that no string literal for a path, or its default
value, shall ever occur twice in the code, relying on long-distance coincidence
of literal values.  Instead, a named Setting object is constructed once, then
read and written.

For now, the Tie... functions in ShuttleGuiBase will take references to
implicitly constructed temporary Setting objects.  But all should later be
made static objects, and the constructors made explicit.
  • Loading branch information
Paul-Licameli committed May 17, 2021
1 parent b6c7b74 commit 5fef82d
Show file tree
Hide file tree
Showing 9 changed files with 240 additions and 52 deletions.
22 changes: 21 additions & 1 deletion src/Prefs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ bool ChoiceSetting::Write( const wxString &value )
}

EnumSettingBase::EnumSettingBase(
const wxString &key,
const SettingBase &key,
EnumValueSymbols symbols,
long defaultSymbol,

Expand Down Expand Up @@ -398,3 +398,23 @@ void PreferenceInitializer::ReinitializeAll()
for ( auto pInitializer : allInitializers() )
(*pInitializer)();
}

wxConfigBase *SettingBase::GetConfig() const
{
return gPrefs;
}

bool SettingBase::Delete()
{
auto config = GetConfig();
return config && config->DeleteEntry( GetPath() );
}

bool BoolSetting::Toggle()
{
bool value = Read();
if ( Write( !value ) )
return !value;
else
return value;
}
172 changes: 168 additions & 4 deletions src/Prefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
// the second part (after the r) indicates the number of times the prefs have been reset within the same version
#define AUDACITY_PREFS_VERSION_STRING "1.1.1r1"

#include <functional>

#include "../include/audacity/ComponentInterface.h"
#include "MemoryX.h" // for wxArrayStringEx
#include "widgets/FileConfig.h"
Expand All @@ -55,6 +57,168 @@ extern int gMenusDirty;
struct ByColumns_t{};
extern ByColumns_t ByColumns;

//! Base class for settings objects. It holds a configuration key path.
/* The constructors are non-explicit for convenience */
class AUDACITY_DLL_API SettingBase
{
public:
SettingBase( const char *path ) : mPath{ path } {}
SettingBase( const wxChar *path ) : mPath{ path } {}
SettingBase( const wxString &path ) : mPath{ path } {}

wxConfigBase *GetConfig() const;

const wxString &GetPath() const { return mPath; }

//! Delete the key if present, and return true iff it was.
bool Delete();

protected:
SettingBase( const SettingBase& ) = default;
const RegistryPath mPath;
};

//! Class template adds an in-memory cache of a value to SettingBase.
template< typename T >
class CachingSettingBase : public SettingBase
{
public:
explicit CachingSettingBase( const SettingBase &path )
: SettingBase{ path } {}
protected:
CachingSettingBase( const CachingSettingBase & ) = default;
mutable T mCurrentValue{};
mutable bool mValid{false};
};

//! Class template adds default value, read, and write methods to CachingSetingBase
template< typename T >
class Setting : public CachingSettingBase< T >
{
public:
using CachingSettingBase< T >::CachingSettingBase;

using DefaultValueFunction = std::function< T() >;

//! Usual overload supplies a default value
Setting( const SettingBase &path, const T &defaultValue )
: CachingSettingBase< T >{ path }
, mDefaultValue{ defaultValue }
{}

//! This overload causes recomputation of the default each time it is needed
Setting( const SettingBase &path, DefaultValueFunction function )
: CachingSettingBase< T >{ path }
, mFunction{ function }
{}


const T& GetDefault() const
{
if ( mFunction )
mDefaultValue = mFunction();
return mDefaultValue;
}

//! overload of Read returning a success flag
/*! The cache is unchanged if that is false */
bool Read( T *pVar ) const
{
if ( pVar && this->mValid ) {
*pVar = this->mCurrentValue;
return true;
}
const auto config = this->GetConfig();
if ( pVar && config ) {
if ((this->mValid = config->Read( this->mPath, &this->mCurrentValue )))
*pVar = this->mCurrentValue;
return this->mValid;
}
return (this->mValid = false);
}

//! overload of Read, always returning a value
/*! The value is the default stored in this in case the key is known to be absent from the config;
but it returns type T's default value if there was failure to read the config */
T Read() const
{
return ReadWithDefault( GetDefault() );
}

//! new direct use is discouraged but it may be needed in legacy code
/*! Use the given default in case the preference is not defined, which may not be the
default-default stored in this object. */
T ReadWithDefault( const T &defaultValue ) const
{
const auto config = this->GetConfig();
return config
? ( this->mValid = true, this->mCurrentValue =
config->ReadObject( this->mPath, defaultValue ) )
: T{};
}

//! Write value to config and return true if successful
bool Write( const T &value )
{
const auto config = this->GetConfig();
if ( config ) {
this->mCurrentValue = value;
return DoWrite();
}
return false;
}

//! Reset to the default value
bool Reset()
{
return Write( GetDefault() );
}

protected:
//! Write cached value to config and return true if successful
/*! (But the config object is not flushed) */
bool DoWrite( )
{
const auto config = this->GetConfig();
return this->mValid =
config ? config->Write( this->mPath, this->mCurrentValue ) : false;
}

mutable T mDefaultValue{};
const DefaultValueFunction mFunction;
};

//! This specialization of Setting for bool adds a Toggle method to negate the saved value
class BoolSetting final : public Setting< bool >
{
public:
using Setting::Setting;

//! Write the negation of the previous value, and then return the current value.
bool Toggle();
};

//! Specialization of Setting for int
class IntSetting final : public Setting< int >
{
public:
using Setting::Setting;
};

//! Specialization of Setting for double
class DoubleSetting final : public Setting< double >
{
public:
using Setting::Setting;
};

//! Specialization of Setting for strings
class StringSetting final : public Setting< wxString >
{
public:
using Setting::Setting;
};

/// A table of EnumValueSymbol that you can access by "row" with
/// operator [] but also allowing access to the "columns" of internal or
/// translated strings, and also allowing convenient column-wise construction
Expand Down Expand Up @@ -90,11 +254,11 @@ class AUDACITY_DLL_API ChoiceSetting
{
public:
ChoiceSetting(
const wxString &key,
const SettingBase &key,
EnumValueSymbols symbols,
long defaultSymbol = -1
)
: mKey{ key }
: mKey{ key.GetPath() }

, mSymbols{ std::move( symbols ) }

Expand Down Expand Up @@ -140,7 +304,7 @@ class AUDACITY_DLL_API EnumSettingBase : public ChoiceSetting
{
public:
EnumSettingBase(
const wxString &key,
const SettingBase &key,
EnumValueSymbols symbols,
long defaultSymbol,

Expand Down Expand Up @@ -175,7 +339,7 @@ class EnumSetting : public EnumSettingBase
public:

EnumSetting(
const wxString &key,
const SettingBase &key,
EnumValueSymbols symbols,
long defaultSymbol,

Expand Down
16 changes: 8 additions & 8 deletions src/ShuttleGui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1815,7 +1815,7 @@ bool ShuttleGuiBase::DoStep( int iStep )
/// between gui and stack variable and stack variable and shuttle.
wxCheckBox * ShuttleGuiBase::TieCheckBox(
const TranslatableString &Prompt,
const SettingSpec< bool > &Setting)
const BoolSetting &Setting)
{
wxCheckBox * pCheck=NULL;

Expand All @@ -1832,7 +1832,7 @@ wxCheckBox * ShuttleGuiBase::TieCheckBox(
/// between gui and stack variable and stack variable and shuttle.
wxCheckBox * ShuttleGuiBase::TieCheckBoxOnRight(
const TranslatableString &Prompt,
const SettingSpec< bool > &Setting)
const BoolSetting & Setting)
{
wxCheckBox * pCheck=NULL;

Expand All @@ -1849,7 +1849,7 @@ wxCheckBox * ShuttleGuiBase::TieCheckBoxOnRight(
/// between gui and stack variable and stack variable and shuttle.
wxSlider * ShuttleGuiBase::TieSlider(
const TranslatableString &Prompt,
const SettingSpec< int > &Setting,
const IntSetting & Setting,
const int max,
const int min)
{
Expand All @@ -1868,7 +1868,7 @@ wxSlider * ShuttleGuiBase::TieSlider(
/// between gui and stack variable and stack variable and shuttle.
wxSpinCtrl * ShuttleGuiBase::TieSpinCtrl(
const TranslatableString &Prompt,
const SettingSpec< int > &Setting,
const IntSetting &Setting,
const int max,
const int min)
{
Expand All @@ -1887,7 +1887,7 @@ wxSpinCtrl * ShuttleGuiBase::TieSpinCtrl(
/// between gui and stack variable and stack variable and shuttle.
wxTextCtrl * ShuttleGuiBase::TieTextBox(
const TranslatableString & Prompt,
const SettingSpec< wxString > &Setting,
const StringSetting & Setting,
const int nChars)
{
wxTextCtrl * pText=(wxTextCtrl*)NULL;
Expand All @@ -1905,7 +1905,7 @@ wxTextCtrl * ShuttleGuiBase::TieTextBox(
/// This one does it for double values...
wxTextCtrl * ShuttleGuiBase::TieIntegerTextBox(
const TranslatableString & Prompt,
const SettingSpec< int > &Setting,
const IntSetting &Setting,
const int nChars)
{
wxTextCtrl * pText=(wxTextCtrl*)NULL;
Expand All @@ -1923,7 +1923,7 @@ wxTextCtrl * ShuttleGuiBase::TieIntegerTextBox(
/// This one does it for double values...
wxTextCtrl * ShuttleGuiBase::TieNumericTextBox(
const TranslatableString & Prompt,
const SettingSpec< double > &Setting,
const DoubleSetting & Setting,
const int nChars)
{
wxTextCtrl * pText=(wxTextCtrl*)NULL;
Expand Down Expand Up @@ -1984,7 +1984,7 @@ wxChoice *ShuttleGuiBase::TieChoice(
/// if null, then use 0, 1, 2, ...
wxChoice * ShuttleGuiBase::TieNumberAsChoice(
const TranslatableString &Prompt,
const SettingSpec< int > &Setting,
const IntSetting & Setting,
const TranslatableStrings & Choices,
const std::vector<int> * pInternalChoices,
int iNoMatchSelector)
Expand Down
31 changes: 9 additions & 22 deletions src/ShuttleGui.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "MemoryX.h"
#include <wx/listbase.h> // for wxLIST_FORMAT_LEFT

#include "Prefs.h"
#include "WrappedType.h"

class ChoiceSetting;
Expand Down Expand Up @@ -103,20 +104,6 @@ using wxStaticBoxWrapper = wxStaticBox;
using wxSliderWrapper = wxSlider;
#endif

template< typename T > class SettingSpec {
public:
SettingSpec( const RegistryPath &path, const T &defaultValue = {} )
: mPath{ path }, mDefaultValue{ defaultValue }
{}

const RegistryPath &GetPath() const { return mPath; }
const T &GetDefault() const { return mDefaultValue; }

private:
RegistryPath mPath;
T mDefaultValue;
};

namespace DialogDefinition {

struct Item {
Expand Down Expand Up @@ -450,10 +437,10 @@ class AUDACITY_DLL_API ShuttleGuiBase /* not final */
// so it doesn't need an argument that is writeable.
virtual wxCheckBox * TieCheckBox(
const TranslatableString &Prompt,
const SettingSpec< bool > &Setting);
const BoolSetting &Setting);
virtual wxCheckBox * TieCheckBoxOnRight(
const TranslatableString &Prompt,
const SettingSpec< bool > &Setting);
const BoolSetting &Setting);

virtual wxChoice *TieChoice(
const TranslatableString &Prompt,
Expand All @@ -466,31 +453,31 @@ class AUDACITY_DLL_API ShuttleGuiBase /* not final */
// emitting scripting information about Preferences.
virtual wxChoice * TieNumberAsChoice(
const TranslatableString &Prompt,
const SettingSpec< int > &Setting,
const IntSetting &Setting,
const TranslatableStrings & Choices,
const std::vector<int> * pInternalChoices = nullptr,
int iNoMatchSelector = 0 );

virtual wxTextCtrl * TieTextBox(
const TranslatableString &Prompt,
const SettingSpec< wxString > &Setting,
const StringSetting &Setting,
const int nChars);
virtual wxTextCtrl * TieIntegerTextBox(
const TranslatableString & Prompt,
const SettingSpec< int > &Setting,
const IntSetting &Setting,
const int nChars);
virtual wxTextCtrl * TieNumericTextBox(
const TranslatableString & Prompt,
const SettingSpec< double > &Setting,
const DoubleSetting &Setting,
const int nChars);
virtual wxSlider * TieSlider(
const TranslatableString & Prompt,
const SettingSpec< int > &Setting,
const IntSetting &Setting,
const int max,
const int min = 0);
virtual wxSpinCtrl * TieSpinCtrl(
const TranslatableString &Prompt,
const SettingSpec< int > &Setting,
const IntSetting &Setting,
const int max,
const int min);
//-- End of variants.
Expand Down
Loading

0 comments on commit 5fef82d

Please sign in to comment.