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] as FilterTabModel;
104 ListFilters.Items.AddRange(tab.GetFilters());
106 if (ListFilters.Items.Count > 0)
107 ListFilters.SelectedIndex = 0;
111 if (tab.IsDefaultTabType)
113 CheckProtected.Checked = true;
114 CheckProtected.Enabled = false;
118 CheckProtected.Checked = tab.Protected;
119 CheckProtected.Enabled = true;
122 CheckManageRead.Checked = tab.UnreadManage;
123 CheckNotifyNew.Checked = tab.Notify;
125 int idx = ComboSound.Items.IndexOf(tab.SoundFile);
126 if (idx == -1) idx = 0;
127 ComboSound.SelectedIndex = idx;
129 if (_directAdd) return;
131 if (tab.TabType == MyCommon.TabUsageType.Mute)
133 this.CheckManageRead.Enabled = false;
134 this.CheckNotifyNew.Enabled = false;
135 this.ComboSound.Enabled = false;
137 this.GroupBox1.Visible = false;
138 this.labelMuteTab.Visible = true;
142 this.CheckManageRead.Enabled = true;
143 this.CheckNotifyNew.Enabled = true;
144 this.ComboSound.Enabled = true;
146 this.GroupBox1.Visible = true;
147 this.labelMuteTab.Visible = false;
150 ListTabs.Enabled = true;
151 GroupTab.Enabled = true;
152 ListFilters.Enabled = true;
153 EditFilterGroup.Enabled = false;
156 case MyCommon.TabUsageType.Home:
157 case MyCommon.TabUsageType.DirectMessage:
158 case MyCommon.TabUsageType.Favorites:
159 case MyCommon.TabUsageType.PublicSearch:
160 case MyCommon.TabUsageType.Lists:
161 case MyCommon.TabUsageType.Related:
162 case MyCommon.TabUsageType.UserTimeline:
163 ButtonNew.Enabled = false;
164 ButtonEdit.Enabled = false;
165 ButtonDelete.Enabled = false;
166 ButtonRuleUp.Enabled = false;
167 ButtonRuleDown.Enabled = false;
168 ButtonRuleCopy.Enabled = false;
169 ButtonRuleMove.Enabled = false;
170 buttonRuleToggleEnabled.Enabled = false;
173 ButtonNew.Enabled = true;
174 if (ListFilters.SelectedIndex > -1)
176 ButtonEdit.Enabled = true;
177 ButtonDelete.Enabled = true;
178 ButtonRuleUp.Enabled = true;
179 ButtonRuleDown.Enabled = true;
180 ButtonRuleCopy.Enabled = true;
181 ButtonRuleMove.Enabled = true;
182 buttonRuleToggleEnabled.Enabled = true;
186 ButtonEdit.Enabled = false;
187 ButtonDelete.Enabled = false;
188 ButtonRuleUp.Enabled = false;
189 ButtonRuleDown.Enabled = false;
190 ButtonRuleCopy.Enabled = false;
191 ButtonRuleMove.Enabled = false;
192 buttonRuleToggleEnabled.Enabled = false;
198 case MyCommon.TabUsageType.Home:
199 LabelTabType.Text = Properties.Resources.TabUsageTypeName_Home;
201 case MyCommon.TabUsageType.Mentions:
202 LabelTabType.Text = Properties.Resources.TabUsageTypeName_Mentions;
204 case MyCommon.TabUsageType.DirectMessage:
205 LabelTabType.Text = Properties.Resources.TabUsageTypeName_DirectMessage;
207 case MyCommon.TabUsageType.Favorites:
208 LabelTabType.Text = Properties.Resources.TabUsageTypeName_Favorites;
210 case MyCommon.TabUsageType.UserDefined:
211 LabelTabType.Text = Properties.Resources.TabUsageTypeName_UserDefined;
213 case MyCommon.TabUsageType.PublicSearch:
214 LabelTabType.Text = Properties.Resources.TabUsageTypeName_PublicSearch;
216 case MyCommon.TabUsageType.Lists:
217 LabelTabType.Text = Properties.Resources.TabUsageTypeName_Lists;
219 case MyCommon.TabUsageType.Related:
220 LabelTabType.Text = Properties.Resources.TabUsageTypeName_Related;
222 case MyCommon.TabUsageType.UserTimeline:
223 LabelTabType.Text = Properties.Resources.TabUsageTypeName_UserTimeline;
225 case MyCommon.TabUsageType.Mute:
226 LabelTabType.Text = "Mute";
228 case MyCommon.TabUsageType.SearchResults:
229 LabelTabType.Text = "SearchResults";
232 LabelTabType.Text = "UNKNOWN";
235 ButtonRenameTab.Enabled = true;
236 if (tab.IsDefaultTabType || tab.Protected)
238 ButtonDeleteTab.Enabled = false;
242 ButtonDeleteTab.Enabled = true;
244 ButtonClose.Enabled = true;
247 public void SetCurrent(string TabName)
252 public void AddNewFilter(string id, string msg)
255 ButtonNew.Enabled = false;
256 ButtonEdit.Enabled = false;
257 ButtonRuleUp.Enabled = false;
258 ButtonRuleDown.Enabled = false;
259 ButtonRuleCopy.Enabled = false;
260 ButtonRuleMove.Enabled = false;
261 buttonRuleToggleEnabled.Enabled = false;
262 ButtonDelete.Enabled = false;
263 ButtonClose.Enabled = false;
264 EditFilterGroup.Enabled = true;
265 ListTabs.Enabled = false;
266 GroupTab.Enabled = false;
267 ListFilters.Enabled = false;
269 RadioAND.Checked = true;
270 RadioPLUS.Checked = false;
275 MSG2.Text = id + msg;
277 TextSource.Text = "";
280 MSG2.Enabled = false;
281 CheckRegex.Checked = false;
282 CheckURL.Checked = false;
283 CheckCaseSensitive.Checked = false;
284 CheckRetweet.Checked = false;
285 CheckLambda.Checked = false;
287 RadioExAnd.Checked = true;
288 RadioExPLUS.Checked = false;
295 TextExSource.Text = "";
296 ExUID.Enabled = true;
297 ExMSG1.Enabled = true;
298 ExMSG2.Enabled = false;
299 CheckExRegex.Checked = false;
300 CheckExURL.Checked = false;
301 CheckExCaseSensitive.Checked = false;
302 CheckExRetweet.Checked = false;
303 CheckExLambDa.Checked = false;
305 OptCopy.Checked = true;
306 CheckMark.Checked = true;
308 _mode = EDITMODE.AddNew;
312 private void ButtonNew_Click(object sender, EventArgs e)
314 ButtonNew.Enabled = false;
315 ButtonEdit.Enabled = false;
316 ButtonClose.Enabled = false;
317 ButtonRuleUp.Enabled = false;
318 ButtonRuleDown.Enabled = false;
319 ButtonRuleCopy.Enabled = false;
320 ButtonRuleMove.Enabled = false;
321 buttonRuleToggleEnabled.Enabled = false;
322 ButtonDelete.Enabled = false;
323 ButtonClose.Enabled = false;
324 EditFilterGroup.Enabled = true;
325 ListTabs.Enabled = false;
326 GroupTab.Enabled = false;
327 ListFilters.Enabled = false;
329 RadioAND.Checked = true;
330 RadioPLUS.Checked = false;
334 TextSource.Text = "";
337 MSG2.Enabled = false;
338 CheckRegex.Checked = false;
339 CheckURL.Checked = false;
340 CheckCaseSensitive.Checked = false;
341 CheckRetweet.Checked = false;
342 CheckLambda.Checked = false;
344 RadioExAnd.Checked = true;
345 RadioExPLUS.Checked = false;
349 TextExSource.Text = "";
350 ExUID.Enabled = true;
351 ExMSG1.Enabled = true;
352 ExMSG2.Enabled = false;
353 CheckExRegex.Checked = false;
354 CheckExURL.Checked = false;
355 CheckExCaseSensitive.Checked = false;
356 CheckExRetweet.Checked = false;
357 CheckExLambDa.Checked = false;
359 OptCopy.Checked = true;
360 CheckMark.Checked = true;
362 _mode = EDITMODE.AddNew;
365 private void ButtonEdit_Click(object sender, EventArgs e)
367 if (ListFilters.SelectedIndex == -1) return;
371 int idx = ListFilters.SelectedIndex;
372 ListFilters.SelectedIndex = -1;
373 ListFilters.SelectedIndex = idx;
374 ListFilters.Enabled = false;
376 ButtonNew.Enabled = false;
377 ButtonEdit.Enabled = false;
378 ButtonDelete.Enabled = false;
379 ButtonClose.Enabled = false;
380 ButtonRuleUp.Enabled = false;
381 ButtonRuleDown.Enabled = false;
382 ButtonRuleCopy.Enabled = false;
383 ButtonRuleMove.Enabled = false;
384 buttonRuleToggleEnabled.Enabled = false;
385 EditFilterGroup.Enabled = true;
386 ListTabs.Enabled = false;
387 GroupTab.Enabled = false;
389 _mode = EDITMODE.Edit;
392 private void ButtonDelete_Click(object sender, EventArgs e)
394 var selectedCount = ListFilters.SelectedIndices.Count;
395 if (selectedCount == 0) return;
399 if (selectedCount == 1)
401 tmp = string.Format(Properties.Resources.ButtonDelete_ClickText1, Environment.NewLine, ListFilters.SelectedItem.ToString());
405 tmp = string.Format(Properties.Resources.ButtonDelete_ClickText3, selectedCount.ToString());
408 var rslt = MessageBox.Show(tmp, Properties.Resources.ButtonDelete_ClickText2, MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
409 if (rslt == DialogResult.Cancel) return;
411 var indices = ListFilters.SelectedIndices.Cast<int>().Reverse().ToArray(); // 後ろの要素から削除
412 var tab = (FilterTabModel)_sts.Tabs[ListTabs.SelectedItem.ToString()];
414 using (ControlTransaction.Update(ListFilters))
416 foreach (var idx in indices)
418 tab.RemoveFilter((PostFilterRule)ListFilters.Items[idx]);
419 ListFilters.Items.RemoveAt(idx);
424 private void ButtonCancel_Click(object sender, EventArgs e)
426 ListTabs.Enabled = true;
427 GroupTab.Enabled = true;
428 ListFilters.Enabled = true;
430 if (ListFilters.SelectedIndex != -1)
434 EditFilterGroup.Enabled = false;
435 ButtonNew.Enabled = true;
436 if (ListFilters.SelectedIndex > -1)
438 ButtonEdit.Enabled = true;
439 ButtonDelete.Enabled = true;
440 ButtonRuleUp.Enabled = true;
441 ButtonRuleDown.Enabled = true;
442 ButtonRuleCopy.Enabled = true;
443 ButtonRuleMove.Enabled = true;
444 buttonRuleToggleEnabled.Enabled = true;
448 ButtonEdit.Enabled = false;
449 ButtonDelete.Enabled = false;
450 ButtonRuleUp.Enabled = false;
451 ButtonRuleDown.Enabled = false;
452 ButtonRuleCopy.Enabled = false;
453 ButtonRuleMove.Enabled = false;
454 buttonRuleToggleEnabled.Enabled = false;
456 ButtonClose.Enabled = true;
463 private void ShowDetail()
465 if (_directAdd) return;
467 if (ListFilters.SelectedIndex > -1)
469 PostFilterRule fc = (PostFilterRule)ListFilters.SelectedItem;
472 RadioAND.Checked = true;
473 RadioPLUS.Checked = false;
476 MSG2.Enabled = false;
477 UID.Text = fc.FilterName;
479 MSG1.Text = string.Join(" ", fc.FilterBody);
485 RadioPLUS.Checked = true;
486 RadioAND.Checked = false;
488 MSG1.Enabled = false;
492 MSG2.Text = string.Join(" ", fc.FilterBody);
495 TextSource.Text = fc.FilterSource;
496 CheckRegex.Checked = fc.UseRegex;
497 CheckURL.Checked = fc.FilterByUrl;
498 CheckCaseSensitive.Checked = fc.CaseSensitive;
499 CheckRetweet.Checked = fc.FilterRt;
500 CheckLambda.Checked = fc.UseLambda;
502 if (fc.ExUseNameField)
504 RadioExAnd.Checked = true;
505 RadioExPLUS.Checked = false;
506 ExUID.Enabled = true;
507 ExMSG1.Enabled = true;
508 ExMSG2.Enabled = false;
509 ExUID.Text = fc.ExFilterName;
511 ExMSG1.Text = string.Join(" ", fc.ExFilterBody);
517 RadioExPLUS.Checked = true;
518 RadioExAnd.Checked = false;
519 ExUID.Enabled = false;
520 ExMSG1.Enabled = false;
521 ExMSG2.Enabled = true;
524 ExMSG2.Text = string.Join(" ", fc.ExFilterBody);
527 TextExSource.Text = fc.ExFilterSource;
528 CheckExRegex.Checked = fc.ExUseRegex;
529 CheckExURL.Checked = fc.ExFilterByUrl;
530 CheckExCaseSensitive.Checked = fc.ExCaseSensitive;
531 CheckExRetweet.Checked = fc.ExFilterRt;
532 CheckExLambDa.Checked = fc.ExUseLambda;
536 OptMove.Checked = true;
540 OptCopy.Checked = true;
542 CheckMark.Checked = fc.MarkMatches;
544 ButtonEdit.Enabled = true;
545 ButtonDelete.Enabled = true;
546 ButtonRuleUp.Enabled = true;
547 ButtonRuleDown.Enabled = true;
548 ButtonRuleCopy.Enabled = true;
549 ButtonRuleMove.Enabled = true;
550 buttonRuleToggleEnabled.Enabled = true;
554 RadioAND.Checked = true;
555 RadioPLUS.Checked = false;
558 MSG2.Enabled = false;
562 TextSource.Text = "";
563 CheckRegex.Checked = false;
564 CheckURL.Checked = false;
565 CheckCaseSensitive.Checked = false;
566 CheckRetweet.Checked = false;
567 CheckLambda.Checked = false;
569 RadioExAnd.Checked = true;
570 RadioExPLUS.Checked = false;
571 ExUID.Enabled = true;
572 ExMSG1.Enabled = true;
573 ExMSG2.Enabled = false;
577 TextExSource.Text = "";
578 CheckExRegex.Checked = false;
579 CheckExURL.Checked = false;
580 CheckExCaseSensitive.Checked = false;
581 CheckExRetweet.Checked = false;
582 CheckExLambDa.Checked = false;
584 OptCopy.Checked = true;
585 CheckMark.Checked = true;
587 ButtonEdit.Enabled = false;
588 ButtonDelete.Enabled = false;
589 ButtonRuleUp.Enabled = false;
590 ButtonRuleDown.Enabled = false;
591 ButtonRuleCopy.Enabled = false;
592 ButtonRuleMove.Enabled = false;
593 buttonRuleToggleEnabled.Enabled = false;
597 private void RadioAND_CheckedChanged(object sender, EventArgs e)
599 bool flg = RadioAND.Checked;
605 private void ButtonOK_Click(object sender, EventArgs e)
607 bool isBlankMatch = false;
608 bool isBlankExclude = false;
611 if (!CheckMatchRule(out isBlankMatch) || !CheckExcludeRule(out isBlankExclude))
615 if (isBlankMatch && isBlankExclude)
617 MessageBox.Show(Properties.Resources.ButtonOK_ClickText1, Properties.Resources.ButtonOK_ClickText2, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
621 var tab = (FilterTabModel)this._sts.Tabs[(string)this.ListTabs.SelectedItem];
622 int i = ListFilters.SelectedIndex;
625 if (_mode == EDITMODE.AddNew)
626 ft = new PostFilterRule();
628 ft = (PostFilterRule)this.ListFilters.SelectedItem;
630 if (tab.TabType != MyCommon.TabUsageType.Mute)
632 ft.MoveMatches = OptMove.Checked;
633 ft.MarkMatches = CheckMark.Checked;
637 ft.MoveMatches = true;
638 ft.MarkMatches = false;
642 if (RadioAND.Checked)
644 ft.FilterName = UID.Text;
645 TweenMain owner = (TweenMain)this.Owner;
646 int cnt = owner.AtIdSupl.ItemCount;
647 owner.AtIdSupl.AddItem("@" + ft.FilterName);
648 if (cnt != owner.AtIdSupl.ItemCount)
650 owner.ModifySettingAtId = true;
652 ft.UseNameField = true;
658 ft.UseNameField = false;
661 ft.FilterSource = TextSource.Text;
663 if (CheckRegex.Checked || CheckLambda.Checked)
665 ft.FilterBody = new[] { bdy };
669 ft.FilterBody = bdy.Split(' ', ' ')
670 .Where(x => !string.IsNullOrEmpty(x))
674 ft.UseRegex = CheckRegex.Checked;
675 ft.FilterByUrl = CheckURL.Checked;
676 ft.CaseSensitive = CheckCaseSensitive.Checked;
677 ft.FilterRt = CheckRetweet.Checked;
678 ft.UseLambda = CheckLambda.Checked;
681 if (RadioExAnd.Checked)
683 ft.ExFilterName = ExUID.Text;
684 ft.ExUseNameField = true;
689 ft.ExFilterName = "";
690 ft.ExUseNameField = false;
693 ft.ExFilterSource = TextExSource.Text;
695 if (CheckExRegex.Checked || CheckExLambDa.Checked)
697 ft.ExFilterBody = new[] { bdy };
701 ft.ExFilterBody = bdy.Split(' ', ' ')
702 .Where(x => !string.IsNullOrEmpty(x))
706 ft.ExUseRegex = CheckExRegex.Checked;
707 ft.ExFilterByUrl = CheckExURL.Checked;
708 ft.ExCaseSensitive = CheckExCaseSensitive.Checked;
709 ft.ExFilterRt = CheckExRetweet.Checked;
710 ft.ExUseLambda = CheckExLambDa.Checked;
712 if (_mode == EDITMODE.AddNew)
714 if (!tab.AddFilter(ft))
715 MessageBox.Show(Properties.Resources.ButtonOK_ClickText4, Properties.Resources.ButtonOK_ClickText2, MessageBoxButtons.OK, MessageBoxIcon.Error);
718 SetFilters(tab.TabName);
719 ListFilters.SelectedIndex = -1;
720 if (_mode == EDITMODE.AddNew)
722 ListFilters.SelectedIndex = ListFilters.Items.Count - 1;
726 ListFilters.SelectedIndex = i;
728 _mode = EDITMODE.None;
736 private bool IsValidLambdaExp(string text)
739 // TODO DynamicQuery相当のGPLv3互換なライブラリで置換する
742 private bool IsValidRegexp(string text)
750 MessageBox.Show(Properties.Resources.ButtonOK_ClickText3 + ex.Message, Properties.Resources.ButtonOK_ClickText2, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
756 private bool CheckMatchRule(out bool isBlank)
759 if (RadioAND.Checked)
761 if (string.IsNullOrEmpty(UID.Text) && string.IsNullOrEmpty(MSG1.Text) && string.IsNullOrEmpty(TextSource.Text) && CheckRetweet.Checked == false)
766 if (CheckLambda.Checked)
768 if (!IsValidLambdaExp(UID.Text))
772 if (!IsValidLambdaExp(MSG1.Text))
777 else if (CheckRegex.Checked)
779 if (!IsValidRegexp(UID.Text))
783 if (!IsValidRegexp(MSG1.Text))
791 if (string.IsNullOrEmpty(MSG2.Text) && string.IsNullOrEmpty(TextSource.Text) && CheckRetweet.Checked == false)
796 if (CheckLambda.Checked && !IsValidLambdaExp(MSG2.Text))
800 else if (CheckRegex.Checked && !IsValidRegexp(MSG2.Text))
806 if (CheckRegex.Checked && !IsValidRegexp(TextSource.Text))
813 private bool CheckExcludeRule(out bool isBlank)
816 if (RadioExAnd.Checked)
818 if (string.IsNullOrEmpty(ExUID.Text) && string.IsNullOrEmpty(ExMSG1.Text) && string.IsNullOrEmpty(TextExSource.Text) && CheckExRetweet.Checked == false)
823 if (CheckExLambDa.Checked)
825 if (!IsValidLambdaExp(ExUID.Text))
829 if (!IsValidLambdaExp(ExMSG1.Text))
834 else if (CheckExRegex.Checked)
836 if (!IsValidRegexp(ExUID.Text))
840 if (!IsValidRegexp(ExMSG1.Text))
848 if (string.IsNullOrEmpty(ExMSG2.Text) && string.IsNullOrEmpty(TextExSource.Text) && CheckExRetweet.Checked == false)
853 if (CheckExLambDa.Checked && !IsValidLambdaExp(ExMSG2.Text))
857 else if (CheckExRegex.Checked && !IsValidRegexp(ExMSG2.Text))
863 if (CheckExRegex.Checked && !IsValidRegexp(TextExSource.Text))
871 private void ListFilters_SelectedIndexChanged(object sender, EventArgs e)
873 if (_multiSelState != MultiSelectionState.None) //複数選択処理中は無視する
878 var selectedCount = this.ListFilters.SelectedIndices.Count;
879 if (selectedCount == 0)
881 this.RuleEnableButtonMode = EnableButtonMode.NotSelected;
885 if (selectedCount == 1 ||
886 this.RuleEnableButtonMode == EnableButtonMode.NotSelected)
888 var topItem = (PostFilterRule)this.ListFilters.SelectedItem;
889 this.RuleEnableButtonMode = topItem.Enabled ? EnableButtonMode.Disable : EnableButtonMode.Enable;
894 private void ButtonClose_Click(object sender, EventArgs e)
899 private void FilterDialog_FormClosed(object sender, FormClosedEventArgs e)
904 private void FilterDialog_KeyDown(object sender, KeyEventArgs e)
906 if (e.KeyCode == Keys.Escape)
908 if (EditFilterGroup.Enabled)
909 ButtonCancel_Click(null, null);
911 ButtonClose_Click(null, null);
915 private void ListFilters_DoubleClick(object sender, EventArgs e)
917 var idx = ListFilters.SelectedIndex;
918 if (idx == -1) return;
920 var midx = ListFilters.IndexFromPoint(ListFilters.PointToClient(Control.MousePosition));
921 if (midx == ListBox.NoMatches || idx != midx) return;
923 ButtonEdit_Click(sender, e);
926 private void FilterDialog_Shown(object sender, EventArgs e)
928 _sts = TabInformations.GetInstance();
929 ListTabs.Items.Clear();
930 foreach (var tab in this._sts.Tabs.Values)
932 if (tab.TabType == MyCommon.TabUsageType.Mute)
935 this.ListTabs.Items.Add(tab.TabName);
938 var muteTab = this._sts.GetTabByType(MyCommon.TabUsageType.Mute);
940 this.ListTabs.Items.Add(muteTab.TabName);
942 ComboSound.Items.Clear();
943 ComboSound.Items.Add("");
944 DirectoryInfo oDir = new DirectoryInfo(Application.StartupPath + Path.DirectorySeparatorChar);
945 if (Directory.Exists(Path.Combine(Application.StartupPath, "Sounds")))
947 oDir = oDir.GetDirectories("Sounds")[0];
949 foreach (FileInfo oFile in oDir.GetFiles("*.wav"))
951 ComboSound.Items.Add(oFile.Name);
955 foreach (string tmp in ((TweenMain)this.Owner).AtIdSupl.GetItemList())
957 idlist.Add(tmp.Remove(0, 1)); // @文字削除
959 UID.AutoCompleteCustomSource.Clear();
960 UID.AutoCompleteCustomSource.AddRange(idlist.ToArray());
962 ExUID.AutoCompleteCustomSource.Clear();
963 ExUID.AutoCompleteCustomSource.AddRange(idlist.ToArray());
966 if (ListTabs.Items.Count > 0)
970 for (int i = 0; i < ListTabs.Items.Count; i++)
972 if (_cur == ListTabs.Items[i].ToString())
974 ListTabs.SelectedIndex = i;
975 //tabdialog.TabList.Items.Remove(_cur);
983 private void ListTabs_SelectedIndexChanged(object sender, EventArgs e)
985 if (ListTabs.SelectedIndex > -1)
986 SetFilters(ListTabs.SelectedItem.ToString());
988 ListFilters.Items.Clear();
991 private async void ButtonAddTab_Click(object sender, EventArgs e)
993 string tabName = null;
994 MyCommon.TabUsageType tabType;
995 using (InputTabName inputName = new InputTabName())
997 inputName.TabName = _sts.MakeTabName("MyTab");
998 inputName.IsShowUsage = true;
999 inputName.ShowDialog();
1000 if (inputName.DialogResult == DialogResult.Cancel) return;
1001 tabName = inputName.TabName;
1002 tabType = inputName.Usage;
1004 if (!string.IsNullOrEmpty(tabName))
1007 ListElement list = null;
1008 if (tabType == MyCommon.TabUsageType.Lists)
1012 using (var dialog = new WaitingDialog(Properties.Resources.ListsGetting))
1014 var cancellationToken = dialog.EnableCancellation();
1016 var task = ((TweenMain)this.Owner).TwitterInstance.GetListsApi();
1017 await dialog.WaitForAsync(this, task);
1019 cancellationToken.ThrowIfCancellationRequested();
1022 catch (OperationCanceledException) { return; }
1023 catch (WebApiException ex)
1025 MessageBox.Show("Failed to get lists. (" + ex.Message + ")");
1027 using (ListAvailable listAvail = new ListAvailable())
1029 if (listAvail.ShowDialog(this) == DialogResult.Cancel) return;
1030 if (listAvail.SelectedList == null) return;
1031 list = listAvail.SelectedList;
1038 case MyCommon.TabUsageType.UserDefined:
1039 tab = new FilterTabModel(tabName);
1041 case MyCommon.TabUsageType.PublicSearch:
1042 tab = new PublicSearchTabModel(tabName);
1044 case MyCommon.TabUsageType.Lists:
1045 tab = new ListTimelineTabModel(tabName, list);
1051 if (!_sts.AddTab(tab) || !((TweenMain)this.Owner).AddNewTab(tab, startup: false))
1053 string tmp = string.Format(Properties.Resources.AddTabMenuItem_ClickText1, tabName);
1054 MessageBox.Show(tmp, Properties.Resources.AddTabMenuItem_ClickText2, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
1062 var lastIdx = this.ListTabs.Items.Count - 1;
1063 var lastTab = lastIdx != -1
1064 ? this._sts.Tabs[(string)this.ListTabs.Items[lastIdx]]
1067 // 末尾がミュートタブであればその手前に追加する
1068 if (lastTab != null && lastTab.TabType == MyCommon.TabUsageType.Mute)
1069 this.ListTabs.Items.Insert(lastIdx, tabName);
1071 this.ListTabs.Items.Add(tabName);
1076 private void ButtonDeleteTab_Click(object sender, EventArgs e)
1078 if (ListTabs.SelectedIndex > -1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
1080 string tb = ListTabs.SelectedItem.ToString();
1081 int idx = ListTabs.SelectedIndex;
1082 if (((TweenMain)this.Owner).RemoveSpecifiedTab(tb, true))
1084 ListTabs.Items.RemoveAt(idx);
1086 if (idx < 0) idx = 0;
1087 ListTabs.SelectedIndex = idx;
1092 private void ButtonRenameTab_Click(object sender, EventArgs e)
1094 if (ListTabs.SelectedIndex > -1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
1096 string tb = ListTabs.SelectedItem.ToString();
1097 int idx = ListTabs.SelectedIndex;
1098 if (((TweenMain)this.Owner).TabRename(ref tb))
1100 ListTabs.Items.RemoveAt(idx);
1101 ListTabs.Items.Insert(idx, tb);
1102 ListTabs.SelectedIndex = idx;
1107 private void CheckManageRead_CheckedChanged(object sender, EventArgs e)
1109 if (ListTabs.SelectedIndex > -1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
1111 ((TweenMain)this.Owner).ChangeTabUnreadManage(
1112 ListTabs.SelectedItem.ToString(),
1113 CheckManageRead.Checked);
1117 private void ButtonUp_Click(object sender, EventArgs e)
1119 if (this.ListTabs.SelectedIndex == -1 || this.ListTabs.SelectedIndex == 0)
1122 var selectedTabName = (string)this.ListTabs.SelectedItem;
1123 var selectedTab = this._sts.Tabs[selectedTabName];
1125 var targetTabName = (string)this.ListTabs.Items[this.ListTabs.SelectedIndex - 1];
1126 var targetTab = this._sts.Tabs[targetTabName];
1129 if (selectedTab.TabType == MyCommon.TabUsageType.Mute || targetTab.TabType == MyCommon.TabUsageType.Mute)
1132 var tweenMain = (TweenMain)this.Owner;
1133 tweenMain.ReOrderTab(selectedTabName, targetTabName, true);
1135 // ListTab のアイテム並び替え
1136 // 選択が解除されてしまうのを防ぐため SelectedIndex のアイテムは操作せず前後のアイテムを移動する
1137 var idx = this.ListTabs.SelectedIndex;
1138 this.ListTabs.Items.RemoveAt(idx - 1);
1139 this.ListTabs.Items.Insert(idx, targetTabName);
1142 private void ButtonDown_Click(object sender, EventArgs e)
1144 if (this.ListTabs.SelectedIndex == -1 || this.ListTabs.SelectedIndex == this.ListTabs.Items.Count - 1)
1147 var selectedTabName = (string)this.ListTabs.SelectedItem;
1148 var selectedTab = this._sts.Tabs[selectedTabName];
1150 var targetTabName = (string)this.ListTabs.Items[this.ListTabs.SelectedIndex + 1];
1151 var targetTab = this._sts.Tabs[targetTabName];
1154 if (selectedTab.TabType == MyCommon.TabUsageType.Mute || targetTab.TabType == MyCommon.TabUsageType.Mute)
1157 var tweenMain = (TweenMain)this.Owner;
1158 tweenMain.ReOrderTab(selectedTabName, targetTabName, false);
1160 // ListTab のアイテム並び替え
1161 // 選択が解除されてしまうのを防ぐため SelectedIndex のアイテムは操作せず前後のアイテムを移動する
1162 var idx = this.ListTabs.SelectedIndex;
1163 this.ListTabs.Items.RemoveAt(idx + 1);
1164 this.ListTabs.Items.Insert(idx, targetTabName);
1167 private void CheckLocked_CheckedChanged(object sender, EventArgs e)
1169 if (ListTabs.SelectedIndex > -1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
1171 _sts.Tabs[ListTabs.SelectedItem.ToString()].Protected = CheckProtected.Checked;
1172 ButtonDeleteTab.Enabled = !CheckProtected.Checked;
1176 private void CheckNotifyNew_CheckedChanged(object sender, EventArgs e)
1178 if (ListTabs.SelectedIndex > -1 && !string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
1180 _sts.Tabs[ListTabs.SelectedItem.ToString()].Notify = CheckNotifyNew.Checked;
1184 private void ComboSound_SelectedIndexChanged(object sender, EventArgs e)
1186 if (ListTabs.SelectedIndex > -1 && string.IsNullOrEmpty(ListTabs.SelectedItem.ToString()))
1188 string filename = "";
1189 if (ComboSound.SelectedIndex > -1) filename = ComboSound.SelectedItem.ToString();
1190 _sts.Tabs[ListTabs.SelectedItem.ToString()].SoundFile = filename;
1194 private void RadioExAnd_CheckedChanged(object sender, EventArgs e)
1196 bool flg = RadioExAnd.Checked;
1197 ExUID.Enabled = flg;
1198 ExMSG1.Enabled = flg;
1199 ExMSG2.Enabled = !flg;
1202 private void OptMove_CheckedChanged(object sender, EventArgs e)
1204 CheckMark.Enabled = !OptMove.Checked;
1207 private void ButtonRuleUp_Click(object sender, EventArgs e)
1209 MoveSelectedRules(up: true);
1212 private void ButtonRuleDown_Click(object sender, EventArgs e)
1214 MoveSelectedRules(up: false);
1217 private void MoveSelectedRules(bool up)
1219 var tabIdx = ListTabs.SelectedIndex;
1221 ListFilters.SelectedIndices.Count == 0) return;
1223 var indices = ListFilters.SelectedIndices.Cast<int>().ToArray();
1228 if (indices[0] <= 0) return;
1233 if (indices[indices.Length - 1] >= ListFilters.Items.Count - 1) return;
1235 Array.Reverse(indices); // 逆順にして、下にある要素から処理する
1238 var lastSelIdx = indices[0] + diff;
1239 var tab = (FilterTabModel)_sts.Tabs[ListTabs.Items[tabIdx].ToString()];
1243 _multiSelState |= MultiSelectionState.MoveSelected;
1245 using (ControlTransaction.Update(ListFilters))
1247 ListFilters.SelectedIndices.Clear();
1249 foreach (var idx in indices)
1251 var tidx = idx + diff;
1252 var target = (PostFilterRule)ListFilters.Items[tidx];
1254 // 移動先にある要素と位置を入れ替える
1255 ListFilters.Items.RemoveAt(tidx);
1256 ListFilters.Items.Insert(idx, target);
1258 // 移動方向の先頭要素以外なら選択する
1259 if (tidx != lastSelIdx)
1260 ListFilters.SelectedIndex = tidx;
1263 tab.FilterArray = ListFilters.Items.Cast<PostFilterRule>().ToArray();
1265 // 移動方向の先頭要素は最後に選択する
1267 ListFilters.SelectedIndex = lastSelIdx;
1272 _multiSelState &= ~MultiSelectionState.MoveSelected;
1276 private void buttonRuleToggleEnabled_Click(object sender, EventArgs e)
1278 if (this.RuleEnableButtonMode == EnableButtonMode.NotSelected)
1281 var enabled = this.RuleEnableButtonMode == EnableButtonMode.Enable;
1283 foreach (var idx in this.ListFilters.SelectedIndices.Cast<int>())
1285 var filter = (PostFilterRule)this.ListFilters.Items[idx];
1286 if (filter.Enabled != enabled)
1288 filter.Enabled = enabled;
1290 var itemRect = this.ListFilters.GetItemRectangle(idx);
1291 this.ListFilters.Invalidate(itemRect);
1295 this.RuleEnableButtonMode = enabled ? EnableButtonMode.Disable : EnableButtonMode.Enable;
1298 private void ButtonRuleCopy_Click(object sender, EventArgs e)
1300 if (ListTabs.SelectedIndex > -1 && ListFilters.SelectedItem != null)
1302 TabModel[] selectedTabs;
1303 using (TabsDialog dialog = new TabsDialog(_sts))
1305 dialog.MultiSelect = true;
1306 dialog.Text = Properties.Resources.ButtonRuleCopy_ClickText1;
1308 if (dialog.ShowDialog(this) == DialogResult.Cancel) return;
1310 selectedTabs = dialog.SelectedTabs;
1313 string tabname = ListTabs.SelectedItem.ToString();
1314 List<PostFilterRule> filters = new List<PostFilterRule>();
1316 foreach (int idx in ListFilters.SelectedIndices)
1318 var tab = (FilterTabModel)_sts.Tabs[tabname];
1319 filters.Add(tab.FilterArray[idx].Clone());
1321 foreach (var tb in selectedTabs.Cast<FilterTabModel>())
1323 if (tb.TabName == tabname) continue;
1325 foreach (PostFilterRule flt in filters)
1327 if (!tb.FilterArray.Contains(flt))
1328 tb.AddFilter(flt.Clone());
1331 SetFilters(tabname);
1335 private void ButtonRuleMove_Click(object sender, EventArgs e)
1337 if (ListTabs.SelectedIndex > -1 && ListFilters.SelectedItem != null)
1339 TabModel[] selectedTabs;
1340 using (var dialog = new TabsDialog(_sts))
1342 dialog.MultiSelect = true;
1343 dialog.Text = Properties.Resources.ButtonRuleMove_ClickText1;
1345 if (dialog.ShowDialog(this) == DialogResult.Cancel) return;
1347 selectedTabs = dialog.SelectedTabs;
1349 string tabname = ListTabs.SelectedItem.ToString();
1350 List<PostFilterRule> filters = new List<PostFilterRule>();
1352 foreach (int idx in ListFilters.SelectedIndices)
1354 var tab = (FilterTabModel)_sts.Tabs[tabname];
1355 filters.Add(tab.FilterArray[idx].Clone());
1357 if (selectedTabs.Length == 1 && selectedTabs[0].TabName == tabname) return;
1358 foreach (var tb in selectedTabs.Cast<FilterTabModel>())
1360 if (tb.TabName == tabname) continue;
1362 foreach (PostFilterRule flt in filters)
1364 if (!tb.FilterArray.Contains(flt))
1365 tb.AddFilter(flt.Clone());
1368 for (int idx = ListFilters.Items.Count - 1; idx >= 0; idx--)
1370 if (ListFilters.GetSelected(idx))
1372 var tab = (FilterTabModel)_sts.Tabs[ListTabs.SelectedItem.ToString()];
1373 tab.RemoveFilter((PostFilterRule)ListFilters.Items[idx]);
1374 ListFilters.Items.RemoveAt(idx);
1377 SetFilters(tabname);
1381 private void FilterTextBox_KeyDown(object sender, KeyEventArgs e)
1383 if (e.KeyCode == Keys.Space && e.Modifiers == (Keys.Shift | Keys.Control))
1385 TweenMain main = (TweenMain)this.Owner;
1386 TextBox tbox = (TextBox)sender;
1387 if (tbox.SelectionStart > 0)
1389 int endidx = tbox.SelectionStart - 1;
1390 string startstr = "";
1391 for (int i = tbox.SelectionStart - 1; i >= 0; i--)
1393 char c = tbox.Text[i];
1394 if (Char.IsLetterOrDigit(c) || c == '_')
1400 startstr = tbox.Text.Substring(i + 1, endidx - i);
1401 main.ShowSuplDialog(tbox, main.AtIdSupl, startstr.Length + 1, startstr);
1405 startstr = tbox.Text.Substring(i + 1, endidx - i);
1406 main.ShowSuplDialog(tbox, main.HashSupl, startstr.Length + 1, startstr);
1418 private void FilterTextBox_KeyPress(object sender, KeyPressEventArgs e)
1420 TweenMain main = (TweenMain)this.Owner;
1421 TextBox tbox = (TextBox)sender;
1422 if (e.KeyChar == '@')
1424 //if (!SettingDialog.UseAtIdSupplement) return;
1426 main.ShowSuplDialog(tbox, main.AtIdSupl);
1429 else if (e.KeyChar == '#')
1431 //if (!SettingDialog.UseHashSupplement) return;
1432 main.ShowSuplDialog(tbox, main.HashSupl);
1437 private void ListFilters_DrawItem(object sender, DrawItemEventArgs e)
1443 var filter = (PostFilterRule)this.ListFilters.Items[e.Index];
1444 var isSelected = e.State.HasFlag(DrawItemState.Selected);
1448 textBrush = SystemBrushes.HighlightText;
1449 else if (filter.Enabled)
1450 textBrush = SystemBrushes.WindowText;
1452 textBrush = SystemBrushes.GrayText;
1454 e.Graphics.DrawString(filter.ToString(), e.Font, textBrush, e.Bounds);
1457 e.DrawFocusRectangle();
1460 private void ListFilters_KeyDown(object sender, KeyEventArgs e)
1462 if (e.Control && e.KeyCode == Keys.A)
1464 var itemCount = this.ListFilters.Items.Count;
1465 if (itemCount == 0) return;
1467 using (ControlTransaction.Update(this.ListFilters))
1473 _multiSelState |= MultiSelectionState.SelectAll;
1475 for (int i = 1; i < itemCount; i++)
1477 this.ListFilters.SetSelected(i, true);
1482 _multiSelState &= ~MultiSelectionState.SelectAll;
1486 this.ListFilters.SetSelected(0, true);
1491 protected override void ScaleControl(SizeF factor, BoundsSpecified specified)
1493 base.ScaleControl(factor, specified);
1494 this.ListFilters.ItemHeight = this.ListFilters.Font.Height;