Skip to content

Commit

Permalink
#5532: Refactoring to reduce code duplication
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed Mar 21, 2021
1 parent fdd8a4c commit 5d371ca
Showing 1 changed file with 45 additions and 75 deletions.
120 changes: 45 additions & 75 deletions radiant/ui/materials/Binding.h
Expand Up @@ -36,19 +36,33 @@ class Binding
{}
};

template<typename Source, typename Target>
template<typename Source, typename Target, typename ValueType>
class TwoWayBinding :
public Binding<Source>
{
private:
std::function<Target()> _acquireTarget;
public:
using LoadFunc = std::function<ValueType(const Source&)>;
using UpdateFunc = std::function<void(const Target&, ValueType)>;
using AcquireTargetFunc = std::function<Target()>;
using PostUpdateFunc = std::function<void()>;

protected:
LoadFunc _loadValue;
AcquireTargetFunc _acquireTarget;
UpdateFunc _updateValue;
PostUpdateFunc _postUpdate;

protected:
bool _blockUpdates;

protected:
TwoWayBinding(const std::function<Target()>& acquireTarget) :
TwoWayBinding(const LoadFunc& loadValue,
const AcquireTargetFunc& acquireTarget,
const UpdateFunc& updateValue,
const PostUpdateFunc& postChangeNotify = PostUpdateFunc()) :
_loadValue(loadValue),
_acquireTarget(acquireTarget),
_updateValue(updateValue),
_blockUpdates(false)
{}

Expand All @@ -61,26 +75,6 @@ class TwoWayBinding :

return _acquireTarget();
}
};

template<typename ValueType>
class TwoWayMaterialBinding :
public TwoWayBinding<MaterialPtr, MaterialPtr>
{
protected:
std::function<ValueType(const MaterialPtr&)> _getValue;
std::function<void(const MaterialPtr&, ValueType)> _updateValue;
std::function<void()> _postChangeNotify;

public:
TwoWayMaterialBinding(const std::function<ValueType(const MaterialPtr&)>& loadFunc,
const std::function<void(const MaterialPtr&, ValueType)>& saveFunc,
const std::function<void()>& postChangeNotify = std::function<void()>()) :
TwoWayBinding([this] { return getSource(); }),
_getValue(loadFunc),
_updateValue(saveFunc),
_postChangeNotify(postChangeNotify)
{}

protected:
// Just load the given value into the control
Expand All @@ -90,13 +84,13 @@ class TwoWayMaterialBinding :
{
util::ScopedBoolLock lock(_blockUpdates);

if (!getSource())
if (!Binding<Source>::getSource())
{
setValueOnControl(ValueType());
return;
}

setValueOnControl(_getValue(getSource()));
setValueOnControl(_loadValue(Binding<Source>::getSource()));
}

virtual void updateValueOnTarget(const ValueType& newValue)
Expand All @@ -106,66 +100,42 @@ class TwoWayMaterialBinding :
if (target)
{
_updateValue(target, newValue);
}

if (_postChangeNotify)
{
_postChangeNotify();
if (_postUpdate)
{
_postUpdate();
}
}
}
};

template<typename ValueType>
class TwoWayStageBinding :
public TwoWayBinding<IShaderLayer::Ptr, IEditableShaderLayer::Ptr>
class TwoWayMaterialBinding :
public TwoWayBinding<MaterialPtr, MaterialPtr, ValueType>
{
protected:
std::function<ValueType(const IShaderLayer::Ptr&)> _getValue;
std::function<void(const IEditableShaderLayer::Ptr&, ValueType)> _updateValue;
std::function<void()> _postChangeNotify;

public:
TwoWayStageBinding(const std::function<ValueType(const IShaderLayer::Ptr&)>& loadFunc,
const std::function<IEditableShaderLayer::Ptr()>& acquireSaveTarget,
const std::function<void(const IEditableShaderLayer::Ptr&, ValueType)>& saveFunc,
const std::function<void()>& postChangeNotify = std::function<void()>()) :
TwoWayBinding(acquireSaveTarget),
_getValue(loadFunc),
_updateValue(saveFunc),
_postChangeNotify(postChangeNotify)
{}
using BaseBinding = TwoWayBinding<MaterialPtr, MaterialPtr, ValueType>;

protected:
// Just load the given value into the control
virtual void setValueOnControl(const ValueType& value) = 0;

virtual void updateFromSource() override
{
util::ScopedBoolLock lock(_blockUpdates);

if (!getSource())
{
setValueOnControl(ValueType());
return;
}

setValueOnControl(_getValue(getSource()));
}

virtual void updateValueOnTarget(const ValueType& newValue)
{
auto target = getTarget();
TwoWayMaterialBinding(const typename BaseBinding::LoadFunc& loadValue,
const typename BaseBinding::UpdateFunc& updateValue,
const typename BaseBinding::PostUpdateFunc& postChangeNotify = PostUpdateFunc()) :
BaseBinding(loadValue, [this] { return getSource(); }, updateValue, postChangeNotify)
{}
};

if (target)
{
_updateValue(target, newValue);
}
template<typename ValueType>
class TwoWayStageBinding :
public TwoWayBinding<IShaderLayer::Ptr, IEditableShaderLayer::Ptr, ValueType>
{
public:
using BaseBinding = TwoWayBinding<IShaderLayer::Ptr, IEditableShaderLayer::Ptr, ValueType>;

if (_postChangeNotify)
{
_postChangeNotify();
}
}
TwoWayStageBinding(const typename BaseBinding::LoadFunc& loadValue,
const typename BaseBinding::AcquireTargetFunc& acquireSaveTarget,
const typename BaseBinding::UpdateFunc& updateValue,
const typename BaseBinding::PostUpdateFunc& postChangeNotify = typename BaseBinding::PostUpdateFunc()) :
BaseBinding(loadValue, acquireSaveTarget, updateValue, postChangeNotify)
{}
};

template<typename Source>
Expand Down

0 comments on commit 5d371ca

Please sign in to comment.