OSDN Git Service

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