OSDN Git Service

graphqlエンドポイント使用時にツイート検索の言語指定が効かない不具合を修正
[opentween/open-tween.git] / OpenTween / TweetThumbnailControl.cs
1 // OpenTween - Client of Twitter
2 // Copyright (c) 2012 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
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 #nullable enable
23
24 using System;
25 using System.Collections.Generic;
26 using System.ComponentModel;
27 using System.Drawing;
28 using System.Linq;
29 using System.Runtime.InteropServices;
30 using System.Text;
31 using System.Threading.Tasks;
32 using System.Windows.Forms;
33 using OpenTween.Thumbnail;
34
35 namespace OpenTween
36 {
37     public partial class TweetThumbnailControl : UserControl
38     {
39         private readonly MouseWheelMessageFilter filter = new();
40
41         [Browsable(false)]
42         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
43         public TweetThumbnail Model { get; } = new();
44
45         public TweetThumbnailControl()
46         {
47             this.InitializeComponent();
48             this.filter.Register(this.pictureBox);
49
50             this.Model.PropertyChanged +=
51                 (s, e) => this.TryInvoke(() => this.Model_PropertyChanged(s, e));
52         }
53
54         protected override void Dispose(bool disposing)
55         {
56             if (disposing)
57             {
58                 this.components?.Dispose();
59                 this.filter.Dispose();
60             }
61             base.Dispose(disposing);
62         }
63
64         private void Model_PropertyChanged(object sender, PropertyChangedEventArgs e)
65         {
66             switch (e.PropertyName)
67             {
68                 case nameof(TweetThumbnail.ThumbnailAvailable):
69                     this.UpdateThumbnailAvailability();
70                     break;
71                 case nameof(TweetThumbnail.SelectedIndex):
72                     this.UpdateSelectedIndex();
73                     break;
74                 default:
75                     break;
76             }
77         }
78
79         private void UpdateThumbnailAvailability()
80         {
81             if (this.Model.ThumbnailAvailable)
82             {
83                 this.UpdateSelectedIndex();
84
85                 var hasMultipleThumbnails = this.Model.Thumbnails.Length > 1;
86                 this.scrollBar.Enabled = hasMultipleThumbnails;
87                 this.scrollBar.Visible = hasMultipleThumbnails;
88
89                 if (hasMultipleThumbnails)
90                 {
91                     this.scrollBar.Value = 0;
92                     this.scrollBar.Maximum = this.Model.Thumbnails.Length - 1;
93                 }
94             }
95             else
96             {
97                 this.pictureBox.Image = null;
98                 this.pictureBox.AccessibleDescription = "";
99                 this.toolTip.SetToolTip(this.pictureBox, "");
100                 this.scrollBar.Visible = false;
101             }
102         }
103
104         private void UpdateSelectedIndex()
105         {
106             if (!this.Model.ThumbnailAvailable)
107                 return;
108
109             this.scrollBar.Value = this.Model.SelectedIndex;
110
111             var thumbnail = this.Model.CurrentThumbnail;
112             this.pictureBox.PlayableMark = thumbnail.IsPlayable;
113             this.pictureBox.AccessibleDescription = thumbnail.TooltipText;
114             this.toolTip.SetToolTip(this.pictureBox, thumbnail.TooltipText);
115             _ = this.pictureBox.SetImageFromTask(this.Model.LoadSelectedThumbnail);
116         }
117
118         public async Task OpenImageInBrowser()
119         {
120             if (!this.Model.ThumbnailAvailable)
121                 return;
122
123             var thumbnail = this.Model.CurrentThumbnail;
124             var mediaUrl = thumbnail.FullSizeImageUrl ?? thumbnail.MediaPageUrl;
125             await MyCommon.OpenInBrowserAsync(this, mediaUrl);
126         }
127
128         protected override void ScaleControl(SizeF factor, BoundsSpecified specified)
129         {
130             base.ScaleControl(factor, specified);
131             OTBaseForm.ScaleChildControl(this.scrollBar, factor);
132         }
133
134         private void ScrollBar_ValueChanged(object sender, EventArgs e)
135             => this.Model.SelectedIndex = this.scrollBar.Value;
136
137         private void PictureBox_MouseWheel(object sender, MouseEventArgs e)
138         {
139             if (e.Delta > 0)
140                 this.Model.ScrollUp();
141             else
142                 this.Model.ScrollDown();
143         }
144
145         private async void PictureBox_DoubleClick(object sender, EventArgs e)
146             => await this.OpenImageInBrowser();
147
148         private async void SearchSimilarImageMenuItem_Click(object sender, EventArgs e)
149         {
150             var searchUri = this.Model.GetImageSearchUriGoogle();
151             await MyCommon.OpenInBrowserAsync(this, searchUri);
152         }
153
154         private async void SearchImageSauceNaoMenuItem_Click(object sender, EventArgs e)
155         {
156             var searchUri = this.Model.GetImageSearchUriSauceNao();
157             await MyCommon.OpenInBrowserAsync(this, searchUri);
158         }
159
160         private async void OpenMenuItem_Click(object sender, EventArgs e)
161             => await this.OpenImageInBrowser();
162
163         private void CopyUrlMenuItem_Click(object sender, EventArgs e)
164         {
165             try
166             {
167                 var thumb = this.Model.CurrentThumbnail;
168                 Clipboard.SetText(thumb.FullSizeImageUrl ?? thumb.MediaPageUrl);
169             }
170             catch (ExternalException ex)
171             {
172                 MessageBox.Show(ex.Message);
173             }
174         }
175
176         private void CopyToClipboardMenuItem_Click(object sender, EventArgs e)
177         {
178             try
179             {
180                 if (this.pictureBox.Image is { } memoryImage)
181                     Clipboard.SetImage(memoryImage.Image);
182             }
183             catch (ExternalException ex)
184             {
185                 MessageBox.Show(ex.Message);
186             }
187         }
188     }
189 }