-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
ImageSource.cs
155 lines (128 loc) · 4.65 KB
/
ImageSource.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#nullable disable
using System;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.Maui.Controls
{
/// <include file="../../docs/Microsoft.Maui.Controls/ImageSource.xml" path="Type[@FullName='Microsoft.Maui.Controls.ImageSource']/Docs/*" />
[System.ComponentModel.TypeConverter(typeof(ImageSourceConverter))]
public abstract partial class ImageSource : Element
{
readonly object _synchandle = new object();
CancellationTokenSource _cancellationTokenSource;
TaskCompletionSource<bool> _completionSource;
readonly WeakEventManager _weakEventManager = new WeakEventManager();
protected ImageSource()
{
}
/// <include file="../../docs/Microsoft.Maui.Controls/ImageSource.xml" path="//Member[@MemberName='IsEmpty']/Docs/*" />
public virtual bool IsEmpty => false;
public static bool IsNullOrEmpty(ImageSource imageSource) =>
imageSource == null || imageSource.IsEmpty;
private protected CancellationTokenSource CancellationTokenSource
{
get { return _cancellationTokenSource; }
private set
{
if (_cancellationTokenSource == value)
return;
if (_cancellationTokenSource != null)
_cancellationTokenSource.Cancel();
_cancellationTokenSource = value;
}
}
bool IsLoading
{
get { return _cancellationTokenSource != null; }
}
/// <include file="../../docs/Microsoft.Maui.Controls/ImageSource.xml" path="//Member[@MemberName='Cancel']/Docs/*" />
public virtual Task<bool> Cancel()
{
if (!IsLoading)
return Task.FromResult(false);
TaskCompletionSource<bool> original = Interlocked.CompareExchange(ref _completionSource, new TaskCompletionSource<bool>(), null);
if (original is null)
{
_cancellationTokenSource.Cancel();
return Task.FromResult(false);
}
return original.Task;
}
/// <include file="../../docs/Microsoft.Maui.Controls/ImageSource.xml" path="//Member[@MemberName='FromFile']/Docs/*" />
public static ImageSource FromFile(string file)
{
return new FileImageSource { File = file };
}
/// <include file="../../docs/Microsoft.Maui.Controls/ImageSource.xml" path="//Member[@MemberName='FromResource'][2]/Docs/*" />
public static ImageSource FromResource(string resource, Type resolvingType)
{
return FromResource(resource, resolvingType.Assembly);
}
/// <include file="../../docs/Microsoft.Maui.Controls/ImageSource.xml" path="//Member[@MemberName='FromResource'][1]/Docs/*" />
public static ImageSource FromResource(string resource, Assembly sourceAssembly = null)
{
sourceAssembly = sourceAssembly ?? Assembly.GetCallingAssembly();
return FromStream(() => sourceAssembly.GetManifestResourceStream(resource));
}
/// <include file="../../docs/Microsoft.Maui.Controls/ImageSource.xml" path="//Member[@MemberName='FromStream'][1]/Docs/*" />
public static ImageSource FromStream(Func<Stream> stream)
{
return new StreamImageSource { Stream = token => Task.Run(stream, token) };
}
/// <include file="../../docs/Microsoft.Maui.Controls/ImageSource.xml" path="//Member[@MemberName='FromStream'][2]/Docs/*" />
public static ImageSource FromStream(Func<CancellationToken, Task<Stream>> stream)
{
return new StreamImageSource { Stream = stream };
}
/// <include file="../../docs/Microsoft.Maui.Controls/ImageSource.xml" path="//Member[@MemberName='FromUri']/Docs/*" />
public static ImageSource FromUri(Uri uri)
{
if (!uri.IsAbsoluteUri)
throw new ArgumentException("uri is relative");
return new UriImageSource { Uri = uri };
}
public static implicit operator ImageSource(string source)
{
Uri uri;
return Uri.TryCreate(source, UriKind.Absolute, out uri) && uri.Scheme != "file" ? FromUri(uri) : FromFile(source);
}
public static implicit operator ImageSource(Uri uri)
{
if (uri == null)
return null;
if (!uri.IsAbsoluteUri)
throw new ArgumentException("uri is relative");
return FromUri(uri);
}
private protected void OnLoadingCompleted(bool cancelled)
{
if (!IsLoading || _completionSource == null)
return;
TaskCompletionSource<bool> tcs = Interlocked.Exchange(ref _completionSource, null);
if (tcs != null)
tcs.SetResult(cancelled);
lock (_synchandle)
{
CancellationTokenSource = null;
}
}
private protected void OnLoadingStarted()
{
lock (_synchandle)
{
CancellationTokenSource = new CancellationTokenSource();
}
}
protected void OnSourceChanged()
{
_weakEventManager.HandleEvent(this, EventArgs.Empty, nameof(SourceChanged));
}
internal event EventHandler SourceChanged
{
add { _weakEventManager.AddEventHandler(value); }
remove { _weakEventManager.RemoveEventHandler(value); }
}
}
}