1 // OpenTween - Client of Twitter
2 // Copyright (c) 2012 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
3 // All rights reserved.
5 // This file is part of OpenTween.
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)
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
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.
25 using System.Collections.Generic;
26 using System.ComponentModel;
29 using System.Runtime.InteropServices;
31 using System.Threading.Tasks;
32 using System.Windows.Forms;
33 using OpenTween.Thumbnail;
37 public partial class TweetThumbnailControl : UserControl
39 private readonly MouseWheelMessageFilter filter = new();
42 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
43 public TweetThumbnail Model { get; } = new();
45 public TweetThumbnailControl()
47 this.InitializeComponent();
48 this.filter.Register(this.pictureBox);
50 this.Model.PropertyChanged +=
51 (s, e) => this.TryInvoke(() => this.Model_PropertyChanged(s, e));
54 protected override void Dispose(bool disposing)
58 this.components?.Dispose();
59 this.filter.Dispose();
61 base.Dispose(disposing);
64 private void Model_PropertyChanged(object sender, PropertyChangedEventArgs e)
66 switch (e.PropertyName)
68 case nameof(TweetThumbnail.ThumbnailAvailable):
69 this.UpdateThumbnailAvailability();
71 case nameof(TweetThumbnail.SelectedIndex):
72 this.UpdateSelectedIndex();
79 private void UpdateThumbnailAvailability()
81 if (this.Model.ThumbnailAvailable)
83 this.UpdateSelectedIndex();
85 var hasMultipleThumbnails = this.Model.Thumbnails.Length > 1;
86 this.scrollBar.Enabled = hasMultipleThumbnails;
87 this.scrollBar.Visible = hasMultipleThumbnails;
89 if (hasMultipleThumbnails)
91 this.scrollBar.Value = 0;
92 this.scrollBar.Maximum = this.Model.Thumbnails.Length - 1;
97 this.pictureBox.Image = null;
98 this.pictureBox.AccessibleDescription = "";
99 this.toolTip.SetToolTip(this.pictureBox, "");
100 this.scrollBar.Visible = false;
104 private void UpdateSelectedIndex()
106 if (!this.Model.ThumbnailAvailable)
109 this.scrollBar.Value = this.Model.SelectedIndex;
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);
118 public async Task OpenImageInBrowser()
120 if (!this.Model.ThumbnailAvailable)
123 var thumbnail = this.Model.CurrentThumbnail;
124 var mediaUrl = thumbnail.FullSizeImageUrl ?? thumbnail.MediaPageUrl;
125 await MyCommon.OpenInBrowserAsync(this, mediaUrl);
128 protected override void ScaleControl(SizeF factor, BoundsSpecified specified)
130 base.ScaleControl(factor, specified);
131 OTBaseForm.ScaleChildControl(this.scrollBar, factor);
134 private void ScrollBar_ValueChanged(object sender, EventArgs e)
135 => this.Model.SelectedIndex = this.scrollBar.Value;
137 private void PictureBox_MouseWheel(object sender, MouseEventArgs e)
140 this.Model.ScrollUp();
142 this.Model.ScrollDown();
145 private async void PictureBox_DoubleClick(object sender, EventArgs e)
146 => await this.OpenImageInBrowser();
148 private async void SearchSimilarImageMenuItem_Click(object sender, EventArgs e)
150 var searchUri = this.Model.GetImageSearchUriGoogle();
151 await MyCommon.OpenInBrowserAsync(this, searchUri);
154 private async void SearchImageSauceNaoMenuItem_Click(object sender, EventArgs e)
156 var searchUri = this.Model.GetImageSearchUriSauceNao();
157 await MyCommon.OpenInBrowserAsync(this, searchUri);
160 private async void OpenMenuItem_Click(object sender, EventArgs e)
161 => await this.OpenImageInBrowser();
163 private void CopyUrlMenuItem_Click(object sender, EventArgs e)
167 var thumb = this.Model.CurrentThumbnail;
168 Clipboard.SetText(thumb.FullSizeImageUrl ?? thumb.MediaPageUrl);
170 catch (ExternalException ex)
172 MessageBox.Show(ex.Message);
176 private void CopyToClipboardMenuItem_Click(object sender, EventArgs e)
180 if (this.pictureBox.Image is { } memoryImage)
181 Clipboard.SetImage(memoryImage.Image);
183 catch (ExternalException ex)
185 MessageBox.Show(ex.Message);