OSDN Git Service

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