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 { return 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;
91 InitializeComponent();
94 private void SetFilters(string tabName)
96 if (ListTabs.Items.Count == 0) return;
98 ListFilters.Items.Clear();
100 var tab = _sts.Tabs[tabName];
102 if (tab is FilterTabModel filterTab)
103 ListFilters.Items.AddRange(filterTab.GetFilters());
105 if (ListFilters.Items.Count > 0)
106 ListFilters.SelectedIndex = 0;
110 if (tab.IsDefaultTabType)
112 CheckProtected.Checked = true;
113 CheckProtected.Enabled = false;
117 CheckProtected.Checked = tab.Protected;
118 CheckProtected.Enabled = true;
121 CheckManageRead.Checked = tab.UnreadManage;
122 CheckNotifyNew.Checked = tab.Notify;
124 int idx = ComboSound.Items.IndexOf(tab.SoundFile);
125 if (idx == -1) idx = 0;
126 ComboSound.SelectedIndex = idx;
128 if (_directAdd) return;
130 if (tab.TabType == MyCommon.TabUsageType.Mute)
132 this.CheckManageRead.Enabled = false;
133 this.CheckNotifyNew.Enabled = false;
134 this.ComboSound.Enabled = false;
136 this.GroupBox1.Visible = false;
137 this.labelMuteTab.Visible = true;
141 this.CheckManageRead.Enabled = true;
142 this.CheckNotifyNew.Enabled = true;
143 this.ComboSound.Enabled = true;
145 this.GroupBox1.Visible = true;
146 this.labelMuteTab.Visible = false;
149 ListTabs.Enabled = true;
150 GroupTab.Enabled = true;
151 ListFilters.Enabled = true;
152 EditFilterGroup.Enabled = false;
154 if (tab.IsDistributableTabType)
156 ButtonNew.Enabled = true;
157 if (ListFilters.SelectedIndex > -1)
159 ButtonEdit.Enabled = true;
160 ButtonDelete.Enabled = true;
161 ButtonRuleUp.Enabled = true;
162 ButtonRuleDown.Enabled = true;
163 ButtonRuleCopy.Enabled = true;
164 ButtonRuleMove.Enabled = true;
165 buttonRuleToggleEnabled.Enabled = true;
169 ButtonEdit.Enabled = false;
170 ButtonDelete.Enabled = false;
171 ButtonRuleUp.Enabled = false;
172 ButtonRuleDown.Enabled = false;
173 ButtonRuleCopy.Enabled = false;
174 ButtonRuleMove.Enabled = false;
175 buttonRuleToggleEnabled.Enabled = false;
180 ButtonNew.Enabled = false;
181 ButtonEdit.Enabled = false;
182 ButtonDelete.Enabled = false;
183 ButtonRuleUp.Enabled = false;
184 ButtonRuleDown.Enabled = false;
185 ButtonRuleCopy.Enabled = false;
186 ButtonRuleMove.Enabled = false;
187 buttonRuleToggleEnabled.Enabled = false;
192 case MyCommon.TabUsageType.Home:
193 LabelTabType.Text = Properties.Resources.TabUsageTypeName_Home;
195 case MyCommon.TabUsageType.Mentions:
196 LabelTabType.Text = Properties.Resources.TabUsageTypeName_Mentions;
198 case MyCommon.TabUsageType.DirectMessage:
199 LabelTabType.Text = Properties.Resources.TabUsageTypeName_DirectMessage;
201 case MyCommon.TabUsageType.Favorites:
202 LabelTabType.Text = Properties.Resources.TabUsageTypeName_Favorites;
204 case MyCommon.TabUsageType.UserDefined:
205 LabelTabType.Text = Properties.Resources.TabUsageTypeName_UserDefined;
207 case MyCommon.TabUsageType.PublicSearch:
208 LabelTabType.Text = Properties.Resources.TabUsageTypeName_PublicSearch;
210 case MyCommon.TabUsageType.Lists:
211 LabelTabType.Text = Properties.Resources.TabUsageTypeName_Lists;
213 case MyCommon.TabUsageType.Related:
214 LabelTabType.Text = Properties.Resources.TabUsageTypeName_Related;
216 case MyCommon.TabUsageType.UserTimeline:
217 LabelTabType.Text = Properties.Resources.TabUsageTypeName_UserTimeline;
219 case MyCommon.TabUsageType.Mute:
220 LabelTabType.Text = "Mute";
222 case MyCommon.TabUsageType.SearchResults:
223 LabelTabType.Text = "SearchResults";
226 LabelTabType.Text = "UNKNOWN";
229 ButtonRenameTab.Enabled = true;
230 if (tab.IsDefaultTabType || tab.Protected)
232 ButtonDeleteTab.Enabled = false;
236 ButtonDeleteTab.Enabled = true;
238 ButtonClose.Enabled = true;
241 public void SetCurrent(string TabName)
246 public void AddNewFilter(string id, string msg)
249 ButtonNew.Enabled = false;
250 ButtonEdit.Enabled = false;
251 ButtonRuleUp.Enabled = false;
252 ButtonRuleDown.Enabled = false;
253 ButtonRuleCopy.Enabled = false;
254 ButtonRuleMove.Enabled = false;
255 buttonRuleToggleEnabled.Enabled = false;
256 ButtonDelete.Enabled = false;
257 ButtonClose.Enabled = false;
258 EditFilterGroup.Enabled = true;
259 ListTabs.Enabled = false;
260 GroupTab.Enabled = false;
261 ListFilters.Enabled = false;
263 RadioAND.Checked = true;
264 RadioPLUS.Checked = false;
269 MSG2.Text = id + msg;
271 TextSource.Text = "";
274 MSG2.Enabled = false;
275 CheckRegex.Checked = false;
276 CheckURL.Checked = false;
277 CheckCaseSensitive.Checked = false;
278 CheckRetweet.Checked = false;
279 CheckLambda.Checked = false;
281 RadioExAnd.Checked = true;
282 RadioExPLUS.Checked = false;
289 TextExSource.Text = "";
290 ExUID.Enabled = true;
291 ExMSG1.Enabled = true;
292 ExMSG2.Enabled = false;
293 CheckExRegex.Checked = false;
294 CheckExURL.Checked = false;
295 CheckExCaseSensitive.Checked = false;
296 CheckExRetweet.Checked = false;
297 CheckExLambDa.Checked = false;
299 OptCopy.Checked = true;
300 CheckMark.Checked = true;
302 _mode = EDITMODE.AddNew;
306 private void ButtonNew_Click(object sender, EventArgs e)
308 ButtonNew.Enabled = false;
309 ButtonEdit.Enabled = false;
310 ButtonClose.Enabled = false;
311 ButtonRuleUp.Enabled = false;
312 ButtonRuleDown.Enabled = false;
313 ButtonRuleCopy.Enabled = false;
314 ButtonRuleMove.Enabled = false;
315 buttonRuleToggleEnabled.Enabled = false;
316 ButtonDelete.Enabled = false;
317 ButtonClose.Enabled = false;
318 EditFilterGroup.Enabled = true;
319 ListTabs.Enabled = false;
320 GroupTab.Enabled = false;
321 ListFilters.Enabled = false;
323 RadioAND.Checked = true;
324 RadioPLUS.Checked = false;
328 TextSource.Text = "";
331 MSG2.Enabled = false;
332 CheckRegex.Checked = false;
333 CheckURL.Checked = false;
334 CheckCaseSensitive.Checked = false;
335 CheckRetweet.Checked = false;
336 CheckLambda.Checked = false;
338 RadioExAnd.Checked = true;
339 RadioExPLUS.Checked = false;
343 TextExSource.Text = "";
344 ExUID.Enabled = true;
345 ExMSG1.Enabled = true;
346 ExMSG2.Enabled = false;
347 CheckExRegex.Checked = false;
348 CheckExURL.Checked = false;
349 CheckExCaseSensitive.Checked = false;
350 CheckExRetweet.Checked = false;
351 CheckExLambDa.Checked = false;
353 OptCopy.Checked = true;
354 CheckMark.Checked = true;
356 _mode = EDITMODE.AddNew;
359 private void ButtonEdit_Click(object sender, EventArgs e)
361 if (ListFilters.SelectedIndex == -1) return;
365 int idx = ListFilters.SelectedIndex;
366 ListFilters.SelectedIndex = -1;
367 ListFilters.SelectedIndex = idx;
368 ListFilters.Enabled = false;
370 ButtonNew.Enabled = false;
371 ButtonEdit.Enabled = false;
372 ButtonDelete.Enabled = false;
373 ButtonClose.Enabled = false;
374 ButtonRuleUp.Enabled = false;
375 ButtonRuleDown.Enabled = false;
376 ButtonRuleCopy.Enabled = false;
377 ButtonRuleMove.Enabled = false;
378 buttonRuleToggleEnabled.Enabled = false;
379 EditFilterGroup.Enabled = true;
380 ListTabs.Enabled = false;
381 GroupTab.Enabled = false;
383 _mode = EDITMODE.Edit;
386 private void ButtonDelete_Click(object sender, EventArgs e)
388 var selectedCount = ListFilters.SelectedIndices.Count;
389 if (selectedCount == 0) return;
393 if (selectedCount == 1)
395 tmp = string.Format(Properties.Resources.ButtonDelete_ClickText1, Environment.NewLine, ListFilters.SelectedItem);
399 tmp = string.Format(Properties.Resources.ButtonDelete_ClickText3, selectedCount);
402 var rslt = MessageBox.Show(tmp, Properties.Resources.ButtonDelete_ClickText2, MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
403 if (rslt == DialogResult.Cancel) return;
405 var indices = ListFilters.SelectedIndices.Cast<int>().Reverse().ToArray(); // 後ろの要素から削除
406 var tab = (FilterTabModel)_sts.Tabs[ListTabs.SelectedItem.ToString()];
408 using (ControlTransaction.Update(ListFilters))
410 foreach (var idx in indices)
412 tab.RemoveFilter((PostFilterRule)ListFilters.Items[idx]);
413 ListFilters.Items.RemoveAt(idx);
418 private void ButtonCancel_Click(object sender, EventArgs e)
420 ListTabs.Enabled = true;
421 GroupTab.Enabled = true;
422 ListFilters.Enabled = true;
424 if (ListFilters.SelectedIndex != -1)
428 EditFilterGroup.Enabled = false;
429 ButtonNew.Enabled = true;
430 if (ListFilters.SelectedIndex > -1)
432 ButtonEdit.Enabled = true;
433 ButtonDelete.Enabled = true;
434 ButtonRuleUp.Enabled = true;
435 ButtonRuleDown.Enabled = true;
436 ButtonRuleCopy.Enabled = true;
437 ButtonRuleMove.Enabled = true;
438 buttonRuleToggleEnabled.Enabled = true;
442 ButtonEdit.Enabled = false;
443 ButtonDelete.Enabled = false;
444 ButtonRuleUp.Enabled = false;
445 ButtonRuleDown.Enabled = false;
446 ButtonRuleCopy.Enabled = false;
447 ButtonRuleMove.Enabled = false;
448 buttonRuleToggleEnabled.Enabled = false;
450 ButtonClose.Enabled = true;
457 private void ShowDetail()
459 if (_directAdd) return;
461 if (ListFilters.SelectedIndex > -1)
463 PostFilterRule fc = (PostFilterRule)ListFilters.SelectedItem;
466 RadioAND.Checked = true;
467 RadioPLUS.Checked = false;
470 MSG2.Enabled = false;
471 UID.Text = fc.FilterName;
473 MSG1.Text = string.Join(" ", fc.FilterBody);
479 RadioPLUS.Checked = true;
480 RadioAND.Checked = false;
482 MSG1.Enabled = false;
486 MSG2.Text = string.Join(" ", fc.FilterBody);
489 TextSource.Text = fc.FilterSource;
490 CheckRegex.Checked = fc.UseRegex;
491 CheckURL.Checked = fc.FilterByUrl;
492 CheckCaseSensitive.Checked = fc.CaseSensitive;
493 CheckRetweet.Checked = fc.FilterRt;
494 CheckLambda.Checked = fc.UseLambda;
496 if (fc.ExUseNameField)
498 RadioExAnd.Checked = true;
499 RadioExPLUS.Checked = false;
500 ExUID.Enabled = true;
501 ExMSG1.Enabled = true;
502 ExMSG2.Enabled = false;
503 ExUID.Text = fc.ExFilterName;
505 ExMSG1.Text = string.Join(" ", fc.ExFilterBody);
511 RadioExPLUS.Checked = true;
512 RadioExAnd.Checked = false;
513 ExUID.Enabled = false;
514 ExMSG1.Enabled = false;
515 ExMSG2.Enabled = true;
518 ExMSG2.Text = string.Join(" ", fc.ExFilterBody);
521 TextExSource.Text = fc.ExFilterSource;
522 CheckExRegex.Checked = fc.ExUseRegex;
523 CheckExURL.Checked = fc.ExFilterByUrl;
524 CheckExCaseSensitive.Checked = fc.ExCaseSensitive;
525 CheckExRetweet.Checked = fc.ExFilterRt;
526 CheckExLambDa.Checked = fc.ExUseLambda;
530 OptMove.Checked = true;
534 OptCopy.Checked = true;
536 CheckMark.Checked = fc.MarkMatches;
538 ButtonEdit.Enabled = true;
539 ButtonDelete.Enabled = true;
540 ButtonRuleUp.Enabled = true;
541 ButtonRuleDown.Enabled = true;
542 ButtonRuleCopy.Enabled = true;
543 ButtonRuleMove.Enabled = true;
544 buttonRuleToggleEnabled.Enabled = true;
548 RadioAND.Checked = true;
549 RadioPLUS.Checked = false;
552 MSG2.Enabled = false;
556 TextSource.Text = "";
557 CheckRegex.Checked = false;
558 CheckURL.Checked = false;
559 CheckCaseSensitive.Checked = false;
560 CheckRetweet.Checked = false;
561 CheckLambda.Checked = false;
563 RadioExAnd.Checked = true;
564 RadioExPLUS.Checked = false;
565 ExUID.Enabled = true;
566 ExMSG1.Enabled = true;
567 ExMSG2.Enabled = false;
571 TextExSource.Text = "";
572 CheckExRegex.Checked = false;
573 CheckExURL.Checked = false;
574 CheckExCaseSensitive.Checked = false;
575 CheckExRetweet.Checked = false;
576 CheckExLambDa.Checked = false;
578 OptCopy.Checked = true;
579 CheckMark.Checked = true;
581 ButtonEdit.Enabled = false;
582 ButtonDelete.Enabled = false;
583 ButtonRuleUp.Enabled = false;
584 ButtonRuleDown.Enabled = false;
585 ButtonRuleCopy.Enabled = false;
586 ButtonRuleMove.Enabled = false;
587 buttonRuleToggleEnabled.Enabled = false;
591 private void RadioAND_CheckedChanged(object sender, EventArgs e)
593 bool flg = RadioAND.Checked;
599 private void ButtonOK_Click(object sender, EventArgs e)
602 if (!CheckMatchRule(out var isBlankMatch) || !CheckExcludeRule(out var isBlankExclude))
606 if (isBlankMatch && isBlankExclude)
608 MessageBox.Show(Properties.Resources.ButtonOK_ClickText1, Properties.Resources.ButtonOK_ClickText2, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
612 var tab = (FilterTabModel)this._sts.Tabs[(string)this.ListTabs.SelectedItem];
613 int i = ListFilters.SelectedIndex;
616 if (_mode == EDITMODE.AddNew)
617 ft = new PostFilterRule();
619 ft = (PostFilterRule)this.ListFilters.SelectedItem;
621 if (tab.TabType != MyCommon.TabUsageType.Mute)
623 ft.MoveMatches = OptMove.Checked;
624 ft.MarkMatches = CheckMark.Checked;
628 ft.MoveMatches = true;
629 ft.MarkMatches = false;
633 if (RadioAND.Checked)
635 ft.FilterName = UID.Text;
636 TweenMain owner = (TweenMain)this.Owner;
637 int cnt = owner.AtIdSupl.ItemCount;
638 owner.AtIdSupl.AddItem("@" + ft.FilterName);
639 if (cnt != owner.AtIdSupl.ItemCount)
641 owner.ModifySettingAtId = true;
643 ft.UseNameField = true;
649 ft.UseNameField = false;
652 ft.FilterSource = TextSource.Text;
654 if (CheckRegex.Checked || CheckLambda.Checked)
656 ft.FilterBody = new[] { bdy };
660 ft.FilterBody = bdy.Split(' ', ' ')
661 .Where(x => !string.IsNullOrEmpty(x))
665 ft.UseRegex = CheckRegex.Checked;
666 ft.FilterByUrl = CheckURL.Checked;
667 ft.CaseSensitive = CheckCaseSensitive.Checked;
668 ft.FilterRt = CheckRetweet.Checked;
669 ft.UseLambda = CheckLambda.Checked;
672 if (RadioExAnd.Checked)
674 ft.ExFilterName = ExUID.Text;
675 ft.ExUseNameField = true;
680 ft.ExFilterName = "";
681 ft.ExUseNameField = false;
684 ft.ExFilterSource = TextExSource.Text;
686 if (CheckExRegex.Checked || CheckExLambDa.Checked)
688 ft.ExFilterBody = new[] { bdy };
692 ft.ExFilterBody = bdy.Split(' ', ' ')
693 .Where(x => !string.IsNullOrEmpty(x))
697 ft.ExUseRegex = CheckExRegex.Checked;
698 ft.ExFilterByUrl = CheckExURL.Checked;
699 ft.ExCaseSensitive = CheckExCaseSensitive.Checked;
700 ft.ExFilterRt = CheckExRetweet.Checked;
701 ft.ExUseLambda = CheckExLambDa.Checked;
703 if (_mode == EDITMODE.AddNew)
705 if (!tab.AddFilter(ft))
706 MessageBox.Show(Properties.Resources.ButtonOK_ClickText4, Properties.Resources.ButtonOK_ClickText2, MessageBoxButtons.OK, MessageBoxIcon.Error);
709 SetFilters(tab.TabName);
710 ListFilters.SelectedIndex = -1;
711 if (_mode == EDITMODE.AddNew)
713 ListFilters.SelectedIndex = ListFilters.Items.Count - 1;
717 ListFilters.SelectedIndex = i;
719 _mode = EDITMODE.None;
727 private bool IsValidLambdaExp(string text)
730 // TODO DynamicQuery相当のGPLv3互換なライブラリで置換する
733 private bool IsValidRegexp(string text)
741 MessageBox.Show(Properties.Resources.ButtonOK_ClickText3 + ex.Message, Properties.Resources.ButtonOK_ClickText2, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
747 private bool CheckMatchRule(out bool isBlank)
750 if (RadioAND.Checked)
752 if (string.IsNullOrEmpty(UID.Text) && string.IsNullOrEmpty(MSG1.Text) && string.IsNullOrEmpty(TextSource.Text) && CheckRetweet.Checked == false)
757 if (CheckLambda.Checked)
759 if (!IsValidLambdaExp(UID.Text))
763 if (!IsValidLambdaExp(MSG1.Text))
768 else if (CheckRegex.Checked)
770 if (!IsValidRegexp(UID.Text))
774 if (!IsValidRegexp(MSG1.Text))
782 if (string.IsNullOrEmpty(MSG2.Text) && string.IsNullOrEmpty(TextSource.Text) && CheckRetweet.Checked == false)
787 if (CheckLambda.Checked && !IsValidLambdaExp(MSG2.Text))
791 else if (CheckRegex.Checked && !IsValidRegexp(MSG2.Text))
797 if (CheckRegex.Checked && !IsValidRegexp(TextSource.Text))
804 private bool CheckExcludeRule(out bool isBlank)
807 if (RadioExAnd.Checked)
809 if (string.IsNullOrEmpty(ExUID.Text) && string.IsNullOrEmpty(ExMSG1.Text) && string.IsNullOrEmpty(TextExSource.Text) && CheckExRetweet.Checked == false)
814 if (CheckExLambDa.Checked)
816 if (!IsValidLambdaExp(ExUID.Text))
820 if (!IsValidLambdaExp(ExMSG1.Text))
825 else if (CheckExRegex.Checked)
827 if (!IsValidRegexp(ExUID.Text))
831 if (!IsValidRegexp(ExMSG1.Text))
839 if (string.IsNullOrEmpty(ExMSG2.Text) && string.IsNullOrEmpty(TextExSource.Text) && CheckExRetweet.Checked == false)
844 if (CheckExLambDa.Checked && !IsValidLambdaExp(ExMSG2.Text))
848 else if (CheckExRegex.Checked && !IsValidRegexp(ExMSG2.Text))
854 if (CheckExRegex.Checked && !IsValidRegexp(TextExSource.Text))
862 private void ListFilters_SelectedIndexChanged(object sender, EventArgs e)
864 if (_multiSelState != MultiSelectionState.None) //複数選択処理中は無視する
869 var selectedCount = this.ListFilters.SelectedIndices.Count;
870 if (selectedCount == 0)
872 this.RuleEnableButtonMode = EnableButtonMode.NotSelected;
876 if (selectedCount == 1 ||
877 this.RuleEnableButtonMode == EnableButtonMode.NotSelected)
879 var topItem = (PostFilterRule)this.ListFilters.SelectedItem;
880 this.RuleEnableButtonMode = topItem.Enabled ? EnableButtonMode.Disable : EnableButtonMode.Enable;
885 private void ButtonClose_Click(object sender, EventArgs e)
890 private void FilterDialog_FormClosed(object sender, FormClosedEventArgs e)
895 private void FilterDialog_KeyDown(object sender, KeyEventArgs e)
897 if (e.KeyCode == Keys.Escape)
899 if (EditFilterGroup.Enabled)
900 ButtonCancel_Click(null, null);
902 ButtonClose_Click(null, null);
906 private void ListFilters_DoubleClick(object sender, EventArgs e)
908 var idx = ListFilters.SelectedIndex;
909 if (idx == -1) return;
911 var midx = ListFilters.IndexFromPoint(ListFilters.PointToClient(Control.MousePosition));
912 if (midx == ListBox.NoMatches || idx != midx) return;
914 ButtonEdit_Click(sender, e);
917 private void FilterDialog_Shown(object sender, EventArgs e)
919 _sts = TabInformations.GetInstance();
920 ListTabs.Items.Clear();
921 foreach (var tab in this._sts.Tabs.Values)
923 if (tab.TabType == MyCommon.TabUsageType.Mute)
926 this.ListTabs.Items.Add(tab.TabName);
929 var muteTab = this._sts.GetTabByType(MyCommon.TabUsageType.Mute);
931 this.ListTabs.Items.Add(muteTab.TabName);
933 ComboSound.Items.Clear();
934 ComboSound.Items.Add("");
935 DirectoryInfo oDir = new DirectoryInfo(Application.StartupPath + Path.DirectorySeparatorChar);
936 if (Directory.Exists(Path.Combine(Application.StartupPath, "Sounds")))
938 oDir = oDir.GetDirectories("Sounds")[0];
940 foreach (FileInfo oFile in oDir.GetFiles("*.wav"))
942 ComboSound.Items.Add(oFile.Name);
946 foreach (string tmp in ((TweenMain)this.Owner).AtIdSupl.GetItemList())
948 idlist.Add(tmp.Remove(0, 1)); // @文字削除
950 UID.AutoCompleteCustomSource.Clear();
951 UID.AutoCompleteCustomSource.AddRange(idlist.ToArray());
953 ExUID.AutoCompleteCustomSource.Clear();
954 ExUID.AutoCompleteCustomSource.AddRange(idlist.ToArray());
957 if (ListTabs.Items.Count > 0)
961 for (int i = 0; i < ListTabs.Items.Count; i++)
963 if (_cur == ListTabs.Items[i].ToString())
965 ListTabs.SelectedIndex = i;
966 //tabdialog.TabList.Items.Remove(_cur);
974 private void ListTabs_SelectedIndexChanged(object sender, EventArgs e)
976 if (ListTabs.SelectedIndex > -1)
977 SetFilters(ListTabs.SelectedItem.ToString());
979 ListFilters.Items.Clear();
982 private async void ButtonAddTab_Click(object sender, EventArgs e)
984 string tabName = null;
985 MyCommon.TabUsageType tabType;
986 using (InputTabName inputName = new InputTabName())
988 inputName.TabName = _sts.MakeTabName("MyTab");
989 inputName.IsShowUsage = true;
990 inputName.ShowDialog();
991 if (inputName.DialogResult == DialogResult.Cancel) return;
992 tabName = inputName.TabName;
993 tabType = inputName.Usage;
995 if (!string.IsNullOrEmpty(tabName))
998 ListElement list = null;
999 if (tabType == MyCommon.TabUsageType.Lists)
1003 using (var dialog = new WaitingDialog(Properties.Resources.ListsGetting))
1005 var cancellationToken = dialog.EnableCancellation();
1007 var task = ((TweenMain)this.Owner).TwitterInstance.GetListsApi();
1008 await dialog.WaitForAsync(this, task);
1010 cancellationToken.ThrowIfCancellationRequested();
1013 catch (OperationCanceledException) { return; }
1014 catch (WebApiException ex)
1016 MessageBox.Show("Failed to get lists. (" + ex.Message + ")");
1018 using (ListAvailable listAvail = new ListAvailable())
1020 if (listAvail.ShowDialog(this) == DialogResult.Cancel) return;
1021 if (listAvail.SelectedList == null) return;
1022 list = listAvail.SelectedList;
1029 case MyCommon.TabUsageType.UserDefined:
1030 tab = new FilterTabModel(tabName);
1032 case MyCommon.TabUsageType.PublicSearch:
1033 tab = new PublicSearchTabModel(tabName);
1035 case MyCommon.TabUsageType.Lists:
1036 tab = new ListTimelineTabModel(tabName, list);
1042 if (!_sts.AddTab(tab) || !((TweenMain)this.Owner).AddNewTab(tab, startup: false))
1044 string tmp = string.Format(Properties.Resources.AddTabMenuItem_ClickText1, tabName);
1045 MessageBox.Show(tmp, Properties.Resources.AddTabMenuItem_ClickText2, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
1053 var lastIdx = this.ListTabs.Items.Count - 1;
1054 var lastTab = lastIdx != -1
1055 ? this._sts.Tabs[(string)this.ListTabs.Items[lastIdx]]
1058 // 末尾がミュートタブであればその手前に追加する
1059 if (lastTab != null && lastTab.TabType == MyCommon.TabUsageType.Mute)
1060 this.ListTabs.Items.Insert(lastIdx, tabName);
1062 this.ListTabs.Items.Add(tabName);
1067 private void ButtonDeleteTab_Click(object sender, EventArgs e)
1069 if (ListTabs.SelectedIndex > -1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
1071 string tb = ListTabs.SelectedItem.ToString();
1072 int idx = ListTabs.SelectedIndex;
1073 if (((TweenMain)this.Owner).RemoveSpecifiedTab(tb, true))
1075 ListTabs.Items.RemoveAt(idx);
1077 if (idx < 0) idx = 0;
1078 ListTabs.SelectedIndex = idx;
1083 private void ButtonRenameTab_Click(object sender, EventArgs e)
1085 if (ListTabs.SelectedIndex > -1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
1087 int idx = ListTabs.SelectedIndex;
1089 var origTabName = (string)this.ListTabs.SelectedItem;
1090 if (((TweenMain)this.Owner).TabRename(origTabName, out var newTabName))
1092 ListTabs.Items.RemoveAt(idx);
1093 ListTabs.Items.Insert(idx, newTabName);
1094 ListTabs.SelectedIndex = idx;
1099 private void CheckManageRead_CheckedChanged(object sender, EventArgs e)
1101 if (ListTabs.SelectedIndex > -1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
1103 ((TweenMain)this.Owner).ChangeTabUnreadManage(
1104 ListTabs.SelectedItem.ToString(),
1105 CheckManageRead.Checked);
1109 private void ButtonUp_Click(object sender, EventArgs e)
1111 if (this.ListTabs.SelectedIndex == -1 || this.ListTabs.SelectedIndex == 0)
1114 var selectedTabName = (string)this.ListTabs.SelectedItem;
1115 var selectedTab = this._sts.Tabs[selectedTabName];
1117 var targetTabName = (string)this.ListTabs.Items[this.ListTabs.SelectedIndex - 1];
1118 var targetTab = this._sts.Tabs[targetTabName];
1121 if (selectedTab.TabType == MyCommon.TabUsageType.Mute || targetTab.TabType == MyCommon.TabUsageType.Mute)
1124 var tweenMain = (TweenMain)this.Owner;
1125 tweenMain.ReOrderTab(selectedTabName, targetTabName, true);
1127 // ListTab のアイテム並び替え
1128 // 選択が解除されてしまうのを防ぐため SelectedIndex のアイテムは操作せず前後のアイテムを移動する
1129 var idx = this.ListTabs.SelectedIndex;
1130 this.ListTabs.Items.RemoveAt(idx - 1);
1131 this.ListTabs.Items.Insert(idx, targetTabName);
1134 private void ButtonDown_Click(object sender, EventArgs e)
1136 if (this.ListTabs.SelectedIndex == -1 || this.ListTabs.SelectedIndex == this.ListTabs.Items.Count - 1)
1139 var selectedTabName = (string)this.ListTabs.SelectedItem;
1140 var selectedTab = this._sts.Tabs[selectedTabName];
1142 var targetTabName = (string)this.ListTabs.Items[this.ListTabs.SelectedIndex + 1];
1143 var targetTab = this._sts.Tabs[targetTabName];
1146 if (selectedTab.TabType == MyCommon.TabUsageType.Mute || targetTab.TabType == MyCommon.TabUsageType.Mute)
1149 var tweenMain = (TweenMain)this.Owner;
1150 tweenMain.ReOrderTab(selectedTabName, targetTabName, false);
1152 // ListTab のアイテム並び替え
1153 // 選択が解除されてしまうのを防ぐため SelectedIndex のアイテムは操作せず前後のアイテムを移動する
1154 var idx = this.ListTabs.SelectedIndex;
1155 this.ListTabs.Items.RemoveAt(idx + 1);
1156 this.ListTabs.Items.Insert(idx, targetTabName);
1159 private void CheckLocked_CheckedChanged(object sender, EventArgs e)
1161 if (ListTabs.SelectedIndex > -1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
1163 _sts.Tabs[ListTabs.SelectedItem.ToString()].Protected = CheckProtected.Checked;
1164 ButtonDeleteTab.Enabled = !CheckProtected.Checked;
1168 private void CheckNotifyNew_CheckedChanged(object sender, EventArgs e)
1170 if (ListTabs.SelectedIndex > -1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
1172 _sts.Tabs[ListTabs.SelectedItem.ToString()].Notify = CheckNotifyNew.Checked;
1176 private void ComboSound_SelectedIndexChanged(object sender, EventArgs e)
1178 if (ListTabs.SelectedIndex > -1 && string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
1180 string filename = "";
1181 if (ComboSound.SelectedIndex > -1) filename = ComboSound.SelectedItem.ToString();
1182 _sts.Tabs[ListTabs.SelectedItem.ToString()].SoundFile = filename;
1186 private void RadioExAnd_CheckedChanged(object sender, EventArgs e)
1188 bool flg = RadioExAnd.Checked;
1189 ExUID.Enabled = flg;
1190 ExMSG1.Enabled = flg;
1191 ExMSG2.Enabled = !flg;
1194 private void OptMove_CheckedChanged(object sender, EventArgs e)
1196 CheckMark.Enabled = !OptMove.Checked;
1199 private void ButtonRuleUp_Click(object sender, EventArgs e)
1201 MoveSelectedRules(up: true);
1204 private void ButtonRuleDown_Click(object sender, EventArgs e)
1206 MoveSelectedRules(up: false);
1209 private void MoveSelectedRules(bool up)
1211 var tabIdx = ListTabs.SelectedIndex;
1213 ListFilters.SelectedIndices.Count == 0) return;
1215 var indices = ListFilters.SelectedIndices.Cast<int>().ToArray();
1220 if (indices[0] <= 0) return;
1225 if (indices[indices.Length - 1] >= ListFilters.Items.Count - 1) return;
1227 Array.Reverse(indices); // 逆順にして、下にある要素から処理する
1230 var lastSelIdx = indices[0] + diff;
1231 var tab = (FilterTabModel)_sts.Tabs[ListTabs.Items[tabIdx].ToString()];
1235 _multiSelState |= MultiSelectionState.MoveSelected;
1237 using (ControlTransaction.Update(ListFilters))
1239 ListFilters.SelectedIndices.Clear();
1241 foreach (var idx in indices)
1243 var tidx = idx + diff;
1244 var target = (PostFilterRule)ListFilters.Items[tidx];
1246 // 移動先にある要素と位置を入れ替える
1247 ListFilters.Items.RemoveAt(tidx);
1248 ListFilters.Items.Insert(idx, target);
1250 // 移動方向の先頭要素以外なら選択する
1251 if (tidx != lastSelIdx)
1252 ListFilters.SelectedIndex = tidx;
1255 tab.FilterArray = ListFilters.Items.Cast<PostFilterRule>().ToArray();
1257 // 移動方向の先頭要素は最後に選択する
1259 ListFilters.SelectedIndex = lastSelIdx;
1264 _multiSelState &= ~MultiSelectionState.MoveSelected;
1268 private void buttonRuleToggleEnabled_Click(object sender, EventArgs e)
1270 if (this.RuleEnableButtonMode == EnableButtonMode.NotSelected)
1273 var enabled = this.RuleEnableButtonMode == EnableButtonMode.Enable;
1275 foreach (var idx in this.ListFilters.SelectedIndices.Cast<int>())
1277 var filter = (PostFilterRule)this.ListFilters.Items[idx];
1278 if (filter.Enabled != enabled)
1280 filter.Enabled = enabled;
1282 var itemRect = this.ListFilters.GetItemRectangle(idx);
1283 this.ListFilters.Invalidate(itemRect);
1287 this.RuleEnableButtonMode = enabled ? EnableButtonMode.Disable : EnableButtonMode.Enable;
1290 private void ButtonRuleCopy_Click(object sender, EventArgs e)
1292 if (ListTabs.SelectedIndex > -1 && ListFilters.SelectedItem != null)
1294 TabModel[] selectedTabs;
1295 using (TabsDialog dialog = new TabsDialog(_sts))
1297 dialog.MultiSelect = true;
1298 dialog.Text = Properties.Resources.ButtonRuleCopy_ClickText1;
1300 if (dialog.ShowDialog(this) == DialogResult.Cancel) return;
1302 selectedTabs = dialog.SelectedTabs;
1305 string tabname = ListTabs.SelectedItem.ToString();
1306 List<PostFilterRule> filters = new List<PostFilterRule>();
1308 foreach (int idx in ListFilters.SelectedIndices)
1310 var tab = (FilterTabModel)_sts.Tabs[tabname];
1311 filters.Add(tab.FilterArray[idx].Clone());
1313 foreach (var tb in selectedTabs.Cast<FilterTabModel>())
1315 if (tb.TabName == tabname) continue;
1317 foreach (PostFilterRule flt in filters)
1319 if (!tb.FilterArray.Contains(flt))
1320 tb.AddFilter(flt.Clone());
1323 SetFilters(tabname);
1327 private void ButtonRuleMove_Click(object sender, EventArgs e)
1329 if (ListTabs.SelectedIndex > -1 && ListFilters.SelectedItem != null)
1331 TabModel[] selectedTabs;
1332 using (var dialog = new TabsDialog(_sts))
1334 dialog.MultiSelect = true;
1335 dialog.Text = Properties.Resources.ButtonRuleMove_ClickText1;
1337 if (dialog.ShowDialog(this) == DialogResult.Cancel) return;
1339 selectedTabs = dialog.SelectedTabs;
1341 string tabname = ListTabs.SelectedItem.ToString();
1342 List<PostFilterRule> filters = new List<PostFilterRule>();
1344 foreach (int idx in ListFilters.SelectedIndices)
1346 var tab = (FilterTabModel)_sts.Tabs[tabname];
1347 filters.Add(tab.FilterArray[idx].Clone());
1349 if (selectedTabs.Length == 1 && selectedTabs[0].TabName == tabname) return;
1350 foreach (var tb in selectedTabs.Cast<FilterTabModel>())
1352 if (tb.TabName == tabname) continue;
1354 foreach (PostFilterRule flt in filters)
1356 if (!tb.FilterArray.Contains(flt))
1357 tb.AddFilter(flt.Clone());
1360 for (int idx = ListFilters.Items.Count - 1; idx >= 0; idx--)
1362 if (ListFilters.GetSelected(idx))
1364 var tab = (FilterTabModel)_sts.Tabs[ListTabs.SelectedItem.ToString()];
1365 tab.RemoveFilter((PostFilterRule)ListFilters.Items[idx]);
1366 ListFilters.Items.RemoveAt(idx);
1369 SetFilters(tabname);
1373 private void FilterTextBox_KeyDown(object sender, KeyEventArgs e)
1375 if (e.KeyCode == Keys.Space && e.Modifiers == (Keys.Shift | Keys.Control))
1377 TweenMain main = (TweenMain)this.Owner;
1378 TextBox tbox = (TextBox)sender;
1379 if (tbox.SelectionStart > 0)
1381 int endidx = tbox.SelectionStart - 1;
1382 string startstr = "";
1383 for (int i = tbox.SelectionStart - 1; i >= 0; i--)
1385 char c = tbox.Text[i];
1386 if (Char.IsLetterOrDigit(c) || c == '_')
1392 startstr = tbox.Text.Substring(i + 1, endidx - i);
1393 main.ShowSuplDialog(tbox, main.AtIdSupl, startstr.Length + 1, startstr);
1397 startstr = tbox.Text.Substring(i + 1, endidx - i);
1398 main.ShowSuplDialog(tbox, main.HashSupl, startstr.Length + 1, startstr);
1410 private void FilterTextBox_KeyPress(object sender, KeyPressEventArgs e)
1412 TweenMain main = (TweenMain)this.Owner;
1413 TextBox tbox = (TextBox)sender;
1414 if (e.KeyChar == '@')
1416 //if (!SettingDialog.UseAtIdSupplement) return;
1418 main.ShowSuplDialog(tbox, main.AtIdSupl);
1421 else if (e.KeyChar == '#')
1423 //if (!SettingDialog.UseHashSupplement) return;
1424 main.ShowSuplDialog(tbox, main.HashSupl);
1429 private void ListFilters_DrawItem(object sender, DrawItemEventArgs e)
1435 var filter = (PostFilterRule)this.ListFilters.Items[e.Index];
1436 var isSelected = e.State.HasFlag(DrawItemState.Selected);
1440 textBrush = SystemBrushes.HighlightText;
1441 else if (filter.Enabled)
1442 textBrush = SystemBrushes.WindowText;
1444 textBrush = SystemBrushes.GrayText;
1446 e.Graphics.DrawString(filter.ToString(), e.Font, textBrush, e.Bounds);
1449 e.DrawFocusRectangle();
1452 private void ListFilters_KeyDown(object sender, KeyEventArgs e)
1454 if (e.Control && e.KeyCode == Keys.A)
1456 var itemCount = this.ListFilters.Items.Count;
1457 if (itemCount == 0) return;
1459 using (ControlTransaction.Update(this.ListFilters))
1465 _multiSelState |= MultiSelectionState.SelectAll;
1467 for (int i = 1; i < itemCount; i++)
1469 this.ListFilters.SetSelected(i, true);
1474 _multiSelState &= ~MultiSelectionState.SelectAll;
1478 this.ListFilters.SetSelected(0, true);
1483 protected override void ScaleControl(SizeF factor, BoundsSpecified specified)
1485 base.ScaleControl(factor, specified);
1486 this.ListFilters.ItemHeight = this.ListFilters.Font.Height;