OSDN Git Service

8822349afb06325ed5a347e3e51c7dafd511dc3b
[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 using System;
28 using System.Collections.Generic;
29 using System.ComponentModel;
30 using System.Data;
31 using System.Drawing;
32 using System.Globalization;
33 using System.Linq;
34 using System.Text;
35 using System.Windows.Forms;
36
37 namespace OpenTween
38 {
39     public partial class HashtagManage : OTBaseForm
40     {
41         /// <summary>
42         /// エラー時にダイアログを表示させない (ユニットテストなどで使用)
43         /// </summary>
44         public bool RunSilent { get; set; }
45
46         //入力補助画面
47         private AtIdSupplement _hashSupl;
48         //I/F用
49         private string _useHash = "";
50         private bool _isPermanent = false;
51         private bool _isHead = false;
52         private bool _isNotAddToAtReply = true;
53         //編集モード
54         private bool _isAdd = false;
55
56         private void ChangeMode(bool isEdit)
57         {
58             this.GroupHashtag.Enabled = !isEdit;
59             this.GroupDetail.Enabled = isEdit;
60             this.TableLayoutButtons.Enabled = !isEdit;
61             if (isEdit)
62                 this.UseHashText.Focus();
63             else
64                 this.HistoryHashList.Focus();
65         }
66
67         private void Cancel_Button_Click(object sender, EventArgs e)
68         {
69             this.DialogResult = DialogResult.Cancel;
70             this.Close();
71         }
72
73         private void AddButton_Click(object sender, EventArgs e)
74         {
75             this.UseHashText.Text = "";
76             ChangeMode(true);
77             _isAdd = true;
78         }
79
80         private void EditButton_Click(object sender, EventArgs e)
81         {
82             if (this.HistoryHashList.SelectedIndices.Count == 0) return;
83             this.UseHashText.Text = this.HistoryHashList.SelectedItems[0].ToString();
84             ChangeMode(true);
85             _isAdd = false;
86         }
87
88         private void DeleteButton_Click(object sender, EventArgs e)
89         {
90             if (this.HistoryHashList.SelectedIndices.Count == 0) return;
91             if (!this.RunSilent &&
92                 MessageBox.Show(Properties.Resources.DeleteHashtagsMessage1,
93                                 "Delete Hashtags",
94                                 MessageBoxButtons.OKCancel,
95                                 MessageBoxIcon.Question) == DialogResult.Cancel)
96             {
97                 return;
98             }
99
100             // 削除によってインデックス番号が変わらないように逆順に処理する
101             var selectedIndices = this.HistoryHashList.SelectedIndices.Cast<int>()
102                 .OrderByDescending(x => x).ToArray();
103
104             foreach (var idx in selectedIndices)
105             {
106                 if (UseHashText.Text == HistoryHashList.Items[idx].ToString()) UseHashText.Text = "";
107                 HistoryHashList.Items.RemoveAt(idx);
108             }
109             if (HistoryHashList.Items.Count > 0)
110             {
111                 HistoryHashList.SelectedIndex = 0;
112             }
113         }
114
115         private void UnSelectButton_Click(object sender, EventArgs e)
116         {
117             do
118             {
119                 HistoryHashList.SelectedIndices.Clear();
120             } while (HistoryHashList.SelectedIndices.Count > 0);
121         }
122
123         private int GetIndexOf(ListBox.ObjectCollection list, string value)
124         {
125             if (string.IsNullOrEmpty(value)) return -1;
126
127             int idx = 0;
128
129             foreach (object l in list)
130             {
131                 string src = l as string;
132                 if (string.IsNullOrEmpty(src))
133                 {
134                     idx += 1;
135                     continue;
136                 }
137                 if (string.Compare(src, value, StringComparison.OrdinalIgnoreCase) == 0)
138                 {
139                     return idx;
140                 }
141                 idx += 1;
142             }
143
144             // Not Found
145             return -1;
146         }
147
148         public void AddHashToHistory(string hash, bool isIgnorePermanent)
149         {
150             hash = hash.Trim();
151             if (!string.IsNullOrEmpty(hash))
152             {
153                 if (isIgnorePermanent || !_isPermanent)
154                 {
155                     //無条件に先頭に挿入
156                     int idx = GetIndexOf(HistoryHashList.Items, hash);
157
158                     if (idx != -1) HistoryHashList.Items.RemoveAt(idx);
159                     HistoryHashList.Items.Insert(0, hash);
160                 }
161                 else
162                 {
163                     //固定されていたら2行目に挿入
164                     int idx = GetIndexOf(HistoryHashList.Items, hash);
165                     if (_isPermanent)
166                     {
167                         if (idx > 0)
168                         {
169                             //重複アイテムが2行目以降にあれば2行目へ
170                             HistoryHashList.Items.RemoveAt(idx);
171                             HistoryHashList.Items.Insert(1, hash);
172                         }
173                         else if (idx == -1)
174                         {
175                             //重複アイテムなし
176                             if (HistoryHashList.Items.Count == 0)
177                             {
178                                 //リストが空なら追加
179                                 HistoryHashList.Items.Add(hash);
180                             }
181                             else
182                             {
183                                 //リストにアイテムがあれば2行目へ
184                                 HistoryHashList.Items.Insert(1, hash);
185                             }
186                         }
187                     }
188                 }
189             }
190         }
191
192         private void HashtagManage_Shown(object sender, EventArgs e)
193         {
194             //オプション
195             this.CheckPermanent.Checked = this._isPermanent;
196             this.RadioHead.Checked = this._isHead;
197             this.RadioLast.Checked = !this._isHead;
198             //リスト選択
199             if (this.HistoryHashList.Items.Contains(this._useHash))
200             {
201                 this.HistoryHashList.SelectedItem = this._useHash;
202             }
203             else
204             {
205                 if (this.HistoryHashList.Items.Count > 0)
206                     this.HistoryHashList.SelectedIndex = 0;
207             }
208             this.ChangeMode(false);
209         }
210
211         public HashtagManage(AtIdSupplement hashSuplForm, string[] history, string permanentHash, bool IsPermanent, bool IsHead, bool IsNotAddToAtReply)
212         {
213             // この呼び出しは、Windows フォーム デザイナで必要です。
214             InitializeComponent();
215
216             // InitializeComponent() 呼び出しの後で初期化を追加します。
217
218             _hashSupl = hashSuplForm;
219             HistoryHashList.Items.AddRange(history);
220             _useHash = permanentHash;
221             _isPermanent = IsPermanent;
222             _isHead = IsHead;
223             _isNotAddToAtReply = IsNotAddToAtReply;
224         }
225
226         private void UseHashText_KeyPress(object sender, KeyPressEventArgs e)
227         {
228             if (e.KeyChar == '#')
229             {
230                 _hashSupl.ShowDialog();
231                 if (!string.IsNullOrEmpty(_hashSupl.inputText))
232                 {
233                     string fHalf = "";
234                     string eHalf = "";
235                     int selStart = UseHashText.SelectionStart;
236                     if (selStart > 0)
237                     {
238                         fHalf = UseHashText.Text.Substring(0, selStart);
239                     }
240                     if (selStart < UseHashText.Text.Length)
241                     {
242                         eHalf = UseHashText.Text.Substring(selStart);
243                     }
244                     UseHashText.Text = fHalf + _hashSupl.inputText + eHalf;
245                     UseHashText.SelectionStart = selStart + _hashSupl.inputText.Length;
246                 }
247                 e.Handled = true;
248             }
249         }
250
251         private void HistoryHashList_DoubleClick(object sender, EventArgs e)
252         {
253             this.OK_Button_Click(null, null);
254         }
255
256         public void ToggleHash()
257         {
258             if (string.IsNullOrEmpty(this._useHash))
259             {
260                 if (this.HistoryHashList.Items.Count > 0)
261                     this._useHash = this.HistoryHashList.Items[0].ToString();
262             }
263             else
264             {
265                 this._useHash = "";
266             }
267         }
268
269         public List<string> HashHistories
270         {
271             get
272             {
273                 List<string> hash = new List<string>();
274                 foreach (string item in HistoryHashList.Items)
275                 {
276                     hash.Add(item);
277                 }
278                 return hash;
279             }
280         }
281
282         public string UseHash
283         {
284             get { return _useHash; }
285         }
286
287         public void ClearHashtag()
288         {
289             this._useHash = "";
290         }
291
292         public void SetPermanentHash(string hash)
293         {
294             //固定ハッシュタグの変更
295             _useHash = hash.Trim();
296             this.AddHashToHistory(_useHash, false);
297             this._isPermanent = true;
298         }
299
300         public bool IsPermanent
301         {
302             get { return _isPermanent; }
303         }
304
305         public bool IsHead
306         {
307             get { return _isHead; }
308         }
309
310         public bool IsNotAddToAtReply
311         {
312             get { return _isNotAddToAtReply; }
313         }
314
315         private void PermOK_Button_Click(object sender, EventArgs e)
316         {
317             //ハッシュタグの整形
318             string hashStr = UseHashText.Text;
319             if (!this.AdjustHashtags(ref hashStr, !this.RunSilent)) return;
320
321             UseHashText.Text = hashStr;
322             int idx = 0;
323             if (!this._isAdd && this.HistoryHashList.SelectedIndices.Count > 0)
324             {
325                 idx = this.HistoryHashList.SelectedIndices[0];
326                 this.HistoryHashList.Items.RemoveAt(idx);
327                 do
328                 {
329                     this.HistoryHashList.SelectedIndices.Clear();
330                 } while (this.HistoryHashList.SelectedIndices.Count > 0);
331                 this.HistoryHashList.Items.Insert(idx, hashStr);
332                 this.HistoryHashList.SelectedIndex = idx;
333             }
334             else
335             {
336                 this.AddHashToHistory(hashStr, false);
337                 do
338                 {
339                     this.HistoryHashList.SelectedIndices.Clear();
340                 } while (this.HistoryHashList.SelectedIndices.Count > 0);
341                 this.HistoryHashList.SelectedIndex = this.HistoryHashList.Items.IndexOf(hashStr);
342             }
343
344             ChangeMode(false);
345         }
346
347         private void PermCancel_Button_Click(object sender, EventArgs e)
348         {
349             if (this.HistoryHashList.Items.Count > 0 && this.HistoryHashList.SelectedIndices.Count > 0)
350                 this.UseHashText.Text = this.HistoryHashList.Items[this.HistoryHashList.SelectedIndices[0]].ToString();
351             else
352                 this.UseHashText.Text = "";
353
354             ChangeMode(false);
355         }
356
357         private void HistoryHashList_KeyDown(object sender, KeyEventArgs e)
358         {
359             if (e.KeyCode == Keys.Delete)
360                 this.DeleteButton_Click(null, null);
361             else if (e.KeyCode == Keys.Insert)
362                 this.AddButton_Click(null, null);
363         }
364
365         private bool AdjustHashtags(ref string hashtag, bool isShowWarn)
366         {
367             //ハッシュタグの整形
368             hashtag = hashtag.Trim();
369             if (string.IsNullOrEmpty(hashtag))
370             {
371                 if (isShowWarn) MessageBox.Show("emply hashtag.", "Hashtag warning", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
372                 return false;
373             }
374             hashtag = hashtag.Replace("#", "#");
375             hashtag = hashtag.Replace(" ", " ");
376             string adjust = "";
377             foreach (string hash in hashtag.Split(' '))
378             {
379                 if (hash.Length > 0)
380                 {
381                     if (!hash.StartsWith("#", StringComparison.Ordinal))
382                     {
383                         if (isShowWarn) MessageBox.Show("Invalid hashtag. -> " + hash, "Hashtag warning", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
384                         return false;
385                     }
386                     if (hash.Length == 1)
387                     {
388                         if (isShowWarn) MessageBox.Show("empty hashtag.", "Hashtag warning", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
389                         return false;
390                     }
391                     //使用不可の文字チェックはしない
392                     adjust += hash + " ";
393                 }
394             }
395             hashtag = adjust.Trim();
396             return true;
397         }
398
399         private void OK_Button_Click(object sender, EventArgs e)
400         {
401             string hash = "";
402             foreach (string hs in this.HistoryHashList.SelectedItems)
403             {
404                 hash += hs + " ";
405             }
406             hash = hash.Trim();
407             if (!string.IsNullOrEmpty(hash))
408             {
409                 this.AddHashToHistory(hash, true);
410                 this._isPermanent = this.CheckPermanent.Checked;
411             }
412             else
413             {
414                 //使用ハッシュが未選択ならば、固定オプション外す
415                 this._isPermanent = false;
416             }
417             this._isHead = this.RadioHead.Checked;
418             this._useHash = hash;
419
420             this.DialogResult = DialogResult.OK;
421             this.Close();
422         }
423
424         private void HashtagManage_KeyDown(object sender, KeyEventArgs e)
425         {
426             if (e.KeyCode == Keys.Enter)
427             {
428                 e.Handled = true;
429                 if (this.GroupDetail.Enabled)
430                     this.PermOK_Button_Click(null, null);
431                 else
432                     this.OK_Button_Click(null, null);
433             }
434             else if (e.KeyCode == Keys.Escape)
435             {
436                 e.Handled = true;
437                 if (this.GroupDetail.Enabled)
438                     this.PermCancel_Button_Click(null, null);
439                 else
440                     this.Cancel_Button_Click(null, null);
441             }
442         }
443
444         private void CheckNotAddToAtReply_CheckedChanged(object sender, EventArgs e)
445         {
446             _isNotAddToAtReply = CheckNotAddToAtReply.Checked;
447         }
448     }
449 }