OSDN Git Service

usingの順序を揃える (SA1208, SA1210)
[opentween/open-tween.git] / OpenTween / FilterDialog.cs
index ebc0798..ef373cb 100644 (file)
@@ -6,46 +6,53 @@
 //           (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
 //           (c) 2011-2012 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
 // All rights reserved.
-// 
+//
 // This file is part of OpenTween.
-// 
+//
 // This program is free software; you can redistribute it and/or modify it
 // under the terms of the GNU General Public License as published by the Free
 // Software Foundation; either version 3 of the License, or (at your option)
 // any later version.
-// 
+//
 // This program is distributed in the hope that it will be useful, but
 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-// for more details. 
-// 
+// for more details.
+//
 // You should have received a copy of the GNU General Public License along
 // with this program. If not, see <http://www.gnu.org/licenses/>, or write to
 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 // Boston, MA 02110-1301, USA.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
+using System.Collections.Specialized;
 using System.ComponentModel;
 using System.Data;
 using System.Drawing;
+using System.IO;
 using System.Linq;
-using System.Text;
-using System.Windows.Forms;
 using System.Linq.Expressions;
+using System.Text;
 using System.Text.RegularExpressions;
-using System.IO;
-using System.Collections.Specialized;
+using System.Windows.Forms;
+using OpenTween.Models;
 
 namespace OpenTween
 {
-    public partial class FilterDialog : Form
+    public partial class FilterDialog : OTBaseForm
     {
         private EDITMODE _mode;
         private bool _directAdd;
-        private TabInformations _sts;
-        private string _cur;
-        private List<string> idlist = new List<string>();
+        private MultiSelectionState _multiSelState = MultiSelectionState.None;
+        private readonly TabInformations _sts;
+
+        private List<TabModel> tabs = new List<TabModel>();
+        private int selectedTabIndex = -1;
+
+        private readonly List<string> idlist = new List<string>();
 
         private enum EDITMODE
         {
@@ -54,335 +61,403 @@ namespace OpenTween
             None,
         }
 
+        private enum EnableButtonMode
+        {
+            NotSelected,
+            Enable,
+            Disable,
+        }
+
+        [Flags]
+        private enum MultiSelectionState
+        {
+            None = 0,
+            MoveSelected = 1,
+            SelectAll = 2,
+        }
+
+        private EnableButtonMode RuleEnableButtonMode
+        {
+            get => this._ruleEnableButtonMode;
+            set
+            {
+                this._ruleEnableButtonMode = value;
+
+                this.buttonRuleToggleEnabled.Text = value == FilterDialog.EnableButtonMode.Enable
+                    ? Properties.Resources.EnableButtonCaption
+                    : Properties.Resources.DisableButtonCaption;
+                this.buttonRuleToggleEnabled.Enabled = value != EnableButtonMode.NotSelected;
+            }
+        }
+        private EnableButtonMode _ruleEnableButtonMode = FilterDialog.EnableButtonMode.NotSelected;
+
+        public TabModel? SelectedTab
+            => this.selectedTabIndex != -1 ? this.tabs[this.selectedTabIndex] : null;
+
         public FilterDialog()
         {
-            InitializeComponent();
+            this.InitializeComponent();
+
+            this._sts = TabInformations.GetInstance();
+            this.RefreshListTabs();
+        }
+
+        private void RefreshListTabs()
+        {
+            this.tabs = this._sts.Tabs.Append(this._sts.MuteTab).ToList();
+
+            using (ControlTransaction.Update(this.ListTabs))
+            {
+                var selectedTab = this.ListTabs.SelectedItem;
+                this.ListTabs.Items.Clear();
+                this.ListTabs.Items.AddRange(this.tabs.ToArray());
+                this.ListTabs.SelectedIndex = this.tabs.FindIndex(x => x == selectedTab);
+            }
         }
 
-        private void SetFilters(string tabName)
+        private void SetFilters(TabModel tab)
         {
-            if (ListTabs.Items.Count == 0) return;
+            if (this.ListTabs.Items.Count == 0) return;
+
+            this.ListFilters.Items.Clear();
 
-            ListFilters.Items.Clear();
-            ListFilters.Items.AddRange(_sts.Tabs[tabName].GetFilters());
-            if (ListFilters.Items.Count > 0) ListFilters.SelectedIndex = 0;
+            if (tab is FilterTabModel filterTab)
+                this.ListFilters.Items.AddRange(filterTab.GetFilters());
 
-            if (TabInformations.GetInstance().IsDefaultTab(tabName))
+            if (this.ListFilters.Items.Count > 0)
+                this.ListFilters.SelectedIndex = 0;
+            else
+                this.ShowDetail();
+
+            if (tab.IsDefaultTabType)
             {
-                CheckProtected.Checked = true;
-                CheckProtected.Enabled = false;
+                this.CheckProtected.Checked = true;
+                this.CheckProtected.Enabled = false;
             }
             else
             {
-                CheckProtected.Checked = _sts.Tabs[tabName].Protected;
-                CheckProtected.Enabled = true;
+                this.CheckProtected.Checked = tab.Protected;
+                this.CheckProtected.Enabled = true;
             }
 
-            CheckManageRead.Checked = _sts.Tabs[tabName].UnreadManage;
-            CheckNotifyNew.Checked = _sts.Tabs[tabName].Notify;
+            this.CheckManageRead.CheckedChanged -= this.CheckManageRead_CheckedChanged;
+            this.CheckManageRead.Checked = tab.UnreadManage;
+            this.CheckManageRead.CheckedChanged += this.CheckManageRead_CheckedChanged;
+
+            this.CheckNotifyNew.CheckedChanged -= this.CheckNotifyNew_CheckedChanged;
+            this.CheckNotifyNew.Checked = tab.Notify;
+            this.CheckNotifyNew.CheckedChanged += this.CheckNotifyNew_CheckedChanged;
 
-            int idx = ComboSound.Items.IndexOf(_sts.Tabs[tabName].SoundFile);
+            var idx = this.ComboSound.Items.IndexOf(tab.SoundFile);
             if (idx == -1) idx = 0;
-            ComboSound.SelectedIndex = idx;
-
-            if (_directAdd) return;
-
-            ListTabs.Enabled = true;
-            GroupTab.Enabled = true;
-            ListFilters.Enabled = true;
-            if (ListFilters.SelectedIndex != -1)
-            {
-                ShowDetail();
-            }
-            EditFilterGroup.Enabled = false;
-            switch (TabInformations.GetInstance().Tabs[tabName].TabType)
-            {
-                case MyCommon.TabUsageType.Home:
-                case MyCommon.TabUsageType.DirectMessage:
-                case MyCommon.TabUsageType.Favorites:
-                case MyCommon.TabUsageType.PublicSearch:
-                case MyCommon.TabUsageType.Lists:
-                case MyCommon.TabUsageType.Related:
-                case MyCommon.TabUsageType.UserTimeline:
-                    ButtonNew.Enabled = false;
-                    ButtonEdit.Enabled = false;
-                    ButtonDelete.Enabled = false;
-                    ButtonRuleUp.Enabled = false;
-                    ButtonRuleDown.Enabled = false;
-                    ButtonRuleCopy.Enabled = false;
-                    ButtonRuleMove.Enabled = false;
-                    break;
-                default:
-                    ButtonNew.Enabled = true;
-                    if (ListFilters.SelectedIndex > -1)
-                    {
-                        ButtonEdit.Enabled = true;
-                        ButtonDelete.Enabled = true;
-                        ButtonRuleUp.Enabled = true;
-                        ButtonRuleDown.Enabled = true;
-                        ButtonRuleCopy.Enabled = true;
-                        ButtonRuleMove.Enabled = true;
-                    }
-                    else
-                    {
-                        ButtonEdit.Enabled = false;
-                        ButtonDelete.Enabled = false;
-                        ButtonRuleUp.Enabled = false;
-                        ButtonRuleDown.Enabled = false;
-                        ButtonRuleCopy.Enabled = false;
-                        ButtonRuleMove.Enabled = false;
-                    }
-                    break;
-            }
-            switch (TabInformations.GetInstance().Tabs[tabName].TabType)
-            {
-                case MyCommon.TabUsageType.Home:
-                    LabelTabType.Text = Properties.Resources.TabUsageTypeName_Home;
-                    break;
-                case MyCommon.TabUsageType.Mentions:
-                    LabelTabType.Text = Properties.Resources.TabUsageTypeName_Mentions;
-                    break;
-                case MyCommon.TabUsageType.DirectMessage:
-                    LabelTabType.Text = Properties.Resources.TabUsageTypeName_DirectMessage;
-                    break;
-                case MyCommon.TabUsageType.Favorites:
-                    LabelTabType.Text = Properties.Resources.TabUsageTypeName_Favorites;
-                    break;
-                case MyCommon.TabUsageType.UserDefined:
-                    LabelTabType.Text = Properties.Resources.TabUsageTypeName_UserDefined;
-                    break;
-                case MyCommon.TabUsageType.PublicSearch:
-                    LabelTabType.Text = Properties.Resources.TabUsageTypeName_PublicSearch;
-                    break;
-                case MyCommon.TabUsageType.Lists:
-                    LabelTabType.Text = Properties.Resources.TabUsageTypeName_Lists;
-                    break;
-                case MyCommon.TabUsageType.Related:
-                    LabelTabType.Text = Properties.Resources.TabUsageTypeName_Related;
-                    break;
-                case MyCommon.TabUsageType.UserTimeline:
-                    LabelTabType.Text = Properties.Resources.TabUsageTypeName_UserTimeline;
-                    break;
-                default:
-                    LabelTabType.Text = "UNKNOWN";
-                    break;
-            }
-            ButtonRenameTab.Enabled = true;
-            if (TabInformations.GetInstance().IsDefaultTab(tabName) || TabInformations.GetInstance().Tabs[tabName].Protected)
-            {
-                ButtonDeleteTab.Enabled = false;
+            this.ComboSound.SelectedIndex = idx;
+
+            if (this._directAdd) return;
+
+            if (tab.TabType == MyCommon.TabUsageType.Mute)
+            {
+                this.ButtonRenameTab.Enabled = false;
+                this.CheckManageRead.Enabled = false;
+                this.CheckNotifyNew.Enabled = false;
+                this.ComboSound.Enabled = false;
+
+                this.GroupBox1.Visible = false;
+                this.labelMuteTab.Visible = true;
+            }
+            else
+            {
+                this.ButtonRenameTab.Enabled = true;
+                this.CheckManageRead.Enabled = true;
+                this.CheckNotifyNew.Enabled = true;
+                this.ComboSound.Enabled = true;
+
+                this.GroupBox1.Visible = true;
+                this.labelMuteTab.Visible = false;
+            }
+
+            this.ListTabs.Enabled = true;
+            this.GroupTab.Enabled = true;
+            this.ListFilters.Enabled = true;
+            this.EditFilterGroup.Enabled = false;
+
+            if (tab.IsDistributableTabType)
+            {
+                this.ButtonNew.Enabled = true;
+                if (this.ListFilters.SelectedIndex > -1)
+                {
+                    this.ButtonEdit.Enabled = true;
+                    this.ButtonDelete.Enabled = true;
+                    this.ButtonRuleUp.Enabled = true;
+                    this.ButtonRuleDown.Enabled = true;
+                    this.ButtonRuleCopy.Enabled = true;
+                    this.ButtonRuleMove.Enabled = true;
+                    this.buttonRuleToggleEnabled.Enabled = true;
+                }
+                else
+                {
+                    this.ButtonEdit.Enabled = false;
+                    this.ButtonDelete.Enabled = false;
+                    this.ButtonRuleUp.Enabled = false;
+                    this.ButtonRuleDown.Enabled = false;
+                    this.ButtonRuleCopy.Enabled = false;
+                    this.ButtonRuleMove.Enabled = false;
+                    this.buttonRuleToggleEnabled.Enabled = false;
+                }
             }
             else
             {
-                ButtonDeleteTab.Enabled = true;
+                this.ButtonNew.Enabled = false;
+                this.ButtonEdit.Enabled = false;
+                this.ButtonDelete.Enabled = false;
+                this.ButtonRuleUp.Enabled = false;
+                this.ButtonRuleDown.Enabled = false;
+                this.ButtonRuleCopy.Enabled = false;
+                this.ButtonRuleMove.Enabled = false;
+                this.buttonRuleToggleEnabled.Enabled = false;
             }
-            ButtonClose.Enabled = true;
+
+            this.LabelTabType.Text = tab.TabType switch
+            {
+                MyCommon.TabUsageType.Home => Properties.Resources.TabUsageTypeName_Home,
+                MyCommon.TabUsageType.Mentions => Properties.Resources.TabUsageTypeName_Mentions,
+                MyCommon.TabUsageType.DirectMessage => Properties.Resources.TabUsageTypeName_DirectMessage,
+                MyCommon.TabUsageType.Favorites => Properties.Resources.TabUsageTypeName_Favorites,
+                MyCommon.TabUsageType.UserDefined => Properties.Resources.TabUsageTypeName_UserDefined,
+                MyCommon.TabUsageType.PublicSearch => Properties.Resources.TabUsageTypeName_PublicSearch,
+                MyCommon.TabUsageType.Lists => Properties.Resources.TabUsageTypeName_Lists,
+                MyCommon.TabUsageType.Related => Properties.Resources.TabUsageTypeName_Related,
+                MyCommon.TabUsageType.UserTimeline => Properties.Resources.TabUsageTypeName_UserTimeline,
+                MyCommon.TabUsageType.Mute => "Mute",
+                MyCommon.TabUsageType.SearchResults => "SearchResults",
+                _ => "UNKNOWN",
+            };
+
+            if (tab.IsDefaultTabType || tab.Protected)
+            {
+                this.ButtonDeleteTab.Enabled = false;
+            }
+            else
+            {
+                this.ButtonDeleteTab.Enabled = true;
+            }
+            this.ButtonClose.Enabled = true;
         }
 
-        public void SetCurrent(string TabName)
+        public void SetCurrent(string tabName)
         {
-            _cur = TabName;
+            var index = this.tabs.FindIndex(x => x.TabName == tabName);
+            if (index == -1)
+                throw new ArgumentException($"Unknown tab: {tabName}", nameof(tabName));
+
+            this.selectedTabIndex = index;
         }
 
         public void AddNewFilter(string id, string msg)
         {
-            //元フォームから直接呼ばれる
-            ButtonNew.Enabled = false;
-            ButtonEdit.Enabled = false;
-            ButtonRuleUp.Enabled = false;
-            ButtonRuleDown.Enabled = false;
-            ButtonRuleCopy.Enabled = false;
-            ButtonRuleMove.Enabled = false;
-            ButtonDelete.Enabled = false;
-            ButtonClose.Enabled = false;
-            EditFilterGroup.Enabled = true;
-            ListTabs.Enabled = false;
-            GroupTab.Enabled = false;
-            ListFilters.Enabled = false;
-
-            RadioAND.Checked = true;
-            RadioPLUS.Checked = false;
-            UID.Text = id;
-            UID.SelectAll();
-            MSG1.Text = msg;
-            MSG1.SelectAll();
-            MSG2.Text = id + msg;
-            MSG2.SelectAll();
-            TextSource.Text = "";
-            UID.Enabled = true;
-            MSG1.Enabled = true;
-            MSG2.Enabled = false;
-            CheckRegex.Checked = false;
-            CheckURL.Checked = false;
-            CheckCaseSensitive.Checked = false;
-            CheckRetweet.Checked = false;
-            CheckLambda.Checked = false;
-
-            RadioExAnd.Checked = true;
-            RadioExPLUS.Checked = false;
-            ExUID.Text = "";
-            ExUID.SelectAll();
-            ExMSG1.Text = "";
-            ExMSG1.SelectAll();
-            ExMSG2.Text = "";
-            ExMSG2.SelectAll();
-            TextExSource.Text = "";
-            ExUID.Enabled = true;
-            ExMSG1.Enabled = true;
-            ExMSG2.Enabled = false;
-            CheckExRegex.Checked = false;
-            CheckExURL.Checked = false;
-            CheckExCaseSensitive.Checked = false;
-            CheckExRetweet.Checked = false;
-            CheckExLambDa.Checked = false;
-
-            OptCopy.Checked = true;
-            CheckMark.Checked = true;
-            UID.Focus();
-            _mode = EDITMODE.AddNew;
-            _directAdd = true;
+            // 元フォームから直接呼ばれる
+            this.ButtonNew.Enabled = false;
+            this.ButtonEdit.Enabled = false;
+            this.ButtonRuleUp.Enabled = false;
+            this.ButtonRuleDown.Enabled = false;
+            this.ButtonRuleCopy.Enabled = false;
+            this.ButtonRuleMove.Enabled = false;
+            this.buttonRuleToggleEnabled.Enabled = false;
+            this.ButtonDelete.Enabled = false;
+            this.ButtonClose.Enabled = false;
+            this.EditFilterGroup.Enabled = true;
+            this.ListTabs.Enabled = false;
+            this.GroupTab.Enabled = false;
+            this.ListFilters.Enabled = false;
+
+            this.RadioAND.Checked = true;
+            this.RadioPLUS.Checked = false;
+            this.UID.Text = id;
+            this.UID.SelectAll();
+            this.MSG1.Text = msg;
+            this.MSG1.SelectAll();
+            this.MSG2.Text = id + msg;
+            this.MSG2.SelectAll();
+            this.TextSource.Text = "";
+            this.UID.Enabled = true;
+            this.MSG1.Enabled = true;
+            this.MSG2.Enabled = false;
+            this.CheckRegex.Checked = false;
+            this.CheckURL.Checked = false;
+            this.CheckCaseSensitive.Checked = false;
+            this.CheckRetweet.Checked = false;
+            this.CheckLambda.Checked = false;
+
+            this.RadioExAnd.Checked = true;
+            this.RadioExPLUS.Checked = false;
+            this.ExUID.Text = "";
+            this.ExUID.SelectAll();
+            this.ExMSG1.Text = "";
+            this.ExMSG1.SelectAll();
+            this.ExMSG2.Text = "";
+            this.ExMSG2.SelectAll();
+            this.TextExSource.Text = "";
+            this.ExUID.Enabled = true;
+            this.ExMSG1.Enabled = true;
+            this.ExMSG2.Enabled = false;
+            this.CheckExRegex.Checked = false;
+            this.CheckExURL.Checked = false;
+            this.CheckExCaseSensitive.Checked = false;
+            this.CheckExRetweet.Checked = false;
+            this.CheckExLambDa.Checked = false;
+
+            this.OptCopy.Checked = true;
+            this.CheckMark.Checked = true;
+            this.UID.Focus();
+            this._mode = EDITMODE.AddNew;
+            this._directAdd = true;
         }
 
         private void ButtonNew_Click(object sender, EventArgs e)
         {
-            ButtonNew.Enabled = false;
-            ButtonEdit.Enabled = false;
-            ButtonClose.Enabled = false;
-            ButtonRuleUp.Enabled = false;
-            ButtonRuleDown.Enabled = false;
-            ButtonRuleCopy.Enabled = false;
-            ButtonRuleMove.Enabled = false;
-            ButtonDelete.Enabled = false;
-            ButtonClose.Enabled = false;
-            EditFilterGroup.Enabled = true;
-            ListTabs.Enabled = false;
-            GroupTab.Enabled = false;
-            ListFilters.Enabled = false;
-
-            RadioAND.Checked = true;
-            RadioPLUS.Checked = false;
-            UID.Text = "";
-            MSG1.Text = "";
-            MSG2.Text = "";
-            TextSource.Text = "";
-            UID.Enabled = true;
-            MSG1.Enabled = true;
-            MSG2.Enabled = false;
-            CheckRegex.Checked = false;
-            CheckURL.Checked = false;
-            CheckCaseSensitive.Checked = false;
-            CheckRetweet.Checked = false;
-            CheckLambda.Checked = false;
-
-            RadioExAnd.Checked = true;
-            RadioExPLUS.Checked = false;
-            ExUID.Text = "";
-            ExMSG1.Text = "";
-            ExMSG2.Text = "";
-            TextExSource.Text = "";
-            ExUID.Enabled = true;
-            ExMSG1.Enabled = true;
-            ExMSG2.Enabled = false;
-            CheckExRegex.Checked = false;
-            CheckExURL.Checked = false;
-            CheckExCaseSensitive.Checked = false;
-            CheckExRetweet.Checked = false;
-            CheckExLambDa.Checked = false;
-
-            OptCopy.Checked = true;
-            CheckMark.Checked = true;
-            UID.Focus();
-            _mode = EDITMODE.AddNew;
+            this.ButtonNew.Enabled = false;
+            this.ButtonEdit.Enabled = false;
+            this.ButtonClose.Enabled = false;
+            this.ButtonRuleUp.Enabled = false;
+            this.ButtonRuleDown.Enabled = false;
+            this.ButtonRuleCopy.Enabled = false;
+            this.ButtonRuleMove.Enabled = false;
+            this.buttonRuleToggleEnabled.Enabled = false;
+            this.ButtonDelete.Enabled = false;
+            this.ButtonClose.Enabled = false;
+            this.EditFilterGroup.Enabled = true;
+            this.ListTabs.Enabled = false;
+            this.GroupTab.Enabled = false;
+            this.ListFilters.Enabled = false;
+
+            this.RadioAND.Checked = true;
+            this.RadioPLUS.Checked = false;
+            this.UID.Text = "";
+            this.MSG1.Text = "";
+            this.MSG2.Text = "";
+            this.TextSource.Text = "";
+            this.UID.Enabled = true;
+            this.MSG1.Enabled = true;
+            this.MSG2.Enabled = false;
+            this.CheckRegex.Checked = false;
+            this.CheckURL.Checked = false;
+            this.CheckCaseSensitive.Checked = false;
+            this.CheckRetweet.Checked = false;
+            this.CheckLambda.Checked = false;
+
+            this.RadioExAnd.Checked = true;
+            this.RadioExPLUS.Checked = false;
+            this.ExUID.Text = "";
+            this.ExMSG1.Text = "";
+            this.ExMSG2.Text = "";
+            this.TextExSource.Text = "";
+            this.ExUID.Enabled = true;
+            this.ExMSG1.Enabled = true;
+            this.ExMSG2.Enabled = false;
+            this.CheckExRegex.Checked = false;
+            this.CheckExURL.Checked = false;
+            this.CheckExCaseSensitive.Checked = false;
+            this.CheckExRetweet.Checked = false;
+            this.CheckExLambDa.Checked = false;
+
+            this.OptCopy.Checked = true;
+            this.CheckMark.Checked = true;
+            this.UID.Focus();
+            this._mode = EDITMODE.AddNew;
         }
 
         private void ButtonEdit_Click(object sender, EventArgs e)
         {
-            if (ListFilters.SelectedIndex == -1) return;
-
-            ShowDetail();
-
-            int idx = ListFilters.SelectedIndex;
-            ListFilters.SelectedIndex = -1;
-            ListFilters.SelectedIndex = idx;
-            ListFilters.Enabled = false;
-
-            ButtonNew.Enabled = false;
-            ButtonEdit.Enabled = false;
-            ButtonDelete.Enabled = false;
-            ButtonClose.Enabled = false;
-            ButtonRuleUp.Enabled = false;
-            ButtonRuleDown.Enabled = false;
-            ButtonRuleCopy.Enabled = false;
-            ButtonRuleMove.Enabled = false;
-            EditFilterGroup.Enabled = true;
-            ListTabs.Enabled = false;
-            GroupTab.Enabled = false;
-
-            _mode = EDITMODE.Edit;
+            if (this.ListFilters.SelectedIndex == -1) return;
+
+            this.ShowDetail();
+
+            var idx = this.ListFilters.SelectedIndex;
+            this.ListFilters.SelectedIndex = -1;
+            this.ListFilters.SelectedIndex = idx;
+            this.ListFilters.Enabled = false;
+
+            this.ButtonNew.Enabled = false;
+            this.ButtonEdit.Enabled = false;
+            this.ButtonDelete.Enabled = false;
+            this.ButtonClose.Enabled = false;
+            this.ButtonRuleUp.Enabled = false;
+            this.ButtonRuleDown.Enabled = false;
+            this.ButtonRuleCopy.Enabled = false;
+            this.ButtonRuleMove.Enabled = false;
+            this.buttonRuleToggleEnabled.Enabled = false;
+            this.EditFilterGroup.Enabled = true;
+            this.ListTabs.Enabled = false;
+            this.GroupTab.Enabled = false;
+
+            this._mode = EDITMODE.Edit;
         }
 
         private void ButtonDelete_Click(object sender, EventArgs e)
         {
-            if (ListFilters.SelectedIndex == -1) return;
-            string tmp = "";
-            DialogResult rslt;
+            var selectedCount = this.ListFilters.SelectedIndices.Count;
+            if (selectedCount == 0) return;
 
-            if (ListFilters.SelectedIndices.Count == 1)
+            string tmp;
+
+            if (selectedCount == 1)
             {
-                tmp = string.Format(Properties.Resources.ButtonDelete_ClickText1, "\r\n", ListFilters.SelectedItem.ToString());
-                rslt = MessageBox.Show(tmp, Properties.Resources.ButtonDelete_ClickText2,
-                            MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
+                tmp = string.Format(Properties.Resources.ButtonDelete_ClickText1, Environment.NewLine, this.ListFilters.SelectedItem);
             }
             else
             {
-                tmp = string.Format(Properties.Resources.ButtonDelete_ClickText3, ListFilters.SelectedIndices.Count.ToString());
-                rslt = MessageBox.Show(tmp, Properties.Resources.ButtonDelete_ClickText2,
-                            MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
+                tmp = string.Format(Properties.Resources.ButtonDelete_ClickText3, selectedCount);
             }
+
+            var rslt = MessageBox.Show(tmp, Properties.Resources.ButtonDelete_ClickText2, MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
             if (rslt == DialogResult.Cancel) return;
 
-            for (int idx = ListFilters.Items.Count - 1; idx >= 0; idx--)
+            var indices = this.ListFilters.SelectedIndices.Cast<int>().Reverse().ToArray();  // 後ろの要素から削除
+            var tab = (FilterTabModel)this.SelectedTab!;
+
+            using (ControlTransaction.Update(this.ListFilters))
             {
-                if (ListFilters.GetSelected(idx))
+                foreach (var idx in indices)
                 {
-                    _sts.Tabs[ListTabs.SelectedItem.ToString()].RemoveFilter((PostFilterRule)ListFilters.Items[idx]);
-                    ListFilters.Items.RemoveAt(idx);
+                    tab.RemoveFilter((PostFilterRule)this.ListFilters.Items[idx]);
+                    this.ListFilters.Items.RemoveAt(idx);
                 }
             }
         }
 
         private void ButtonCancel_Click(object sender, EventArgs e)
         {
-            ListTabs.Enabled = true;
-            GroupTab.Enabled = true;
-            ListFilters.Enabled = true;
-            ListFilters.Focus();
-            if (ListFilters.SelectedIndex != -1)
-            {
-                ShowDetail();
-            }
-            EditFilterGroup.Enabled = false;
-            ButtonNew.Enabled = true;
-            if (ListFilters.SelectedIndex > -1)
-            {
-                ButtonEdit.Enabled = true;
-                ButtonDelete.Enabled = true;
-                ButtonRuleUp.Enabled = true;
-                ButtonRuleDown.Enabled = true;
-                ButtonRuleCopy.Enabled = true;
-                ButtonRuleMove.Enabled = true;
+            this.ListTabs.Enabled = true;
+            this.GroupTab.Enabled = true;
+            this.ListFilters.Enabled = true;
+            this.ListFilters.Focus();
+            if (this.ListFilters.SelectedIndex != -1)
+            {
+                this.ShowDetail();
+            }
+            this.EditFilterGroup.Enabled = false;
+            this.ButtonNew.Enabled = true;
+            if (this.ListFilters.SelectedIndex > -1)
+            {
+                this.ButtonEdit.Enabled = true;
+                this.ButtonDelete.Enabled = true;
+                this.ButtonRuleUp.Enabled = true;
+                this.ButtonRuleDown.Enabled = true;
+                this.ButtonRuleCopy.Enabled = true;
+                this.ButtonRuleMove.Enabled = true;
+                this.buttonRuleToggleEnabled.Enabled = true;
             }
             else
             {
-                ButtonEdit.Enabled = false;
-                ButtonDelete.Enabled = false;
-                ButtonRuleUp.Enabled = false;
-                ButtonRuleDown.Enabled = false;
-                ButtonRuleCopy.Enabled = false;
-                ButtonRuleMove.Enabled = false;
+                this.ButtonEdit.Enabled = false;
+                this.ButtonDelete.Enabled = false;
+                this.ButtonRuleUp.Enabled = false;
+                this.ButtonRuleDown.Enabled = false;
+                this.ButtonRuleCopy.Enabled = false;
+                this.ButtonRuleMove.Enabled = false;
+                this.buttonRuleToggleEnabled.Enabled = false;
             }
-            ButtonClose.Enabled = true;
-            if (_directAdd)
+            this.ButtonClose.Enabled = true;
+            if (this._directAdd)
             {
                 this.Close();
             }
@@ -390,171 +465,150 @@ namespace OpenTween
 
         private void ShowDetail()
         {
-            if (_directAdd) return;
+            if (this._directAdd) return;
 
-            if (ListFilters.SelectedIndex > -1)
+            if (this.ListFilters.SelectedIndex > -1)
             {
-                PostFilterRule fc = (PostFilterRule)ListFilters.SelectedItem;
+                var fc = (PostFilterRule)this.ListFilters.SelectedItem;
                 if (fc.UseNameField)
                 {
-                    RadioAND.Checked = true;
-                    RadioPLUS.Checked = false;
-                    UID.Enabled = true;
-                    MSG1.Enabled = true;
-                    MSG2.Enabled = false;
-                    UID.Text = fc.FilterName;
-                    UID.SelectAll();
-                    MSG1.Text = "";
-                    MSG2.Text = "";
-                    foreach (string bf in fc.FilterBody)
-                    {
-                        MSG1.Text += bf + " ";
-                    }
-                    MSG1.Text = MSG1.Text.Trim();
-                    MSG1.SelectAll();
+                    this.RadioAND.Checked = true;
+                    this.RadioPLUS.Checked = false;
+                    this.UID.Enabled = true;
+                    this.MSG1.Enabled = true;
+                    this.MSG2.Enabled = false;
+                    this.UID.Text = fc.FilterName;
+                    this.UID.SelectAll();
+                    this.MSG1.Text = string.Join(" ", fc.FilterBody);
+                    this.MSG1.SelectAll();
+                    this.MSG2.Text = "";
                 }
                 else
                 {
-                    RadioPLUS.Checked = true;
-                    RadioAND.Checked = false;
-                    UID.Enabled = false;
-                    MSG1.Enabled = false;
-                    MSG2.Enabled = true;
-                    UID.Text = "";
-                    MSG1.Text = "";
-                    MSG2.Text = "";
-                    foreach (string bf in fc.FilterBody)
-                    {
-                        MSG2.Text += bf + " ";
-                    }
-                    MSG2.Text = MSG2.Text.Trim();
-                    MSG2.SelectAll();
+                    this.RadioPLUS.Checked = true;
+                    this.RadioAND.Checked = false;
+                    this.UID.Enabled = false;
+                    this.MSG1.Enabled = false;
+                    this.MSG2.Enabled = true;
+                    this.UID.Text = "";
+                    this.MSG1.Text = "";
+                    this.MSG2.Text = string.Join(" ", fc.FilterBody);
+                    this.MSG2.SelectAll();
                 }
-                TextSource.Text = fc.FilterSource;
-                CheckRegex.Checked = fc.UseRegex;
-                CheckURL.Checked = fc.FilterByUrl;
-                CheckCaseSensitive.Checked = fc.CaseSensitive;
-                CheckRetweet.Checked = fc.FilterRt;
-                CheckLambda.Checked = fc.UseLambda;
+                this.TextSource.Text = fc.FilterSource;
+                this.CheckRegex.Checked = fc.UseRegex;
+                this.CheckURL.Checked = fc.FilterByUrl;
+                this.CheckCaseSensitive.Checked = fc.CaseSensitive;
+                this.CheckRetweet.Checked = fc.FilterRt;
+                this.CheckLambda.Checked = fc.UseLambda;
 
                 if (fc.ExUseNameField)
                 {
-                    RadioExAnd.Checked = true;
-                    RadioExPLUS.Checked = false;
-                    ExUID.Enabled = true;
-                    ExMSG1.Enabled = true;
-                    ExMSG2.Enabled = false;
-                    ExUID.Text = fc.ExFilterName;
-                    ExUID.SelectAll();
-                    ExMSG1.Text = "";
-                    ExMSG2.Text = "";
-                    foreach (string bf in fc.ExFilterBody)
-                    {
-                        ExMSG1.Text += bf + " ";
-                    }
-                    ExMSG1.Text = ExMSG1.Text.Trim();
-                    ExMSG1.SelectAll();
+                    this.RadioExAnd.Checked = true;
+                    this.RadioExPLUS.Checked = false;
+                    this.ExUID.Enabled = true;
+                    this.ExMSG1.Enabled = true;
+                    this.ExMSG2.Enabled = false;
+                    this.ExUID.Text = fc.ExFilterName;
+                    this.ExUID.SelectAll();
+                    this.ExMSG1.Text = string.Join(" ", fc.ExFilterBody);
+                    this.ExMSG1.SelectAll();
+                    this.ExMSG2.Text = "";
                 }
                 else
                 {
-                    RadioExPLUS.Checked = true;
-                    RadioExAnd.Checked = false;
-                    ExUID.Enabled = false;
-                    ExMSG1.Enabled = false;
-                    ExMSG2.Enabled = true;
-                    ExUID.Text = "";
-                    ExMSG1.Text = "";
-                    ExMSG2.Text = "";
-                    foreach (string bf in fc.ExFilterBody)
-                    {
-                        ExMSG2.Text += bf + " ";
-                    }
-                    ExMSG2.Text = ExMSG2.Text.Trim();
-                    ExMSG2.SelectAll();
+                    this.RadioExPLUS.Checked = true;
+                    this.RadioExAnd.Checked = false;
+                    this.ExUID.Enabled = false;
+                    this.ExMSG1.Enabled = false;
+                    this.ExMSG2.Enabled = true;
+                    this.ExUID.Text = "";
+                    this.ExMSG1.Text = "";
+                    this.ExMSG2.Text = string.Join(" ", fc.ExFilterBody);
+                    this.ExMSG2.SelectAll();
                 }
-                TextExSource.Text = fc.ExFilterSource;
-                CheckExRegex.Checked = fc.ExUseRegex;
-                CheckExURL.Checked = fc.ExFilterByUrl;
-                CheckExCaseSensitive.Checked = fc.ExCaseSensitive;
-                CheckExRetweet.Checked = fc.ExFilterRt;
-                CheckExLambDa.Checked = fc.ExUseLambda;
+                this.TextExSource.Text = fc.ExFilterSource;
+                this.CheckExRegex.Checked = fc.ExUseRegex;
+                this.CheckExURL.Checked = fc.ExFilterByUrl;
+                this.CheckExCaseSensitive.Checked = fc.ExCaseSensitive;
+                this.CheckExRetweet.Checked = fc.ExFilterRt;
+                this.CheckExLambDa.Checked = fc.ExUseLambda;
 
                 if (fc.MoveMatches)
                 {
-                    OptMove.Checked = true;
+                    this.OptMove.Checked = true;
                 }
                 else
                 {
-                    OptCopy.Checked = true;
+                    this.OptCopy.Checked = true;
                 }
-                CheckMark.Checked = fc.MarkMatches;
+                this.CheckMark.Checked = fc.MarkMatches;
 
-                ButtonEdit.Enabled = true;
-                ButtonDelete.Enabled = true;
-                ButtonRuleUp.Enabled = true;
-                ButtonRuleDown.Enabled = true;
-                ButtonRuleCopy.Enabled = true;
-                ButtonRuleMove.Enabled = true;
+                this.ButtonEdit.Enabled = true;
+                this.ButtonDelete.Enabled = true;
+                this.ButtonRuleUp.Enabled = true;
+                this.ButtonRuleDown.Enabled = true;
+                this.ButtonRuleCopy.Enabled = true;
+                this.ButtonRuleMove.Enabled = true;
+                this.buttonRuleToggleEnabled.Enabled = true;
             }
             else
             {
-                RadioAND.Checked = true;
-                RadioPLUS.Checked = false;
-                UID.Enabled = true;
-                MSG1.Enabled = true;
-                MSG2.Enabled = false;
-                UID.Text = "";
-                MSG1.Text = "";
-                MSG2.Text = "";
-                TextSource.Text = "";
-                CheckRegex.Checked = false;
-                CheckURL.Checked = false;
-                CheckCaseSensitive.Checked = false;
-                CheckRetweet.Checked = false;
-                CheckLambda.Checked = false;
-
-                RadioExAnd.Checked = true;
-                RadioExPLUS.Checked = false;
-                ExUID.Enabled = true;
-                ExMSG1.Enabled = true;
-                ExMSG2.Enabled = false;
-                ExUID.Text = "";
-                ExMSG1.Text = "";
-                ExMSG2.Text = "";
-                TextExSource.Text = "";
-                CheckExRegex.Checked = false;
-                CheckExURL.Checked = false;
-                CheckExCaseSensitive.Checked = false;
-                CheckExRetweet.Checked = false;
-                CheckExLambDa.Checked = false;
-
-                OptCopy.Checked = true;
-                CheckMark.Checked = true;
-
-                ButtonEdit.Enabled = false;
-                ButtonDelete.Enabled = false;
-                ButtonRuleUp.Enabled = false;
-                ButtonRuleDown.Enabled = false;
-                ButtonRuleCopy.Enabled = false;
-                ButtonRuleMove.Enabled = false;
+                this.RadioAND.Checked = true;
+                this.RadioPLUS.Checked = false;
+                this.UID.Enabled = true;
+                this.MSG1.Enabled = true;
+                this.MSG2.Enabled = false;
+                this.UID.Text = "";
+                this.MSG1.Text = "";
+                this.MSG2.Text = "";
+                this.TextSource.Text = "";
+                this.CheckRegex.Checked = false;
+                this.CheckURL.Checked = false;
+                this.CheckCaseSensitive.Checked = false;
+                this.CheckRetweet.Checked = false;
+                this.CheckLambda.Checked = false;
+
+                this.RadioExAnd.Checked = true;
+                this.RadioExPLUS.Checked = false;
+                this.ExUID.Enabled = true;
+                this.ExMSG1.Enabled = true;
+                this.ExMSG2.Enabled = false;
+                this.ExUID.Text = "";
+                this.ExMSG1.Text = "";
+                this.ExMSG2.Text = "";
+                this.TextExSource.Text = "";
+                this.CheckExRegex.Checked = false;
+                this.CheckExURL.Checked = false;
+                this.CheckExCaseSensitive.Checked = false;
+                this.CheckExRetweet.Checked = false;
+                this.CheckExLambDa.Checked = false;
+
+                this.OptCopy.Checked = true;
+                this.CheckMark.Checked = true;
+
+                this.ButtonEdit.Enabled = false;
+                this.ButtonDelete.Enabled = false;
+                this.ButtonRuleUp.Enabled = false;
+                this.ButtonRuleDown.Enabled = false;
+                this.ButtonRuleCopy.Enabled = false;
+                this.ButtonRuleMove.Enabled = false;
+                this.buttonRuleToggleEnabled.Enabled = false;
             }
         }
 
         private void RadioAND_CheckedChanged(object sender, EventArgs e)
         {
-            bool flg = RadioAND.Checked;
-            UID.Enabled = flg;
-            MSG1.Enabled = flg;
-            MSG2.Enabled = !flg;
+            var flg = this.RadioAND.Checked;
+            this.UID.Enabled = flg;
+            this.MSG1.Enabled = flg;
+            this.MSG2.Enabled = !flg;
         }
 
         private void ButtonOK_Click(object sender, EventArgs e)
         {
-            bool isBlankMatch = false;
-            bool isBlankExclude = false;
-
-            //入力チェック
-            if (!CheckMatchRule(out isBlankMatch) || !CheckExcludeRule(out isBlankExclude))
+            // 入力チェック
+            if (!this.CheckMatchRule(out var isBlankMatch) || !this.CheckExcludeRule(out var isBlankExclude))
             {
                 return;
             }
@@ -564,126 +618,129 @@ namespace OpenTween
                 return;
             }
 
-            int i = ListFilters.SelectedIndex;
-            PostFilterRule ft;
+            var tab = (FilterTabModel)this.SelectedTab!;
+            var i = this.ListFilters.SelectedIndex;
 
-            ft = new PostFilterRule();
+            PostFilterRule ft;
+            if (this._mode == EDITMODE.AddNew)
+                ft = new PostFilterRule();
+            else
+                ft = (PostFilterRule)this.ListFilters.SelectedItem;
 
-            ft.MoveMatches = OptMove.Checked;
-            ft.MarkMatches = CheckMark.Checked;
+            if (tab.TabType != MyCommon.TabUsageType.Mute)
+            {
+                ft.MoveMatches = this.OptMove.Checked;
+                ft.MarkMatches = this.CheckMark.Checked;
+            }
+            else
+            {
+                ft.MoveMatches = true;
+                ft.MarkMatches = false;
+            }
 
-            string bdy = "";
-            if (RadioAND.Checked)
+            var bdy = "";
+            if (this.RadioAND.Checked)
             {
-                ft.FilterName = UID.Text;
-                TweenMain owner = (TweenMain)this.Owner;
-                int cnt = owner.AtIdSupl.ItemCount;
+                ft.FilterName = this.UID.Text;
+                var owner = (TweenMain)this.Owner;
+                var cnt = owner.AtIdSupl.ItemCount;
                 owner.AtIdSupl.AddItem("@" + ft.FilterName);
                 if (cnt != owner.AtIdSupl.ItemCount)
                 {
-                    owner.ModifySettingAtId = true;
+                    owner.MarkSettingAtIdModified();
                 }
                 ft.UseNameField = true;
-                bdy = MSG1.Text;
+                bdy = this.MSG1.Text;
             }
             else
             {
                 ft.FilterName = "";
                 ft.UseNameField = false;
-                bdy = MSG2.Text;
+                bdy = this.MSG2.Text;
             }
-            ft.FilterSource = TextSource.Text.Trim();
+            ft.FilterSource = this.TextSource.Text;
 
-            if (CheckRegex.Checked || CheckLambda.Checked)
+            if (this.CheckRegex.Checked || this.CheckLambda.Checked)
             {
                 ft.FilterBody = new[] { bdy };
             }
             else
             {
-                ft.FilterBody = bdy.Split((char)32)
-                    .Select(x => x.Trim())
-                    .Where(x => !string.IsNullOrEmpty(x))
+                ft.FilterBody = bdy.Split(' ', ' ')
+                    .Where(x => !MyCommon.IsNullOrEmpty(x))
                     .ToArray();
             }
 
-            ft.UseRegex = CheckRegex.Checked;
-            ft.FilterByUrl = CheckURL.Checked;
-            ft.CaseSensitive = CheckCaseSensitive.Checked;
-            ft.FilterRt = CheckRetweet.Checked;
-            ft.UseLambda = CheckLambda.Checked;
+            ft.UseRegex = this.CheckRegex.Checked;
+            ft.FilterByUrl = this.CheckURL.Checked;
+            ft.CaseSensitive = this.CheckCaseSensitive.Checked;
+            ft.FilterRt = this.CheckRetweet.Checked;
+            ft.UseLambda = this.CheckLambda.Checked;
 
             bdy = "";
-            if (RadioExAnd.Checked)
+            if (this.RadioExAnd.Checked)
             {
-                ft.ExFilterName = ExUID.Text;
+                ft.ExFilterName = this.ExUID.Text;
                 ft.ExUseNameField = true;
-                bdy = ExMSG1.Text;
+                bdy = this.ExMSG1.Text;
             }
             else
             {
                 ft.ExFilterName = "";
                 ft.ExUseNameField = false;
-                bdy = ExMSG2.Text;
+                bdy = this.ExMSG2.Text;
             }
-            ft.ExFilterSource = TextExSource.Text.Trim();
+            ft.ExFilterSource = this.TextExSource.Text;
 
-            if (CheckExRegex.Checked || CheckExLambDa.Checked)
+            if (this.CheckExRegex.Checked || this.CheckExLambDa.Checked)
             {
                 ft.ExFilterBody = new[] { bdy };
             }
             else
             {
-                ft.ExFilterBody = bdy.Split((char)32)
-                    .Select(x => x.Trim())
-                    .Where(x => !string.IsNullOrEmpty(x))
+                ft.ExFilterBody = bdy.Split(' ', ' ')
+                    .Where(x => !MyCommon.IsNullOrEmpty(x))
                     .ToArray();
             }
 
-            ft.ExUseRegex = CheckExRegex.Checked;
-            ft.ExFilterByUrl = CheckExURL.Checked;
-            ft.ExCaseSensitive = CheckExCaseSensitive.Checked;
-            ft.ExFilterRt = CheckExRetweet.Checked;
-            ft.ExUseLambda = CheckExLambDa.Checked;
+            ft.ExUseRegex = this.CheckExRegex.Checked;
+            ft.ExFilterByUrl = this.CheckExURL.Checked;
+            ft.ExCaseSensitive = this.CheckExCaseSensitive.Checked;
+            ft.ExFilterRt = this.CheckExRetweet.Checked;
+            ft.ExUseLambda = this.CheckExLambDa.Checked;
 
-            if (_mode == EDITMODE.AddNew)
+            if (this._mode == EDITMODE.AddNew)
             {
-                if (!_sts.Tabs[ListTabs.SelectedItem.ToString()].AddFilter(ft))
+                if (!tab.AddFilter(ft))
                     MessageBox.Show(Properties.Resources.ButtonOK_ClickText4, Properties.Resources.ButtonOK_ClickText2, MessageBoxButtons.OK, MessageBoxIcon.Error);
             }
-            else
-            {
-                _sts.Tabs[ListTabs.SelectedItem.ToString()].EditFilter((PostFilterRule)ListFilters.SelectedItem, ft);
-            }
 
-            SetFilters(ListTabs.SelectedItem.ToString());
-            ListFilters.SelectedIndex = -1;
-            if (_mode == EDITMODE.AddNew)
+            this.SetFilters(tab);
+            this.ListFilters.SelectedIndex = -1;
+            if (this._mode == EDITMODE.AddNew)
             {
-                ListFilters.SelectedIndex = ListFilters.Items.Count - 1;
+                this.ListFilters.SelectedIndex = this.ListFilters.Items.Count - 1;
             }
             else
             {
-                ListFilters.SelectedIndex = i;
+                this.ListFilters.SelectedIndex = i;
             }
-            _mode = EDITMODE.None;
+            this._mode = EDITMODE.None;
 
-            if (_directAdd)
+            if (this._directAdd)
             {
                 this.Close();
             }
         }
 
         private bool IsValidLambdaExp(string text)
-        {
-            return false;
-            // TODO DynamicQuery相当のGPLv3互換なライブラリで置換する
-        }
+            => false; // TODO DynamicQuery相当のGPLv3互換なライブラリで置換する
 
         private bool IsValidRegexp(string text)
         {
             try
             {
-                Regex rgx = new Regex(text);
+                new Regex(text);
             }
             catch (Exception ex)
             {
@@ -696,36 +753,31 @@ namespace OpenTween
         private bool CheckMatchRule(out bool isBlank)
         {
             isBlank = false;
-            TextSource.Text = TextSource.Text.Trim();
-            if (RadioAND.Checked)
+            if (this.RadioAND.Checked)
             {
-                MSG1.Text = MSG1.Text.Trim();
-                UID.Text = UID.Text.Trim();
-                if (!CheckRegex.Checked && !CheckLambda.Checked) MSG1.Text = MSG1.Text.Replace(" ", " ");
-
-                if (string.IsNullOrEmpty(UID.Text) && string.IsNullOrEmpty(MSG1.Text) && string.IsNullOrEmpty(TextSource.Text) && CheckRetweet.Checked == false)
+                if (MyCommon.IsNullOrEmpty(this.UID.Text) && MyCommon.IsNullOrEmpty(this.MSG1.Text) && MyCommon.IsNullOrEmpty(this.TextSource.Text) && this.CheckRetweet.Checked == false)
                 {
                     isBlank = true;
                     return true;
                 }
-                if (CheckLambda.Checked)
+                if (this.CheckLambda.Checked)
                 {
-                    if (!IsValidLambdaExp(UID.Text))
+                    if (!this.IsValidLambdaExp(this.UID.Text))
                     {
                         return false;
                     }
-                    if (!IsValidLambdaExp(MSG1.Text))
+                    if (!this.IsValidLambdaExp(this.MSG1.Text))
                     {
                         return false;
                     }
                 }
-                else if (CheckRegex.Checked)
+                else if (this.CheckRegex.Checked)
                 {
-                    if (!IsValidRegexp(UID.Text))
+                    if (!this.IsValidRegexp(this.UID.Text))
                     {
                         return false;
                     }
-                    if (!IsValidRegexp(MSG1.Text))
+                    if (!this.IsValidRegexp(this.MSG1.Text))
                     {
                         return false;
                     }
@@ -733,24 +785,22 @@ namespace OpenTween
             }
             else
             {
-                MSG2.Text = MSG2.Text.Trim();
-                if (!CheckRegex.Checked && !CheckLambda.Checked) MSG2.Text = MSG2.Text.Replace(" ", " ");
-                if (string.IsNullOrEmpty(MSG2.Text) && string.IsNullOrEmpty(TextSource.Text) && CheckRetweet.Checked == false)
+                if (MyCommon.IsNullOrEmpty(this.MSG2.Text) && MyCommon.IsNullOrEmpty(this.TextSource.Text) && this.CheckRetweet.Checked == false)
                 {
                     isBlank = true;
                     return true;
                 }
-                if (CheckLambda.Checked && !IsValidLambdaExp(MSG2.Text))
+                if (this.CheckLambda.Checked && !this.IsValidLambdaExp(this.MSG2.Text))
                 {
                     return false;
                 }
-                else if (CheckRegex.Checked && !IsValidRegexp(MSG2.Text))
+                else if (this.CheckRegex.Checked && !this.IsValidRegexp(this.MSG2.Text))
                 {
                     return false;
                 }
             }
 
-            if (CheckRegex.Checked && !IsValidRegexp(TextSource.Text))
+            if (this.CheckRegex.Checked && !this.IsValidRegexp(this.TextSource.Text))
             {
                 return false;
             }
@@ -760,35 +810,31 @@ namespace OpenTween
         private bool CheckExcludeRule(out bool isBlank)
         {
             isBlank = false;
-            TextExSource.Text = TextExSource.Text.Trim();
-            if (RadioExAnd.Checked)
+            if (this.RadioExAnd.Checked)
             {
-                ExMSG1.Text = ExMSG1.Text.Trim();
-                if (!CheckExRegex.Checked && !CheckExLambDa.Checked) ExMSG1.Text = ExMSG1.Text.Replace(" ", " ");
-                ExUID.Text = ExUID.Text.Trim();
-                if (string.IsNullOrEmpty(ExUID.Text) && string.IsNullOrEmpty(ExMSG1.Text) && string.IsNullOrEmpty(TextExSource.Text) && CheckExRetweet.Checked == false)
+                if (MyCommon.IsNullOrEmpty(this.ExUID.Text) && MyCommon.IsNullOrEmpty(this.ExMSG1.Text) && MyCommon.IsNullOrEmpty(this.TextExSource.Text) && this.CheckExRetweet.Checked == false)
                 {
                     isBlank = true;
                     return true;
                 }
-                if (CheckExLambDa.Checked)
+                if (this.CheckExLambDa.Checked)
                 {
-                    if (!IsValidLambdaExp(ExUID.Text))
+                    if (!this.IsValidLambdaExp(this.ExUID.Text))
                     {
                         return false;
                     }
-                    if (!IsValidLambdaExp(ExMSG1.Text))
+                    if (!this.IsValidLambdaExp(this.ExMSG1.Text))
                     {
                         return false;
                     }
                 }
-                else if (CheckExRegex.Checked)
+                else if (this.CheckExRegex.Checked)
                 {
-                    if (!IsValidRegexp(ExUID.Text))
+                    if (!this.IsValidRegexp(this.ExUID.Text))
                     {
                         return false;
                     }
-                    if (!IsValidRegexp(ExMSG1.Text))
+                    if (!this.IsValidRegexp(this.ExMSG1.Text))
                     {
                         return false;
                     }
@@ -796,24 +842,22 @@ namespace OpenTween
             }
             else
             {
-                ExMSG2.Text = ExMSG2.Text.Trim();
-                if (!CheckExRegex.Checked && !CheckExLambDa.Checked) ExMSG2.Text = ExMSG2.Text.Replace(" ", " ");
-                if (string.IsNullOrEmpty(ExMSG2.Text) && string.IsNullOrEmpty(TextExSource.Text) && CheckExRetweet.Checked == false)
+                if (MyCommon.IsNullOrEmpty(this.ExMSG2.Text) && MyCommon.IsNullOrEmpty(this.TextExSource.Text) && this.CheckExRetweet.Checked == false)
                 {
                     isBlank = true;
                     return true;
                 }
-                if (CheckExLambDa.Checked && !IsValidLambdaExp(ExMSG2.Text))
+                if (this.CheckExLambDa.Checked && !this.IsValidLambdaExp(this.ExMSG2.Text))
                 {
                     return false;
                 }
-                else if (CheckExRegex.Checked && !IsValidRegexp(ExMSG2.Text))
+                else if (this.CheckExRegex.Checked && !this.IsValidRegexp(this.ExMSG2.Text))
                 {
                     return false;
                 }
             }
 
-            if (CheckExRegex.Checked && !IsValidRegexp(TextExSource.Text))
+            if (this.CheckExRegex.Checked && !this.IsValidRegexp(this.TextExSource.Text))
             {
                 return false;
             }
@@ -823,372 +867,463 @@ namespace OpenTween
 
         private void ListFilters_SelectedIndexChanged(object sender, EventArgs e)
         {
-            ShowDetail();
+            if (this._multiSelState != MultiSelectionState.None) // 複数選択処理中は無視する
+                return;
+
+            this.ShowDetail();
+
+            var selectedCount = this.ListFilters.SelectedIndices.Count;
+            if (selectedCount == 0)
+            {
+                this.RuleEnableButtonMode = EnableButtonMode.NotSelected;
+            }
+            else
+            {
+                if (selectedCount == 1 ||
+                    this.RuleEnableButtonMode == EnableButtonMode.NotSelected)
+                {
+                    var topItem = (PostFilterRule)this.ListFilters.SelectedItem;
+                    this.RuleEnableButtonMode = topItem.Enabled ? EnableButtonMode.Disable : EnableButtonMode.Enable;
+                }
+            }
         }
 
         private void ButtonClose_Click(object sender, EventArgs e)
-        {
-            this.Close();
-        }
+            => this.Close();
 
         private void FilterDialog_FormClosed(object sender, FormClosedEventArgs e)
-        {
-            _directAdd = false;
-        }
+            => this._directAdd = false;
 
         private void FilterDialog_KeyDown(object sender, KeyEventArgs e)
         {
             if (e.KeyCode == Keys.Escape)
             {
-                if (EditFilterGroup.Enabled)
-                    ButtonCancel_Click(null, null);
+                if (this.EditFilterGroup.Enabled)
+                    this.ButtonCancel_Click(this.ButtonCancel, EventArgs.Empty);
                 else
-                    ButtonClose_Click(null, null);
+                    this.ButtonClose_Click(this.ButtonClose, EventArgs.Empty);
             }
         }
 
         private void ListFilters_DoubleClick(object sender, EventArgs e)
         {
-            if (ListFilters.SelectedItem == null)
-            {
-                return;
-            }
+            var idx = this.ListFilters.SelectedIndex;
+            if (idx == -1) return;
 
-            if (ListFilters.IndexFromPoint(ListFilters.PointToClient(Control.MousePosition)) == ListBox.NoMatches)
-            {
-                return;
-            }
+            var midx = this.ListFilters.IndexFromPoint(this.ListFilters.PointToClient(Control.MousePosition));
+            if (midx == ListBox.NoMatches || idx != midx) return;
 
-            if (ListFilters.Items[ListFilters.IndexFromPoint(ListFilters.PointToClient(Control.MousePosition))] == null)
-            {
-                return;
-            }
-            ButtonEdit_Click(sender, e);
+            this.ButtonEdit_Click(sender, e);
         }
 
         private void FilterDialog_Shown(object sender, EventArgs e)
         {
-            _sts = TabInformations.GetInstance();
-            ListTabs.Items.Clear();
-            foreach (string key in _sts.Tabs.Keys)
-            {
-                ListTabs.Items.Add(key);
-            }
+            this.ListTabs.DisplayMember = nameof(TabModel.TabName);
 
-            ComboSound.Items.Clear();
-            ComboSound.Items.Add("");
-            DirectoryInfo oDir = new DirectoryInfo(Application.StartupPath + Path.DirectorySeparatorChar);
+            this.ComboSound.Items.Clear();
+            this.ComboSound.Items.Add("");
+            var oDir = new DirectoryInfo(Application.StartupPath + Path.DirectorySeparatorChar);
             if (Directory.Exists(Path.Combine(Application.StartupPath, "Sounds")))
             {
                 oDir = oDir.GetDirectories("Sounds")[0];
             }
-            foreach (FileInfo oFile in oDir.GetFiles("*.wav"))
+            foreach (var oFile in oDir.GetFiles("*.wav"))
             {
-                ComboSound.Items.Add(oFile.Name);
+                this.ComboSound.Items.Add(oFile.Name);
             }
 
-            idlist.Clear();
-            foreach (string tmp in ((TweenMain)this.Owner).AtIdSupl.GetItemList())
+            this.idlist.Clear();
+            foreach (var tmp in ((TweenMain)this.Owner).AtIdSupl.GetItemList())
             {
-                idlist.Add(tmp.Remove(0, 1));  // @文字削除
+                this.idlist.Add(tmp.Remove(0, 1));  // @文字削除
             }
-            UID.AutoCompleteCustomSource.Clear();
-            UID.AutoCompleteCustomSource.AddRange(idlist.ToArray());
+            this.UID.AutoCompleteCustomSource.Clear();
+            this.UID.AutoCompleteCustomSource.AddRange(this.idlist.ToArray());
 
-            ExUID.AutoCompleteCustomSource.Clear();
-            ExUID.AutoCompleteCustomSource.AddRange(idlist.ToArray());
+            this.ExUID.AutoCompleteCustomSource.Clear();
+            this.ExUID.AutoCompleteCustomSource.AddRange(this.idlist.ToArray());
 
-            //選択タブ変更
-            if (ListTabs.Items.Count > 0)
-            {
-                if (_cur.Length > 0)
-                {
-                    for (int i = 0; i < ListTabs.Items.Count; i++)
-                    {
-                        if (_cur == ListTabs.Items[i].ToString())
-                        {
-                            ListTabs.SelectedIndex = i;
-                            //tabdialog.TabList.Items.Remove(_cur);
-                            break;
-                        }
-                    }
-                }
-            }
+            // 選択タブ変更
+            this.ListTabs.SelectedIndex = this.selectedTabIndex;
         }
 
         private void ListTabs_SelectedIndexChanged(object sender, EventArgs e)
         {
-            if (ListTabs.SelectedIndex > -1)
-                SetFilters(ListTabs.SelectedItem.ToString());
+            this.selectedTabIndex = this.ListTabs.SelectedIndex;
+
+            var selectedTab = this.SelectedTab;
+            if (selectedTab != null)
+                this.SetFilters(selectedTab);
             else
-                ListFilters.Items.Clear();
+                this.ListFilters.Items.Clear();
         }
 
-        private void ButtonAddTab_Click(object sender, EventArgs e)
+        private async void ButtonAddTab_Click(object sender, EventArgs e)
         {
-            string tabName = null;
+            string? tabName = null;
             MyCommon.TabUsageType tabType;
-            using (InputTabName inputName = new InputTabName())
+            using (var inputName = new InputTabName())
             {
-                inputName.TabName = _sts.GetUniqueTabName();
+                inputName.TabName = this._sts.MakeTabName("MyTab");
                 inputName.IsShowUsage = true;
                 inputName.ShowDialog();
                 if (inputName.DialogResult == DialogResult.Cancel) return;
                 tabName = inputName.TabName;
                 tabType = inputName.Usage;
             }
-            if (!string.IsNullOrEmpty(tabName))
+            if (!MyCommon.IsNullOrEmpty(tabName))
             {
-                //List対応
-                ListElement list = null;
+                // List対応
+                ListElement? list = null;
                 if (tabType == MyCommon.TabUsageType.Lists)
                 {
-                    string rslt = ((TweenMain)this.Owner).TwitterInstance.GetListsApi();
-                    if (!string.IsNullOrEmpty(rslt))
+                    try
                     {
-                        MessageBox.Show("Failed to get lists. (" + rslt + ")");
+                        using var dialog = new WaitingDialog(Properties.Resources.ListsGetting);
+                        var cancellationToken = dialog.EnableCancellation();
+
+                        var task = ((TweenMain)this.Owner).TwitterInstance.GetListsApi();
+                        await dialog.WaitForAsync(this, task);
+
+                        cancellationToken.ThrowIfCancellationRequested();
                     }
-                    using (ListAvailable listAvail = new ListAvailable())
+                    catch (OperationCanceledException) { return; }
+                    catch (WebApiException ex)
                     {
-                        if (listAvail.ShowDialog(this) == DialogResult.Cancel) return;
-                        if (listAvail.SelectedList == null) return;
-                        list = listAvail.SelectedList;
+                        MessageBox.Show("Failed to get lists. (" + ex.Message + ")");
                     }
+
+                    using var listAvail = new ListAvailable();
+
+                    if (listAvail.ShowDialog(this) == DialogResult.Cancel)
+                        return;
+                    if (listAvail.SelectedList == null)
+                        return;
+                    list = listAvail.SelectedList;
                 }
-                if (!_sts.AddTab(tabName, tabType, list) || !((TweenMain)this.Owner).AddNewTab(tabName, false, tabType, list))
+
+                TabModel tab;
+                switch (tabType)
                 {
-                    string tmp = string.Format(Properties.Resources.AddTabMenuItem_ClickText1, tabName);
+                    case MyCommon.TabUsageType.UserDefined:
+                        tab = new FilterTabModel(tabName);
+                        break;
+                    case MyCommon.TabUsageType.PublicSearch:
+                        tab = new PublicSearchTabModel(tabName);
+                        break;
+                    case MyCommon.TabUsageType.Lists:
+                        tab = new ListTimelineTabModel(tabName, list!);
+                        break;
+                    default:
+                        return;
+                }
+
+                if (!this._sts.AddTab(tab) || !((TweenMain)this.Owner).AddNewTab(tab, startup: false))
+                {
+                    var tmp = string.Format(Properties.Resources.AddTabMenuItem_ClickText1, tabName);
                     MessageBox.Show(tmp, Properties.Resources.AddTabMenuItem_ClickText2, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                     return;
                 }
                 else
                 {
-                    //成功
-                    ListTabs.Items.Add(tabName);
+                    // タブ作成成功
+                    this.RefreshListTabs();
                 }
             }
         }
 
         private void ButtonDeleteTab_Click(object sender, EventArgs e)
         {
-            if (ListTabs.SelectedIndex > -1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
+            var selectedTab = this.SelectedTab;
+            if (selectedTab != null)
             {
-                string tb = ListTabs.SelectedItem.ToString();
-                int idx = ListTabs.SelectedIndex;
+                var tb = selectedTab.TabName;
+                var idx = this.ListTabs.SelectedIndex;
                 if (((TweenMain)this.Owner).RemoveSpecifiedTab(tb, true))
                 {
-                    ListTabs.Items.RemoveAt(idx);
+                    this.RefreshListTabs();
                     idx -= 1;
                     if (idx < 0) idx = 0;
-                    ListTabs.SelectedIndex = idx;
+                    this.ListTabs.SelectedIndex = idx;
                 }
             }
         }
 
         private void ButtonRenameTab_Click(object sender, EventArgs e)
         {
-            if (ListTabs.SelectedIndex > -1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
+            var selectedTab = this.SelectedTab;
+            if (selectedTab != null)
             {
-                string tb = ListTabs.SelectedItem.ToString();
-                int idx = ListTabs.SelectedIndex;
-                if (((TweenMain)this.Owner).TabRename(ref tb))
-                {
-                    ListTabs.Items.RemoveAt(idx);
-                    ListTabs.Items.Insert(idx, tb);
-                    ListTabs.SelectedIndex = idx;
-                }
+                var origTabName = selectedTab.TabName;
+                if (((TweenMain)this.Owner).TabRename(origTabName, out _))
+                    this.RefreshListTabs();
             }
         }
 
         private void CheckManageRead_CheckedChanged(object sender, EventArgs e)
         {
-            if (ListTabs.SelectedIndex > -1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
+            var selectedTab = this.SelectedTab;
+            if (selectedTab != null)
             {
                 ((TweenMain)this.Owner).ChangeTabUnreadManage(
-                    ListTabs.SelectedItem.ToString(),
-                    CheckManageRead.Checked);
+                    selectedTab.TabName,
+                    this.CheckManageRead.Checked);
             }
         }
 
         private void ButtonUp_Click(object sender, EventArgs e)
         {
-            if (ListTabs.SelectedIndex > 0 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
-            {
-                string selName = ListTabs.SelectedItem.ToString();
-                string tgtName = ListTabs.Items[ListTabs.SelectedIndex - 1].ToString();
-                ((TweenMain)this.Owner).ReOrderTab(
-                    selName,
-                    tgtName,
-                    true);
-                int idx = ListTabs.SelectedIndex;
-                ListTabs.Items.RemoveAt(idx - 1);
-                ListTabs.Items.Insert(idx, tgtName);
-            }
+            var selectedIndex = this.ListTabs.SelectedIndex;
+
+            if (selectedIndex == -1 || selectedIndex == 0)
+                return;
+
+            var selectedTab = this.tabs[selectedIndex];
+            var selectedTabName = selectedTab.TabName;
+
+            var targetTab = this.tabs[selectedIndex - 1];
+            var targetTabName = targetTab.TabName;
+
+            // ミュートタブは移動禁止
+            if (selectedTab.TabType == MyCommon.TabUsageType.Mute || targetTab.TabType == MyCommon.TabUsageType.Mute)
+                return;
+
+            var tweenMain = (TweenMain)this.Owner;
+            tweenMain.ReOrderTab(selectedTabName, targetTabName, true);
+
+            this.RefreshListTabs();
         }
 
         private void ButtonDown_Click(object sender, EventArgs e)
         {
-            if (ListTabs.SelectedIndex > -1 && ListTabs.SelectedIndex < ListTabs.Items.Count - 1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
-            {
-                string selName = ListTabs.SelectedItem.ToString();
-                string tgtName = ListTabs.Items[ListTabs.SelectedIndex + 1].ToString();
-                ((TweenMain)this.Owner).ReOrderTab(
-                    selName,
-                    tgtName,
-                    false);
-                int idx = ListTabs.SelectedIndex;
-                ListTabs.Items.RemoveAt(idx + 1);
-                ListTabs.Items.Insert(idx, tgtName);
-            }
+            var selectedIndex = this.ListTabs.SelectedIndex;
+
+            if (selectedIndex == -1 || selectedIndex == this.ListTabs.Items.Count - 1)
+                return;
+
+            var selectedTab = this.tabs[selectedIndex];
+            var selectedTabName = selectedTab.TabName;
+
+            var targetTab = this.tabs[selectedIndex + 1];
+            var targetTabName = targetTab.TabName;
+
+            // ミュートタブは移動禁止
+            if (selectedTab.TabType == MyCommon.TabUsageType.Mute || targetTab.TabType == MyCommon.TabUsageType.Mute)
+                return;
+
+            var tweenMain = (TweenMain)this.Owner;
+            tweenMain.ReOrderTab(selectedTabName, targetTabName, false);
+
+            this.RefreshListTabs();
         }
 
         private void CheckLocked_CheckedChanged(object sender, EventArgs e)
         {
-            if (ListTabs.SelectedIndex > -1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
+            var selectedTab = this.SelectedTab;
+            if (selectedTab != null)
             {
-                _sts.Tabs[ListTabs.SelectedItem.ToString()].Protected = CheckProtected.Checked;
-                ButtonDeleteTab.Enabled = !CheckProtected.Checked;
+                selectedTab.Protected = this.CheckProtected.Checked;
+                this.ButtonDeleteTab.Enabled = !this.CheckProtected.Checked;
             }
         }
 
         private void CheckNotifyNew_CheckedChanged(object sender, EventArgs e)
         {
-            if (ListTabs.SelectedIndex > -1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
+            var selectedTab = this.SelectedTab;
+            if (selectedTab != null)
             {
-                _sts.Tabs[ListTabs.SelectedItem.ToString()].Notify = CheckNotifyNew.Checked;
+                selectedTab.Notify = this.CheckNotifyNew.Checked;
             }
         }
 
         private void ComboSound_SelectedIndexChanged(object sender, EventArgs e)
         {
-            if (ListTabs.SelectedIndex > -1 && string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
+            var selectedTab = this.SelectedTab;
+            if (selectedTab != null)
             {
-                string filename = "";
-                if (ComboSound.SelectedIndex > -1) filename = ComboSound.SelectedItem.ToString();
-                _sts.Tabs[ListTabs.SelectedItem.ToString()].SoundFile = filename;
+                var filename = "";
+                if (this.ComboSound.SelectedIndex > -1) filename = this.ComboSound.SelectedItem.ToString();
+                selectedTab.SoundFile = filename;
             }
         }
 
         private void RadioExAnd_CheckedChanged(object sender, EventArgs e)
         {
-            bool flg = RadioExAnd.Checked;
-            ExUID.Enabled = flg;
-            ExMSG1.Enabled = flg;
-            ExMSG2.Enabled = !flg;
+            var flg = this.RadioExAnd.Checked;
+            this.ExUID.Enabled = flg;
+            this.ExMSG1.Enabled = flg;
+            this.ExMSG2.Enabled = !flg;
         }
 
         private void OptMove_CheckedChanged(object sender, EventArgs e)
-        {
-            CheckMark.Enabled = !OptMove.Checked;
-        }
+            => this.CheckMark.Enabled = !this.OptMove.Checked;
 
         private void ButtonRuleUp_Click(object sender, EventArgs e)
+            => this.MoveSelectedRules(up: true);
+
+        private void ButtonRuleDown_Click(object sender, EventArgs e)
+            => this.MoveSelectedRules(up: false);
+
+        private void MoveSelectedRules(bool up)
         {
-            if (ListTabs.SelectedIndex > -1 && ListFilters.SelectedItem != null && ListFilters.SelectedIndex > 0)
+            var selectedTab = this.SelectedTab;
+            if (selectedTab == null || this.ListFilters.SelectedIndices.Count == 0)
+                return;
+
+            var indices = this.ListFilters.SelectedIndices.Cast<int>().ToArray();
+
+            int diff;
+            if (up)
             {
-                string tabname = ListTabs.SelectedItem.ToString();
-                PostFilterRule selected = _sts.Tabs[tabname].Filters[ListFilters.SelectedIndex];
-                PostFilterRule target = _sts.Tabs[tabname].Filters[ListFilters.SelectedIndex - 1];
-                int idx = ListFilters.SelectedIndex;
-                ListFilters.Items.RemoveAt(idx - 1);
-                ListFilters.Items.Insert(idx, target);
-                _sts.Tabs[tabname].Filters.RemoveAt(idx - 1);
-                _sts.Tabs[tabname].Filters.Insert(idx, target);
+                if (indices[0] <= 0) return;
+                diff = -1;
+            }
+            else
+            {
+                if (indices[indices.Length - 1] >= this.ListFilters.Items.Count - 1) return;
+                diff = +1;
+                Array.Reverse(indices);  // 逆順にして、下にある要素から処理する
+            }
+
+            var lastSelIdx = indices[0] + diff;
+            var tab = (FilterTabModel)selectedTab;
+
+            try
+            {
+                this._multiSelState |= MultiSelectionState.MoveSelected;
+
+                using (ControlTransaction.Update(this.ListFilters))
+                {
+                    this.ListFilters.SelectedIndices.Clear();
+
+                    foreach (var idx in indices)
+                    {
+                        var tidx = idx + diff;
+                        var target = (PostFilterRule)this.ListFilters.Items[tidx];
+
+                        // 移動先にある要素と位置を入れ替える
+                        this.ListFilters.Items.RemoveAt(tidx);
+                        this.ListFilters.Items.Insert(idx, target);
+
+                        // 移動方向の先頭要素以外なら選択する
+                        if (tidx != lastSelIdx)
+                            this.ListFilters.SelectedIndex = tidx;
+                    }
+
+                    tab.FilterArray = this.ListFilters.Items.Cast<PostFilterRule>().ToArray();
+
+                    // 移動方向の先頭要素は最後に選択する
+                    // ※移動方向への自動スクロール目的
+                    this.ListFilters.SelectedIndex = lastSelIdx;
+                }
+            }
+            finally
+            {
+                this._multiSelState &= ~MultiSelectionState.MoveSelected;
             }
         }
 
-        private void ButtonRuleDown_Click(object sender, EventArgs e)
+        private void buttonRuleToggleEnabled_Click(object sender, EventArgs e)
         {
-            if (ListTabs.SelectedIndex > -1 && ListFilters.SelectedItem != null && ListFilters.SelectedIndex < ListFilters.Items.Count - 1)
+            if (this.RuleEnableButtonMode == EnableButtonMode.NotSelected)
+                return;
+
+            var enabled = this.RuleEnableButtonMode == EnableButtonMode.Enable;
+
+            foreach (var idx in this.ListFilters.SelectedIndices.Cast<int>())
             {
-                string tabname = ListTabs.SelectedItem.ToString();
-                PostFilterRule selected = _sts.Tabs[tabname].Filters[ListFilters.SelectedIndex];
-                PostFilterRule target = _sts.Tabs[tabname].Filters[ListFilters.SelectedIndex + 1];
-                int idx = ListFilters.SelectedIndex;
-                ListFilters.Items.RemoveAt(idx + 1);
-                ListFilters.Items.Insert(idx, target);
-                _sts.Tabs[tabname].Filters.RemoveAt(idx + 1);
-                _sts.Tabs[tabname].Filters.Insert(idx, target);
+                var filter = (PostFilterRule)this.ListFilters.Items[idx];
+                if (filter.Enabled != enabled)
+                {
+                    filter.Enabled = enabled;
+
+                    var itemRect = this.ListFilters.GetItemRectangle(idx);
+                    this.ListFilters.Invalidate(itemRect);
+                }
             }
+
+            this.RuleEnableButtonMode = enabled ? EnableButtonMode.Disable : EnableButtonMode.Enable;
         }
 
         private void ButtonRuleCopy_Click(object sender, EventArgs e)
         {
-            if (ListTabs.SelectedIndex > -1 && ListFilters.SelectedItem != null)
+            var selectedTab = this.SelectedTab;
+            if (selectedTab != null && this.ListFilters.SelectedItem != null)
             {
-                TabClass[] selectedTabs;
-                using (TabsDialog dialog = new TabsDialog(_sts))
+                TabModel[] destinationTabs;
+                using (var dialog = new TabsDialog(this._sts))
                 {
                     dialog.MultiSelect = true;
                     dialog.Text = Properties.Resources.ButtonRuleCopy_ClickText1;
 
                     if (dialog.ShowDialog(this) == DialogResult.Cancel) return;
 
-                    selectedTabs = dialog.SelectedTabs;
+                    destinationTabs = dialog.SelectedTabs;
                 }
 
-                string tabname = ListTabs.SelectedItem.ToString();
-                List<PostFilterRule> filters = new List<PostFilterRule>();
+                var currentTab = (FilterTabModel)selectedTab;
+                var filters = new List<PostFilterRule>();
 
-                foreach (int idx in ListFilters.SelectedIndices)
+                foreach (int idx in this.ListFilters.SelectedIndices)
                 {
-                    filters.Add(_sts.Tabs[tabname].Filters[idx].Clone());
+                    filters.Add(currentTab.FilterArray[idx].Clone());
                 }
-                foreach (var tb in selectedTabs)
+                foreach (var tb in destinationTabs.Cast<FilterTabModel>())
                 {
-                    if (tb.TabName == tabname) continue;
+                    if (tb.TabName == currentTab.TabName) continue;
 
-                    foreach (PostFilterRule flt in filters)
+                    foreach (var flt in filters)
                     {
-                        if (!tb.Filters.Contains(flt))
+                        if (!tb.FilterArray.Contains(flt))
                             tb.AddFilter(flt.Clone());
                     }
                 }
-                SetFilters(tabname);
+                this.SetFilters(selectedTab);
             }
         }
 
         private void ButtonRuleMove_Click(object sender, EventArgs e)
         {
-            if (ListTabs.SelectedIndex > -1 && ListFilters.SelectedItem != null)
+            var selectedTab = this.SelectedTab;
+            if (selectedTab != null && this.ListFilters.SelectedItem != null)
             {
-                TabClass[] selectedTabs;
-                using (var dialog = new TabsDialog(_sts))
+                TabModel[] destinationTabs;
+                using (var dialog = new TabsDialog(this._sts))
                 {
                     dialog.MultiSelect = true;
                     dialog.Text = Properties.Resources.ButtonRuleMove_ClickText1;
 
                     if (dialog.ShowDialog(this) == DialogResult.Cancel) return;
 
-                    selectedTabs = dialog.SelectedTabs;
+                    destinationTabs = dialog.SelectedTabs;
                 }
-                string tabname = ListTabs.SelectedItem.ToString();
-                List<PostFilterRule> filters = new List<PostFilterRule>();
+                var currentTab = (FilterTabModel)selectedTab;
+                var filters = new List<PostFilterRule>();
 
-                foreach (int idx in ListFilters.SelectedIndices)
+                foreach (int idx in this.ListFilters.SelectedIndices)
                 {
-                    filters.Add(_sts.Tabs[tabname].Filters[idx].Clone());
+                    filters.Add(currentTab.FilterArray[idx].Clone());
                 }
-                if (selectedTabs.Length == 1 && selectedTabs[0].TabName == tabname) return;
-                foreach (var tb in selectedTabs)
+                if (destinationTabs.Length == 1 && destinationTabs[0].TabName == currentTab.TabName) return;
+                foreach (var tb in destinationTabs.Cast<FilterTabModel>())
                 {
-                    if (tb.TabName == tabname) continue;
+                    if (tb.TabName == currentTab.TabName) continue;
 
-                    foreach (PostFilterRule flt in filters)
+                    foreach (var flt in filters)
                     {
-                        if (!tb.Filters.Contains(flt))
+                        if (!tb.FilterArray.Contains(flt))
                             tb.AddFilter(flt.Clone());
                     }
                 }
-                for (int idx = ListFilters.Items.Count - 1; idx >= 0; idx--)
+                for (var idx = this.ListFilters.Items.Count - 1; idx >= 0; idx--)
                 {
-                    if (ListFilters.GetSelected(idx))
+                    if (this.ListFilters.GetSelected(idx))
                     {
-                        _sts.Tabs[ListTabs.SelectedItem.ToString()].RemoveFilter((PostFilterRule)ListFilters.Items[idx]);
-                        ListFilters.Items.RemoveAt(idx);
+                        currentTab.RemoveFilter((PostFilterRule)this.ListFilters.Items[idx]);
+                        this.ListFilters.Items.RemoveAt(idx);
                     }
                 }
-                SetFilters(tabname);
+                this.SetFilters(selectedTab);
             }
         }
 
@@ -1196,19 +1331,19 @@ namespace OpenTween
         {
             if (e.KeyCode == Keys.Space && e.Modifiers == (Keys.Shift | Keys.Control))
             {
-                TweenMain main = (TweenMain)this.Owner;
-                TextBox tbox = (TextBox)sender;
+                var main = (TweenMain)this.Owner;
+                var tbox = (TextBox)sender;
                 if (tbox.SelectionStart > 0)
                 {
-                    int endidx = tbox.SelectionStart - 1;
-                    string startstr = "";
-                    for (int i = tbox.SelectionStart - 1; i >= 0; i--)
+                    var endidx = tbox.SelectionStart - 1;
+                    for (var i = tbox.SelectionStart - 1; i >= 0; i--)
                     {
-                        char c = tbox.Text[i];
-                        if (Char.IsLetterOrDigit(c) || c == '_')
+                        var c = tbox.Text[i];
+                        if (char.IsLetterOrDigit(c) || c == '_')
                         {
                             continue;
                         }
+                        string startstr;
                         if (c == '@')
                         {
                             startstr = tbox.Text.Substring(i + 1, endidx - i);
@@ -1231,21 +1366,79 @@ namespace OpenTween
 
         private void FilterTextBox_KeyPress(object sender, KeyPressEventArgs e)
         {
-            TweenMain main = (TweenMain)this.Owner;
-            TextBox tbox = (TextBox)sender;
+            var main = (TweenMain)this.Owner;
+            var tbox = (TextBox)sender;
             if (e.KeyChar == '@')
             {
-                //if (!SettingDialog.UseAtIdSupplement) return;
-                //@マーク
+                // @マーク
                 main.ShowSuplDialog(tbox, main.AtIdSupl);
                 e.Handled = true;
             }
             else if (e.KeyChar == '#')
             {
-                //if (!SettingDialog.UseHashSupplement) return;
                 main.ShowSuplDialog(tbox, main.HashSupl);
                 e.Handled = true;
             }
         }
+
+        private void ListFilters_DrawItem(object sender, DrawItemEventArgs e)
+        {
+            e.DrawBackground();
+
+            if (e.Index != -1)
+            {
+                var filter = (PostFilterRule)this.ListFilters.Items[e.Index];
+                var isSelected = e.State.HasFlag(DrawItemState.Selected);
+
+                Brush textBrush;
+                if (isSelected)
+                    textBrush = SystemBrushes.HighlightText;
+                else if (filter.Enabled)
+                    textBrush = SystemBrushes.WindowText;
+                else
+                    textBrush = SystemBrushes.GrayText;
+
+                e.Graphics.DrawString(filter.ToString(), e.Font, textBrush, e.Bounds);
+            }
+
+            e.DrawFocusRectangle();
+        }
+
+        private void ListFilters_KeyDown(object sender, KeyEventArgs e)
+        {
+            if (e.Control && e.KeyCode == Keys.A)
+            {
+                var itemCount = this.ListFilters.Items.Count;
+                if (itemCount == 0) return;
+
+                using (ControlTransaction.Update(this.ListFilters))
+                {
+                    if (itemCount > 1)
+                    {
+                        try
+                        {
+                            this._multiSelState |= MultiSelectionState.SelectAll;
+
+                            for (var i = 1; i < itemCount; i++)
+                            {
+                                this.ListFilters.SetSelected(i, true);
+                            }
+                        }
+                        finally
+                        {
+                            this._multiSelState &= ~MultiSelectionState.SelectAll;
+                        }
+                    }
+
+                    this.ListFilters.SetSelected(0, true);
+                }
+            }
+        }
+
+        protected override void ScaleControl(SizeF factor, BoundsSpecified specified)
+        {
+            base.ScaleControl(factor, specified);
+            this.ListFilters.ItemHeight = this.ListFilters.Font.Height;
+        }
     }
 }