OSDN Git Service

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