OSDN Git Service

Dictionaryの初期化にインデックス初期化子を使用する
[opentween/open-tween.git] / OpenTween / MediaSelector.cs
1 // OpenTween - Client of Twitter
2 // Copyright (c) 2014 spx (@5px)
3 // All rights reserved.
4 // 
5 // This file is part of OpenTween.
6 // 
7 // This program is free software; you can redistribute it and/or modify it
8 // under the terms of the GNU General Public License as published by the Free
9 // Software Foundation; either version 3 of the License, or (at your option)
10 // any later version.
11 // 
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 // for more details. 
16 // 
17 // You should have received a copy of the GNU General Public License along
18 // with this program. If not, see <http://www.gnu.org/licenses/>, or write to
19 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20 // Boston, MA 02110-1301, USA.
21
22 using System;
23 using System.Collections.Generic;
24 using System.ComponentModel;
25 using System.Drawing;
26 using System.Data;
27 using System.IO;
28 using System.Linq;
29 using System.Text;
30 using System.Threading.Tasks;
31 using System.Windows.Forms;
32 using OpenTween.Api;
33 using OpenTween.Connection;
34
35 namespace OpenTween
36 {
37     public partial class MediaSelector : UserControl
38     {
39         public event EventHandler BeginSelecting;
40         public event EventHandler EndSelecting;
41
42         public event EventHandler FilePickDialogOpening;
43         public event EventHandler FilePickDialogClosed;
44
45         public event EventHandler SelectedServiceChanged;
46
47         [Browsable(false)]
48         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
49         public OpenFileDialog FilePickDialog { get; set; }
50
51         /// <summary>
52         /// 選択されている投稿先名を取得する。
53         /// </summary>
54         [Browsable(false)]
55         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
56         public string ServiceName
57         {
58             get { return ImageServiceCombo.Text; }
59         }
60
61         /// <summary>
62         /// 選択されている投稿先を示すインデックスを取得する。
63         /// </summary>
64         [Browsable(false)]
65         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
66         public int ServiceIndex
67         {
68             get { return ImageServiceCombo.SelectedIndex; }
69         }
70
71         /// <summary>
72         /// 選択されている投稿先の IMediaUploadService を取得する。
73         /// </summary>
74         [Browsable(false)]
75         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
76         public IMediaUploadService SelectedService
77         {
78             get
79             {
80                 var serviceName = this.ServiceName;
81                 if (string.IsNullOrEmpty(serviceName))
82                     return null;
83
84                 IMediaUploadService service;
85                 return this.pictureService.TryGetValue(serviceName, out service) ? service : null;
86             }
87         }
88
89         /// <summary>
90         /// 指定された投稿先名から、作成済みの IMediaUploadService インスタンスを取得する。
91         /// </summary>
92         public IMediaUploadService GetService(string serviceName)
93         {
94             IMediaUploadService service;
95             this.pictureService.TryGetValue(serviceName, out service);
96             return service;
97         }
98
99         /// <summary>
100         /// 利用可能な全ての IMediaUploadService インスタンスを取得する。
101         /// </summary>
102         public ICollection<IMediaUploadService> GetServices()
103         {
104             return this.pictureService.Values;
105         }
106
107         private class SelectedMedia
108         {
109             public IMediaItem Item { get; set; }
110             public MyCommon.UploadFileType Type { get; set; }
111             public string Text { get; set; }
112
113             public SelectedMedia(IMediaItem item, MyCommon.UploadFileType type, string text)
114             {
115                 this.Item = item;
116                 this.Type = type;
117                 this.Text = text;
118             }
119
120             public SelectedMedia(string text)
121                 : this(null, MyCommon.UploadFileType.Invalid, text)
122             {
123             }
124
125             public bool IsValid
126             {
127                 get
128                 {
129                     return this.Item != null && this.Type != MyCommon.UploadFileType.Invalid;
130                 }
131             }
132
133             public string Path
134             {
135                 get
136                 {
137                     return (this.Item != null) ? this.Item.Path : "";
138                 }
139             }
140
141             public override string ToString()
142             {
143                 return this.Text;
144             }
145         }
146
147         private Dictionary<string, IMediaUploadService> pictureService;
148
149         private void CreateServices(Twitter tw, TwitterConfiguration twitterConfig)
150         {
151             if (this.pictureService != null) this.pictureService.Clear();
152             this.pictureService = null;
153
154             this.pictureService = new Dictionary<string, IMediaUploadService> {
155                 ["Twitter"] = new TwitterPhoto(tw, twitterConfig),
156                 ["img.ly"] = new imgly(tw, twitterConfig),
157                 ["yfrog"] = new yfrog(tw, twitterConfig),
158                 ["ついっぷるフォト"] = new TwipplePhoto(tw, twitterConfig),
159                 ["Imgur"] = new Imgur(tw, twitterConfig),
160                 ["Mobypicture"] = new Mobypicture(tw, twitterConfig),
161             };
162         }
163
164         public MediaSelector()
165         {
166             InitializeComponent();
167
168             this.ImageSelectedPicture.InitialImage = Properties.Resources.InitialImage;
169         }
170
171         /// <summary>
172         /// 投稿先サービスなどを初期化する。
173         /// </summary>
174         public void Initialize(Twitter tw, TwitterConfiguration twitterConfig, string svc, int? index = null)
175         {
176             CreateServices(tw, twitterConfig);
177
178             SetImageServiceCombo();
179             SetImagePageCombo();
180
181             SelectImageServiceComboItem(svc, index);
182         }
183
184         /// <summary>
185         /// 投稿先サービスを再作成する。
186         /// </summary>
187         public void Reset(Twitter tw, TwitterConfiguration twitterConfig)
188         {
189             CreateServices(tw, twitterConfig);
190
191             SetImageServiceCombo();
192         }
193
194         /// <summary>
195         /// 指定されたファイルの投稿に対応した投稿先があるかどうかを示す値を取得する。
196         /// </summary>
197         public bool HasUploadableService(string fileName, bool ignoreSize)
198         {
199             FileInfo fl = new FileInfo(fileName);
200             string ext = fl.Extension;
201             long? size = ignoreSize ? (long?)null : fl.Length;
202
203             if (IsUploadable(this.ServiceName, ext, size))
204                 return true;
205
206             foreach (string svc in ImageServiceCombo.Items)
207             {
208                 if (IsUploadable(svc, ext, size))
209                     return true;
210             }
211
212             return false;
213         }
214
215         /// <summary>
216         /// 指定された投稿先に投稿可能かどうかを示す値を取得する。
217         /// ファイルサイズの指定がなければ拡張子だけで判定する。
218         /// </summary>
219         private bool IsUploadable(string serviceName, string ext, long? size)
220         {
221             if (!string.IsNullOrEmpty(serviceName))
222             {
223                 var imageService = this.pictureService[serviceName];
224                 if (imageService.CheckFileExtension(ext))
225                 {
226                     if (!size.HasValue)
227                         return true;
228
229                     if (imageService.CheckFileSize(ext, size.Value))
230                         return true;
231                 }
232             }
233             return false;
234         }
235
236         /// <summary>
237         /// 投稿するファイルとその投稿先を選択するためのコントロールを表示する。
238         /// </summary>
239         private void BeginSelection(IMediaItem[] items)
240         {
241             if (items == null || items.Length == 0)
242             {
243                 BeginSelection();
244                 return;
245             }
246
247             var service = this.SelectedService;
248             if (service == null) return;
249
250             var count = Math.Min(items.Length, service.MaxMediaCount);
251             if (!this.Visible || count > 1)
252             {
253                 // 非表示時または複数のファイル指定は新規選択として扱う
254                 SetImagePageCombo();
255
256                 if (this.BeginSelecting != null)
257                     this.BeginSelecting(this, EventArgs.Empty);
258
259                 this.Visible = true;
260             }
261             this.Enabled = true;
262
263             if (count == 1)
264             {
265                 ImagefilePathText.Text = items[0].Path;
266                 ImageFromSelectedFile(items[0], false);
267             }
268             else
269             {
270                 for (int i = 0; i < count; i++)
271                 {
272                     var index = ImagePageCombo.Items.Count - 1;
273                     if (index == 0) ImagefilePathText.Text = items[i].Path;
274                     ImageFromSelectedFile(index, items[i], false);
275                 }
276             }
277         }
278
279         /// <summary>
280         /// 投稿するファイルとその投稿先を選択するためのコントロールを表示する(主にD&amp;D用)。
281         /// </summary>
282         public void BeginSelection(string[] fileNames)
283         {
284             if (fileNames == null || fileNames.Length == 0)
285             {
286                 BeginSelection();
287                 return;
288             }
289
290             var items = fileNames.Select(x => CreateFileMediaItem(x, false)).OfType<IMediaItem>().ToArray();
291             BeginSelection(items);
292         }
293
294         /// <summary>
295         /// 投稿するファイルとその投稿先を選択するためのコントロールを表示する。
296         /// </summary>
297         public void BeginSelection(Image image)
298         {
299             if (image == null)
300             {
301                 BeginSelection();
302                 return;
303             }
304
305             var items = new [] { CreateMemoryImageMediaItem(image, false) }.OfType<IMediaItem>().ToArray();
306             BeginSelection(items);
307         }
308
309         /// <summary>
310         /// 投稿するファイルとその投稿先を選択するためのコントロールを表示する。
311         /// </summary>
312         public void BeginSelection()
313         {
314             if (!this.Visible)
315             {
316                 if (this.BeginSelecting != null)
317                     this.BeginSelecting(this, EventArgs.Empty);
318
319                 this.Visible = true;
320                 this.Enabled = true;
321
322                 var media = (SelectedMedia)ImagePageCombo.SelectedItem;
323                 ImageFromSelectedFile(media.Item, true);
324                 ImagefilePathText.Focus();
325             }
326         }
327
328         /// <summary>
329         /// 選択処理を終了してコントロールを隠す。
330         /// </summary>
331         public void EndSelection()
332         {
333             if (this.Visible)
334             {
335                 ImagefilePathText.CausesValidation = false;
336
337                 if (this.EndSelecting != null)
338                     this.EndSelecting(this, EventArgs.Empty);
339
340                 this.Visible = false;
341                 this.Enabled = false;
342                 ClearImageSelectedPicture();
343
344                 ImagefilePathText.CausesValidation = true;
345             }
346         }
347
348         /// <summary>
349         /// 選択された投稿先名と投稿する MediaItem を取得する。MediaItem は不要になったら呼び出し側にて破棄すること。
350         /// </summary>
351         public bool TryGetSelectedMedia(out string imageService, out IMediaItem[] mediaItems)
352         {
353             var validItems = ImagePageCombo.Items.Cast<SelectedMedia>()
354                              .Where(x => x.IsValid).Select(x => x.Item).OfType<IMediaItem>().ToArray();
355
356             if (validItems.Length > 0 &&
357                 ImageServiceCombo.SelectedIndex > -1)
358             {
359                 var serviceName = this.ServiceName;
360                 if (MessageBox.Show(string.Format(Properties.Resources.PostPictureConfirm1, serviceName, validItems.Length),
361                                    Properties.Resources.PostPictureConfirm2,
362                                    MessageBoxButtons.OKCancel,
363                                    MessageBoxIcon.Question,
364                                    MessageBoxDefaultButton.Button1)
365                                == DialogResult.OK)
366                 {
367                     //収集した MediaItem が破棄されないように、予め null を代入しておく
368                     foreach (SelectedMedia media in ImagePageCombo.Items)
369                     {
370                         if (media != null) media.Item = null;
371                     }
372
373                     imageService = serviceName;
374                     mediaItems = validItems;
375                     EndSelection();
376                     SetImagePageCombo();
377                     return true;
378                 }
379             }
380             else
381             {
382                 MessageBox.Show(Properties.Resources.PostPictureWarn1, Properties.Resources.PostPictureWarn2);
383             }
384
385             EndSelection();
386             imageService = null;
387             mediaItems = null;
388             return false;
389         }
390
391         private IMediaItem CreateMemoryImageMediaItem(Image image, bool noMsgBox)
392         {
393             if (image == null) return null;
394
395             try
396             {
397                 return new MemoryImageMediaItem(image);
398             }
399             catch
400             {
401                 if (!noMsgBox) MessageBox.Show("Unable to create MemoryImage.");
402                 return null;
403             }
404         }
405
406         private IMediaItem CreateFileMediaItem(string path, bool noMsgBox)
407         {
408             if (string.IsNullOrEmpty(path)) return null;
409
410             try
411             {
412                 return new FileMediaItem(path);
413             }
414             catch
415             {
416                 if (!noMsgBox) MessageBox.Show("Invalid file path: " + path);
417                 return null;
418             }
419         }
420
421         private void ValidateNewFileMediaItem(string path, bool noMsgBox)
422         {
423             var media = (SelectedMedia)ImagePageCombo.SelectedItem;
424             var item = media.Item;
425
426             if (path != media.Path)
427             {
428                 DisposeMediaItem(media.Item);
429                 media.Item = null;
430
431                 item = CreateFileMediaItem(path, noMsgBox);
432             }
433
434             ImagefilePathText.Text = path;
435             ImageFromSelectedFile(item, noMsgBox);
436         }
437
438         private void DisposeMediaItem(IMediaItem item)
439         {
440             if (item != null)
441             {
442                 var disposableItem = item as IDisposable;
443                 if (disposableItem != null) disposableItem.Dispose();
444             }
445         }
446
447         private void FilePickButton_Click(object sender, EventArgs e)
448         {
449             var service = this.SelectedService;
450
451             if (FilePickDialog == null || service == null) return;
452             FilePickDialog.Filter = service.SupportedFormatsStrForDialog;
453             FilePickDialog.Title = Properties.Resources.PickPictureDialog1;
454             FilePickDialog.FileName = "";
455
456             if (this.FilePickDialogOpening != null)
457                 this.FilePickDialogOpening(this, EventArgs.Empty);
458
459             try
460             {
461                 if (FilePickDialog.ShowDialog() == DialogResult.Cancel) return;
462             }
463             finally
464             {
465                 if (this.FilePickDialogClosed != null)
466                     this.FilePickDialogClosed(this, EventArgs.Empty);
467             }
468
469             ValidateNewFileMediaItem(FilePickDialog.FileName, false);
470         }
471
472         private void ImagefilePathText_Validating(object sender, CancelEventArgs e)
473         {
474             if (ImageCancelButton.Focused)
475             {
476                 ImagefilePathText.CausesValidation = false;
477                 return;
478             }
479
480             ValidateNewFileMediaItem(ImagefilePathText.Text.Trim(), false);
481         }
482
483         private void ImageFromSelectedFile(IMediaItem item, bool noMsgBox)
484         {
485             ImageFromSelectedFile(-1, item, noMsgBox);
486         }
487
488         private void ImageFromSelectedFile(int index, IMediaItem item, bool noMsgBox)
489         {
490             var valid = false;
491
492             try
493             {
494                 var imageService = this.SelectedService;
495                 if (imageService == null) return;
496
497                 var selectedIndex = ImagePageCombo.SelectedIndex;
498                 if (index < 0) index = selectedIndex;
499
500                 if (index >= ImagePageCombo.Items.Count)
501                     throw new ArgumentOutOfRangeException(nameof(index));
502
503                 var isSelectedPage = (index == selectedIndex);
504
505                 if (isSelectedPage)
506                     this.ClearImageSelectedPicture();
507
508                 if (item == null || string.IsNullOrEmpty(item.Path)) return;
509
510                 try
511                 {
512                     var ext = item.Extension;
513                     var size = item.Size;
514
515                     if (!imageService.CheckFileExtension(ext))
516                     {
517                         //画像以外の形式
518                         if (!noMsgBox)
519                         {
520                             MessageBox.Show(
521                                 string.Format(Properties.Resources.PostPictureWarn3, this.ServiceName, MakeAvailableServiceText(ext, size), ext, item.Name),
522                                 Properties.Resources.PostPictureWarn4,
523                                 MessageBoxButtons.OK,
524                                 MessageBoxIcon.Warning);
525                         }
526                         return;
527                     }
528
529                     if (!imageService.CheckFileSize(ext, size))
530                     {
531                         // ファイルサイズが大きすぎる
532                         if (!noMsgBox)
533                         {
534                             MessageBox.Show(
535                                 string.Format(Properties.Resources.PostPictureWarn5, this.ServiceName, MakeAvailableServiceText(ext, size), item.Name),
536                                 Properties.Resources.PostPictureWarn4,
537                                 MessageBoxButtons.OK,
538                                 MessageBoxIcon.Warning);
539                         }
540                         return;
541                     }
542
543                     if (item.IsImage)
544                     {
545                         if (isSelectedPage)
546                             ImageSelectedPicture.Image = item.CreateImage();
547                         SetImagePage(index, item, MyCommon.UploadFileType.Picture);
548                     }
549                     else
550                     {
551                         SetImagePage(index, item, MyCommon.UploadFileType.MultiMedia);
552                     }
553
554                     valid = true;  //正常終了
555                 }
556                 catch (FileNotFoundException)
557                 {
558                     if (!noMsgBox) MessageBox.Show("File not found.");
559                 }
560                 catch (Exception)
561                 {
562                     if (!noMsgBox) MessageBox.Show("The type of this file is not image.");
563                 }
564             }
565             finally
566             {
567                 if (!valid)
568                 {
569                     ClearImagePage(index);
570                     DisposeMediaItem(item);
571                 }
572             }
573         }
574
575         private string MakeAvailableServiceText(string ext, long fileSize)
576         {
577             var text = string.Join(", ",
578                 ImageServiceCombo.Items.Cast<string>()
579                     .Where(serviceName =>
580                         !string.IsNullOrEmpty(serviceName) &&
581                         this.pictureService[serviceName].CheckFileExtension(ext) &&
582                         this.pictureService[serviceName].CheckFileSize(ext, fileSize)));
583
584             if (string.IsNullOrEmpty(text))
585                 return Properties.Resources.PostPictureWarn6;
586
587             return text;
588         }
589
590         private void ClearImageSelectedPicture()
591         {
592             var oldImage = this.ImageSelectedPicture.Image;
593             if (oldImage != null)
594             {
595                 this.ImageSelectedPicture.Image = null;
596                 oldImage.Dispose();
597             }
598
599             this.ImageSelectedPicture.ShowInitialImage();
600         }
601
602         private void ImageCancelButton_Click(object sender, EventArgs e)
603         {
604             EndSelection();
605         }
606
607         private void ImageSelection_KeyDown(object sender, KeyEventArgs e)
608         {
609             if (e.KeyCode == Keys.Escape)
610             {
611                 EndSelection();
612             }
613         }
614
615         private void ImageSelection_KeyPress(object sender, KeyPressEventArgs e)
616         {
617             if (Convert.ToInt32(e.KeyChar) == 0x1B)
618             {
619                 ImagefilePathText.CausesValidation = false;
620                 e.Handled = true;
621             }
622         }
623
624         private void ImageSelection_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
625         {
626             if (e.KeyCode == Keys.Escape)
627             {
628                 ImagefilePathText.CausesValidation = false;
629             }
630         }
631
632         private void SetImageServiceCombo()
633         {
634             using (ControlTransaction.Update(ImageServiceCombo))
635             {
636                 string svc = "";
637                 if (ImageServiceCombo.SelectedIndex > -1) svc = ImageServiceCombo.Text;
638                 ImageServiceCombo.Items.Clear();
639
640                 // Add service names to combobox
641                 foreach (var key in pictureService.Keys)
642                 {
643                     ImageServiceCombo.Items.Add(key);
644                 }
645
646                 SelectImageServiceComboItem(svc);
647             }
648         }
649
650         private void SelectImageServiceComboItem(string svc, int? index = null)
651         {
652             int idx;
653             if (string.IsNullOrEmpty(svc))
654             {
655                 idx = index ?? 0;
656             }
657             else
658             {
659                 idx = ImageServiceCombo.Items.IndexOf(svc);
660                 if (idx == -1) idx = index ?? 0;
661             }
662
663             try
664             {
665                 ImageServiceCombo.SelectedIndex = idx;
666             }
667             catch (ArgumentOutOfRangeException)
668             {
669                 ImageServiceCombo.SelectedIndex = 0;
670             }
671         }
672
673         private void ImageServiceCombo_SelectedIndexChanged(object sender, EventArgs e)
674         {
675             if (this.Visible)
676             {
677                 var imageService = this.SelectedService;
678                 if (imageService != null)
679                 {
680                     if (ImagePageCombo.Items.Count > 0)
681                     {
682                         // 画像が選択された投稿先に対応しているかをチェックする
683                         // TODO: 複数の選択済み画像があるなら、できれば全てを再チェックしたほうがいい
684                         if (this.ServiceName == "Twitter")
685                         {
686                             ValidateSelectedImagePage();
687                         }
688                         else
689                         {
690                             if (ImagePageCombo.Items.Count > 1)
691                             {
692                                 // 複数の選択済み画像のうち、1枚目のみを残す
693                                 SetImagePageCombo((SelectedMedia)ImagePageCombo.Items[0]);
694                             }
695                             else
696                             {
697                                 ImagePageCombo.Enabled = false;
698                                 var valid = false;
699
700                                 try
701                                 {
702                                     var item = ((SelectedMedia)ImagePageCombo.Items[0]).Item;
703                                     if (item != null)
704                                     {
705                                         var ext = item.Extension;
706                                         if (imageService.CheckFileExtension(ext) &&
707                                             imageService.CheckFileSize(ext, item.Size))
708                                         {
709                                             valid = true;
710                                         }
711                                     }
712                                 }
713                                 catch
714                                 {
715                                 }
716                                 finally
717                                 {
718                                     if (!valid)
719                                     {
720                                         ClearImageSelectedPicture();
721                                         ClearSelectedImagePage();
722                                     }
723                                 }
724                             }
725                         }
726                     }
727                 }
728             }
729
730             if (this.SelectedServiceChanged != null)
731                 this.SelectedServiceChanged(this, EventArgs.Empty);
732         }
733
734         private void SetImagePageCombo(SelectedMedia media = null)
735         {
736             using (ControlTransaction.Update(ImagePageCombo))
737             {
738                 ImagePageCombo.Enabled = false;
739
740                 foreach (SelectedMedia oldMedia in ImagePageCombo.Items)
741                 {
742                     if (oldMedia == null || oldMedia == media) continue;
743                     DisposeMediaItem(oldMedia.Item);
744                 }
745                 ImagePageCombo.Items.Clear();
746
747                 if (media == null)
748                     media = new SelectedMedia("1");
749
750                 ImagePageCombo.Items.Add(media);
751                 ImagefilePathText.Text = media.Path;
752
753                 ImagePageCombo.SelectedIndex = 0;
754             }
755         }
756
757         private void AddNewImagePage(int selectedIndex)
758         {
759             var service = this.SelectedService;
760             if (service == null) return;
761
762             if (selectedIndex < service.MaxMediaCount - 1)
763             {
764                 // 投稿先の投稿可能枚数まで選択できるようにする
765                 var count = ImagePageCombo.Items.Count;
766                 if (selectedIndex == count - 1)
767                 {
768                     count++;
769                     ImagePageCombo.Items.Add(new SelectedMedia(count.ToString()));
770                     ImagePageCombo.Enabled = true;
771                 }
772             }
773         }
774
775         private void SetSelectedImagePage(IMediaItem item, MyCommon.UploadFileType type)
776         {
777             SetImagePage(-1, item, type);
778         }
779
780         private void SetImagePage(int index, IMediaItem item, MyCommon.UploadFileType type)
781         {
782             var selectedIndex = ImagePageCombo.SelectedIndex;
783             if (index < 0) index = selectedIndex;
784
785             var media = (SelectedMedia)ImagePageCombo.Items[index];
786             if (media.Item != item)
787             {
788                 DisposeMediaItem(media.Item);
789                 media.Item = item;
790             }
791             media.Type = type;
792
793             AddNewImagePage(index);
794         }
795
796         private void ClearSelectedImagePage()
797         {
798             ClearImagePage(-1);
799         }
800
801         private void ClearImagePage(int index)
802         {
803             var selectedIndex = ImagePageCombo.SelectedIndex;
804             if (index < 0) index = selectedIndex;
805
806             var media = (SelectedMedia)ImagePageCombo.Items[index];
807             DisposeMediaItem(media.Item);
808             media.Item = null;
809             media.Type = MyCommon.UploadFileType.Invalid;
810
811             if (index == selectedIndex) ImagefilePathText.Text = "";
812         }
813
814         private void ValidateSelectedImagePage()
815         {
816             var idx = ImagePageCombo.SelectedIndex;
817             var media = (SelectedMedia)ImagePageCombo.Items[idx];
818             ImageServiceCombo.Enabled = (idx == 0);  // idx == 0 以外では投稿先サービスを選べないようにする
819             ImagefilePathText.Text = media.Path;
820             ImageFromSelectedFile(media.Item, true);
821         }
822
823         private void ImagePageCombo_SelectedIndexChanged(object sender, EventArgs e)
824         {
825             ValidateSelectedImagePage();
826         }
827     }
828 }