OSDN Git Service

db571f8273c6873f8b7dbbf3fe323bbe273954b3
[opentween/open-tween.git] / OpenTween / EventViewerDialog.cs
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.
9 // 
10 // This file is part of OpenTween.
11 // 
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)
15 // any later version.
16 // 
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
20 // for more details. 
21 // 
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.
26
27 using System;
28 using System.Collections.Generic;
29 using System.ComponentModel;
30 using System.Data;
31 using System.Diagnostics.CodeAnalysis;
32 using System.Drawing;
33 using System.Linq;
34 using System.Text;
35 using System.Windows.Forms;
36 using System.Text.RegularExpressions;
37 using System.IO;
38 using System.Globalization;
39 using OpenTween.Setting;
40 using System.Threading.Tasks;
41
42 namespace OpenTween
43 {
44     public partial class EventViewerDialog : OTBaseForm
45     {
46         public List<Twitter.FormattedEvent> EventSource { get; set; }
47
48         private Twitter.FormattedEvent[] _filterdEventSource;
49
50         private ListViewItem[] _ItemCache = null;
51         private int _itemCacheIndex;
52
53         private TabPage _curTab = null;
54
55         public EventViewerDialog()
56         {
57             InitializeComponent();
58
59             // メイリオフォント指定時にタブの最小幅が広くなる問題の対策
60             this.TabEventType.HandleCreated += (s, e) => NativeMethods.SetMinTabWidth((TabControl)s, 40);
61         }
62
63         protected override void ScaleControl(SizeF factor, BoundsSpecified specified)
64         {
65             base.ScaleControl(factor, specified);
66             ScaleChildControl(this.EventList, factor);
67         }
68
69         private void OK_Button_Click(object sender, EventArgs e)
70         {
71             this.DialogResult = DialogResult.OK;
72             this.Close();
73         }
74
75         private void Cancel_Button_Click(object sender, EventArgs e)
76         {
77             this.DialogResult = DialogResult.Cancel;
78             this.Close();
79         }
80
81         private ListViewItem CreateListViewItem(Twitter.FormattedEvent source)
82         {
83             string[] s = { source.CreatedAt.ToLocalTimeString(), source.Event.ToUpper(CultureInfo.CurrentCulture), source.Username, source.Target };
84             return new ListViewItem(s);
85         }
86
87         private void EventViewerDialog_Shown(object sender, EventArgs e)
88         {
89             // タブ初期化
90             foreach (var tabPage in CreateTabsFromUserStreamsEvent())
91             {
92                 TabEventType.TabPages.Add(tabPage);
93             }
94
95             EventList.BeginUpdate();
96             _curTab = TabEventType.SelectedTab;
97             CreateFilterdEventSource();
98             EventList.EndUpdate();
99             this.TopMost = SettingManager.Common.AlwaysTop;
100         }
101
102         private async void EventList_DoubleClick(object sender, EventArgs e)
103             => await this.OpenEventStatusOrUser();
104
105         private async void EventList_KeyDown(object sender, KeyEventArgs e)
106         {
107             if (e.KeyData == Keys.Enter)
108                 await this.OpenEventStatusOrUser();
109         }
110
111         private async Task OpenEventStatusOrUser()
112         {
113             if (this.EventList.SelectedIndices.Count == 0)
114                 return;
115
116             var tweenMain = (TweenMain)this.Owner;
117             var selectedEvent = this._filterdEventSource[this.EventList.SelectedIndices[0]];
118             if (selectedEvent != null)
119             {
120                 if (selectedEvent.Id != 0)
121                     await tweenMain.OpenRelatedTab(selectedEvent.Id);
122                 else
123                     await tweenMain.OpenUriAsync(new Uri("https://twitter.com/" + selectedEvent.Username));
124             }
125         }
126
127         private MyCommon.EVENTTYPE ParseEventTypeFromTag()
128         {
129             return (MyCommon.EVENTTYPE)Enum.Parse(typeof(MyCommon.EVENTTYPE), _curTab.Tag.ToString());
130         }
131
132         private bool IsFilterMatch(Twitter.FormattedEvent x)
133         {
134             if (!CheckBoxFilter.Checked || string.IsNullOrEmpty(TextBoxKeyword.Text))
135             {
136                 return true;
137             }
138             else
139             {
140                 if (CheckRegex.Checked)
141                 {
142                     try
143                     {
144                         Regex rx = new Regex(TextBoxKeyword.Text);
145                         return rx.Match(x.Username).Success || rx.Match(x.Target).Success;
146                     }
147                     catch (Exception ex)
148                     {
149                         MessageBox.Show(Properties.Resources.ButtonOK_ClickText3 + ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
150                         return false;
151                     }
152                 }
153                 else
154                 {
155                     return x.Username.Contains(TextBoxKeyword.Text) || x.Target.Contains(TextBoxKeyword.Text);
156                 }
157             }
158         }
159
160         private void CreateFilterdEventSource()
161         {
162             if (EventSource != null && EventSource.Count > 0)
163             {
164                 _filterdEventSource = EventSource.FindAll((x) => !(CheckExcludeMyEvent.Checked && x.IsMe) &&
165                                                                  (x.Eventtype & ParseEventTypeFromTag()) != 0 &&
166                                                                  IsFilterMatch(x)).ToArray();
167                 _ItemCache = null;
168                 EventList.VirtualListSize = _filterdEventSource.Count();
169                 StatusLabelCount.Text = string.Format("{0} / {1}", _filterdEventSource.Count(), EventSource.Count());
170             }
171             else
172             {
173                 StatusLabelCount.Text = "0 / 0";
174             }
175         }
176
177         private void CheckExcludeMyEvent_CheckedChanged(object sender, EventArgs e)
178         {
179             CreateFilterdEventSource();
180         }
181
182         private void ButtonRefresh_Click(object sender, EventArgs e)
183         {
184             CreateFilterdEventSource();
185         }
186
187         private void TabEventType_SelectedIndexChanged(object sender, EventArgs e)
188         {
189             CreateFilterdEventSource();
190         }
191
192         private void TabEventType_Selecting(object sender, TabControlCancelEventArgs e)
193         {
194             _curTab = e.TabPage;
195             if (!e.TabPage.Controls.Contains(EventList))
196             {
197                 e.TabPage.Controls.Add(EventList);
198             }
199         }
200
201         private void TextBoxKeyword_KeyPress(object sender, KeyPressEventArgs e)
202         {
203             if (e.KeyChar == (char)Keys.Enter)
204             {
205                 CreateFilterdEventSource();
206                 e.Handled = true;
207             }
208         }
209
210         private void EventList_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
211         {
212             if (_ItemCache != null && e.ItemIndex >= _itemCacheIndex && e.ItemIndex < _itemCacheIndex + _ItemCache.Length)
213             {
214                 //キャッシュヒット
215                 e.Item = _ItemCache[e.ItemIndex - _itemCacheIndex];
216             }
217             else
218             {
219                 //キャッシュミス
220                 e.Item = CreateListViewItem(_filterdEventSource[e.ItemIndex]);
221             }
222         }
223
224         private void EventList_CacheVirtualItems(object sender, CacheVirtualItemsEventArgs e)
225         {
226             CreateCache(e.StartIndex, e.EndIndex);
227         }
228
229         private void CreateCache(int StartIndex, int EndIndex)
230         {
231             //キャッシュ要求(要求範囲±30を作成)
232             StartIndex -= 30;
233             if (StartIndex < 0) StartIndex = 0;
234             EndIndex += 30;
235             if (EndIndex > _filterdEventSource.Count() - 1)
236             {
237                 EndIndex = _filterdEventSource.Count() - 1;
238             }
239             _ItemCache = new ListViewItem[] { };
240             Array.Resize(ref _ItemCache, EndIndex - StartIndex + 1);
241             _itemCacheIndex = StartIndex;
242             for (int i = 0; i < _ItemCache.Length; i++)
243             {
244                 _ItemCache[i] = CreateListViewItem(_filterdEventSource[StartIndex + i]);
245             }
246         }
247
248         private void SaveLogButton_Click(object sender, EventArgs e)
249         {
250             DialogResult rslt = MessageBox.Show(string.Format(Properties.Resources.SaveLogMenuItem_ClickText5, Environment.NewLine),
251                     Properties.Resources.SaveLogMenuItem_ClickText2,
252                     MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
253             switch (rslt)
254             {
255                 case DialogResult.Yes:
256                     SaveFileDialog1.FileName = $"{MyCommon.GetAssemblyName()}Events{_curTab.Tag}{DateTimeUtc.Now.ToLocalTime():yyMMdd-HHmmss}.tsv";
257                     break;
258                 case DialogResult.No:
259                     SaveFileDialog1.FileName = $"{MyCommon.GetAssemblyName()}Events{DateTimeUtc.Now.ToLocalTime():yyMMdd-HHmmss}.tsv";
260                     break;
261                 default:
262                     return;
263             }
264
265             SaveFileDialog1.InitialDirectory = Application.StartupPath;
266             SaveFileDialog1.Filter = Properties.Resources.SaveLogMenuItem_ClickText3;
267             SaveFileDialog1.FilterIndex = 0;
268             SaveFileDialog1.Title = Properties.Resources.SaveLogMenuItem_ClickText4;
269             SaveFileDialog1.RestoreDirectory = true;
270
271             if (SaveFileDialog1.ShowDialog() == DialogResult.OK)
272             {
273                 if (!SaveFileDialog1.ValidateNames) return;
274                 using (StreamWriter sw = new StreamWriter(SaveFileDialog1.FileName, false, Encoding.UTF8))
275                 {
276                     switch (rslt)
277                     {
278                         case DialogResult.Yes:
279                             SaveEventLog(_filterdEventSource.ToList(), sw);
280                             break;
281                         case DialogResult.No:
282                             SaveEventLog(EventSource, sw);
283                             break;
284                         default:
285                             //
286                             break;
287                     }
288                 }
289             }
290             this.TopMost = SettingManager.Common.AlwaysTop;
291         }
292
293         private void SaveEventLog(List<Twitter.FormattedEvent> source, StreamWriter sw)
294         {
295             foreach (Twitter.FormattedEvent _event in source)
296             {
297                 sw.WriteLine(_event.Eventtype + "\t" +
298                              "\"" + _event.CreatedAt.ToLocalTimeString() + "\"\t" +
299                              _event.Event + "\t" +
300                              _event.Username + "\t" +
301                              _event.Target + "\t" +
302                              _event.Id);
303             }
304         }
305
306         [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope")]
307         private static IEnumerable<TabPage> CreateTabsFromUserStreamsEvent()
308         {
309             return Enum.GetNames(typeof(MyCommon.EVENTTYPE))
310                        .Where(e => e != "None" && e != "All")
311                        .Select(e => new TabPage(e)
312                        {
313                            // Name = "TabPage" + e,
314                            Tag = e,
315                            UseVisualStyleBackColor = true,
316                            AccessibleRole = AccessibleRole.PageTab,
317                        });
318         }
319     }
320 }