#ifndef CHROME_BROWSER_VR_DATABINDING_BINDING_H_
#define CHROME_BROWSER_VR_DATABINDING_BINDING_H_
#include <memory>
#include <optional>
#include "base/functional/bind.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/vr/databinding/binding_base.h"
namespace vr {
template <typename T>
class Binding : public BindingBase {
public:
#ifndef NDEBUG
Binding(const base::RepeatingCallback<T()>& getter,
const std::string& getter_text,
const base::RepeatingCallback<void(const T&)>& setter,
const std::string& setter_text)
: getter_(getter),
setter_(setter),
getter_text_(getter_text),
setter_text_(setter_text) {}
Binding(const base::RepeatingCallback<T()>& getter,
const std::string& getter_text,
const base::RepeatingCallback<void(const std::optional<T>&,
const T&)>& setter,
const std::string& setter_text)
: getter_(getter),
historic_setter_(setter),
getter_text_(getter_text),
setter_text_(setter_text) {}
#else
Binding(const base::RepeatingCallback<T()>& getter,
const base::RepeatingCallback<void(const T&)>& setter)
: getter_(getter), setter_(setter) {}
Binding(const base::RepeatingCallback<T()>& getter,
const base::RepeatingCallback<void(const std::optional<T>&,
const T&)>& setter)
: getter_(getter), historic_setter_(setter) {}
#endif
Binding(const Binding&) = delete;
Binding& operator=(const Binding&) = delete;
~Binding() override = default;
bool Update() override {
T current_value = getter_.Run();
if (last_value_ && current_value == last_value_.value())
return false;
if (setter_)
setter_.Run(current_value);
if (historic_setter_)
historic_setter_.Run(last_value_, current_value);
last_value_ = current_value;
return true;
}
std::string ToString() override {
#ifndef NDEBUG
if (getter_text_.empty() && setter_text_.empty())
return "";
return base::StringPrintf("%s => %s", getter_text_.c_str(),
setter_text_.c_str());
#else
return "";
#endif
}
private:
base::RepeatingCallback<T()> getter_;
base::RepeatingCallback<void(const T&)> setter_;
base::RepeatingCallback<void(const std::optional<T>&, const T&)>
historic_setter_;
std::optional<T> last_value_;
#ifndef NDEBUG
std::string getter_text_;
std::string setter_text_;
#endif
};
#ifndef NDEBUG
#define VR_BIND(T, M, m, Get, V, v, Set) \
std::make_unique<Binding<T>>( \
base::BindRepeating([](M* model) { return Get; }, base::Unretained(m)), \
#Get, \
base::BindRepeating([](V* view, T const& value) { Set; }, \
base::Unretained(v)), \
#Set)
#else
#define VR_BIND(T, M, m, Get, V, v, Set) \
std::make_unique<Binding<T>>( \
base::BindRepeating([](M* model) { return Get; }, base::Unretained(m)), \
base::BindRepeating([](V* view, T const& value) { Set; }, \
base::Unretained(v)))
#endif
#define VR_BIND_FUNC(T, M, m, Get, V, v, f) \
VR_BIND(T, M, m, Get, V, v, view->f(value))
#define VR_BIND_FIELD(T, M, m, Get, V, v, f) \
VR_BIND(T, M, m, Get, V, v, view->f = value)
#ifndef NDEBUG
#define VR_BIND_LAMBDA(...) base::BindRepeating(__VA_ARGS__), #__VA_ARGS__
#else
#define VR_BIND_LAMBDA(...) base::BindRepeating(__VA_ARGS__)
#endif
}
#endif