using System; using System.Collections.Generic; using System.Threading.Tasks; namespace Xamarin.PropertyEditing { public class EditorPropertyChangedEventArgs : EventArgs { /// The property that was updated, or null if a full refresh is required. public EditorPropertyChangedEventArgs (IPropertyInfo property, PropertyVariation variation = null) { Property = property; Variation = variation; } /// /// Gets the property that was changed, or null for a full refresh. /// public IPropertyInfo Property { get; } /// /// Gets the variation that was changed, if any. /// public PropertyVariation Variation { get; } } public interface IObjectEditor { /// /// Gets the target object being edited. /// object Target { get; } /// /// Gets the real type of the . /// ITypeInfo TargetType { get; } /// /// These properties should be minimally equatable to the same property for another object of the same type. This includes /// for base class properties for two different derived types. /// IReadOnlyCollection Properties { get; } /// /// Gets a mapping between known properties (such as CommonBrush.Opacity) and their provider counterparts. /// /// /// Should only include known properties present in . Can be null if there are none. /// IReadOnlyDictionary KnownProperties { get; } /// /// Gets the parent object editor for the object this editor represents or null if none. /// IObjectEditor Parent { get; } /// /// These are children that do not participate in the standard element hierarchy, such as segments in a segmented control. /// Note that objects defined by editors do not need to match real objects in the real hierarchy, they can be faked. An existing /// iOS property chooser itself can be mapped to having an object editor for its actual object. /// IReadOnlyList DirectChildren { get; } /// /// Raised when a property's value changes. can be null for a full refresh. /// event EventHandler PropertyChanged; /// The property to get retrieve assignable types for. /// Whether or not to return assignable types for a property's children rather than the property itself. /// An instance containing the assignable types. No assignable types should use an empty array and not return null. Task GetAssignableTypesAsync (IPropertyInfo property, bool childTypes); /* * Dealing with async values in the context of what's possible across all target platforms is a bit complex. * While implicit safety may be able to be ensured, it would be exhaustive to reason it out and could change * at any moment, so we need an explicit safety strategy. As we make value gets and sets async, we open ourselves * to race conditions even on just the UI thread. Value changes can come from the user, or from the object editor * at any point. So, we break these changes into two categories: Blocking UI & Waiting Values. * * Anything that needs to deal with the current state of the values will Wait asynchronously on prior changes to * finish. These largely involve value changes from the object editor, which just acts as a INPC and does not * contain the value itself, so it will be safe and the latest value when queried upon reaching active state in * the wait queue (see AsyncWorkQueue). Selected objects (when >1) need to wait on values as they need to be * able to calculate the intersection values. * * Anything that needs to deal with user input will need to block its UI. We simply can't reason about the user * changing values while waiting for previous changes, because they value they're changing may change underneath * them or become invalid as a result of a prior pending change. */ /// /// Gets or sets variations of values. /// /// /// /// Each that has a value defined for the given . /// No variation set should be returned for a neutral value, it's assumed there is one. /// Task> GetPropertyVariantsAsync (IPropertyInfo property); /// /// Removes a variant version of a property. /// Task RemovePropertyVariantAsync (IPropertyInfo property, PropertyVariation variant); /// /// For the or sources, implementers should /// ignore 's property and unset the value completely. /// For XML based backings this usually means removing the attribute altogether. Implementers should not simply set /// the value to its default value as this would still be a local value and override inheritance, styles, etc. /// When 's is , /// the will be set to a instance. Implementers /// need not see whether the resource contains a value itself. For a source of , /// the will be the binding object created. /// When the 's is an object /// will contain an representing the real type /// of the value. /// When the is and /// is the same as the default value, implementers should consider unsetting the value such that the subsequent /// would return /// for . This allows users to clear the value for a property and have it remove /// the attribute for XML backed platforms without having to issue an . /// Before the returned task completes, in order: /// 1. must be able to retrieve the new value. /// 2. should fire with the appropriate property. /// For defensive purposes, consumers will not assume the they pass in will be the same /// as the new value and as a result will re-query the value upon the assumed firing. /// There should not be a case where is not fired when SetValueAsync is called, consumers /// will do basic verification before calling. Even changes with the value staying the /// same is a change in the property. /// /// /// For , a set call for a that is not yet set should be /// considered a "create new variation" call. Similarly, a call in which 's source is /// should be considered a "delete variation" call when is set. /// /// Task SetValueAsync (IPropertyInfo property, ValueInfo value, PropertyVariation variations = null); /// /// Implementers should strive to include the actual value of resources or bindings for /// wherever possible. /// If the platform can know the value of a property when unset, it should return that value and the /// source. If the platform only knows that the value is unset, use instead. ///When the property's value is , /// the should be set to a instance. Implementers should /// strive to retrieve the resource's value and use instead. For a source of /// , the will be the binding object created. /// When the 's is an object /// should contain an representing the real type /// of the value. /// /// is null. Task> GetValueAsync (IPropertyInfo property, PropertyVariation variations = null); } }