]> git.lyx.org Git - lyx.git/blobdiff - src/support/Changer.h
Let paragraph::requestSpellcheck() consider contained insets
[lyx.git] / src / support / Changer.h
index 2de7520341789cf9b860ed20b92aafe41694b477..4c790526650283d86ae34994f58fa1c465bb28f2 100644 (file)
 
 namespace lyx {
 
-// Forward declaration for support/RefChanger.h
 struct Revertible {
-       virtual ~Revertible() {}
-       virtual void revert() {}
-       virtual void keep() {}
+       virtual ~Revertible() = default;
 };
 
-//for gcc 4.6
-//using Changer = unique_ptr<Revertible>;
-typedef unique_ptr<Revertible> Changer;
+using Changer = unique_ptr<Revertible>;
 
 
+/// A RefChanger records the current value of \param ref, allowing to
+/// temporarily assign new values to it.  The original value is restored
+/// automatically when the object is destroyed, unless it is disabled.
+///
+/// RefChanger is movable, and doing so prolongs the duration of the temporary
+/// assignment. This allows classes to supply their own changer methods.
+///
+/// Naturally, be careful not to extend the life of a RefChanger beyond that of
+/// the reference it modifies. The RefChanger can be disabled by calling
+/// ->keep() or ->revert(). Once disabled, the reference is never accessed
+/// again.
+template<typename X>
+class RevertibleRef : public Revertible {
+public:
+       RevertibleRef(X & ref) : ref(ref), old(ref), enabled(true) {}
+       //
+       ~RevertibleRef() override { revert(); }
+       //
+       void revert() { if (enabled) { enabled = false; ref = old; } }
+       //
+       void keep() { enabled = false; }
+       //
+       X & ref;
+       X const old;
+private:
+       bool enabled;
+};
+
+
+template <typename X>
+using RefChanger = unique_ptr<RevertibleRef<X>>;
+
+
+/// Saves the value of \param ref in a movable object
+template <typename X>
+inline RefChanger<X> make_save(X & ref)
+{
+       return make_unique<RevertibleRef<X>>(ref);
+}
+
+inline Changer noChange()
+{
+       return Changer();
+}
+
+/// Temporarily assign value val to reference ref.
+/// To apply the change conditionally, one can write:
+///     Changer dummy = (cond) ? changeVar(ref, val) : noChange();
+template <typename X>
+inline RefChanger<X> changeVar(X & ref, X const val)
+{
+       auto rc = make_save(ref);
+       ref = val;
+       return rc;
+}
+
 } // namespace lyx
 
+
 #endif //LYX_CHANGER_H