just wanted to add how this is useful.
so, in your standard project that you need to save/load settings from, you might have this:
struct Foo
{
private:
ApplicationProperties props;
void initProperties();
void loadParams();
void saveParams();
int paramA{0};
float paramB{0.f};
bool paramC{false};
implemented thusly:
void Foo::initProperties()
{
PropertiesFile::Options options;
options.applicationName = ProjectInfo::projectName;
options.filenameSuffix = ".settings";
options.osxLibrarySubFolder = "Application Support";
options.folderName = String(ProjectInfo::companyName) + File::separatorString + String(ProjectInfo::projectName);
options.storageFormat = PropertiesFile::storeAsXML;
props.setStorageParameters(options);
}
loading is accomplished like this:
void Foo::loadParams()
{
String pA = props.getProperties().getUserSettings()->getValue("paramA",
"0");
var tempVar = VariantConverter<String>::toVar(pA);
paramA = VariantConverter<int>::fromVar( tempVar );
String pB = props.getProperties().getUserSettings()->getValue("paramB",
"0");
tempVar = VariantConverter<String>::toVar(pB);
paramB = VariantConverter<float>::fromVar( tempVar );
String pC = props.getProperties().getUserSettings()->getValue("paramC",
"0");
tempVar = VariantConverter<String>::toVar(pC);
paramC = VariantConverter<bool>::fromVar( tempVar );
}
and saving is accomplished like this:
void Foo::saveParams()
{
var pA(paramA);
props.getProperties().getUserSettings()->setValue("paramA",
pA);
var pB(paramB);
props.getProperties().getUserSettings()->setValue("paramB",
pB);
var pC(paramC);
props.getProperties().getUserSettings()->setValue("paramC",
pC);
}
very boring, boilerplate-ish code that’s tedious to implement, and easy to forget to include a parameter in your saved settings.
now, because those params are private members, if you need to access them or change them, you gotta add getters/setters to your class. and if you want something to happen when you modify them, you gotta do it manually:
void setParamA( int i ) { paramA = i; doSomethingWithA(); }
int getParamA() { return paramA; }
void setParamB( float f ) { paramB = f; doSomethingWithB(); }
float getParamB() { return paramB; }
void setParamC( bool b ) { paramC = b; doSomethingWithC(); }
bool getParamC() { return paramC; }
Accessing them from an outside class also sucks:
struct Bar
{
Bar(Foo& foo_) : i( foo_.getParamA() ), foo( foo_ ) { }
void update() { if( foo.getParamC() ) { doSomethingAmazing(); }
private:
int& i;
Foo& foo;
};
So, this is all you do with ScopedValueSaver:
struct Foo
{
Foo() {}
~Foo() {}
auto& getParamA() { return paramA; }
auto& getParamC() { return paramC; }
private:
ScopedValueSaver<int> paramA{"paramA", 0, [this](Value&) { doSomethingWithA(); } }
ScopedValueSaver<float> paramB{"paramB", 0.f, [this](Value&) { doSomethingWithB(); } }
ScopedValueSaver<float> paramC{"paramC", false, [this](Value&) { doSomethingWithC(); } }
};
struct Bar
{
Bar(Foo& f) :
svsBool(f.getParamC(),
"svsBool",
[this](Value& v) { if( v == svsBool ) { this->doSomethingAmazing(); } )
{
}
ScopedValueSaver<bool> svsBool;
void doSomethingAmazing()
{
DBG( "amazing" );
svsBool = true; //Foo::paramC is now true
}
};
and, when you quit the app, paramC
is saved as true. the next time you run it, paramC
is restored as true
, even though it was initialized the first time the program was run as false
.