2018-07-19 00:19:51 +03:00
using System ;
2017-01-13 00:55:01 +03:00
using System.Collections.Generic ;
2017-07-11 21:45:10 +03:00
using System.Threading.Tasks ;
2017-01-13 00:55:01 +03:00
namespace Xamarin.PropertyEditing
{
public class EditorPropertyChangedEventArgs
: EventArgs
{
2017-01-13 01:43:11 +03:00
/// <param name="property">The property that was updated, or <c>null</c> if a full refresh is required.</param>
2018-08-17 23:41:47 +03:00
public EditorPropertyChangedEventArgs ( IPropertyInfo property , PropertyVariation variation = null )
2017-01-13 00:55:01 +03:00
{
Property = property ;
2018-08-17 23:41:47 +03:00
Variation = variation ;
2017-01-13 00:55:01 +03:00
}
2017-01-24 00:58:33 +03:00
/// <summary>
/// Gets the property that was changed, or <c>null</c> for a full refresh.
/// </summary>
2017-01-13 00:55:01 +03:00
public IPropertyInfo Property
{
get ;
}
2018-08-14 23:27:42 +03:00
/// <summary>
/// Gets the variation that was changed, if any.
/// </summary>
2018-08-17 23:41:47 +03:00
public PropertyVariation Variation
2018-08-14 23:27:42 +03:00
{
get ;
}
2017-01-13 00:55:01 +03:00
}
public interface IObjectEditor
{
2017-01-26 04:21:36 +03:00
/// <summary>
/// Gets the target object being edited.
/// </summary>
object Target { get ; }
2017-09-08 23:11:40 +03:00
/// <summary>
2018-06-23 01:09:16 +03:00
/// Gets the real type of the <see cref="Target"/>.
2017-09-08 23:11:40 +03:00
/// </summary>
2018-06-23 01:09:16 +03:00
ITypeInfo TargetType { get ; }
2017-09-08 23:11:40 +03:00
2017-01-13 00:55:01 +03:00
/// <remarks>
/// 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.
/// </remarks>
IReadOnlyCollection < IPropertyInfo > Properties { get ; }
2018-05-15 22:06:33 +03:00
/// <summary>
/// Gets a mapping between known properties (such as CommonBrush.Opacity) and their provider counterparts.
/// </summary>
/// <remarks>
/// Should only include known properties present in <see cref="Properties"/>. Can be <c>null</c> if there are none.
/// </remarks>
2018-06-27 21:46:05 +03:00
IReadOnlyDictionary < IPropertyInfo , KnownProperty > KnownProperties { get ; }
2018-05-15 22:06:33 +03:00
2017-01-24 00:58:33 +03:00
/// <summary>
/// Gets the parent object editor for the object this editor represents or <c>null</c> if none.
/// </summary>
2017-01-13 00:55:01 +03:00
IObjectEditor Parent { get ; }
/// <remarks>
/// 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
2018-08-14 21:53:00 +03:00
/// iOS property chooser itself can be mapped to having an object editor for its actual object.
2017-01-13 00:55:01 +03:00
/// </remarks>
IReadOnlyList < IObjectEditor > DirectChildren { get ; }
2017-01-24 00:58:33 +03:00
/// <summary>
/// Raised when a property's value changes. <see cref="EditorPropertyChangedEventArgs.Property"/> can be <c>null</c> for a full refresh.
/// </summary>
2017-01-13 00:55:01 +03:00
event EventHandler < EditorPropertyChangedEventArgs > PropertyChanged ;
2018-04-17 23:06:04 +03:00
/// <param name="property">The property to get retrieve assignable types for.</param>
/// <param name="childTypes">Whether or not to return assignable types for a property's children rather than the property itself.</param>
/// <returns>An <see cref="AssignableTypesResult"/> instance containing the assignable types. No assignable types should use an empty array and not return <c>null</c>.</returns>
Task < AssignableTypesResult > GetAssignableTypesAsync ( IPropertyInfo property , bool childTypes ) ;
2017-12-08 23:16:02 +03:00
2017-07-11 21:45:10 +03:00
/ *
* 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 .
* /
2018-08-14 23:27:42 +03:00
/// <summary>
2018-08-17 23:41:47 +03:00
/// Gets or sets variations of <paramref name="property"/> values.
2018-08-14 23:27:42 +03:00
/// </summary>
/// <param name="property"></param>
/// <returns>
2018-08-17 23:41:47 +03:00
/// Each <see cref="PropertyVariation"/> that has a value defined for the given <paramref name="property"/>.
2018-08-14 23:27:42 +03:00
/// No variation set should be returned for a neutral value, it's assumed there is one.
/// </returns>
2018-08-17 23:41:47 +03:00
Task < IReadOnlyCollection < PropertyVariation > > GetPropertyVariantsAsync ( IPropertyInfo property ) ;
/// <summary>
/// Removes a variant version of a property.
/// </summary>
Task RemovePropertyVariantAsync ( IPropertyInfo property , PropertyVariation variant ) ;
2018-07-19 00:19:51 +03:00
2018-01-30 21:38:20 +03:00
/// <remarks>
/// <para>For the <see cref="ValueSource.Default"/> or <see cref="ValueSource.Unset"/> sources, implementers should
/// ignore <paramref name="value"/>'s <see cref="ValueInfo{T}.Value"/> 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.</para>
/// <para>When <paramref name="value"/>'s <see cref="ValueInfo{T}.Source"/> is <see cref="ValueSource.Resource"/>,
2018-07-13 18:54:33 +03:00
/// the <see cref="ValueInfo{T}.SourceDescriptor"/> will be set to a <see cref="Resource"/> instance. Implementers
2018-07-19 00:19:51 +03:00
/// need not see whether the resource contains a value itself. For a source of <see cref="ValueSource.Binding"/>,
/// the <see cref="ValueInfo{T}.SourceDescriptor"/> will be the binding object created.</para>
/// <para>When the <paramref name="property"/>'s <see cref="IPropertyInfo.Type"/> is an <c>object</c>
/// <see cref="ValueInfo{T}.ValueDescriptor"/> will contain an <see cref="ITypeInfo"/> representing the real type
/// of the value.</para>
2018-02-02 00:20:04 +03:00
/// <para>When the <see cref="ValueInfo{T}.Source"/> is <see cref="ValueSource.Local"/> and <see cref="ValueInfo{T}.Value"/>
/// is the same as the default value, implementers should consider unsetting the value such that the subsequent
2018-08-17 23:41:47 +03:00
/// <see cref="GetValueAsync{T}(IPropertyInfo, PropertyVariation)"/> would return <see cref="ValueSource.Default"/>
2018-02-02 00:20:04 +03:00
/// for <see cref="ValueInfo{T}.Source"/>. 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 <see cref="ValueSource.Unset"/>.</para>
2018-01-30 21:38:20 +03:00
/// <para>Before the returned task completes, in order:
2018-08-17 23:41:47 +03:00
/// 1. <see cref="GetValueAsync{T}(IPropertyInfo, PropertyVariation)"/> must be able to retrieve the new value.
2018-01-30 21:38:20 +03:00
/// 2. <see cref="PropertyChanged"/> should fire with the appropriate property.
/// For defensive purposes, consumers will not assume the <paramref name="value"/> they pass in will be the same
/// as the new value and as a result will re-query the value upon the assumed <see cref="PropertyChanged"/> firing.
/// There should not be a case where <see cref="PropertyChanged"/> is not fired when SetValueAsync is called, consumers
/// will do basic verification before calling. Even <see cref="ValueInfo{T}.Source"/> changes with the value staying the
/// same is a change in the property.
/// </para>
2018-08-14 23:27:42 +03:00
/// <para>
2018-08-17 23:41:47 +03:00
/// For <paramref name="variations"/>, a set call for a <see cref="PropertyVariation"/> that is not yet set should be
2018-08-14 23:27:42 +03:00
/// considered a "create new variation" call. Similarly, a call in which <paramref name="value"/>'s source is <see cref="ValueSource.Unset"/>
/// should be considered a "delete variation" call when <paramref name="variations"/> is set.
/// </para>
2018-01-30 21:38:20 +03:00
/// </remarks>
2018-08-17 23:41:47 +03:00
Task SetValueAsync < T > ( IPropertyInfo property , ValueInfo < T > value , PropertyVariation variations = null ) ;
2017-01-24 00:58:33 +03:00
2018-01-30 21:38:20 +03:00
/// <remarks>
/// <para>Implementers should strive to include the actual value of resources or bindings for <see cref="ValueInfo{T}.Value"/>
2018-08-14 21:53:00 +03:00
/// wherever possible.</para>
2018-01-30 21:38:20 +03:00
/// <para>If the platform can know the value of a property when unset, it should return that value and the <see cref="ValueSource.Default"/>
/// source. If the platform only knows that the value is unset, use <see cref="ValueSource.Unset"/> instead.</para>
2018-07-19 00:19:51 +03:00
///<para>When the property's value <see cref="ValueInfo{T}.Source"/> is <see cref="ValueSource.Resource"/>,
/// the <see cref="ValueInfo{T}.SourceDescriptor"/> should be set to a <see cref="Resource"/> instance. Implementers should
2018-07-19 00:43:28 +03:00
/// strive to retrieve the resource's value and use <see cref="Resource{T}"/> instead. For a source of
2018-07-19 00:19:51 +03:00
/// <see cref="ValueSource.Binding"/>, the <see cref="ValueInfo{T}.SourceDescriptor"/> will be the binding object created.</para>
/// <para>When the <paramref name="property"/>'s <see cref="IPropertyInfo.Type"/> is an <c>object</c>
/// <see cref="ValueInfo{T}.ValueDescriptor"/> should contain an <see cref="ITypeInfo"/> representing the real type
/// of the value.</para>
2018-01-30 21:38:20 +03:00
/// </remarks>
2017-01-24 00:58:33 +03:00
/// <exception cref="ArgumentNullException"><paramref name="property"/> is <c>null</c>.</exception>
2018-08-17 23:41:47 +03:00
Task < ValueInfo < T > > GetValueAsync < T > ( IPropertyInfo property , PropertyVariation variations = null ) ;
2017-01-13 00:55:01 +03:00
}
}