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.
10 // This file is part of OpenTween.
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)
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
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.
28 using System.Collections.Generic;
29 using System.ComponentModel;
34 using System.Windows.Forms;
35 using System.Linq.Expressions;
36 using System.Text.RegularExpressions;
38 using System.Collections.Specialized;
39 using OpenTween.Models;
43 public partial class FilterDialog : OTBaseForm
45 private EDITMODE _mode;
46 private bool _directAdd;
47 private MultiSelectionState _multiSelState = MultiSelectionState.None;
48 private TabInformations _sts;
50 private List<string> idlist = new List<string>();
59 private enum EnableButtonMode
67 private enum MultiSelectionState
74 private EnableButtonMode RuleEnableButtonMode
76 get => this._ruleEnableButtonMode;
79 this._ruleEnableButtonMode = value;
81 this.buttonRuleToggleEnabled.Text = value == FilterDialog.EnableButtonMode.Enable
82 ? Properties.Resources.EnableButtonCaption
83 : Properties.Resources.DisableButtonCaption;
84 this.buttonRuleToggleEnabled.Enabled = value != EnableButtonMode.NotSelected;
87 private EnableButtonMode _ruleEnableButtonMode = FilterDialog.EnableButtonMode.NotSelected;
90 => this.InitializeComponent();
92 private void SetFilters(string tabName)
94 if (ListTabs.Items.Count == 0) return;
96 ListFilters.Items.Clear();
98 var tab = _sts.Tabs[tabName];
100 if (tab is FilterTabModel filterTab)
101 ListFilters.Items.AddRange(filterTab.GetFilters());
103 if (ListFilters.Items.Count > 0)
104 ListFilters.SelectedIndex = 0;
108 if (tab.IsDefaultTabType)
110 CheckProtected.Checked = true;
111 CheckProtected.Enabled = false;
115 CheckProtected.Checked = tab.Protected;
116 CheckProtected.Enabled = true;
119 CheckManageRead.Checked = tab.UnreadManage;
120 CheckNotifyNew.Checked = tab.Notify;
122 int idx = ComboSound.Items.IndexOf(tab.SoundFile);
123 if (idx == -1) idx = 0;
124 ComboSound.SelectedIndex = idx;
126 if (_directAdd) return;
128 if (tab.TabType == MyCommon.TabUsageType.Mute)
130 this.CheckManageRead.Enabled = false;
131 this.CheckNotifyNew.Enabled = false;
132 this.ComboSound.Enabled = false;
134 this.GroupBox1.Visible = false;
135 this.labelMuteTab.Visible = true;
139 this.CheckManageRead.Enabled = true;
140 this.CheckNotifyNew.Enabled = true;
141 this.ComboSound.Enabled = true;
143 this.GroupBox1.Visible = true;
144 this.labelMuteTab.Visible = false;
147 ListTabs.Enabled = true;
148 GroupTab.Enabled = true;
149 ListFilters.Enabled = true;
150 EditFilterGroup.Enabled = false;
152 if (tab.IsDistributableTabType)
154 ButtonNew.Enabled = true;
155 if (ListFilters.SelectedIndex > -1)
157 ButtonEdit.Enabled = true;
158 ButtonDelete.Enabled = true;
159 ButtonRuleUp.Enabled = true;
160 ButtonRuleDown.Enabled = true;
161 ButtonRuleCopy.Enabled = true;
162 ButtonRuleMove.Enabled = true;
163 buttonRuleToggleEnabled.Enabled = true;
167 ButtonEdit.Enabled = false;
168 ButtonDelete.Enabled = false;
169 ButtonRuleUp.Enabled = false;
170 ButtonRuleDown.Enabled = false;
171 ButtonRuleCopy.Enabled = false;
172 ButtonRuleMove.Enabled = false;
173 buttonRuleToggleEnabled.Enabled = false;
178 ButtonNew.Enabled = false;
179 ButtonEdit.Enabled = false;
180 ButtonDelete.Enabled = false;
181 ButtonRuleUp.Enabled = false;
182 ButtonRuleDown.Enabled = false;
183 ButtonRuleCopy.Enabled = false;
184 ButtonRuleMove.Enabled = false;
185 buttonRuleToggleEnabled.Enabled = false;
190 case MyCommon.TabUsageType.Home:
191 LabelTabType.Text = Properties.Resources.TabUsageTypeName_Home;
193 case MyCommon.TabUsageType.Mentions:
194 LabelTabType.Text = Properties.Resources.TabUsageTypeName_Mentions;
196 case MyCommon.TabUsageType.DirectMessage:
197 LabelTabType.Text = Properties.Resources.TabUsageTypeName_DirectMessage;
199 case MyCommon.TabUsageType.Favorites:
200 LabelTabType.Text = Properties.Resources.TabUsageTypeName_Favorites;
202 case MyCommon.TabUsageType.UserDefined:
203 LabelTabType.Text = Properties.Resources.TabUsageTypeName_UserDefined;
205 case MyCommon.TabUsageType.PublicSearch:
206 LabelTabType.Text = Properties.Resources.TabUsageTypeName_PublicSearch;
208 case MyCommon.TabUsageType.Lists:
209 LabelTabType.Text = Properties.Resources.TabUsageTypeName_Lists;
211 case MyCommon.TabUsageType.Related:
212 LabelTabType.Text = Properties.Resources.TabUsageTypeName_Related;
214 case MyCommon.TabUsageType.UserTimeline:
215 LabelTabType.Text = Properties.Resources.TabUsageTypeName_UserTimeline;
217 case MyCommon.TabUsageType.Mute:
218 LabelTabType.Text = "Mute";
220 case MyCommon.TabUsageType.SearchResults:
221 LabelTabType.Text = "SearchResults";
224 LabelTabType.Text = "UNKNOWN";
227 ButtonRenameTab.Enabled = true;
228 if (tab.IsDefaultTabType || tab.Protected)
230 ButtonDeleteTab.Enabled = false;
234 ButtonDeleteTab.Enabled = true;
236 ButtonClose.Enabled = true;
239 public void SetCurrent(string TabName)
240 => this._cur = TabName;
242 public void AddNewFilter(string id, string msg)
245 ButtonNew.Enabled = false;
246 ButtonEdit.Enabled = false;
247 ButtonRuleUp.Enabled = false;
248 ButtonRuleDown.Enabled = false;
249 ButtonRuleCopy.Enabled = false;
250 ButtonRuleMove.Enabled = false;
251 buttonRuleToggleEnabled.Enabled = false;
252 ButtonDelete.Enabled = false;
253 ButtonClose.Enabled = false;
254 EditFilterGroup.Enabled = true;
255 ListTabs.Enabled = false;
256 GroupTab.Enabled = false;
257 ListFilters.Enabled = false;
259 RadioAND.Checked = true;
260 RadioPLUS.Checked = false;
265 MSG2.Text = id + msg;
267 TextSource.Text = "";
270 MSG2.Enabled = false;
271 CheckRegex.Checked = false;
272 CheckURL.Checked = false;
273 CheckCaseSensitive.Checked = false;
274 CheckRetweet.Checked = false;
275 CheckLambda.Checked = false;
277 RadioExAnd.Checked = true;
278 RadioExPLUS.Checked = false;
285 TextExSource.Text = "";
286 ExUID.Enabled = true;
287 ExMSG1.Enabled = true;
288 ExMSG2.Enabled = false;
289 CheckExRegex.Checked = false;
290 CheckExURL.Checked = false;
291 CheckExCaseSensitive.Checked = false;
292 CheckExRetweet.Checked = false;
293 CheckExLambDa.Checked = false;
295 OptCopy.Checked = true;
296 CheckMark.Checked = true;
298 _mode = EDITMODE.AddNew;
302 private void ButtonNew_Click(object sender, EventArgs e)
304 ButtonNew.Enabled = false;
305 ButtonEdit.Enabled = false;
306 ButtonClose.Enabled = false;
307 ButtonRuleUp.Enabled = false;
308 ButtonRuleDown.Enabled = false;
309 ButtonRuleCopy.Enabled = false;
310 ButtonRuleMove.Enabled = false;
311 buttonRuleToggleEnabled.Enabled = false;
312 ButtonDelete.Enabled = false;
313 ButtonClose.Enabled = false;
314 EditFilterGroup.Enabled = true;
315 ListTabs.Enabled = false;
316 GroupTab.Enabled = false;
317 ListFilters.Enabled = false;
319 RadioAND.Checked = true;
320 RadioPLUS.Checked = false;
324 TextSource.Text = "";
327 MSG2.Enabled = false;
328 CheckRegex.Checked = false;
329 CheckURL.Checked = false;
330 CheckCaseSensitive.Checked = false;
331 CheckRetweet.Checked = false;
332 CheckLambda.Checked = false;
334 RadioExAnd.Checked = true;
335 RadioExPLUS.Checked = false;
339 TextExSource.Text = "";
340 ExUID.Enabled = true;
341 ExMSG1.Enabled = true;
342 ExMSG2.Enabled = false;
343 CheckExRegex.Checked = false;
344 CheckExURL.Checked = false;
345 CheckExCaseSensitive.Checked = false;
346 CheckExRetweet.Checked = false;
347 CheckExLambDa.Checked = false;
349 OptCopy.Checked = true;
350 CheckMark.Checked = true;
352 _mode = EDITMODE.AddNew;
355 private void ButtonEdit_Click(object sender, EventArgs e)
357 if (ListFilters.SelectedIndex == -1) return;
361 int idx = ListFilters.SelectedIndex;
362 ListFilters.SelectedIndex = -1;
363 ListFilters.SelectedIndex = idx;
364 ListFilters.Enabled = false;
366 ButtonNew.Enabled = false;
367 ButtonEdit.Enabled = false;
368 ButtonDelete.Enabled = false;
369 ButtonClose.Enabled = false;
370 ButtonRuleUp.Enabled = false;
371 ButtonRuleDown.Enabled = false;
372 ButtonRuleCopy.Enabled = false;
373 ButtonRuleMove.Enabled = false;
374 buttonRuleToggleEnabled.Enabled = false;
375 EditFilterGroup.Enabled = true;
376 ListTabs.Enabled = false;
377 GroupTab.Enabled = false;
379 _mode = EDITMODE.Edit;
382 private void ButtonDelete_Click(object sender, EventArgs e)
384 var selectedCount = ListFilters.SelectedIndices.Count;
385 if (selectedCount == 0) return;
389 if (selectedCount == 1)
391 tmp = string.Format(Properties.Resources.ButtonDelete_ClickText1, Environment.NewLine, ListFilters.SelectedItem);
395 tmp = string.Format(Properties.Resources.ButtonDelete_ClickText3, selectedCount);
398 var rslt = MessageBox.Show(tmp, Properties.Resources.ButtonDelete_ClickText2, MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
399 if (rslt == DialogResult.Cancel) return;
401 var indices = ListFilters.SelectedIndices.Cast<int>().Reverse().ToArray(); // 後ろの要素から削除
402 var tab = (FilterTabModel)_sts.Tabs[ListTabs.SelectedItem.ToString()];
404 using (ControlTransaction.Update(ListFilters))
406 foreach (var idx in indices)
408 tab.RemoveFilter((PostFilterRule)ListFilters.Items[idx]);
409 ListFilters.Items.RemoveAt(idx);
414 private void ButtonCancel_Click(object sender, EventArgs e)
416 ListTabs.Enabled = true;
417 GroupTab.Enabled = true;
418 ListFilters.Enabled = true;
420 if (ListFilters.SelectedIndex != -1)
424 EditFilterGroup.Enabled = false;
425 ButtonNew.Enabled = true;
426 if (ListFilters.SelectedIndex > -1)
428 ButtonEdit.Enabled = true;
429 ButtonDelete.Enabled = true;
430 ButtonRuleUp.Enabled = true;
431 ButtonRuleDown.Enabled = true;
432 ButtonRuleCopy.Enabled = true;
433 ButtonRuleMove.Enabled = true;
434 buttonRuleToggleEnabled.Enabled = true;
438 ButtonEdit.Enabled = false;
439 ButtonDelete.Enabled = false;
440 ButtonRuleUp.Enabled = false;
441 ButtonRuleDown.Enabled = false;
442 ButtonRuleCopy.Enabled = false;
443 ButtonRuleMove.Enabled = false;
444 buttonRuleToggleEnabled.Enabled = false;
446 ButtonClose.Enabled = true;
453 private void ShowDetail()
455 if (_directAdd) return;
457 if (ListFilters.SelectedIndex > -1)
459 PostFilterRule fc = (PostFilterRule)ListFilters.SelectedItem;
462 RadioAND.Checked = true;
463 RadioPLUS.Checked = false;
466 MSG2.Enabled = false;
467 UID.Text = fc.FilterName;
469 MSG1.Text = string.Join(" ", fc.FilterBody);
475 RadioPLUS.Checked = true;
476 RadioAND.Checked = false;
478 MSG1.Enabled = false;
482 MSG2.Text = string.Join(" ", fc.FilterBody);
485 TextSource.Text = fc.FilterSource;
486 CheckRegex.Checked = fc.UseRegex;
487 CheckURL.Checked = fc.FilterByUrl;
488 CheckCaseSensitive.Checked = fc.CaseSensitive;
489 CheckRetweet.Checked = fc.FilterRt;
490 CheckLambda.Checked = fc.UseLambda;
492 if (fc.ExUseNameField)
494 RadioExAnd.Checked = true;
495 RadioExPLUS.Checked = false;
496 ExUID.Enabled = true;
497 ExMSG1.Enabled = true;
498 ExMSG2.Enabled = false;
499 ExUID.Text = fc.ExFilterName;
501 ExMSG1.Text = string.Join(" ", fc.ExFilterBody);
507 RadioExPLUS.Checked = true;
508 RadioExAnd.Checked = false;
509 ExUID.Enabled = false;
510 ExMSG1.Enabled = false;
511 ExMSG2.Enabled = true;
514 ExMSG2.Text = string.Join(" ", fc.ExFilterBody);
517 TextExSource.Text = fc.ExFilterSource;
518 CheckExRegex.Checked = fc.ExUseRegex;
519 CheckExURL.Checked = fc.ExFilterByUrl;
520 CheckExCaseSensitive.Checked = fc.ExCaseSensitive;
521 CheckExRetweet.Checked = fc.ExFilterRt;
522 CheckExLambDa.Checked = fc.ExUseLambda;
526 OptMove.Checked = true;
530 OptCopy.Checked = true;
532 CheckMark.Checked = fc.MarkMatches;
534 ButtonEdit.Enabled = true;
535 ButtonDelete.Enabled = true;
536 ButtonRuleUp.Enabled = true;
537 ButtonRuleDown.Enabled = true;
538 ButtonRuleCopy.Enabled = true;
539 ButtonRuleMove.Enabled = true;
540 buttonRuleToggleEnabled.Enabled = true;
544 RadioAND.Checked = true;
545 RadioPLUS.Checked = false;
548 MSG2.Enabled = false;
552 TextSource.Text = "";
553 CheckRegex.Checked = false;
554 CheckURL.Checked = false;
555 CheckCaseSensitive.Checked = false;
556 CheckRetweet.Checked = false;
557 CheckLambda.Checked = false;
559 RadioExAnd.Checked = true;
560 RadioExPLUS.Checked = false;
561 ExUID.Enabled = true;
562 ExMSG1.Enabled = true;
563 ExMSG2.Enabled = false;
567 TextExSource.Text = "";
568 CheckExRegex.Checked = false;
569 CheckExURL.Checked = false;
570 CheckExCaseSensitive.Checked = false;
571 CheckExRetweet.Checked = false;
572 CheckExLambDa.Checked = false;
574 OptCopy.Checked = true;
575 CheckMark.Checked = true;
577 ButtonEdit.Enabled = false;
578 ButtonDelete.Enabled = false;
579 ButtonRuleUp.Enabled = false;
580 ButtonRuleDown.Enabled = false;
581 ButtonRuleCopy.Enabled = false;
582 ButtonRuleMove.Enabled = false;
583 buttonRuleToggleEnabled.Enabled = false;
587 private void RadioAND_CheckedChanged(object sender, EventArgs e)
589 bool flg = RadioAND.Checked;
595 private void ButtonOK_Click(object sender, EventArgs e)
598 if (!CheckMatchRule(out var isBlankMatch) || !CheckExcludeRule(out var isBlankExclude))
602 if (isBlankMatch && isBlankExclude)
604 MessageBox.Show(Properties.Resources.ButtonOK_ClickText1, Properties.Resources.ButtonOK_ClickText2, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
608 var tab = (FilterTabModel)this._sts.Tabs[(string)this.ListTabs.SelectedItem];
609 int i = ListFilters.SelectedIndex;
612 if (_mode == EDITMODE.AddNew)
613 ft = new PostFilterRule();
615 ft = (PostFilterRule)this.ListFilters.SelectedItem;
617 if (tab.TabType != MyCommon.TabUsageType.Mute)
619 ft.MoveMatches = OptMove.Checked;
620 ft.MarkMatches = CheckMark.Checked;
624 ft.MoveMatches = true;
625 ft.MarkMatches = false;
629 if (RadioAND.Checked)
631 ft.FilterName = UID.Text;
632 TweenMain owner = (TweenMain)this.Owner;
633 int cnt = owner.AtIdSupl.ItemCount;
634 owner.AtIdSupl.AddItem("@" + ft.FilterName);
635 if (cnt != owner.AtIdSupl.ItemCount)
637 owner.ModifySettingAtId = true;
639 ft.UseNameField = true;
645 ft.UseNameField = false;
648 ft.FilterSource = TextSource.Text;
650 if (CheckRegex.Checked || CheckLambda.Checked)
652 ft.FilterBody = new[] { bdy };
656 ft.FilterBody = bdy.Split(' ', ' ')
657 .Where(x => !string.IsNullOrEmpty(x))
661 ft.UseRegex = CheckRegex.Checked;
662 ft.FilterByUrl = CheckURL.Checked;
663 ft.CaseSensitive = CheckCaseSensitive.Checked;
664 ft.FilterRt = CheckRetweet.Checked;
665 ft.UseLambda = CheckLambda.Checked;
668 if (RadioExAnd.Checked)
670 ft.ExFilterName = ExUID.Text;
671 ft.ExUseNameField = true;
676 ft.ExFilterName = "";
677 ft.ExUseNameField = false;
680 ft.ExFilterSource = TextExSource.Text;
682 if (CheckExRegex.Checked || CheckExLambDa.Checked)
684 ft.ExFilterBody = new[] { bdy };
688 ft.ExFilterBody = bdy.Split(' ', ' ')
689 .Where(x => !string.IsNullOrEmpty(x))
693 ft.ExUseRegex = CheckExRegex.Checked;
694 ft.ExFilterByUrl = CheckExURL.Checked;
695 ft.ExCaseSensitive = CheckExCaseSensitive.Checked;
696 ft.ExFilterRt = CheckExRetweet.Checked;
697 ft.ExUseLambda = CheckExLambDa.Checked;
699 if (_mode == EDITMODE.AddNew)
701 if (!tab.AddFilter(ft))
702 MessageBox.Show(Properties.Resources.ButtonOK_ClickText4, Properties.Resources.ButtonOK_ClickText2, MessageBoxButtons.OK, MessageBoxIcon.Error);
705 SetFilters(tab.TabName);
706 ListFilters.SelectedIndex = -1;
707 if (_mode == EDITMODE.AddNew)
709 ListFilters.SelectedIndex = ListFilters.Items.Count - 1;
713 ListFilters.SelectedIndex = i;
715 _mode = EDITMODE.None;
723 private bool IsValidLambdaExp(string text)
724 => false; // TODO DynamicQuery相当のGPLv3互換なライブラリで置換する
726 private bool IsValidRegexp(string text)
734 MessageBox.Show(Properties.Resources.ButtonOK_ClickText3 + ex.Message, Properties.Resources.ButtonOK_ClickText2, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
740 private bool CheckMatchRule(out bool isBlank)
743 if (RadioAND.Checked)
745 if (string.IsNullOrEmpty(UID.Text) && string.IsNullOrEmpty(MSG1.Text) && string.IsNullOrEmpty(TextSource.Text) && CheckRetweet.Checked == false)
750 if (CheckLambda.Checked)
752 if (!IsValidLambdaExp(UID.Text))
756 if (!IsValidLambdaExp(MSG1.Text))
761 else if (CheckRegex.Checked)
763 if (!IsValidRegexp(UID.Text))
767 if (!IsValidRegexp(MSG1.Text))
775 if (string.IsNullOrEmpty(MSG2.Text) && string.IsNullOrEmpty(TextSource.Text) && CheckRetweet.Checked == false)
780 if (CheckLambda.Checked && !IsValidLambdaExp(MSG2.Text))
784 else if (CheckRegex.Checked && !IsValidRegexp(MSG2.Text))
790 if (CheckRegex.Checked && !IsValidRegexp(TextSource.Text))
797 private bool CheckExcludeRule(out bool isBlank)
800 if (RadioExAnd.Checked)
802 if (string.IsNullOrEmpty(ExUID.Text) && string.IsNullOrEmpty(ExMSG1.Text) && string.IsNullOrEmpty(TextExSource.Text) && CheckExRetweet.Checked == false)
807 if (CheckExLambDa.Checked)
809 if (!IsValidLambdaExp(ExUID.Text))
813 if (!IsValidLambdaExp(ExMSG1.Text))
818 else if (CheckExRegex.Checked)
820 if (!IsValidRegexp(ExUID.Text))
824 if (!IsValidRegexp(ExMSG1.Text))
832 if (string.IsNullOrEmpty(ExMSG2.Text) && string.IsNullOrEmpty(TextExSource.Text) && CheckExRetweet.Checked == false)
837 if (CheckExLambDa.Checked && !IsValidLambdaExp(ExMSG2.Text))
841 else if (CheckExRegex.Checked && !IsValidRegexp(ExMSG2.Text))
847 if (CheckExRegex.Checked && !IsValidRegexp(TextExSource.Text))
855 private void ListFilters_SelectedIndexChanged(object sender, EventArgs e)
857 if (_multiSelState != MultiSelectionState.None) //複数選択処理中は無視する
862 var selectedCount = this.ListFilters.SelectedIndices.Count;
863 if (selectedCount == 0)
865 this.RuleEnableButtonMode = EnableButtonMode.NotSelected;
869 if (selectedCount == 1 ||
870 this.RuleEnableButtonMode == EnableButtonMode.NotSelected)
872 var topItem = (PostFilterRule)this.ListFilters.SelectedItem;
873 this.RuleEnableButtonMode = topItem.Enabled ? EnableButtonMode.Disable : EnableButtonMode.Enable;
878 private void ButtonClose_Click(object sender, EventArgs e)
881 private void FilterDialog_FormClosed(object sender, FormClosedEventArgs e)
882 => this._directAdd = false;
884 private void FilterDialog_KeyDown(object sender, KeyEventArgs e)
886 if (e.KeyCode == Keys.Escape)
888 if (EditFilterGroup.Enabled)
889 ButtonCancel_Click(null, null);
891 ButtonClose_Click(null, null);
895 private void ListFilters_DoubleClick(object sender, EventArgs e)
897 var idx = ListFilters.SelectedIndex;
898 if (idx == -1) return;
900 var midx = ListFilters.IndexFromPoint(ListFilters.PointToClient(Control.MousePosition));
901 if (midx == ListBox.NoMatches || idx != midx) return;
903 ButtonEdit_Click(sender, e);
906 private void FilterDialog_Shown(object sender, EventArgs e)
908 _sts = TabInformations.GetInstance();
909 ListTabs.Items.Clear();
910 foreach (var tab in this._sts.Tabs)
912 if (tab.TabType == MyCommon.TabUsageType.Mute)
915 this.ListTabs.Items.Add(tab.TabName);
918 var muteTab = this._sts.GetTabByType(MyCommon.TabUsageType.Mute);
920 this.ListTabs.Items.Add(muteTab.TabName);
922 ComboSound.Items.Clear();
923 ComboSound.Items.Add("");
924 DirectoryInfo oDir = new DirectoryInfo(Application.StartupPath + Path.DirectorySeparatorChar);
925 if (Directory.Exists(Path.Combine(Application.StartupPath, "Sounds")))
927 oDir = oDir.GetDirectories("Sounds")[0];
929 foreach (FileInfo oFile in oDir.GetFiles("*.wav"))
931 ComboSound.Items.Add(oFile.Name);
935 foreach (string tmp in ((TweenMain)this.Owner).AtIdSupl.GetItemList())
937 idlist.Add(tmp.Remove(0, 1)); // @文字削除
939 UID.AutoCompleteCustomSource.Clear();
940 UID.AutoCompleteCustomSource.AddRange(idlist.ToArray());
942 ExUID.AutoCompleteCustomSource.Clear();
943 ExUID.AutoCompleteCustomSource.AddRange(idlist.ToArray());
946 if (ListTabs.Items.Count > 0)
950 for (int i = 0; i < ListTabs.Items.Count; i++)
952 if (_cur == ListTabs.Items[i].ToString())
954 ListTabs.SelectedIndex = i;
955 //tabdialog.TabList.Items.Remove(_cur);
963 private void ListTabs_SelectedIndexChanged(object sender, EventArgs e)
965 if (ListTabs.SelectedIndex > -1)
966 SetFilters(ListTabs.SelectedItem.ToString());
968 ListFilters.Items.Clear();
971 private async void ButtonAddTab_Click(object sender, EventArgs e)
973 string tabName = null;
974 MyCommon.TabUsageType tabType;
975 using (InputTabName inputName = new InputTabName())
977 inputName.TabName = _sts.MakeTabName("MyTab");
978 inputName.IsShowUsage = true;
979 inputName.ShowDialog();
980 if (inputName.DialogResult == DialogResult.Cancel) return;
981 tabName = inputName.TabName;
982 tabType = inputName.Usage;
984 if (!string.IsNullOrEmpty(tabName))
987 ListElement list = null;
988 if (tabType == MyCommon.TabUsageType.Lists)
992 using (var dialog = new WaitingDialog(Properties.Resources.ListsGetting))
994 var cancellationToken = dialog.EnableCancellation();
996 var task = ((TweenMain)this.Owner).TwitterInstance.GetListsApi();
997 await dialog.WaitForAsync(this, task);
999 cancellationToken.ThrowIfCancellationRequested();
1002 catch (OperationCanceledException) { return; }
1003 catch (WebApiException ex)
1005 MessageBox.Show("Failed to get lists. (" + ex.Message + ")");
1007 using (ListAvailable listAvail = new ListAvailable())
1009 if (listAvail.ShowDialog(this) == DialogResult.Cancel) return;
1010 if (listAvail.SelectedList == null) return;
1011 list = listAvail.SelectedList;
1018 case MyCommon.TabUsageType.UserDefined:
1019 tab = new FilterTabModel(tabName);
1021 case MyCommon.TabUsageType.PublicSearch:
1022 tab = new PublicSearchTabModel(tabName);
1024 case MyCommon.TabUsageType.Lists:
1025 tab = new ListTimelineTabModel(tabName, list);
1031 if (!_sts.AddTab(tab) || !((TweenMain)this.Owner).AddNewTab(tab, startup: false))
1033 string tmp = string.Format(Properties.Resources.AddTabMenuItem_ClickText1, tabName);
1034 MessageBox.Show(tmp, Properties.Resources.AddTabMenuItem_ClickText2, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
1042 var lastIdx = this.ListTabs.Items.Count - 1;
1043 var lastTab = lastIdx != -1
1044 ? this._sts.Tabs[(string)this.ListTabs.Items[lastIdx]]
1047 // 末尾がミュートタブであればその手前に追加する
1048 if (lastTab != null && lastTab.TabType == MyCommon.TabUsageType.Mute)
1049 this.ListTabs.Items.Insert(lastIdx, tabName);
1051 this.ListTabs.Items.Add(tabName);
1056 private void ButtonDeleteTab_Click(object sender, EventArgs e)
1058 if (ListTabs.SelectedIndex > -1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
1060 string tb = ListTabs.SelectedItem.ToString();
1061 int idx = ListTabs.SelectedIndex;
1062 if (((TweenMain)this.Owner).RemoveSpecifiedTab(tb, true))
1064 ListTabs.Items.RemoveAt(idx);
1066 if (idx < 0) idx = 0;
1067 ListTabs.SelectedIndex = idx;
1072 private void ButtonRenameTab_Click(object sender, EventArgs e)
1074 if (ListTabs.SelectedIndex > -1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
1076 int idx = ListTabs.SelectedIndex;
1078 var origTabName = (string)this.ListTabs.SelectedItem;
1079 if (((TweenMain)this.Owner).TabRename(origTabName, out var newTabName))
1081 ListTabs.Items.RemoveAt(idx);
1082 ListTabs.Items.Insert(idx, newTabName);
1083 ListTabs.SelectedIndex = idx;
1088 private void CheckManageRead_CheckedChanged(object sender, EventArgs e)
1090 if (ListTabs.SelectedIndex > -1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
1092 ((TweenMain)this.Owner).ChangeTabUnreadManage(
1093 ListTabs.SelectedItem.ToString(),
1094 CheckManageRead.Checked);
1098 private void ButtonUp_Click(object sender, EventArgs e)
1100 if (this.ListTabs.SelectedIndex == -1 || this.ListTabs.SelectedIndex == 0)
1103 var selectedTabName = (string)this.ListTabs.SelectedItem;
1104 var selectedTab = this._sts.Tabs[selectedTabName];
1106 var targetTabName = (string)this.ListTabs.Items[this.ListTabs.SelectedIndex - 1];
1107 var targetTab = this._sts.Tabs[targetTabName];
1110 if (selectedTab.TabType == MyCommon.TabUsageType.Mute || targetTab.TabType == MyCommon.TabUsageType.Mute)
1113 var tweenMain = (TweenMain)this.Owner;
1114 tweenMain.ReOrderTab(selectedTabName, targetTabName, true);
1116 // ListTab のアイテム並び替え
1117 // 選択が解除されてしまうのを防ぐため SelectedIndex のアイテムは操作せず前後のアイテムを移動する
1118 var idx = this.ListTabs.SelectedIndex;
1119 this.ListTabs.Items.RemoveAt(idx - 1);
1120 this.ListTabs.Items.Insert(idx, targetTabName);
1123 private void ButtonDown_Click(object sender, EventArgs e)
1125 if (this.ListTabs.SelectedIndex == -1 || this.ListTabs.SelectedIndex == this.ListTabs.Items.Count - 1)
1128 var selectedTabName = (string)this.ListTabs.SelectedItem;
1129 var selectedTab = this._sts.Tabs[selectedTabName];
1131 var targetTabName = (string)this.ListTabs.Items[this.ListTabs.SelectedIndex + 1];
1132 var targetTab = this._sts.Tabs[targetTabName];
1135 if (selectedTab.TabType == MyCommon.TabUsageType.Mute || targetTab.TabType == MyCommon.TabUsageType.Mute)
1138 var tweenMain = (TweenMain)this.Owner;
1139 tweenMain.ReOrderTab(selectedTabName, targetTabName, false);
1141 // ListTab のアイテム並び替え
1142 // 選択が解除されてしまうのを防ぐため SelectedIndex のアイテムは操作せず前後のアイテムを移動する
1143 var idx = this.ListTabs.SelectedIndex;
1144 this.ListTabs.Items.RemoveAt(idx + 1);
1145 this.ListTabs.Items.Insert(idx, targetTabName);
1148 private void CheckLocked_CheckedChanged(object sender, EventArgs e)
1150 if (ListTabs.SelectedIndex > -1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
1152 _sts.Tabs[ListTabs.SelectedItem.ToString()].Protected = CheckProtected.Checked;
1153 ButtonDeleteTab.Enabled = !CheckProtected.Checked;
1157 private void CheckNotifyNew_CheckedChanged(object sender, EventArgs e)
1159 if (ListTabs.SelectedIndex > -1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
1161 _sts.Tabs[ListTabs.SelectedItem.ToString()].Notify = CheckNotifyNew.Checked;
1165 private void ComboSound_SelectedIndexChanged(object sender, EventArgs e)
1167 if (ListTabs.SelectedIndex > -1 && string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
1169 string filename = "";
1170 if (ComboSound.SelectedIndex > -1) filename = ComboSound.SelectedItem.ToString();
1171 _sts.Tabs[ListTabs.SelectedItem.ToString()].SoundFile = filename;
1175 private void RadioExAnd_CheckedChanged(object sender, EventArgs e)
1177 bool flg = RadioExAnd.Checked;
1178 ExUID.Enabled = flg;
1179 ExMSG1.Enabled = flg;
1180 ExMSG2.Enabled = !flg;
1183 private void OptMove_CheckedChanged(object sender, EventArgs e)
1184 => this.CheckMark.Enabled = !OptMove.Checked;
1186 private void ButtonRuleUp_Click(object sender, EventArgs e)
1187 => this.MoveSelectedRules(up: true);
1189 private void ButtonRuleDown_Click(object sender, EventArgs e)
1190 => this.MoveSelectedRules(up: false);
1192 private void MoveSelectedRules(bool up)
1194 var tabIdx = ListTabs.SelectedIndex;
1196 ListFilters.SelectedIndices.Count == 0) return;
1198 var indices = ListFilters.SelectedIndices.Cast<int>().ToArray();
1203 if (indices[0] <= 0) return;
1208 if (indices[indices.Length - 1] >= ListFilters.Items.Count - 1) return;
1210 Array.Reverse(indices); // 逆順にして、下にある要素から処理する
1213 var lastSelIdx = indices[0] + diff;
1214 var tab = (FilterTabModel)_sts.Tabs[ListTabs.Items[tabIdx].ToString()];
1218 _multiSelState |= MultiSelectionState.MoveSelected;
1220 using (ControlTransaction.Update(ListFilters))
1222 ListFilters.SelectedIndices.Clear();
1224 foreach (var idx in indices)
1226 var tidx = idx + diff;
1227 var target = (PostFilterRule)ListFilters.Items[tidx];
1229 // 移動先にある要素と位置を入れ替える
1230 ListFilters.Items.RemoveAt(tidx);
1231 ListFilters.Items.Insert(idx, target);
1233 // 移動方向の先頭要素以外なら選択する
1234 if (tidx != lastSelIdx)
1235 ListFilters.SelectedIndex = tidx;
1238 tab.FilterArray = ListFilters.Items.Cast<PostFilterRule>().ToArray();
1240 // 移動方向の先頭要素は最後に選択する
1242 ListFilters.SelectedIndex = lastSelIdx;
1247 _multiSelState &= ~MultiSelectionState.MoveSelected;
1251 private void buttonRuleToggleEnabled_Click(object sender, EventArgs e)
1253 if (this.RuleEnableButtonMode == EnableButtonMode.NotSelected)
1256 var enabled = this.RuleEnableButtonMode == EnableButtonMode.Enable;
1258 foreach (var idx in this.ListFilters.SelectedIndices.Cast<int>())
1260 var filter = (PostFilterRule)this.ListFilters.Items[idx];
1261 if (filter.Enabled != enabled)
1263 filter.Enabled = enabled;
1265 var itemRect = this.ListFilters.GetItemRectangle(idx);
1266 this.ListFilters.Invalidate(itemRect);
1270 this.RuleEnableButtonMode = enabled ? EnableButtonMode.Disable : EnableButtonMode.Enable;
1273 private void ButtonRuleCopy_Click(object sender, EventArgs e)
1275 if (ListTabs.SelectedIndex > -1 && ListFilters.SelectedItem != null)
1277 TabModel[] selectedTabs;
1278 using (TabsDialog dialog = new TabsDialog(_sts))
1280 dialog.MultiSelect = true;
1281 dialog.Text = Properties.Resources.ButtonRuleCopy_ClickText1;
1283 if (dialog.ShowDialog(this) == DialogResult.Cancel) return;
1285 selectedTabs = dialog.SelectedTabs;
1288 string tabname = ListTabs.SelectedItem.ToString();
1289 List<PostFilterRule> filters = new List<PostFilterRule>();
1291 foreach (int idx in ListFilters.SelectedIndices)
1293 var tab = (FilterTabModel)_sts.Tabs[tabname];
1294 filters.Add(tab.FilterArray[idx].Clone());
1296 foreach (var tb in selectedTabs.Cast<FilterTabModel>())
1298 if (tb.TabName == tabname) continue;
1300 foreach (PostFilterRule flt in filters)
1302 if (!tb.FilterArray.Contains(flt))
1303 tb.AddFilter(flt.Clone());
1306 SetFilters(tabname);
1310 private void ButtonRuleMove_Click(object sender, EventArgs e)
1312 if (ListTabs.SelectedIndex > -1 && ListFilters.SelectedItem != null)
1314 TabModel[] selectedTabs;
1315 using (var dialog = new TabsDialog(_sts))
1317 dialog.MultiSelect = true;
1318 dialog.Text = Properties.Resources.ButtonRuleMove_ClickText1;
1320 if (dialog.ShowDialog(this) == DialogResult.Cancel) return;
1322 selectedTabs = dialog.SelectedTabs;
1324 string tabname = ListTabs.SelectedItem.ToString();
1325 List<PostFilterRule> filters = new List<PostFilterRule>();
1327 foreach (int idx in ListFilters.SelectedIndices)
1329 var tab = (FilterTabModel)_sts.Tabs[tabname];
1330 filters.Add(tab.FilterArray[idx].Clone());
1332 if (selectedTabs.Length == 1 && selectedTabs[0].TabName == tabname) return;
1333 foreach (var tb in selectedTabs.Cast<FilterTabModel>())
1335 if (tb.TabName == tabname) continue;
1337 foreach (PostFilterRule flt in filters)
1339 if (!tb.FilterArray.Contains(flt))
1340 tb.AddFilter(flt.Clone());
1343 for (int idx = ListFilters.Items.Count - 1; idx >= 0; idx--)
1345 if (ListFilters.GetSelected(idx))
1347 var tab = (FilterTabModel)_sts.Tabs[ListTabs.SelectedItem.ToString()];
1348 tab.RemoveFilter((PostFilterRule)ListFilters.Items[idx]);
1349 ListFilters.Items.RemoveAt(idx);
1352 SetFilters(tabname);
1356 private void FilterTextBox_KeyDown(object sender, KeyEventArgs e)
1358 if (e.KeyCode == Keys.Space && e.Modifiers == (Keys.Shift | Keys.Control))
1360 TweenMain main = (TweenMain)this.Owner;
1361 TextBox tbox = (TextBox)sender;
1362 if (tbox.SelectionStart > 0)
1364 int endidx = tbox.SelectionStart - 1;
1365 string startstr = "";
1366 for (int i = tbox.SelectionStart - 1; i >= 0; i--)
1368 char c = tbox.Text[i];
1369 if (Char.IsLetterOrDigit(c) || c == '_')
1375 startstr = tbox.Text.Substring(i + 1, endidx - i);
1376 main.ShowSuplDialog(tbox, main.AtIdSupl, startstr.Length + 1, startstr);
1380 startstr = tbox.Text.Substring(i + 1, endidx - i);
1381 main.ShowSuplDialog(tbox, main.HashSupl, startstr.Length + 1, startstr);
1393 private void FilterTextBox_KeyPress(object sender, KeyPressEventArgs e)
1395 TweenMain main = (TweenMain)this.Owner;
1396 TextBox tbox = (TextBox)sender;
1397 if (e.KeyChar == '@')
1399 //if (!SettingDialog.UseAtIdSupplement) return;
1401 main.ShowSuplDialog(tbox, main.AtIdSupl);
1404 else if (e.KeyChar == '#')
1406 //if (!SettingDialog.UseHashSupplement) return;
1407 main.ShowSuplDialog(tbox, main.HashSupl);
1412 private void ListFilters_DrawItem(object sender, DrawItemEventArgs e)
1418 var filter = (PostFilterRule)this.ListFilters.Items[e.Index];
1419 var isSelected = e.State.HasFlag(DrawItemState.Selected);
1423 textBrush = SystemBrushes.HighlightText;
1424 else if (filter.Enabled)
1425 textBrush = SystemBrushes.WindowText;
1427 textBrush = SystemBrushes.GrayText;
1429 e.Graphics.DrawString(filter.ToString(), e.Font, textBrush, e.Bounds);
1432 e.DrawFocusRectangle();
1435 private void ListFilters_KeyDown(object sender, KeyEventArgs e)
1437 if (e.Control && e.KeyCode == Keys.A)
1439 var itemCount = this.ListFilters.Items.Count;
1440 if (itemCount == 0) return;
1442 using (ControlTransaction.Update(this.ListFilters))
1448 _multiSelState |= MultiSelectionState.SelectAll;
1450 for (int i = 1; i < itemCount; i++)
1452 this.ListFilters.SetSelected(i, true);
1457 _multiSelState &= ~MultiSelectionState.SelectAll;
1461 this.ListFilters.SetSelected(0, true);
1466 protected override void ScaleControl(SizeF factor, BoundsSpecified specified)
1468 base.ScaleControl(factor, specified);
1469 this.ListFilters.ItemHeight = this.ListFilters.Font.Height;