1 // OpenTween - Client of Twitter
2 // Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
3 // (c) 2008-2011 Moz (@syo68k)
4 // (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
5 // (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
6 // (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
7 // (c) 2011-2012 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
8 // All rights reserved.
10 // This file is part of OpenTween.
12 // This program is free software; you can redistribute it and/or modify it
13 // under the terms of the GNU General public License as published by the Free
14 // Software Foundation; either version 3 of the License, or (at your option)
17 // This program is distributed in the hope that it will be useful, but
18 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General public License
22 // You should have received a copy of the GNU General public License along
23 // with this program. If not, see <http://www.gnu.org/licenses/>, or write to
24 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
25 // Boston, MA 02110-1301, USA.
30 using System.Collections.Generic;
31 using System.ComponentModel;
33 using System.Diagnostics.CodeAnalysis;
37 using System.Windows.Forms;
38 using System.Text.RegularExpressions;
40 using System.Globalization;
41 using OpenTween.Setting;
42 using System.Threading.Tasks;
46 public partial class EventViewerDialog : OTBaseForm
48 public List<Twitter.FormattedEvent> EventSource { get; set; } = new List<Twitter.FormattedEvent>();
50 private Twitter.FormattedEvent[] _filterdEventSource = Array.Empty<Twitter.FormattedEvent>();
52 private ListViewItem[]? _ItemCache = null;
53 private int _itemCacheIndex;
55 private TabPage _curTab = null!;
57 public EventViewerDialog()
59 InitializeComponent();
61 // メイリオフォント指定時にタブの最小幅が広くなる問題の対策
62 this.TabEventType.HandleCreated += (s, e) => NativeMethods.SetMinTabWidth((TabControl)s, 40);
65 protected override void ScaleControl(SizeF factor, BoundsSpecified specified)
67 base.ScaleControl(factor, specified);
68 ScaleChildControl(this.EventList, factor);
71 private void OK_Button_Click(object sender, EventArgs e)
73 this.DialogResult = DialogResult.OK;
77 private void Cancel_Button_Click(object sender, EventArgs e)
79 this.DialogResult = DialogResult.Cancel;
83 private ListViewItem CreateListViewItem(Twitter.FormattedEvent source)
85 string[] s = { source.CreatedAt.ToLocalTimeString(), source.Event.ToUpper(CultureInfo.CurrentCulture), source.Username, source.Target };
86 return new ListViewItem(s);
89 private void EventViewerDialog_Shown(object sender, EventArgs e)
92 foreach (var tabPage in CreateTabsFromUserStreamsEvent())
94 TabEventType.TabPages.Add(tabPage);
97 EventList.BeginUpdate();
98 _curTab = TabEventType.SelectedTab;
99 CreateFilterdEventSource();
100 EventList.EndUpdate();
101 this.TopMost = SettingManager.Common.AlwaysTop;
104 private async void EventList_DoubleClick(object sender, EventArgs e)
105 => await this.OpenEventStatusOrUser();
107 private async void EventList_KeyDown(object sender, KeyEventArgs e)
109 if (e.KeyData == Keys.Enter)
110 await this.OpenEventStatusOrUser();
113 private async Task OpenEventStatusOrUser()
115 if (this.EventList.SelectedIndices.Count == 0)
118 var tweenMain = (TweenMain)this.Owner;
119 var selectedEvent = this._filterdEventSource[this.EventList.SelectedIndices[0]];
120 if (selectedEvent != null)
122 if (selectedEvent.Id != 0)
123 await tweenMain.OpenRelatedTab(selectedEvent.Id);
125 await tweenMain.OpenUriAsync(new Uri("https://twitter.com/" + selectedEvent.Username));
129 private MyCommon.EVENTTYPE ParseEventTypeFromTag()
130 => (MyCommon.EVENTTYPE)Enum.Parse(typeof(MyCommon.EVENTTYPE), _curTab.Tag.ToString());
132 private bool IsFilterMatch(Twitter.FormattedEvent x)
134 if (!CheckBoxFilter.Checked || string.IsNullOrEmpty(TextBoxKeyword.Text))
140 if (CheckRegex.Checked)
144 var rx = new Regex(TextBoxKeyword.Text);
145 return rx.Match(x.Username).Success || rx.Match(x.Target).Success;
149 MessageBox.Show(Properties.Resources.ButtonOK_ClickText3 + ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
155 return x.Username.Contains(TextBoxKeyword.Text) || x.Target.Contains(TextBoxKeyword.Text);
160 private void CreateFilterdEventSource()
162 if (EventSource != null && EventSource.Count > 0)
164 _filterdEventSource = EventSource.FindAll((x) => !(CheckExcludeMyEvent.Checked && x.IsMe) &&
165 (x.Eventtype & ParseEventTypeFromTag()) != 0 &&
166 IsFilterMatch(x)).ToArray();
168 EventList.VirtualListSize = _filterdEventSource.Count();
169 StatusLabelCount.Text = string.Format("{0} / {1}", _filterdEventSource.Count(), EventSource.Count());
173 StatusLabelCount.Text = "0 / 0";
177 private void CheckExcludeMyEvent_CheckedChanged(object sender, EventArgs e)
178 => this.CreateFilterdEventSource();
180 private void ButtonRefresh_Click(object sender, EventArgs e)
181 => this.CreateFilterdEventSource();
183 private void TabEventType_SelectedIndexChanged(object sender, EventArgs e)
184 => this.CreateFilterdEventSource();
186 private void TabEventType_Selecting(object sender, TabControlCancelEventArgs e)
189 if (!e.TabPage.Controls.Contains(EventList))
191 e.TabPage.Controls.Add(EventList);
195 private void TextBoxKeyword_KeyPress(object sender, KeyPressEventArgs e)
197 if (e.KeyChar == (char)Keys.Enter)
199 CreateFilterdEventSource();
204 private void EventList_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
206 if (_ItemCache != null && e.ItemIndex >= _itemCacheIndex && e.ItemIndex < _itemCacheIndex + _ItemCache.Length)
209 e.Item = _ItemCache[e.ItemIndex - _itemCacheIndex];
214 e.Item = CreateListViewItem(_filterdEventSource[e.ItemIndex]);
218 private void EventList_CacheVirtualItems(object sender, CacheVirtualItemsEventArgs e)
219 => this.CreateCache(e.StartIndex, e.EndIndex);
221 private void CreateCache(int StartIndex, int EndIndex)
223 //キャッシュ要求(要求範囲±30を作成)
225 if (StartIndex < 0) StartIndex = 0;
227 if (EndIndex > _filterdEventSource.Count() - 1)
229 EndIndex = _filterdEventSource.Count() - 1;
231 _ItemCache = new ListViewItem[] { };
232 Array.Resize(ref _ItemCache, EndIndex - StartIndex + 1);
233 _itemCacheIndex = StartIndex;
234 for (var i = 0; i < _ItemCache.Length; i++)
236 _ItemCache[i] = CreateListViewItem(_filterdEventSource[StartIndex + i]);
240 private void SaveLogButton_Click(object sender, EventArgs e)
242 var rslt = MessageBox.Show(string.Format(Properties.Resources.SaveLogMenuItem_ClickText5, Environment.NewLine),
243 Properties.Resources.SaveLogMenuItem_ClickText2,
244 MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
247 case DialogResult.Yes:
248 SaveFileDialog1.FileName = $"{ApplicationSettings.AssemblyName}Events{_curTab.Tag}{DateTimeUtc.Now.ToLocalTime():yyMMdd-HHmmss}.tsv";
250 case DialogResult.No:
251 SaveFileDialog1.FileName = $"{ApplicationSettings.AssemblyName}Events{DateTimeUtc.Now.ToLocalTime():yyMMdd-HHmmss}.tsv";
257 SaveFileDialog1.InitialDirectory = Application.StartupPath;
258 SaveFileDialog1.Filter = Properties.Resources.SaveLogMenuItem_ClickText3;
259 SaveFileDialog1.FilterIndex = 0;
260 SaveFileDialog1.Title = Properties.Resources.SaveLogMenuItem_ClickText4;
261 SaveFileDialog1.RestoreDirectory = true;
263 if (SaveFileDialog1.ShowDialog() == DialogResult.OK)
265 if (!SaveFileDialog1.ValidateNames) return;
266 using var sw = new StreamWriter(SaveFileDialog1.FileName, false, Encoding.UTF8);
270 case DialogResult.Yes:
271 SaveEventLog(_filterdEventSource.ToList(), sw);
273 case DialogResult.No:
274 SaveEventLog(EventSource, sw);
280 this.TopMost = SettingManager.Common.AlwaysTop;
283 private void SaveEventLog(List<Twitter.FormattedEvent> source, StreamWriter sw)
285 foreach (var _event in source)
287 sw.WriteLine(_event.Eventtype + "\t" +
288 "\"" + _event.CreatedAt.ToLocalTimeString() + "\"\t" +
289 _event.Event + "\t" +
290 _event.Username + "\t" +
291 _event.Target + "\t" +
296 [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope")]
297 private static IEnumerable<TabPage> CreateTabsFromUserStreamsEvent()
299 return Enum.GetNames(typeof(MyCommon.EVENTTYPE))
300 .Where(e => e != "None" && e != "All")
301 .Select(e => new TabPage(e)
304 UseVisualStyleBackColor = true,
305 AccessibleRole = AccessibleRole.PageTab,