OSDN Git Service

振り分けルールの表示色を変更
[opentween/open-tween.git] / OpenTween / FilterDialog.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.Linq.Expressions;
36 using System.Text.RegularExpressions;
37 using System.IO;
38 using System.Collections.Specialized;
39
40 namespace OpenTween
41 {
42     public partial class FilterDialog : OTBaseForm
43     {
44         private EDITMODE _mode;
45         private bool _directAdd;
46         private bool _moveRules = false;
47         private TabInformations _sts;
48         private string _cur;
49         private List<string> idlist = new List<string>();
50
51         private enum EDITMODE
52         {
53             AddNew,
54             Edit,
55             None,
56         }
57
58         private enum EnableButtonMode
59         {
60             NotSelected,
61             Enable,
62             Disable,
63         }
64
65         private EnableButtonMode RuleEnableButtonMode
66         {
67             get { return this._ruleEnableButtonMode; }
68             set
69             {
70                 this._ruleEnableButtonMode = value;
71
72                 this.buttonRuleToggleEnabled.Text = value == FilterDialog.EnableButtonMode.Enable
73                     ? Properties.Resources.EnableButtonCaption
74                     : Properties.Resources.DisableButtonCaption;
75                 this.buttonRuleToggleEnabled.Enabled = value != EnableButtonMode.NotSelected;
76             }
77         }
78         private EnableButtonMode _ruleEnableButtonMode = FilterDialog.EnableButtonMode.NotSelected;
79
80         public FilterDialog()
81         {
82             InitializeComponent();
83         }
84
85         private void SetFilters(string tabName)
86         {
87             if (ListTabs.Items.Count == 0) return;
88
89             var tab = _sts.Tabs[tabName];
90
91             ListFilters.Items.Clear();
92             ListFilters.Items.AddRange(tab.GetFilters());
93
94             if (ListFilters.Items.Count > 0)
95                 ListFilters.SelectedIndex = 0;
96             else
97                 ShowDetail();
98
99             if (tab.IsDefaultTabType)
100             {
101                 CheckProtected.Checked = true;
102                 CheckProtected.Enabled = false;
103             }
104             else
105             {
106                 CheckProtected.Checked = tab.Protected;
107                 CheckProtected.Enabled = true;
108             }
109
110             CheckManageRead.Checked = tab.UnreadManage;
111             CheckNotifyNew.Checked = tab.Notify;
112
113             int idx = ComboSound.Items.IndexOf(tab.SoundFile);
114             if (idx == -1) idx = 0;
115             ComboSound.SelectedIndex = idx;
116
117             if (_directAdd) return;
118
119             if (tab.TabType == MyCommon.TabUsageType.Mute)
120             {
121                 this.CheckManageRead.Enabled = false;
122                 this.CheckNotifyNew.Enabled = false;
123                 this.ComboSound.Enabled = false;
124
125                 this.GroupBox1.Visible = false;
126                 this.labelMuteTab.Visible = true;
127             }
128             else
129             {
130                 this.CheckManageRead.Enabled = true;
131                 this.CheckNotifyNew.Enabled = true;
132                 this.ComboSound.Enabled = true;
133
134                 this.GroupBox1.Visible = true;
135                 this.labelMuteTab.Visible = false;
136             }
137
138             ListTabs.Enabled = true;
139             GroupTab.Enabled = true;
140             ListFilters.Enabled = true;
141             EditFilterGroup.Enabled = false;
142             switch (tab.TabType)
143             {
144                 case MyCommon.TabUsageType.Home:
145                 case MyCommon.TabUsageType.DirectMessage:
146                 case MyCommon.TabUsageType.Favorites:
147                 case MyCommon.TabUsageType.PublicSearch:
148                 case MyCommon.TabUsageType.Lists:
149                 case MyCommon.TabUsageType.Related:
150                 case MyCommon.TabUsageType.UserTimeline:
151                     ButtonNew.Enabled = false;
152                     ButtonEdit.Enabled = false;
153                     ButtonDelete.Enabled = false;
154                     ButtonRuleUp.Enabled = false;
155                     ButtonRuleDown.Enabled = false;
156                     ButtonRuleCopy.Enabled = false;
157                     ButtonRuleMove.Enabled = false;
158                     buttonRuleToggleEnabled.Enabled = false;
159                     break;
160                 default:
161                     ButtonNew.Enabled = true;
162                     if (ListFilters.SelectedIndex > -1)
163                     {
164                         ButtonEdit.Enabled = true;
165                         ButtonDelete.Enabled = true;
166                         ButtonRuleUp.Enabled = true;
167                         ButtonRuleDown.Enabled = true;
168                         ButtonRuleCopy.Enabled = true;
169                         ButtonRuleMove.Enabled = true;
170                         buttonRuleToggleEnabled.Enabled = true;
171                     }
172                     else
173                     {
174                         ButtonEdit.Enabled = false;
175                         ButtonDelete.Enabled = false;
176                         ButtonRuleUp.Enabled = false;
177                         ButtonRuleDown.Enabled = false;
178                         ButtonRuleCopy.Enabled = false;
179                         ButtonRuleMove.Enabled = false;
180                         buttonRuleToggleEnabled.Enabled = false;
181                     }
182                     break;
183             }
184             switch (tab.TabType)
185             {
186                 case MyCommon.TabUsageType.Home:
187                     LabelTabType.Text = Properties.Resources.TabUsageTypeName_Home;
188                     break;
189                 case MyCommon.TabUsageType.Mentions:
190                     LabelTabType.Text = Properties.Resources.TabUsageTypeName_Mentions;
191                     break;
192                 case MyCommon.TabUsageType.DirectMessage:
193                     LabelTabType.Text = Properties.Resources.TabUsageTypeName_DirectMessage;
194                     break;
195                 case MyCommon.TabUsageType.Favorites:
196                     LabelTabType.Text = Properties.Resources.TabUsageTypeName_Favorites;
197                     break;
198                 case MyCommon.TabUsageType.UserDefined:
199                     LabelTabType.Text = Properties.Resources.TabUsageTypeName_UserDefined;
200                     break;
201                 case MyCommon.TabUsageType.PublicSearch:
202                     LabelTabType.Text = Properties.Resources.TabUsageTypeName_PublicSearch;
203                     break;
204                 case MyCommon.TabUsageType.Lists:
205                     LabelTabType.Text = Properties.Resources.TabUsageTypeName_Lists;
206                     break;
207                 case MyCommon.TabUsageType.Related:
208                     LabelTabType.Text = Properties.Resources.TabUsageTypeName_Related;
209                     break;
210                 case MyCommon.TabUsageType.UserTimeline:
211                     LabelTabType.Text = Properties.Resources.TabUsageTypeName_UserTimeline;
212                     break;
213                 case MyCommon.TabUsageType.Mute:
214                     LabelTabType.Text = "Mute";
215                     break;
216                 default:
217                     LabelTabType.Text = "UNKNOWN";
218                     break;
219             }
220             ButtonRenameTab.Enabled = true;
221             if (tab.IsDefaultTabType || tab.Protected)
222             {
223                 ButtonDeleteTab.Enabled = false;
224             }
225             else
226             {
227                 ButtonDeleteTab.Enabled = true;
228             }
229             ButtonClose.Enabled = true;
230         }
231
232         public void SetCurrent(string TabName)
233         {
234             _cur = TabName;
235         }
236
237         public void AddNewFilter(string id, string msg)
238         {
239             //元フォームから直接呼ばれる
240             ButtonNew.Enabled = false;
241             ButtonEdit.Enabled = false;
242             ButtonRuleUp.Enabled = false;
243             ButtonRuleDown.Enabled = false;
244             ButtonRuleCopy.Enabled = false;
245             ButtonRuleMove.Enabled = false;
246             buttonRuleToggleEnabled.Enabled = false;
247             ButtonDelete.Enabled = false;
248             ButtonClose.Enabled = false;
249             EditFilterGroup.Enabled = true;
250             ListTabs.Enabled = false;
251             GroupTab.Enabled = false;
252             ListFilters.Enabled = false;
253
254             RadioAND.Checked = true;
255             RadioPLUS.Checked = false;
256             UID.Text = id;
257             UID.SelectAll();
258             MSG1.Text = msg;
259             MSG1.SelectAll();
260             MSG2.Text = id + msg;
261             MSG2.SelectAll();
262             TextSource.Text = "";
263             UID.Enabled = true;
264             MSG1.Enabled = true;
265             MSG2.Enabled = false;
266             CheckRegex.Checked = false;
267             CheckURL.Checked = false;
268             CheckCaseSensitive.Checked = false;
269             CheckRetweet.Checked = false;
270             CheckLambda.Checked = false;
271
272             RadioExAnd.Checked = true;
273             RadioExPLUS.Checked = false;
274             ExUID.Text = "";
275             ExUID.SelectAll();
276             ExMSG1.Text = "";
277             ExMSG1.SelectAll();
278             ExMSG2.Text = "";
279             ExMSG2.SelectAll();
280             TextExSource.Text = "";
281             ExUID.Enabled = true;
282             ExMSG1.Enabled = true;
283             ExMSG2.Enabled = false;
284             CheckExRegex.Checked = false;
285             CheckExURL.Checked = false;
286             CheckExCaseSensitive.Checked = false;
287             CheckExRetweet.Checked = false;
288             CheckExLambDa.Checked = false;
289
290             OptCopy.Checked = true;
291             CheckMark.Checked = true;
292             UID.Focus();
293             _mode = EDITMODE.AddNew;
294             _directAdd = true;
295         }
296
297         private void ButtonNew_Click(object sender, EventArgs e)
298         {
299             ButtonNew.Enabled = false;
300             ButtonEdit.Enabled = false;
301             ButtonClose.Enabled = false;
302             ButtonRuleUp.Enabled = false;
303             ButtonRuleDown.Enabled = false;
304             ButtonRuleCopy.Enabled = false;
305             ButtonRuleMove.Enabled = false;
306             buttonRuleToggleEnabled.Enabled = false;
307             ButtonDelete.Enabled = false;
308             ButtonClose.Enabled = false;
309             EditFilterGroup.Enabled = true;
310             ListTabs.Enabled = false;
311             GroupTab.Enabled = false;
312             ListFilters.Enabled = false;
313
314             RadioAND.Checked = true;
315             RadioPLUS.Checked = false;
316             UID.Text = "";
317             MSG1.Text = "";
318             MSG2.Text = "";
319             TextSource.Text = "";
320             UID.Enabled = true;
321             MSG1.Enabled = true;
322             MSG2.Enabled = false;
323             CheckRegex.Checked = false;
324             CheckURL.Checked = false;
325             CheckCaseSensitive.Checked = false;
326             CheckRetweet.Checked = false;
327             CheckLambda.Checked = false;
328
329             RadioExAnd.Checked = true;
330             RadioExPLUS.Checked = false;
331             ExUID.Text = "";
332             ExMSG1.Text = "";
333             ExMSG2.Text = "";
334             TextExSource.Text = "";
335             ExUID.Enabled = true;
336             ExMSG1.Enabled = true;
337             ExMSG2.Enabled = false;
338             CheckExRegex.Checked = false;
339             CheckExURL.Checked = false;
340             CheckExCaseSensitive.Checked = false;
341             CheckExRetweet.Checked = false;
342             CheckExLambDa.Checked = false;
343
344             OptCopy.Checked = true;
345             CheckMark.Checked = true;
346             UID.Focus();
347             _mode = EDITMODE.AddNew;
348         }
349
350         private void ButtonEdit_Click(object sender, EventArgs e)
351         {
352             if (ListFilters.SelectedIndex == -1) return;
353
354             ShowDetail();
355
356             int idx = ListFilters.SelectedIndex;
357             ListFilters.SelectedIndex = -1;
358             ListFilters.SelectedIndex = idx;
359             ListFilters.Enabled = false;
360
361             ButtonNew.Enabled = false;
362             ButtonEdit.Enabled = false;
363             ButtonDelete.Enabled = false;
364             ButtonClose.Enabled = false;
365             ButtonRuleUp.Enabled = false;
366             ButtonRuleDown.Enabled = false;
367             ButtonRuleCopy.Enabled = false;
368             ButtonRuleMove.Enabled = false;
369             buttonRuleToggleEnabled.Enabled = false;
370             EditFilterGroup.Enabled = true;
371             ListTabs.Enabled = false;
372             GroupTab.Enabled = false;
373
374             _mode = EDITMODE.Edit;
375         }
376
377         private void ButtonDelete_Click(object sender, EventArgs e)
378         {
379             var selectedCount = ListFilters.SelectedIndices.Count;
380             if (selectedCount == 0) return;
381
382             string tmp;
383
384             if (selectedCount == 1)
385             {
386                 tmp = string.Format(Properties.Resources.ButtonDelete_ClickText1, Environment.NewLine, ListFilters.SelectedItem.ToString());
387             }
388             else
389             {
390                 tmp = string.Format(Properties.Resources.ButtonDelete_ClickText3, selectedCount.ToString());
391             }
392
393             var rslt = MessageBox.Show(tmp, Properties.Resources.ButtonDelete_ClickText2, MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
394             if (rslt == DialogResult.Cancel) return;
395
396             var indices = ListFilters.SelectedIndices.Cast<int>().Reverse().ToArray();  // 後ろの要素から削除
397             var tab = _sts.Tabs[ListTabs.SelectedItem.ToString()];
398
399             using (ControlTransaction.Update(ListFilters))
400             {
401                 foreach (var idx in indices)
402                 {
403                     tab.RemoveFilter((PostFilterRule)ListFilters.Items[idx]);
404                     ListFilters.Items.RemoveAt(idx);
405                 }
406             }
407         }
408
409         private void ButtonCancel_Click(object sender, EventArgs e)
410         {
411             ListTabs.Enabled = true;
412             GroupTab.Enabled = true;
413             ListFilters.Enabled = true;
414             ListFilters.Focus();
415             if (ListFilters.SelectedIndex != -1)
416             {
417                 ShowDetail();
418             }
419             EditFilterGroup.Enabled = false;
420             ButtonNew.Enabled = true;
421             if (ListFilters.SelectedIndex > -1)
422             {
423                 ButtonEdit.Enabled = true;
424                 ButtonDelete.Enabled = true;
425                 ButtonRuleUp.Enabled = true;
426                 ButtonRuleDown.Enabled = true;
427                 ButtonRuleCopy.Enabled = true;
428                 ButtonRuleMove.Enabled = true;
429                 buttonRuleToggleEnabled.Enabled = true;
430             }
431             else
432             {
433                 ButtonEdit.Enabled = false;
434                 ButtonDelete.Enabled = false;
435                 ButtonRuleUp.Enabled = false;
436                 ButtonRuleDown.Enabled = false;
437                 ButtonRuleCopy.Enabled = false;
438                 ButtonRuleMove.Enabled = false;
439                 buttonRuleToggleEnabled.Enabled = false;
440             }
441             ButtonClose.Enabled = true;
442             if (_directAdd)
443             {
444                 this.Close();
445             }
446         }
447
448         private void ShowDetail()
449         {
450             if (_directAdd) return;
451
452             if (ListFilters.SelectedIndex > -1)
453             {
454                 PostFilterRule fc = (PostFilterRule)ListFilters.SelectedItem;
455                 if (fc.UseNameField)
456                 {
457                     RadioAND.Checked = true;
458                     RadioPLUS.Checked = false;
459                     UID.Enabled = true;
460                     MSG1.Enabled = true;
461                     MSG2.Enabled = false;
462                     UID.Text = fc.FilterName;
463                     UID.SelectAll();
464                     MSG1.Text = string.Join(" ", fc.FilterBody);
465                     MSG1.SelectAll();
466                     MSG2.Text = "";
467                 }
468                 else
469                 {
470                     RadioPLUS.Checked = true;
471                     RadioAND.Checked = false;
472                     UID.Enabled = false;
473                     MSG1.Enabled = false;
474                     MSG2.Enabled = true;
475                     UID.Text = "";
476                     MSG1.Text = "";
477                     MSG2.Text = string.Join(" ", fc.FilterBody);
478                     MSG2.SelectAll();
479                 }
480                 TextSource.Text = fc.FilterSource;
481                 CheckRegex.Checked = fc.UseRegex;
482                 CheckURL.Checked = fc.FilterByUrl;
483                 CheckCaseSensitive.Checked = fc.CaseSensitive;
484                 CheckRetweet.Checked = fc.FilterRt;
485                 CheckLambda.Checked = fc.UseLambda;
486
487                 if (fc.ExUseNameField)
488                 {
489                     RadioExAnd.Checked = true;
490                     RadioExPLUS.Checked = false;
491                     ExUID.Enabled = true;
492                     ExMSG1.Enabled = true;
493                     ExMSG2.Enabled = false;
494                     ExUID.Text = fc.ExFilterName;
495                     ExUID.SelectAll();
496                     ExMSG1.Text = string.Join(" ", fc.ExFilterBody);
497                     ExMSG1.SelectAll();
498                     ExMSG2.Text = "";
499                 }
500                 else
501                 {
502                     RadioExPLUS.Checked = true;
503                     RadioExAnd.Checked = false;
504                     ExUID.Enabled = false;
505                     ExMSG1.Enabled = false;
506                     ExMSG2.Enabled = true;
507                     ExUID.Text = "";
508                     ExMSG1.Text = "";
509                     ExMSG2.Text = string.Join(" ", fc.ExFilterBody);
510                     ExMSG2.SelectAll();
511                 }
512                 TextExSource.Text = fc.ExFilterSource;
513                 CheckExRegex.Checked = fc.ExUseRegex;
514                 CheckExURL.Checked = fc.ExFilterByUrl;
515                 CheckExCaseSensitive.Checked = fc.ExCaseSensitive;
516                 CheckExRetweet.Checked = fc.ExFilterRt;
517                 CheckExLambDa.Checked = fc.ExUseLambda;
518
519                 if (fc.MoveMatches)
520                 {
521                     OptMove.Checked = true;
522                 }
523                 else
524                 {
525                     OptCopy.Checked = true;
526                 }
527                 CheckMark.Checked = fc.MarkMatches;
528
529                 ButtonEdit.Enabled = true;
530                 ButtonDelete.Enabled = true;
531                 ButtonRuleUp.Enabled = true;
532                 ButtonRuleDown.Enabled = true;
533                 ButtonRuleCopy.Enabled = true;
534                 ButtonRuleMove.Enabled = true;
535                 buttonRuleToggleEnabled.Enabled = true;
536             }
537             else
538             {
539                 RadioAND.Checked = true;
540                 RadioPLUS.Checked = false;
541                 UID.Enabled = true;
542                 MSG1.Enabled = true;
543                 MSG2.Enabled = false;
544                 UID.Text = "";
545                 MSG1.Text = "";
546                 MSG2.Text = "";
547                 TextSource.Text = "";
548                 CheckRegex.Checked = false;
549                 CheckURL.Checked = false;
550                 CheckCaseSensitive.Checked = false;
551                 CheckRetweet.Checked = false;
552                 CheckLambda.Checked = false;
553
554                 RadioExAnd.Checked = true;
555                 RadioExPLUS.Checked = false;
556                 ExUID.Enabled = true;
557                 ExMSG1.Enabled = true;
558                 ExMSG2.Enabled = false;
559                 ExUID.Text = "";
560                 ExMSG1.Text = "";
561                 ExMSG2.Text = "";
562                 TextExSource.Text = "";
563                 CheckExRegex.Checked = false;
564                 CheckExURL.Checked = false;
565                 CheckExCaseSensitive.Checked = false;
566                 CheckExRetweet.Checked = false;
567                 CheckExLambDa.Checked = false;
568
569                 OptCopy.Checked = true;
570                 CheckMark.Checked = true;
571
572                 ButtonEdit.Enabled = false;
573                 ButtonDelete.Enabled = false;
574                 ButtonRuleUp.Enabled = false;
575                 ButtonRuleDown.Enabled = false;
576                 ButtonRuleCopy.Enabled = false;
577                 ButtonRuleMove.Enabled = false;
578                 buttonRuleToggleEnabled.Enabled = false;
579             }
580         }
581
582         private void RadioAND_CheckedChanged(object sender, EventArgs e)
583         {
584             bool flg = RadioAND.Checked;
585             UID.Enabled = flg;
586             MSG1.Enabled = flg;
587             MSG2.Enabled = !flg;
588         }
589
590         private void ButtonOK_Click(object sender, EventArgs e)
591         {
592             bool isBlankMatch = false;
593             bool isBlankExclude = false;
594
595             //入力チェック
596             if (!CheckMatchRule(out isBlankMatch) || !CheckExcludeRule(out isBlankExclude))
597             {
598                 return;
599             }
600             if (isBlankMatch && isBlankExclude)
601             {
602                 MessageBox.Show(Properties.Resources.ButtonOK_ClickText1, Properties.Resources.ButtonOK_ClickText2, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
603                 return;
604             }
605
606             var tab = this._sts.Tabs[(string)this.ListTabs.SelectedItem];
607             int i = ListFilters.SelectedIndex;
608
609             PostFilterRule ft;
610             if (_mode == EDITMODE.AddNew)
611                 ft = new PostFilterRule();
612             else
613                 ft = (PostFilterRule)this.ListFilters.SelectedItem;
614
615             if (tab.TabType != MyCommon.TabUsageType.Mute)
616             {
617                 ft.MoveMatches = OptMove.Checked;
618                 ft.MarkMatches = CheckMark.Checked;
619             }
620             else
621             {
622                 ft.MoveMatches = true;
623                 ft.MarkMatches = false;
624             }
625
626             string bdy = "";
627             if (RadioAND.Checked)
628             {
629                 ft.FilterName = UID.Text;
630                 TweenMain owner = (TweenMain)this.Owner;
631                 int cnt = owner.AtIdSupl.ItemCount;
632                 owner.AtIdSupl.AddItem("@" + ft.FilterName);
633                 if (cnt != owner.AtIdSupl.ItemCount)
634                 {
635                     owner.ModifySettingAtId = true;
636                 }
637                 ft.UseNameField = true;
638                 bdy = MSG1.Text;
639             }
640             else
641             {
642                 ft.FilterName = "";
643                 ft.UseNameField = false;
644                 bdy = MSG2.Text;
645             }
646             ft.FilterSource = TextSource.Text;
647
648             if (CheckRegex.Checked || CheckLambda.Checked)
649             {
650                 ft.FilterBody = new[] { bdy };
651             }
652             else
653             {
654                 ft.FilterBody = bdy.Split(' ', ' ')
655                     .Where(x => !string.IsNullOrEmpty(x))
656                     .ToArray();
657             }
658
659             ft.UseRegex = CheckRegex.Checked;
660             ft.FilterByUrl = CheckURL.Checked;
661             ft.CaseSensitive = CheckCaseSensitive.Checked;
662             ft.FilterRt = CheckRetweet.Checked;
663             ft.UseLambda = CheckLambda.Checked;
664
665             bdy = "";
666             if (RadioExAnd.Checked)
667             {
668                 ft.ExFilterName = ExUID.Text;
669                 ft.ExUseNameField = true;
670                 bdy = ExMSG1.Text;
671             }
672             else
673             {
674                 ft.ExFilterName = "";
675                 ft.ExUseNameField = false;
676                 bdy = ExMSG2.Text;
677             }
678             ft.ExFilterSource = TextExSource.Text;
679
680             if (CheckExRegex.Checked || CheckExLambDa.Checked)
681             {
682                 ft.ExFilterBody = new[] { bdy };
683             }
684             else
685             {
686                 ft.ExFilterBody = bdy.Split(' ', ' ')
687                     .Where(x => !string.IsNullOrEmpty(x))
688                     .ToArray();
689             }
690
691             ft.ExUseRegex = CheckExRegex.Checked;
692             ft.ExFilterByUrl = CheckExURL.Checked;
693             ft.ExCaseSensitive = CheckExCaseSensitive.Checked;
694             ft.ExFilterRt = CheckExRetweet.Checked;
695             ft.ExUseLambda = CheckExLambDa.Checked;
696
697             if (_mode == EDITMODE.AddNew)
698             {
699                 if (!tab.AddFilter(ft))
700                     MessageBox.Show(Properties.Resources.ButtonOK_ClickText4, Properties.Resources.ButtonOK_ClickText2, MessageBoxButtons.OK, MessageBoxIcon.Error);
701             }
702
703             SetFilters(tab.TabName);
704             ListFilters.SelectedIndex = -1;
705             if (_mode == EDITMODE.AddNew)
706             {
707                 ListFilters.SelectedIndex = ListFilters.Items.Count - 1;
708             }
709             else
710             {
711                 ListFilters.SelectedIndex = i;
712             }
713             _mode = EDITMODE.None;
714
715             if (_directAdd)
716             {
717                 this.Close();
718             }
719         }
720
721         private bool IsValidLambdaExp(string text)
722         {
723             return false;
724             // TODO DynamicQuery相当のGPLv3互換なライブラリで置換する
725         }
726
727         private bool IsValidRegexp(string text)
728         {
729             try
730             {
731                 new Regex(text);
732             }
733             catch (Exception ex)
734             {
735                 MessageBox.Show(Properties.Resources.ButtonOK_ClickText3 + ex.Message, Properties.Resources.ButtonOK_ClickText2, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
736                 return false;
737             }
738             return true;
739         }
740
741         private bool CheckMatchRule(out bool isBlank)
742         {
743             isBlank = false;
744             if (RadioAND.Checked)
745             {
746                 if (string.IsNullOrEmpty(UID.Text) && string.IsNullOrEmpty(MSG1.Text) && string.IsNullOrEmpty(TextSource.Text) && CheckRetweet.Checked == false)
747                 {
748                     isBlank = true;
749                     return true;
750                 }
751                 if (CheckLambda.Checked)
752                 {
753                     if (!IsValidLambdaExp(UID.Text))
754                     {
755                         return false;
756                     }
757                     if (!IsValidLambdaExp(MSG1.Text))
758                     {
759                         return false;
760                     }
761                 }
762                 else if (CheckRegex.Checked)
763                 {
764                     if (!IsValidRegexp(UID.Text))
765                     {
766                         return false;
767                     }
768                     if (!IsValidRegexp(MSG1.Text))
769                     {
770                         return false;
771                     }
772                 }
773             }
774             else
775             {
776                 if (string.IsNullOrEmpty(MSG2.Text) && string.IsNullOrEmpty(TextSource.Text) && CheckRetweet.Checked == false)
777                 {
778                     isBlank = true;
779                     return true;
780                 }
781                 if (CheckLambda.Checked && !IsValidLambdaExp(MSG2.Text))
782                 {
783                     return false;
784                 }
785                 else if (CheckRegex.Checked && !IsValidRegexp(MSG2.Text))
786                 {
787                     return false;
788                 }
789             }
790
791             if (CheckRegex.Checked && !IsValidRegexp(TextSource.Text))
792             {
793                 return false;
794             }
795             return true;
796         }
797
798         private bool CheckExcludeRule(out bool isBlank)
799         {
800             isBlank = false;
801             if (RadioExAnd.Checked)
802             {
803                 if (string.IsNullOrEmpty(ExUID.Text) && string.IsNullOrEmpty(ExMSG1.Text) && string.IsNullOrEmpty(TextExSource.Text) && CheckExRetweet.Checked == false)
804                 {
805                     isBlank = true;
806                     return true;
807                 }
808                 if (CheckExLambDa.Checked)
809                 {
810                     if (!IsValidLambdaExp(ExUID.Text))
811                     {
812                         return false;
813                     }
814                     if (!IsValidLambdaExp(ExMSG1.Text))
815                     {
816                         return false;
817                     }
818                 }
819                 else if (CheckExRegex.Checked)
820                 {
821                     if (!IsValidRegexp(ExUID.Text))
822                     {
823                         return false;
824                     }
825                     if (!IsValidRegexp(ExMSG1.Text))
826                     {
827                         return false;
828                     }
829                 }
830             }
831             else
832             {
833                 if (string.IsNullOrEmpty(ExMSG2.Text) && string.IsNullOrEmpty(TextExSource.Text) && CheckExRetweet.Checked == false)
834                 {
835                     isBlank = true;
836                     return true;
837                 }
838                 if (CheckExLambDa.Checked && !IsValidLambdaExp(ExMSG2.Text))
839                 {
840                     return false;
841                 }
842                 else if (CheckExRegex.Checked && !IsValidRegexp(ExMSG2.Text))
843                 {
844                     return false;
845                 }
846             }
847
848             if (CheckExRegex.Checked && !IsValidRegexp(TextExSource.Text))
849             {
850                 return false;
851             }
852
853             return true;
854         }
855
856         private void ListFilters_SelectedIndexChanged(object sender, EventArgs e)
857         {
858             if (_moveRules)
859                 return;
860
861             ShowDetail();
862
863             var selectedCount = this.ListFilters.SelectedIndices.Count;
864             if (selectedCount == 0)
865             {
866                 this.RuleEnableButtonMode = EnableButtonMode.NotSelected;
867             }
868             else
869             {
870                 if (selectedCount == 1 ||
871                     this.RuleEnableButtonMode == EnableButtonMode.NotSelected)
872                 {
873                     var topItem = (PostFilterRule)this.ListFilters.SelectedItem;
874                     this.RuleEnableButtonMode = topItem.Enabled ? EnableButtonMode.Disable : EnableButtonMode.Enable;
875                 }
876             }
877         }
878
879         private void ButtonClose_Click(object sender, EventArgs e)
880         {
881             this.Close();
882         }
883
884         private void FilterDialog_FormClosed(object sender, FormClosedEventArgs e)
885         {
886             _directAdd = false;
887         }
888
889         private void FilterDialog_KeyDown(object sender, KeyEventArgs e)
890         {
891             if (e.KeyCode == Keys.Escape)
892             {
893                 if (EditFilterGroup.Enabled)
894                     ButtonCancel_Click(null, null);
895                 else
896                     ButtonClose_Click(null, null);
897             }
898         }
899
900         private void ListFilters_DoubleClick(object sender, EventArgs e)
901         {
902             var idx = ListFilters.SelectedIndex;
903             if (idx == -1) return;
904
905             var midx = ListFilters.IndexFromPoint(ListFilters.PointToClient(Control.MousePosition));
906             if (midx == ListBox.NoMatches || idx != midx) return;
907
908             ButtonEdit_Click(sender, e);
909         }
910
911         private void FilterDialog_Shown(object sender, EventArgs e)
912         {
913             _sts = TabInformations.GetInstance();
914             ListTabs.Items.Clear();
915             foreach (var tab in this._sts.Tabs.Values)
916             {
917                 if (tab.TabType == MyCommon.TabUsageType.Mute)
918                     continue;
919
920                 this.ListTabs.Items.Add(tab.TabName);
921             }
922
923             var muteTab = this._sts.GetTabByType(MyCommon.TabUsageType.Mute);
924             if (muteTab != null)
925                 this.ListTabs.Items.Add(muteTab.TabName);
926
927             ComboSound.Items.Clear();
928             ComboSound.Items.Add("");
929             DirectoryInfo oDir = new DirectoryInfo(Application.StartupPath + Path.DirectorySeparatorChar);
930             if (Directory.Exists(Path.Combine(Application.StartupPath, "Sounds")))
931             {
932                 oDir = oDir.GetDirectories("Sounds")[0];
933             }
934             foreach (FileInfo oFile in oDir.GetFiles("*.wav"))
935             {
936                 ComboSound.Items.Add(oFile.Name);
937             }
938
939             idlist.Clear();
940             foreach (string tmp in ((TweenMain)this.Owner).AtIdSupl.GetItemList())
941             {
942                 idlist.Add(tmp.Remove(0, 1));  // @文字削除
943             }
944             UID.AutoCompleteCustomSource.Clear();
945             UID.AutoCompleteCustomSource.AddRange(idlist.ToArray());
946
947             ExUID.AutoCompleteCustomSource.Clear();
948             ExUID.AutoCompleteCustomSource.AddRange(idlist.ToArray());
949
950             //選択タブ変更
951             if (ListTabs.Items.Count > 0)
952             {
953                 if (_cur.Length > 0)
954                 {
955                     for (int i = 0; i < ListTabs.Items.Count; i++)
956                     {
957                         if (_cur == ListTabs.Items[i].ToString())
958                         {
959                             ListTabs.SelectedIndex = i;
960                             //tabdialog.TabList.Items.Remove(_cur);
961                             break;
962                         }
963                     }
964                 }
965             }
966         }
967
968         private void ListTabs_SelectedIndexChanged(object sender, EventArgs e)
969         {
970             if (ListTabs.SelectedIndex > -1)
971                 SetFilters(ListTabs.SelectedItem.ToString());
972             else
973                 ListFilters.Items.Clear();
974         }
975
976         private void ButtonAddTab_Click(object sender, EventArgs e)
977         {
978             string tabName = null;
979             MyCommon.TabUsageType tabType;
980             using (InputTabName inputName = new InputTabName())
981             {
982                 inputName.TabName = _sts.GetUniqueTabName();
983                 inputName.IsShowUsage = true;
984                 inputName.ShowDialog();
985                 if (inputName.DialogResult == DialogResult.Cancel) return;
986                 tabName = inputName.TabName;
987                 tabType = inputName.Usage;
988             }
989             if (!string.IsNullOrEmpty(tabName))
990             {
991                 //List対応
992                 ListElement list = null;
993                 if (tabType == MyCommon.TabUsageType.Lists)
994                 {
995                     string rslt = ((TweenMain)this.Owner).TwitterInstance.GetListsApi();
996                     if (!string.IsNullOrEmpty(rslt))
997                     {
998                         MessageBox.Show("Failed to get lists. (" + rslt + ")");
999                     }
1000                     using (ListAvailable listAvail = new ListAvailable())
1001                     {
1002                         if (listAvail.ShowDialog(this) == DialogResult.Cancel) return;
1003                         if (listAvail.SelectedList == null) return;
1004                         list = listAvail.SelectedList;
1005                     }
1006                 }
1007                 if (!_sts.AddTab(tabName, tabType, list) || !((TweenMain)this.Owner).AddNewTab(tabName, false, tabType, list))
1008                 {
1009                     string tmp = string.Format(Properties.Resources.AddTabMenuItem_ClickText1, tabName);
1010                     MessageBox.Show(tmp, Properties.Resources.AddTabMenuItem_ClickText2, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
1011                     return;
1012                 }
1013                 else
1014                 {
1015                     // タブ作成成功
1016
1017                     // 末尾のタブを取得する
1018                     var lastIdx = this.ListTabs.Items.Count - 1;
1019                     var lastTab = lastIdx != -1
1020                         ? this._sts.Tabs[(string)this.ListTabs.Items[lastIdx]]
1021                         : null;
1022
1023                     // 末尾がミュートタブであればその手前に追加する
1024                     if (lastTab != null && lastTab.TabType == MyCommon.TabUsageType.Mute)
1025                         this.ListTabs.Items.Insert(lastIdx, tabName);
1026                     else
1027                         this.ListTabs.Items.Add(tabName);
1028                 }
1029             }
1030         }
1031
1032         private void ButtonDeleteTab_Click(object sender, EventArgs e)
1033         {
1034             if (ListTabs.SelectedIndex > -1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
1035             {
1036                 string tb = ListTabs.SelectedItem.ToString();
1037                 int idx = ListTabs.SelectedIndex;
1038                 if (((TweenMain)this.Owner).RemoveSpecifiedTab(tb, true))
1039                 {
1040                     ListTabs.Items.RemoveAt(idx);
1041                     idx -= 1;
1042                     if (idx < 0) idx = 0;
1043                     ListTabs.SelectedIndex = idx;
1044                 }
1045             }
1046         }
1047
1048         private void ButtonRenameTab_Click(object sender, EventArgs e)
1049         {
1050             if (ListTabs.SelectedIndex > -1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
1051             {
1052                 string tb = ListTabs.SelectedItem.ToString();
1053                 int idx = ListTabs.SelectedIndex;
1054                 if (((TweenMain)this.Owner).TabRename(ref tb))
1055                 {
1056                     ListTabs.Items.RemoveAt(idx);
1057                     ListTabs.Items.Insert(idx, tb);
1058                     ListTabs.SelectedIndex = idx;
1059                 }
1060             }
1061         }
1062
1063         private void CheckManageRead_CheckedChanged(object sender, EventArgs e)
1064         {
1065             if (ListTabs.SelectedIndex > -1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
1066             {
1067                 ((TweenMain)this.Owner).ChangeTabUnreadManage(
1068                     ListTabs.SelectedItem.ToString(),
1069                     CheckManageRead.Checked);
1070             }
1071         }
1072
1073         private void ButtonUp_Click(object sender, EventArgs e)
1074         {
1075             if (this.ListTabs.SelectedIndex == -1 || this.ListTabs.SelectedIndex == 0)
1076                 return;
1077
1078             var selectedTabName = (string)this.ListTabs.SelectedItem;
1079             var selectedTab = this._sts.Tabs[selectedTabName];
1080
1081             var targetTabName = (string)this.ListTabs.Items[this.ListTabs.SelectedIndex - 1];
1082             var targetTab = this._sts.Tabs[targetTabName];
1083
1084             // ミュートタブは移動禁止
1085             if (selectedTab.TabType == MyCommon.TabUsageType.Mute || targetTab.TabType == MyCommon.TabUsageType.Mute)
1086                 return;
1087
1088             var tweenMain = (TweenMain)this.Owner;
1089             tweenMain.ReOrderTab(selectedTabName, targetTabName, true);
1090
1091             // ListTab のアイテム並び替え
1092             // 選択が解除されてしまうのを防ぐため SelectedIndex のアイテムは操作せず前後のアイテムを移動する
1093             var idx = this.ListTabs.SelectedIndex;
1094             this.ListTabs.Items.RemoveAt(idx - 1);
1095             this.ListTabs.Items.Insert(idx, targetTabName);
1096         }
1097
1098         private void ButtonDown_Click(object sender, EventArgs e)
1099         {
1100             if (this.ListTabs.SelectedIndex == -1 || this.ListTabs.SelectedIndex == this.ListTabs.Items.Count - 1)
1101                 return;
1102
1103             var selectedTabName = (string)this.ListTabs.SelectedItem;
1104             var selectedTab = this._sts.Tabs[selectedTabName];
1105
1106             var targetTabName = (string)this.ListTabs.Items[this.ListTabs.SelectedIndex + 1];
1107             var targetTab = this._sts.Tabs[targetTabName];
1108
1109             // ミュートタブは移動禁止
1110             if (selectedTab.TabType == MyCommon.TabUsageType.Mute || targetTab.TabType == MyCommon.TabUsageType.Mute)
1111                 return;
1112
1113             var tweenMain = (TweenMain)this.Owner;
1114             tweenMain.ReOrderTab(selectedTabName, targetTabName, false);
1115
1116             // ListTab のアイテム並び替え
1117             // 選択が解除されてしまうのを防ぐため SelectedIndex のアイテムは操作せず前後のアイテムを移動する
1118             var idx = this.ListTabs.SelectedIndex;
1119             this.ListTabs.Items.RemoveAt(idx + 1);
1120             this.ListTabs.Items.Insert(idx, targetTabName);
1121         }
1122
1123         private void CheckLocked_CheckedChanged(object sender, EventArgs e)
1124         {
1125             if (ListTabs.SelectedIndex > -1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
1126             {
1127                 _sts.Tabs[ListTabs.SelectedItem.ToString()].Protected = CheckProtected.Checked;
1128                 ButtonDeleteTab.Enabled = !CheckProtected.Checked;
1129             }
1130         }
1131
1132         private void CheckNotifyNew_CheckedChanged(object sender, EventArgs e)
1133         {
1134             if (ListTabs.SelectedIndex > -1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
1135             {
1136                 _sts.Tabs[ListTabs.SelectedItem.ToString()].Notify = CheckNotifyNew.Checked;
1137             }
1138         }
1139
1140         private void ComboSound_SelectedIndexChanged(object sender, EventArgs e)
1141         {
1142             if (ListTabs.SelectedIndex > -1 && string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
1143             {
1144                 string filename = "";
1145                 if (ComboSound.SelectedIndex > -1) filename = ComboSound.SelectedItem.ToString();
1146                 _sts.Tabs[ListTabs.SelectedItem.ToString()].SoundFile = filename;
1147             }
1148         }
1149
1150         private void RadioExAnd_CheckedChanged(object sender, EventArgs e)
1151         {
1152             bool flg = RadioExAnd.Checked;
1153             ExUID.Enabled = flg;
1154             ExMSG1.Enabled = flg;
1155             ExMSG2.Enabled = !flg;
1156         }
1157
1158         private void OptMove_CheckedChanged(object sender, EventArgs e)
1159         {
1160             CheckMark.Enabled = !OptMove.Checked;
1161         }
1162
1163         private void ButtonRuleUp_Click(object sender, EventArgs e)
1164         {
1165             MoveSelectedRules(up: true);
1166         }
1167
1168         private void ButtonRuleDown_Click(object sender, EventArgs e)
1169         {
1170             MoveSelectedRules(up: false);
1171         }
1172
1173         private void MoveSelectedRules(bool up)
1174         {
1175             var tabIdx = ListTabs.SelectedIndex;
1176             if (tabIdx == -1 ||
1177                 ListFilters.SelectedIndices.Count == 0) return;
1178
1179             var indices = ListFilters.SelectedIndices.Cast<int>().ToArray();
1180
1181             int diff;
1182             if (up)
1183             {
1184                 if (indices[0] <= 0) return;
1185                 diff = -1;
1186             }
1187             else
1188             {
1189                 if (indices[indices.Length - 1] >= ListFilters.Items.Count - 1) return;
1190                 diff = +1;
1191                 Array.Reverse(indices);  // 逆順にして、下にある要素から処理する
1192             }
1193
1194             var lastSelIdx = indices[0] + diff;
1195             var tab = _sts.Tabs[ListTabs.Items[tabIdx].ToString()];
1196
1197             try
1198             {
1199                 _moveRules = true;  // SelectedIndexChanged を無視する
1200
1201                 using (ControlTransaction.Update(ListFilters))
1202                 {
1203                     ListFilters.SelectedIndices.Clear();
1204
1205                     foreach (var idx in indices)
1206                     {
1207                         var tidx = idx + diff;
1208                         var target = (PostFilterRule)ListFilters.Items[tidx];
1209
1210                         // 移動先にある要素と位置を入れ替える
1211                         ListFilters.Items.RemoveAt(tidx);
1212                         ListFilters.Items.Insert(idx, target);
1213
1214                         // 移動方向の先頭要素以外なら選択する
1215                         if (tidx != lastSelIdx)
1216                             ListFilters.SelectedIndex = tidx;
1217                     }
1218
1219                     tab.FilterArray = ListFilters.Items.Cast<PostFilterRule>().ToArray();
1220
1221                     // 移動方向の先頭要素は最後に選択する
1222                     // ※移動方向への自動スクロール目的
1223                     ListFilters.SelectedIndex = lastSelIdx;
1224                 }
1225             }
1226             finally
1227             {
1228                 _moveRules = false;
1229             }
1230         }
1231
1232         private void buttonRuleToggleEnabled_Click(object sender, EventArgs e)
1233         {
1234             if (this.RuleEnableButtonMode == EnableButtonMode.NotSelected)
1235                 return;
1236
1237             var enabled = this.RuleEnableButtonMode == EnableButtonMode.Enable;
1238
1239             foreach (var idx in this.ListFilters.SelectedIndices.Cast<int>())
1240             {
1241                 var filter = (PostFilterRule)this.ListFilters.Items[idx];
1242                 if (filter.Enabled != enabled)
1243                 {
1244                     filter.Enabled = enabled;
1245
1246                     var itemRect = this.ListFilters.GetItemRectangle(idx);
1247                     this.ListFilters.Invalidate(itemRect);
1248                 }
1249             }
1250
1251             this.RuleEnableButtonMode = enabled ? EnableButtonMode.Disable : EnableButtonMode.Enable;
1252         }
1253
1254         private void ButtonRuleCopy_Click(object sender, EventArgs e)
1255         {
1256             if (ListTabs.SelectedIndex > -1 && ListFilters.SelectedItem != null)
1257             {
1258                 TabClass[] selectedTabs;
1259                 using (TabsDialog dialog = new TabsDialog(_sts))
1260                 {
1261                     dialog.MultiSelect = true;
1262                     dialog.Text = Properties.Resources.ButtonRuleCopy_ClickText1;
1263
1264                     if (dialog.ShowDialog(this) == DialogResult.Cancel) return;
1265
1266                     selectedTabs = dialog.SelectedTabs;
1267                 }
1268
1269                 string tabname = ListTabs.SelectedItem.ToString();
1270                 List<PostFilterRule> filters = new List<PostFilterRule>();
1271
1272                 foreach (int idx in ListFilters.SelectedIndices)
1273                 {
1274                     filters.Add(_sts.Tabs[tabname].FilterArray[idx].Clone());
1275                 }
1276                 foreach (var tb in selectedTabs)
1277                 {
1278                     if (tb.TabName == tabname) continue;
1279
1280                     foreach (PostFilterRule flt in filters)
1281                     {
1282                         if (!tb.FilterArray.Contains(flt))
1283                             tb.AddFilter(flt.Clone());
1284                     }
1285                 }
1286                 SetFilters(tabname);
1287             }
1288         }
1289
1290         private void ButtonRuleMove_Click(object sender, EventArgs e)
1291         {
1292             if (ListTabs.SelectedIndex > -1 && ListFilters.SelectedItem != null)
1293             {
1294                 TabClass[] selectedTabs;
1295                 using (var dialog = new TabsDialog(_sts))
1296                 {
1297                     dialog.MultiSelect = true;
1298                     dialog.Text = Properties.Resources.ButtonRuleMove_ClickText1;
1299
1300                     if (dialog.ShowDialog(this) == DialogResult.Cancel) return;
1301
1302                     selectedTabs = dialog.SelectedTabs;
1303                 }
1304                 string tabname = ListTabs.SelectedItem.ToString();
1305                 List<PostFilterRule> filters = new List<PostFilterRule>();
1306
1307                 foreach (int idx in ListFilters.SelectedIndices)
1308                 {
1309                     filters.Add(_sts.Tabs[tabname].FilterArray[idx].Clone());
1310                 }
1311                 if (selectedTabs.Length == 1 && selectedTabs[0].TabName == tabname) return;
1312                 foreach (var tb in selectedTabs)
1313                 {
1314                     if (tb.TabName == tabname) continue;
1315
1316                     foreach (PostFilterRule flt in filters)
1317                     {
1318                         if (!tb.FilterArray.Contains(flt))
1319                             tb.AddFilter(flt.Clone());
1320                     }
1321                 }
1322                 for (int idx = ListFilters.Items.Count - 1; idx >= 0; idx--)
1323                 {
1324                     if (ListFilters.GetSelected(idx))
1325                     {
1326                         _sts.Tabs[ListTabs.SelectedItem.ToString()].RemoveFilter((PostFilterRule)ListFilters.Items[idx]);
1327                         ListFilters.Items.RemoveAt(idx);
1328                     }
1329                 }
1330                 SetFilters(tabname);
1331             }
1332         }
1333
1334         private void FilterTextBox_KeyDown(object sender, KeyEventArgs e)
1335         {
1336             if (e.KeyCode == Keys.Space && e.Modifiers == (Keys.Shift | Keys.Control))
1337             {
1338                 TweenMain main = (TweenMain)this.Owner;
1339                 TextBox tbox = (TextBox)sender;
1340                 if (tbox.SelectionStart > 0)
1341                 {
1342                     int endidx = tbox.SelectionStart - 1;
1343                     string startstr = "";
1344                     for (int i = tbox.SelectionStart - 1; i >= 0; i--)
1345                     {
1346                         char c = tbox.Text[i];
1347                         if (Char.IsLetterOrDigit(c) || c == '_')
1348                         {
1349                             continue;
1350                         }
1351                         if (c == '@')
1352                         {
1353                             startstr = tbox.Text.Substring(i + 1, endidx - i);
1354                             main.ShowSuplDialog(tbox, main.AtIdSupl, startstr.Length + 1, startstr);
1355                         }
1356                         else if (c == '#')
1357                         {
1358                             startstr = tbox.Text.Substring(i + 1, endidx - i);
1359                             main.ShowSuplDialog(tbox, main.HashSupl, startstr.Length + 1, startstr);
1360                         }
1361                         else
1362                         {
1363                             break;
1364                         }
1365                     }
1366                     e.Handled = true;
1367                 }
1368             }
1369         }
1370
1371         private void FilterTextBox_KeyPress(object sender, KeyPressEventArgs e)
1372         {
1373             TweenMain main = (TweenMain)this.Owner;
1374             TextBox tbox = (TextBox)sender;
1375             if (e.KeyChar == '@')
1376             {
1377                 //if (!SettingDialog.UseAtIdSupplement) return;
1378                 //@マーク
1379                 main.ShowSuplDialog(tbox, main.AtIdSupl);
1380                 e.Handled = true;
1381             }
1382             else if (e.KeyChar == '#')
1383             {
1384                 //if (!SettingDialog.UseHashSupplement) return;
1385                 main.ShowSuplDialog(tbox, main.HashSupl);
1386                 e.Handled = true;
1387             }
1388         }
1389
1390         private void ListFilters_DrawItem(object sender, DrawItemEventArgs e)
1391         {
1392             e.DrawBackground();
1393
1394             if (e.Index != -1)
1395             {
1396                 var filter = (PostFilterRule)this.ListFilters.Items[e.Index];
1397                 var isSelected = e.State.HasFlag(DrawItemState.Selected);
1398
1399                 Brush textBrush;
1400                 if (isSelected)
1401                     textBrush = SystemBrushes.HighlightText;
1402                 else if (filter.Enabled)
1403                     textBrush = SystemBrushes.WindowText;
1404                 else
1405                     textBrush = SystemBrushes.GrayText;
1406
1407                 e.Graphics.DrawString(filter.ToString(), e.Font, textBrush, e.Bounds);
1408             }
1409
1410             e.DrawFocusRectangle();
1411         }
1412
1413         protected override void OnFontChanged(EventArgs e)
1414         {
1415             base.OnFontChanged(e);
1416             this.ListFilters.ItemHeight = this.ListFilters.Font.Height;
1417         }
1418     }
1419 }