committed by
GitHub
175 changed files with 2928 additions and 1274 deletions
@ -1,7 +1,6 @@ |
|||
<ProjectConfiguration> |
|||
<Settings> |
|||
<DefaultTestTimeout>1000</DefaultTestTimeout> |
|||
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely> |
|||
<DefaultTestTimeout>3000</DefaultTestTimeout> |
|||
<PreviouslyBuiltSuccessfully>True</PreviouslyBuiltSuccessfully> |
|||
</Settings> |
|||
</ProjectConfiguration> |
|||
@ -1,4 +1,5 @@ |
|||
copy ..\samples\ControlCatalog.NetCore\bin\Release\netcoreapp2.0\Avalonia**.dll ~\.nuget\packages\avalonia\$args\lib\netcoreapp2.0\ |
|||
copy ..\samples\ControlCatalog.NetCore.\bin\Release\netcoreapp2.0\Avalonia**.dll ~\.nuget\packages\avalonia\$args\lib\netstandard2.0\ |
|||
copy ..\samples\ControlCatalog.NetCore.\bin\Release\netcoreapp2.0\Avalonia**.dll ~\.nuget\packages\avalonia.gtk3\$args\lib\netstandard2.0\ |
|||
copy ..\samples\ControlCatalog.NetCore.\bin\Release\netcoreapp2.0\Avalonia**.dll ~\.nuget\packages\avalonia.win32\$args\lib\netstandard2.0\ |
|||
copy ..\samples\ControlCatalog.NetCore.\bin\Release\netcoreapp2.0\Avalonia**.dll ~\.nuget\packages\avalonia.win32\$args\lib\netstandard2.0\ |
|||
copy ..\samples\ControlCatalog.NetCore.\bin\Release\netcoreapp2.0\Avalonia**.dll ~\.nuget\packages\avalonia.skia\$args\lib\netstandard2.0\ |
|||
@ -1,16 +0,0 @@ |
|||
// Copyright (c) The Avalonia Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using System.Reactive.Subjects; |
|||
|
|||
namespace Avalonia.Reactive |
|||
{ |
|||
public class AnonymousSubject<T> : AnonymousSubject<T, T>, ISubject<T> |
|||
{ |
|||
public AnonymousSubject(IObserver<T> observer, IObservable<T> observable) |
|||
: base(observer, observable) |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -1,49 +0,0 @@ |
|||
// Copyright (c) The Avalonia Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System; |
|||
using System.Reactive.Subjects; |
|||
|
|||
namespace Avalonia.Reactive |
|||
{ |
|||
public class AnonymousSubject<T, U> : ISubject<T, U> |
|||
{ |
|||
private readonly IObserver<T> _observer; |
|||
private readonly IObservable<U> _observable; |
|||
|
|||
public AnonymousSubject(IObserver<T> observer, IObservable<U> observable) |
|||
{ |
|||
_observer = observer; |
|||
_observable = observable; |
|||
} |
|||
|
|||
public void OnCompleted() |
|||
{ |
|||
_observer.OnCompleted(); |
|||
} |
|||
|
|||
public void OnError(Exception error) |
|||
{ |
|||
if (error == null) |
|||
throw new ArgumentNullException("error"); |
|||
|
|||
_observer.OnError(error); |
|||
} |
|||
|
|||
public void OnNext(T value) |
|||
{ |
|||
_observer.OnNext(value); |
|||
} |
|||
|
|||
public IDisposable Subscribe(IObserver<U> observer) |
|||
{ |
|||
if (observer == null) |
|||
throw new ArgumentNullException("observer"); |
|||
|
|||
//
|
|||
// [OK] Use of unsafe Subscribe: non-pretentious wrapping of an observable sequence.
|
|||
//
|
|||
return _observable.Subscribe/*Unsafe*/(observer); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,156 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Reactive.Disposables; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Text; |
|||
|
|||
namespace Avalonia.Utilities |
|||
{ |
|||
/// <summary>
|
|||
/// A utility class to enable deferring assignment until after property-changed notifications are sent.
|
|||
/// </summary>
|
|||
/// <typeparam name="TProperty">The type of the object that represents the property.</typeparam>
|
|||
/// <typeparam name="TSetRecord">The type of value with which to track the delayed assignment.</typeparam>
|
|||
class DeferredSetter<TProperty, TSetRecord> |
|||
where TProperty: class |
|||
{ |
|||
private struct NotifyDisposable : IDisposable |
|||
{ |
|||
private readonly SettingStatus status; |
|||
|
|||
internal NotifyDisposable(SettingStatus status) |
|||
{ |
|||
this.status = status; |
|||
status.Notifying = true; |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
status.Notifying = false; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Information on current setting/notification status of a property.
|
|||
/// </summary>
|
|||
private class SettingStatus |
|||
{ |
|||
public bool Notifying { get; set; } |
|||
|
|||
private Queue<TSetRecord> pendingValues; |
|||
|
|||
public Queue<TSetRecord> PendingValues |
|||
{ |
|||
get |
|||
{ |
|||
return pendingValues ?? (pendingValues = new Queue<TSetRecord>()); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private readonly ConditionalWeakTable<TProperty, SettingStatus> setRecords = new ConditionalWeakTable<TProperty, SettingStatus>(); |
|||
|
|||
/// <summary>
|
|||
/// Mark the property as currently notifying.
|
|||
/// </summary>
|
|||
/// <param name="property">The property to mark as notifying.</param>
|
|||
/// <returns>Returns a disposable that when disposed, marks the property as done notifying.</returns>
|
|||
private NotifyDisposable MarkNotifying(TProperty property) |
|||
{ |
|||
Contract.Requires<InvalidOperationException>(!IsNotifying(property)); |
|||
|
|||
return new NotifyDisposable(setRecords.GetOrCreateValue(property)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Check if the property is currently notifying listeners.
|
|||
/// </summary>
|
|||
/// <param name="property">The property.</param>
|
|||
/// <returns>If the property is currently notifying listeners.</returns>
|
|||
private bool IsNotifying(TProperty property) |
|||
=> setRecords.TryGetValue(property, out var value) && value.Notifying; |
|||
|
|||
/// <summary>
|
|||
/// Add a pending assignment for the property.
|
|||
/// </summary>
|
|||
/// <param name="property">The property.</param>
|
|||
/// <param name="value">The value to assign.</param>
|
|||
private void AddPendingSet(TProperty property, TSetRecord value) |
|||
{ |
|||
Contract.Requires<InvalidOperationException>(IsNotifying(property)); |
|||
|
|||
setRecords.GetOrCreateValue(property).PendingValues.Enqueue(value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Checks if there are any pending assignments for the property.
|
|||
/// </summary>
|
|||
/// <param name="property">The property to check.</param>
|
|||
/// <returns>If the property has any pending assignments.</returns>
|
|||
private bool HasPendingSet(TProperty property) |
|||
{ |
|||
return setRecords.TryGetValue(property, out var status) && status.PendingValues.Count != 0; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the first pending assignment for the property.
|
|||
/// </summary>
|
|||
/// <param name="property">The property to check.</param>
|
|||
/// <returns>The first pending assignment for the property.</returns>
|
|||
private TSetRecord GetFirstPendingSet(TProperty property) |
|||
{ |
|||
return setRecords.GetOrCreateValue(property).PendingValues.Dequeue(); |
|||
} |
|||
|
|||
public delegate bool SetterDelegate<TValue>(TSetRecord record, ref TValue backing, Action<Action> notifyCallback); |
|||
|
|||
/// <summary>
|
|||
/// Set the property and notify listeners while ensuring we don't get into a stack overflow as happens with #855 and #824
|
|||
/// </summary>
|
|||
/// <param name="property">The property to set.</param>
|
|||
/// <param name="backing">The backing field for the property</param>
|
|||
/// <param name="setterCallback">
|
|||
/// A callback that actually sets the property.
|
|||
/// The first parameter is the value to set, and the second is a wrapper that takes a callback that sends the property-changed notification.
|
|||
/// </param>
|
|||
/// <param name="value">The value to try to set.</param>
|
|||
public bool SetAndNotify<TValue>( |
|||
TProperty property, |
|||
ref TValue backing, |
|||
SetterDelegate<TValue> setterCallback, |
|||
TSetRecord value) |
|||
{ |
|||
Contract.Requires<ArgumentNullException>(setterCallback != null); |
|||
if (!IsNotifying(property)) |
|||
{ |
|||
bool updated = false; |
|||
if (!object.Equals(value, backing)) |
|||
{ |
|||
updated = setterCallback(value, ref backing, notification => |
|||
{ |
|||
using (MarkNotifying(property)) |
|||
{ |
|||
notification(); |
|||
} |
|||
}); |
|||
} |
|||
while (HasPendingSet(property)) |
|||
{ |
|||
updated |= setterCallback(GetFirstPendingSet(property), ref backing, notification => |
|||
{ |
|||
using (MarkNotifying(property)) |
|||
{ |
|||
notification(); |
|||
} |
|||
}); |
|||
} |
|||
return updated; |
|||
} |
|||
else if(!object.Equals(value, backing)) |
|||
{ |
|||
AddPendingSet(property, value); |
|||
} |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
@ -1 +1 @@ |
|||
Subproject commit d50ae8335eb50d4b9606de6f5fa1cbbc78bfd72f |
|||
Subproject commit c0664014455392ac221a765e66f9837704339b6f |
|||
@ -0,0 +1,24 @@ |
|||
using System; |
|||
using System.Runtime.Serialization; |
|||
|
|||
namespace Avalonia.Markup.Xaml |
|||
{ |
|||
public class XamlLoadException: Exception |
|||
{ |
|||
public XamlLoadException() |
|||
{ |
|||
} |
|||
|
|||
protected XamlLoadException(SerializationInfo info, StreamingContext context): base(info, context) |
|||
{ |
|||
} |
|||
|
|||
public XamlLoadException(string message): base(message) |
|||
{ |
|||
} |
|||
|
|||
public XamlLoadException(string message, Exception innerException): base(message, innerException) |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue