//////////////////////////////////////////////////////////////////////////////////////////////////// // NoesisGUI - http://www.noesisengine.com // Copyright (c) Noesis Technologies S.L. All Rights Reserved. //////////////////////////////////////////////////////////////////////////////////////////////////// #ifndef __GUI_FREEZABLE_H__ #define __GUI_FREEZABLE_H__ #include #include #include #include namespace Noesis { //////////////////////////////////////////////////////////////////////////////////////////////////// /// Type of change occurred in the freezable //////////////////////////////////////////////////////////////////////////////////////////////////// enum FreezableEventReason: int32_t { FreezableEventReason_Frozen, FreezableEventReason_PropertyChanged }; NS_WARNING_PUSH NS_MSVC_WARNING_DISABLE(4251 4275) //////////////////////////////////////////////////////////////////////////////////////////////////// /// Defines an object that has a modifiable state and a read-only (frozen) state. /// /// Classes that derive from Freezable provide detailed change notification, can be made immutable, /// and can clone themselves. The Freezable class provides special features that can help improve /// application performance when using objects that are expensive to modify or copy. /// /// A class that derives from Freezable gains the following features: /// /// * Special states: a read-only (frozen) state and a writable state. /// * Thread safety: a frozen Freezable object can be shared across threads. /// * Detailed change notification: Unlike other DependencyObject objects, a Freezable object /// provides change notifications when sub-property values change /// * Easy cloning: the Freezable class has already implemented several methods that produce /// deep clones /// /// https://docs.microsoft.com/en-us/dotnet/api/system.windows.freezable //////////////////////////////////////////////////////////////////////////////////////////////////// class NS_GUI_DEPENDENCYSYSTEM_API Freezable: public DependencyObject, public ISealable { public: Freezable(); virtual ~Freezable() = 0; /// Gets a value that indicates whether the object can be made unmodifiable. /// \prop bool CanFreeze() const; /// Gets a value that indicates whether the object is currently modifiable. /// \prop bool IsFrozen() const; /// Makes the current object unmodifiable and sets its IsFrozen property to true. void Freeze(); /// Creates a modifiable clone of the Freezable, making deep copies of the object's values. /// When copying the object's dependency properties, this method copies expressions (which /// might no longer resolve) but not animations or their current values. /// The cloned Freezable::IsFrozen property is false even if the source's IsFrozen property is /// true. /// \note The cloned element is not initialized Ptr Clone() const; /// Creates a modifiable clone (deep copy) of the Freezable using its current values. /// The cloned object's IsFrozen property is false even if the source's IsFrozen property is /// true. /// \note The cloned element is not initialized Ptr CloneCurrentValue() const; /// Creates a frozen copy of the Freezable, using base (non-animated) property values. Because /// the copy is frozen, any frozen sub-objects are copied by reference. /// The copy's IsFrozen property is set to true. /// Throws if the Freezable cannot be frozen because it contains expressions or animated /// properties. /// \note The cloned element is not initialized Ptr GetAsFrozen() const; /// Creates a frozen copy of the Freezable using current property values. Because the copy is /// frozen, any frozen sub-objects are copied by reference. /// The copy's IsFrozen property is set to true. /// \note The cloned element is not initialized Ptr GetCurrentValueAsFrozen() const; /// Occurs when the Freezable or an object it contains is modified. typedef Delegate FreezableChangedEvent; FreezableChangedEvent& Changed(); /// From ISealable //@{ bool CanSeal() const final override; bool IsSealed() const final override; void Seal() final override; //@} NS_IMPLEMENT_INTERFACE_FIXUP protected: /// Makes the Freezable object unmodifiable or tests whether it can be made unmodifiable. virtual bool FreezeCore(bool isChecking); /// Makes the instance a clone (deep copy) of the specified Freezable using base (non-animated) /// property values. virtual void CloneCore(const Freezable* source); /// Makes the instance a modifiable clone (deep copy) of the specified Freezable using current /// property values. virtual void CloneCurrentValueCore(const Freezable* source); /// Makes the instance a frozen clone of the specified Freezable using base (non-animated) /// property values. virtual void GetAsFrozenCore(const Freezable* source); /// Makes the current instance a frozen clone of the specified Freezable. If the object has /// animated dependency properties, their current animated values are copied. virtual void GetCurrentValueAsFrozenCore(const Freezable* source); /// Called at the end of CloneCommon (this implies this method is called at the end of /// CloneCore, CloneCurrentValueCore, GetAsFrozenValue and GetCurrentValueAsFrozenCore virtual void CloneCommonCore(const Freezable* source); /// When implemented in a derived class, creates a new instance of the Freezable derived class. virtual Ptr CreateInstanceCore() const = 0; /// Called when the current Freezable object is modified. virtual void OnChanged(FreezableEventReason reason); /// Raises modification event void RaiseEvent(FreezableEventReason reason); /// From DependencyObject //@{ bool OnPropertyChanged(const DependencyPropertyChangedEventArgs& e) override; //@} private: void CloneCommon(const Freezable* source, bool useBaseValue, bool cloneFreezables); private: FreezableChangedEvent mFreezableChangedEvent; NS_DECLARE_REFLECTION(Freezable, DependencyObject) }; NS_WARNING_POP } #endif