OSDN Git Service

PostClass.CreatedAtの型をDateTimeUtcに変更
[opentween/open-tween.git] / OpenTween / ImageListViewItem.cs
index e4380f9..43b6da6 100644 (file)
 // Boston, MA 02110-1301, USA.
 
 using System;
-using System.Drawing;
-using System.Net;
-using System.Windows.Forms;
+using System.Net.Http;
+using System.Runtime.Serialization;
 using System.Threading.Tasks;
+using System.Windows.Forms;
 
 namespace OpenTween
 {
+    [Serializable]
     public class ImageListViewItem : ListViewItem
     {
         protected readonly ImageCache imageCache;
         protected readonly string imageUrl;
 
+        /// <summary>
+        /// 状態表示に使用するアイコンのインデックスを取得・設定する。
+        /// </summary>
+        /// <remarks>
+        /// StateImageIndex は不必要な処理が挟まるため、使用しないようにする。
+        /// </remarks>
+        public int StateIndex { get; set; }
+
         private WeakReference imageReference = new WeakReference(null);
+        private Task imageTask = null;
 
         public event EventHandler ImageDownloaded;
 
@@ -47,51 +57,60 @@ namespace OpenTween
         }
 
         public ImageListViewItem(string[] items, ImageCache imageCache, string imageUrl)
-            : base(items, imageUrl)
+            : base(items)
         {
             this.imageCache = imageCache;
             this.imageUrl = imageUrl;
+            this.StateIndex = -1;
 
-            if (imageCache != null)
-            {
-                var image = imageCache.TryGetFromCache(imageUrl);
+            var image = imageCache?.TryGetFromCache(imageUrl);
+
+            if (image != null)
+                this.imageReference.Target = image;
+        }
+
+        protected ImageListViewItem(SerializationInfo info, StreamingContext context)
+            : base(info, context)
+        {
+        }
 
-                if (image == null)
-                    this.GetImageAsync();
-                else
-                    this.imageReference.Target = image;
+        public Task GetImageAsync(bool force = false)
+        {
+            if (this.imageTask == null || this.imageTask.IsCompleted)
+            {
+                this.imageTask = this.GetImageAsyncInternal(force);
             }
+
+            return this.imageTask;
         }
 
-        private Task GetImageAsync(bool force = false)
+        private async Task GetImageAsyncInternal(bool force)
         {
             if (string.IsNullOrEmpty(this.imageUrl))
-                return Task.FromResult(0);
+                return;
 
-            var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
+            if (!force && this.imageReference.Target != null)
+                return;
 
-            return this.imageCache.DownloadImageAsync(this.imageUrl, force)
-                .ContinueWith(t =>
-                {
-                    if (t.IsFaulted)
-                    {
-                        t.Exception.Flatten().Handle(x => x is WebException || x is InvalidImageException || x is TaskCanceledException);
-                        return;
-                    }
+            try
+            {
+                var image = await this.imageCache.DownloadImageAsync(this.imageUrl, force);
 
-                    this.imageReference.Target = t.Result;
+                this.imageReference.Target = image;
 
-                    if (this.ListView == null || !this.ListView.Created || this.ListView.IsDisposed)
-                        return;
+                if (this.ListView == null || !this.ListView.Created || this.ListView.IsDisposed)
+                    return;
 
-                    if (this.Index < this.ListView.VirtualListSize)
-                    {
-                        this.ListView.RedrawItems(this.Index, this.Index, true);
+                if (this.Index < this.ListView.VirtualListSize)
+                {
+                    this.ListView.RedrawItems(this.Index, this.Index, true);
 
-                        if (this.ImageDownloaded != null)
-                            this.ImageDownloaded(this, EventArgs.Empty);
-                    }
-                }, uiScheduler);
+                    this.ImageDownloaded?.Invoke(this, EventArgs.Empty);
+                }
+            }
+            catch (HttpRequestException) { }
+            catch (InvalidImageException) { }
+            catch (TaskCanceledException) { }
         }
 
         public MemoryImage Image
@@ -102,10 +121,10 @@ namespace OpenTween
             }
         }
 
-        public void RefreshImage()
+        public Task RefreshImageAsync()
         {
             this.imageReference.Target = null;
-            this.GetImageAsync(true);
+            return this.GetImageAsync(true);
         }
     }
 }