ScopedValueSaver - never worry about App State again

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.

1 Like