fa59903e1881208cd6539008a6aadfad7b76e2a6
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / internal / XamlBinding / ImageSource.cs
1 using System;
2 using System.IO;
3 using System.Reflection;
4 using System.Threading;
5 using System.Threading.Tasks;
6
7 namespace Tizen.NUI.Binding
8 {
9     [TypeConverter(typeof(ImageSourceConverter))]
10     internal abstract class ImageSource : Element
11     {
12         readonly object _synchandle = new object();
13         CancellationTokenSource _cancellationTokenSource;
14
15         TaskCompletionSource<bool> _completionSource;
16
17         readonly WeakEventManager _weakEventManager = new WeakEventManager();
18
19         protected ImageSource()
20         {
21         }
22
23         protected CancellationTokenSource CancellationTokenSource
24         {
25             get { return _cancellationTokenSource; }
26             private set
27             {
28                 if (_cancellationTokenSource == value)
29                     return;
30                 if (_cancellationTokenSource != null)
31                     _cancellationTokenSource.Cancel();
32                 _cancellationTokenSource = value;
33             }
34         }
35
36         bool IsLoading
37         {
38             get { return _cancellationTokenSource != null; }
39         }
40
41         public virtual Task<bool> Cancel()
42         {
43             if (!IsLoading)
44                 return Task.FromResult(false);
45
46             var tcs = new TaskCompletionSource<bool>();
47             TaskCompletionSource<bool> original = Interlocked.CompareExchange(ref _completionSource, tcs, null);
48             if (original == null)
49             {
50                 _cancellationTokenSource.Cancel();
51             }
52             else
53                 tcs = original;
54
55             return tcs.Task;
56         }
57
58         public static ImageSource FromFile(string file)
59         {
60             return new FileImageSource { File = file };
61         }
62
63         public static ImageSource FromResource(string resource, Type resolvingType)
64         {
65             return FromResource(resource, resolvingType.GetTypeInfo().Assembly);
66         }
67
68         public static ImageSource FromResource(string resource, Assembly sourceAssembly = null)
69         {
70 #if NETSTANDARD2_0
71             sourceAssembly = sourceAssembly ?? Assembly.GetCallingAssembly();
72 #else
73             if (sourceAssembly == null)
74             {
75                 MethodInfo callingAssemblyMethod = typeof(Assembly).GetTypeInfo().GetDeclaredMethod("GetCallingAssembly");
76                 if (callingAssemblyMethod != null)
77                 {
78                     sourceAssembly = (Assembly)callingAssemblyMethod.Invoke(null, new object[0]);
79                 }
80                 else
81                 {
82                     Internals.Log.Warning("Warning", "Can not find CallingAssembly, pass resolvingType to FromResource to ensure proper resolution");
83                     return null;
84                 }
85             }
86 #endif
87             return FromStream(() => sourceAssembly.GetManifestResourceStream(resource));
88         }
89
90         public static ImageSource FromStream(Func<Stream> stream)
91         {
92             // return new StreamImageSource { Stream = token => Task.Run(stream, token) };
93             return null;
94         }
95
96         public static ImageSource FromUri(Uri uri)
97         {
98             if (!uri.IsAbsoluteUri)
99                 throw new ArgumentException("uri is relative");
100             // return new UriImageSource { Uri = uri };
101             return null;
102         }
103
104         public static implicit operator ImageSource(string source)
105         {
106             Uri uri;
107             return Uri.TryCreate(source, UriKind.Absolute, out uri) && uri.Scheme != "file" ? FromUri(uri) : FromFile(source);
108         }
109
110         public static implicit operator ImageSource(Uri uri)
111         {
112             if (!uri.IsAbsoluteUri)
113                 throw new ArgumentException("uri is relative");
114             return FromUri(uri);
115         }
116
117         protected void OnLoadingCompleted(bool cancelled)
118         {
119             if (!IsLoading || _completionSource == null)
120                 return;
121
122             TaskCompletionSource<bool> tcs = Interlocked.Exchange(ref _completionSource, null);
123             if (tcs != null)
124                 tcs.SetResult(cancelled);
125
126             lock (_synchandle)
127             {
128                 CancellationTokenSource = null;
129             }
130         }
131
132         protected void OnLoadingStarted()
133         {
134             lock (_synchandle)
135             {
136                 CancellationTokenSource = new CancellationTokenSource();
137             }
138         }
139
140         protected void OnSourceChanged()
141         {
142             _weakEventManager.HandleEvent(this, EventArgs.Empty, nameof(SourceChanged));
143         }
144
145         internal event EventHandler SourceChanged
146         {
147             add { _weakEventManager.AddEventHandler(nameof(SourceChanged), value); }
148             remove { _weakEventManager.RemoveEventHandler(nameof(SourceChanged), value); }
149         }
150     }
151 }