OSDN Git Service

PostRequestクラスを追加
[opentween/open-tween.git] / OpenTween / HashtagManage.cs
1 // OpenTween - Client of Twitter
2 // Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
3 //           (c) 2008-2011 Moz (@syo68k)
4 //           (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
5 //           (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
6 //           (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
7 //           (c) 2012      kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
8 // All rights reserved.
9 //
10 // This file is part of OpenTween.
11 //
12 // This program is free software; you can redistribute it and/or modify it
13 // under the terms of the GNU General public License as published by the Free
14 // Software Foundation; either version 3 of the License, or (at your option)
15 // any later version.
16 //
17 // This program is distributed in the hope that it will be useful, but
18 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General public License along
23 // with this program. If not, see <http://www.gnu.org/licenses/>, or write to
24 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
25 // Boston, MA 02110-1301, USA.
26
27 #nullable enable
28
29 using System;
30 using System.Collections.Generic;
31 using System.ComponentModel;
32 using System.Data;
33 using System.Drawing;
34 using System.Globalization;
35 using System.Linq;
36 using System.Text;
37 using System.Windows.Forms;
38
39 namespace OpenTween
40 {
41     public partial class HashtagManage : OTBaseForm
42     {
43         public string UseHash { get; private set; } = "";
44
45         public bool IsPermanent { get; private set; } = false;
46
47         public bool IsHead { get; private set; } = false;
48
49         public bool IsNotAddToAtReply { get; private set; } = true;
50
51         /// <summary>
52         /// エラー時にダイアログを表示させない (ユニットテストなどで使用)
53         /// </summary>
54         public bool RunSilent { get; set; }
55
56         // 入力補助画面
57         private readonly AtIdSupplement hashSupl;
58
59         // 編集モード
60         private bool isAdd = false;
61
62         private void ChangeMode(bool isEdit)
63         {
64             this.GroupHashtag.Enabled = !isEdit;
65             this.GroupDetail.Enabled = isEdit;
66             this.TableLayoutButtons.Enabled = !isEdit;
67             if (isEdit)
68                 this.UseHashText.Focus();
69             else
70                 this.HistoryHashList.Focus();
71         }
72
73         private void Cancel_Button_Click(object sender, EventArgs e)
74         {
75             this.DialogResult = DialogResult.Cancel;
76             this.Close();
77         }
78
79         private void AddButton_Click(object sender, EventArgs e)
80         {
81             this.UseHashText.Text = "";
82             this.ChangeMode(true);
83             this.isAdd = true;
84         }
85
86         private void EditButton_Click(object sender, EventArgs e)
87         {
88             if (this.HistoryHashList.SelectedIndices.Count == 0) return;
89             this.UseHashText.Text = this.HistoryHashList.SelectedItems[0].ToString();
90             this.ChangeMode(true);
91             this.isAdd = false;
92         }
93
94         private void DeleteButton_Click(object sender, EventArgs e)
95         {
96             if (this.HistoryHashList.SelectedIndices.Count == 0) return;
97             if (!this.RunSilent &&
98                 MessageBox.Show(Properties.Resources.DeleteHashtagsMessage1,
99                                 "Delete Hashtags",
100                                 MessageBoxButtons.OKCancel,
101                                 MessageBoxIcon.Question) == DialogResult.Cancel)
102             {
103                 return;
104             }
105
106             // 削除によってインデックス番号が変わらないように逆順に処理する
107             var selectedIndices = this.HistoryHashList.SelectedIndices.Cast<int>()
108                 .OrderByDescending(x => x).ToArray();
109
110             foreach (var idx in selectedIndices)
111             {
112                 if (this.UseHashText.Text == this.HistoryHashList.Items[idx].ToString()) this.UseHashText.Text = "";
113                 this.HistoryHashList.Items.RemoveAt(idx);
114             }
115             if (this.HistoryHashList.Items.Count > 0)
116             {
117                 this.HistoryHashList.SelectedIndex = 0;
118             }
119         }
120
121         private void UnSelectButton_Click(object sender, EventArgs e)
122         {
123             do
124             {
125                 this.HistoryHashList.SelectedIndices.Clear();
126             }
127             while (this.HistoryHashList.SelectedIndices.Count > 0);
128         }
129
130         private int GetIndexOf(ListBox.ObjectCollection list, string value)
131         {
132             if (MyCommon.IsNullOrEmpty(value)) return -1;
133
134             var idx = 0;
135
136             foreach (var l in list)
137             {
138                 var src = (string)l;
139                 if (MyCommon.IsNullOrEmpty(src))
140                 {
141                     idx += 1;
142                     continue;
143                 }
144                 if (string.Compare(src, value, StringComparison.OrdinalIgnoreCase) == 0)
145                 {
146                     return idx;
147                 }
148                 idx += 1;
149             }
150
151             // Not Found
152             return -1;
153         }
154
155         public void AddHashToHistory(string hash, bool isIgnorePermanent)
156         {
157             hash = hash.Trim();
158             if (!MyCommon.IsNullOrEmpty(hash))
159             {
160                 if (isIgnorePermanent || !this.IsPermanent)
161                 {
162                     // 無条件に先頭に挿入
163                     var idx = this.GetIndexOf(this.HistoryHashList.Items, hash);
164
165                     if (idx != -1) this.HistoryHashList.Items.RemoveAt(idx);
166                     this.HistoryHashList.Items.Insert(0, hash);
167                 }
168                 else
169                 {
170                     // 固定されていたら2行目に挿入
171                     var idx = this.GetIndexOf(this.HistoryHashList.Items, hash);
172                     if (this.IsPermanent)
173                     {
174                         if (idx > 0)
175                         {
176                             // 重複アイテムが2行目以降にあれば2行目へ
177                             this.HistoryHashList.Items.RemoveAt(idx);
178                             this.HistoryHashList.Items.Insert(1, hash);
179                         }
180                         else if (idx == -1)
181                         {
182                             // 重複アイテムなし
183                             if (this.HistoryHashList.Items.Count == 0)
184                             {
185                                 // リストが空なら追加
186                                 this.HistoryHashList.Items.Add(hash);
187                             }
188                             else
189                             {
190                                 // リストにアイテムがあれば2行目へ
191                                 this.HistoryHashList.Items.Insert(1, hash);
192                             }
193                         }
194                     }
195                 }
196             }
197         }
198
199         private void HashtagManage_Shown(object sender, EventArgs e)
200         {
201             // オプション
202             this.CheckPermanent.Checked = this.IsPermanent;
203             this.RadioHead.Checked = this.IsHead;
204             this.RadioLast.Checked = !this.IsHead;
205             // リスト選択
206             if (this.HistoryHashList.Items.Contains(this.UseHash))
207             {
208                 this.HistoryHashList.SelectedItem = this.UseHash;
209             }
210             else
211             {
212                 if (this.HistoryHashList.Items.Count > 0)
213                     this.HistoryHashList.SelectedIndex = 0;
214             }
215             this.ChangeMode(false);
216         }
217
218         public HashtagManage(AtIdSupplement hashSuplForm, string[] history, string permanentHash, bool isPermanent, bool isHead, bool isNotAddToAtReply)
219         {
220             // この呼び出しは、Windows フォーム デザイナで必要です。
221             this.InitializeComponent();
222
223             // InitializeComponent() 呼び出しの後で初期化を追加します。
224
225             this.hashSupl = hashSuplForm;
226             this.HistoryHashList.Items.AddRange(history);
227             this.UseHash = permanentHash;
228             this.IsPermanent = isPermanent;
229             this.IsHead = isHead;
230             this.IsNotAddToAtReply = isNotAddToAtReply;
231         }
232
233         private void UseHashText_KeyPress(object sender, KeyPressEventArgs e)
234         {
235             if (e.KeyChar == '#')
236             {
237                 this.hashSupl.ShowDialog();
238                 if (!MyCommon.IsNullOrEmpty(this.hashSupl.InputText))
239                 {
240                     var fHalf = "";
241                     var eHalf = "";
242                     var selStart = this.UseHashText.SelectionStart;
243                     if (selStart > 0)
244                     {
245                         fHalf = this.UseHashText.Text.Substring(0, selStart);
246                     }
247                     if (selStart < this.UseHashText.Text.Length)
248                     {
249                         eHalf = this.UseHashText.Text.Substring(selStart);
250                     }
251                     this.UseHashText.Text = fHalf + this.hashSupl.InputText + eHalf;
252                     this.UseHashText.SelectionStart = selStart + this.hashSupl.InputText.Length;
253                 }
254                 e.Handled = true;
255             }
256         }
257
258         private void HistoryHashList_DoubleClick(object sender, EventArgs e)
259             => this.OK_Button_Click(this.OK_Button, EventArgs.Empty);
260
261         public void ToggleHash()
262         {
263             if (MyCommon.IsNullOrEmpty(this.UseHash))
264             {
265                 if (this.HistoryHashList.Items.Count > 0)
266                     this.UseHash = this.HistoryHashList.Items[0].ToString();
267             }
268             else
269             {
270                 this.UseHash = "";
271             }
272         }
273
274         public List<string> HashHistories
275         {
276             get
277             {
278                 var hash = new List<string>();
279                 foreach (string item in this.HistoryHashList.Items)
280                 {
281                     hash.Add(item);
282                 }
283                 return hash;
284             }
285         }
286
287         public void ClearHashtag()
288             => this.UseHash = "";
289
290         public void SetPermanentHash(string hash)
291         {
292             // 固定ハッシュタグの変更
293             this.UseHash = hash.Trim();
294             this.AddHashToHistory(this.UseHash, false);
295             this.IsPermanent = true;
296         }
297
298         private void PermOK_Button_Click(object sender, EventArgs e)
299         {
300             // ハッシュタグの整形
301             var hashStr = this.UseHashText.Text;
302             if (!this.AdjustHashtags(ref hashStr, !this.RunSilent)) return;
303
304             this.UseHashText.Text = hashStr;
305             if (!this.isAdd && this.HistoryHashList.SelectedIndices.Count > 0)
306             {
307                 var idx = this.HistoryHashList.SelectedIndices[0];
308                 this.HistoryHashList.Items.RemoveAt(idx);
309                 do
310                 {
311                     this.HistoryHashList.SelectedIndices.Clear();
312                 }
313                 while (this.HistoryHashList.SelectedIndices.Count > 0);
314                 this.HistoryHashList.Items.Insert(idx, hashStr);
315                 this.HistoryHashList.SelectedIndex = idx;
316             }
317             else
318             {
319                 this.AddHashToHistory(hashStr, false);
320                 do
321                 {
322                     this.HistoryHashList.SelectedIndices.Clear();
323                 }
324                 while (this.HistoryHashList.SelectedIndices.Count > 0);
325                 this.HistoryHashList.SelectedIndex = this.HistoryHashList.Items.IndexOf(hashStr);
326             }
327
328             this.ChangeMode(false);
329         }
330
331         private void PermCancel_Button_Click(object sender, EventArgs e)
332         {
333             if (this.HistoryHashList.Items.Count > 0 && this.HistoryHashList.SelectedIndices.Count > 0)
334                 this.UseHashText.Text = this.HistoryHashList.Items[this.HistoryHashList.SelectedIndices[0]].ToString();
335             else
336                 this.UseHashText.Text = "";
337
338             this.ChangeMode(false);
339         }
340
341         private void HistoryHashList_KeyDown(object sender, KeyEventArgs e)
342         {
343             if (e.KeyCode == Keys.Delete)
344                 this.DeleteButton_Click(this.DeleteButton, EventArgs.Empty);
345             else if (e.KeyCode == Keys.Insert)
346                 this.AddButton_Click(this.AddButton, EventArgs.Empty);
347         }
348
349         private bool AdjustHashtags(ref string hashtag, bool isShowWarn)
350         {
351             // ハッシュタグの整形
352             hashtag = hashtag.Trim();
353             if (MyCommon.IsNullOrEmpty(hashtag))
354             {
355                 if (isShowWarn) MessageBox.Show("emply hashtag.", "Hashtag warning", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
356                 return false;
357             }
358             hashtag = hashtag.Replace("#", "#");
359             hashtag = hashtag.Replace(" ", " ");
360             var adjust = "";
361             foreach (var hash in hashtag.Split(' '))
362             {
363                 if (hash.Length > 0)
364                 {
365                     if (!hash.StartsWith("#", StringComparison.Ordinal))
366                     {
367                         if (isShowWarn) MessageBox.Show("Invalid hashtag. -> " + hash, "Hashtag warning", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
368                         return false;
369                     }
370                     if (hash.Length == 1)
371                     {
372                         if (isShowWarn) MessageBox.Show("empty hashtag.", "Hashtag warning", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
373                         return false;
374                     }
375                     // 使用不可の文字チェックはしない
376                     adjust += hash + " ";
377                 }
378             }
379             hashtag = adjust.Trim();
380             return true;
381         }
382
383         private void OK_Button_Click(object sender, EventArgs e)
384         {
385             var hash = "";
386             foreach (string hs in this.HistoryHashList.SelectedItems)
387             {
388                 hash += hs + " ";
389             }
390             hash = hash.Trim();
391             if (!MyCommon.IsNullOrEmpty(hash))
392             {
393                 this.AddHashToHistory(hash, true);
394                 this.IsPermanent = this.CheckPermanent.Checked;
395             }
396             else
397             {
398                 // 使用ハッシュが未選択ならば、固定オプション外す
399                 this.IsPermanent = false;
400             }
401             this.IsHead = this.RadioHead.Checked;
402             this.UseHash = hash;
403
404             this.DialogResult = DialogResult.OK;
405             this.Close();
406         }
407
408         private void HashtagManage_KeyDown(object sender, KeyEventArgs e)
409         {
410             if (e.KeyCode == Keys.Enter)
411             {
412                 e.Handled = true;
413                 if (this.GroupDetail.Enabled)
414                     this.PermOK_Button_Click(this.PermOK_Button, EventArgs.Empty);
415                 else
416                     this.OK_Button_Click(this.OK_Button, EventArgs.Empty);
417             }
418             else if (e.KeyCode == Keys.Escape)
419             {
420                 e.Handled = true;
421                 if (this.GroupDetail.Enabled)
422                     this.PermCancel_Button_Click(this.PermCancel_Button, EventArgs.Empty);
423                 else
424                     this.Cancel_Button_Click(this.Cancel_Button, EventArgs.Empty);
425             }
426         }
427
428         private void CheckNotAddToAtReply_CheckedChanged(object sender, EventArgs e)
429             => this.IsNotAddToAtReply = this.CheckNotAddToAtReply.Checked;
430     }
431 }