using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using Artemis.Storage.Entities.Profile.DataBindings; namespace Artemis.Core; /// public class DataBinding : IDataBinding { private readonly List _properties = new(); private bool _disposed; private bool _isEnabled; private DataBindingNodeScript _script; internal DataBinding(LayerProperty layerProperty) { LayerProperty = layerProperty; Entity = new DataBindingEntity(); _script = new DataBindingNodeScript(GetScriptName(), "The value to put into the data binding", this, LayerProperty.ProfileElement.Profile); Save(); } internal DataBinding(LayerProperty layerProperty, DataBindingEntity entity) { LayerProperty = layerProperty; Entity = entity; _script = new DataBindingNodeScript(GetScriptName(), "The value to put into the data binding", this, LayerProperty.ProfileElement.Profile); // Load will add children so be initialized before that Load(); } /// /// Gets the layer property this data binding targets /// public LayerProperty LayerProperty { get; } /// /// Gets the data binding entity this data binding uses for persistent storage /// public DataBindingEntity Entity { get; } /// /// Updates the pending values of this data binding /// public void Update() { if (_disposed) throw new ObjectDisposedException("DataBinding"); if (!IsEnabled) return; // TODO: Update the 'base value' node Script.Run(); } /// /// Registers a data binding property so that is available to the data binding system /// /// The type of the layer property /// The function to call to get the value of the property /// The action to call to set the value of the property /// The display name of the data binding property public DataBindingProperty RegisterDataBindingProperty(Func getter, Action setter, string displayName) { if (_disposed) throw new ObjectDisposedException("DataBinding"); if (Properties.Any(d => d.DisplayName == displayName)) throw new ArtemisCoreException($"A data binding property named '{displayName}' is already registered."); DataBindingProperty property = new(getter, setter, displayName); _properties.Add(property); OnDataBindingPropertyRegistered(); return property; } /// /// Removes all data binding properties so they are no longer available to the data binding system /// public void ClearDataBindingProperties() { if (_disposed) throw new ObjectDisposedException("LayerProperty"); _properties.Clear(); OnDataBindingPropertiesCleared(); } /// /// Releases the unmanaged resources used by the object and optionally releases the managed resources. /// /// /// to release both managed and unmanaged resources; /// to release only unmanaged resources. /// protected virtual void Dispose(bool disposing) { if (disposing) { _disposed = true; _isEnabled = false; Script.Dispose(); } } /// /// Invokes the event /// protected virtual void OnDataBindingPropertyRegistered() { DataBindingPropertyRegistered?.Invoke(this, new DataBindingEventArgs(this)); } /// /// Invokes the event /// protected virtual void OnDataBindingPropertiesCleared() { DataBindingPropertiesCleared?.Invoke(this, new DataBindingEventArgs(this)); } /// /// Invokes the event /// protected virtual void OnDataBindingEnabled(DataBindingEventArgs e) { DataBindingEnabled?.Invoke(this, e); } /// /// Invokes the event /// protected virtual void OnDataBindingDisabled(DataBindingEventArgs e) { DataBindingDisabled?.Invoke(this, e); } private string GetScriptName() { return LayerProperty.PropertyDescription.Name ?? LayerProperty.Path; } /// public INodeScript Script => _script; /// public ILayerProperty BaseLayerProperty => LayerProperty; /// public bool IsEnabled { get => _isEnabled; set { _isEnabled = value; if (_isEnabled) OnDataBindingEnabled(new DataBindingEventArgs(this)); else OnDataBindingDisabled(new DataBindingEventArgs(this)); } } /// public ReadOnlyCollection Properties => _properties.AsReadOnly(); /// public void Apply() { if (_disposed) throw new ObjectDisposedException("DataBinding"); if (!IsEnabled) return; _script.DataBindingExitNode.ApplyToDataBinding(); } /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// public event EventHandler? DataBindingPropertyRegistered; /// public event EventHandler? DataBindingPropertiesCleared; /// public event EventHandler? DataBindingEnabled; /// public event EventHandler? DataBindingDisabled; #region Storage /// public void Load() { if (_disposed) throw new ObjectDisposedException("DataBinding"); IsEnabled = Entity.IsEnabled; } /// public void LoadNodeScript() { _script.Dispose(); _script = Entity.NodeScript != null ? new DataBindingNodeScript(GetScriptName(), "The value to put into the data binding", this, Entity.NodeScript, LayerProperty.ProfileElement.Profile) : new DataBindingNodeScript(GetScriptName(), "The value to put into the data binding", this, LayerProperty.ProfileElement.Profile); } /// public void Save() { if (_disposed) throw new ObjectDisposedException("DataBinding"); Entity.IsEnabled = IsEnabled; if (_script.ExitNodeConnected || _script.Nodes.Count() > 1) { _script.Save(); Entity.NodeScript = _script.Entity; } else { Entity.NodeScript = null; } } #endregion }