OSDN Git Service

55b76596880c5d974344caca6a87e78270a0b185
[nt-manager/nt-manager.git] / src / twitter / gui / action / TweetMainAction.java
1 package twitter.gui.action;
2
3 import java.awt.Color;
4 import java.awt.Desktop;
5 import java.awt.Dimension;
6 import java.awt.Font;
7 import java.awt.Point;
8 import java.awt.event.ActionEvent;
9 import java.io.File;
10 import java.io.FileInputStream;
11 import java.io.FileNotFoundException;
12 import java.io.FileOutputStream;
13 import java.io.IOException;
14 import java.io.UnsupportedEncodingException;
15 import java.net.URI;
16 import java.net.URL;
17 import java.net.URLEncoder;
18 import java.text.DateFormat;
19 import java.util.ArrayList;
20 import java.util.Comparator;
21 import java.util.List;
22 import java.util.Properties;
23 import java.util.Set;
24 import java.util.TreeSet;
25 import java.util.logging.Level;
26 import java.util.logging.Logger;
27 import java.util.regex.Matcher;
28 import java.util.regex.Pattern;
29 import javax.swing.ImageIcon;
30 import javax.swing.JCheckBoxMenuItem;
31
32 import javax.swing.JEditorPane;
33 import javax.swing.JFrame;
34 import javax.swing.JLabel;
35 import javax.swing.JOptionPane;
36 import javax.swing.JPanel;
37 import javax.swing.JTabbedPane;
38 import javax.swing.JTable;
39 import javax.swing.JTextPane;
40 import javax.swing.JToggleButton;
41 import javax.swing.table.TableModel;
42 import javax.swing.text.Style;
43 import javax.swing.text.StyleConstants;
44 import javax.swing.text.html.HTMLDocument;
45 import javax.swing.text.html.StyleSheet;
46 import twitter.action.TweetDirectMessageGetter;
47 import twitter.action.TweetFavoriteGetter;
48 import twitter.action.TweetGetter;
49 import twitter.action.TweetMentionGetter;
50 import twitter.action.TweetSearchResultGetter;
51 import twitter.action.TweetSendDirectMessageGetter;
52 import twitter.action.TweetTimelineGetter;
53 import twitter.action.TweetUserTimelineGetter;
54 import twitter.action.list.ListGetterSelection;
55 import twitter.action.list.UserListGetter;
56 import twitter.action.list.UserListMembershipsGetter;
57 import twitter.action.list.UserListSpecificUserListsGetter;
58 import twitter.action.list.UserListSubscriptionGetter;
59 import twitter.gui.component.DnDTabbedPane;
60
61 import twitter.gui.component.TweetTabbedTable;
62 import twitter.gui.component.TweetTableModel;
63 import twitter.gui.form.AboutDialog;
64 import twitter.gui.form.AccountDialog;
65 import twitter.gui.form.ConfigurationDialog;
66 import twitter.gui.form.DirectMessageDialog;
67 import twitter.gui.form.HashtagSearchDialog;
68 import twitter.gui.form.KeywordSearchDialog;
69 import twitter.gui.form.UserListDialog;
70 import twitter.manage.TweetConfiguration;
71 import twitter.manage.TweetManager;
72 import twitter.task.ExistTimerIDException;
73 import twitter.task.TimerID;
74 import twitter.task.TweetTaskException;
75 import twitter.task.TweetTaskManager;
76 import twitter.task.TweetUpdateTask;
77 import twitter.util.HTMLEncode;
78 import twitter4j.Status;
79 import twitter4j.TwitterException;
80
81 /**
82  * GUIのアクション部分
83  * 
84  * @author nishio
85  * 
86  */
87 public class TweetMainAction {
88
89     // 基本設定を保存するファイル名
90     public static final String BASIC_SETTING_FILENAME = TweetConfiguration.BASIC_SETTING_FILENAME;
91     // httpのパターン
92     private static final Pattern convURLLinkPtn = Pattern.compile(
93             "(http://|https://){1}[\\w\\.\\-/:\\#\\?\\=\\&\\;\\%\\~\\+]+",
94             Pattern.CASE_INSENSITIVE);
95     // default char encoding
96     private static final String DEFAULT_CHARACTER_ENCODING = "UTF-8";
97     // 設定ファイルを保存するディレクトリ名
98     public static final String PROPERTIES_DIRECTORY = "properties";
99     // search twitterのクエリ
100     private static final String SEARCH_QUERY = "search?q=";
101     // search twitterのURL
102     private static final String SEARCH_TWITTER_URL = "http://" + TweetConfiguration.SEARCH_TWITTER_HOSTNAME + "/";
103     // Direct Messageタブに表示する文字
104     public static final String TAB_DIRECT_MESSAGE_STRING = "Message";
105     // Mentionタブに表示する文字
106     public static final String TAB_MENTION_STRING = "Mention";
107     // タイムラインタブに表示する文字
108     public static final String TAB_TIMELINE_STRING = "Timeline";
109     //Send Direct Messageタブに表示する文字
110     public static final String TAB_SEND_DIRECT_MESSAGE_STRING = "Send";
111     // テーブルのデータ量が以下の値を超えたら古いデータから削除
112     private static final int TABLE_ELEMENT_MAX_SIZE = 200;
113     // twitterの公式URL
114     private static final String TWITTER_URL = "http://twitter.com/";
115     // 基本設定用ダイアログ
116     private ConfigurationDialog configurationDialog = null;
117     // 現在選択しているStatus情報
118     private Status currentStatus = null;
119     // reply予定のStatus
120     private Status replyStatus = null;
121     // 詳細情報パネル
122     private JPanel detailInfoPanel = null;
123     // ダイレクトメッセージ送信用ダイアログ
124     private DirectMessageDialog directMessageDialog = null;
125     //Twitter全体からキーワード検索ダイアログ
126     private KeywordSearchDialog keywordSearchDialog = null;
127     //hashtag search dialog
128     private HashtagSearchDialog hashtagSearchDialog = null;
129     // 新しく取得した部分のテーブルカラー
130     private Color newTableColor = new Color(224, 255, 255);
131     // TLのフォント名
132     private String tlFontName = "Takao Pゴシック";
133     // TLのフォントサイズ
134     private int tlFontSize = 13;
135     // 詳細情報のフォント名
136     private String detailFontName = "Takao Pゴシック";
137     // 詳細情報のフォントサイズ
138     private int detailFontSize = 13;
139     // テーブル1要素の高さ
140     private int tableElementHeight = 50;
141     //メインフレームの幅
142     private int mainFrameWidth = 729;
143     //メインフレームの高さ
144     private int mainFrameHeight = 629;
145     // MainFrame
146     private JFrame mainFrame = null;
147     // 設定
148     private Properties property = null;
149     // 現在テーブルで選択しているユーザ画像のURL
150     private URL selectedUserImageURL = null;
151     // 現在テーブルで選択しているユーザの名前
152     private String selectedUsername = null;
153     // ステータス表示ラベル
154     private JLabel statusBarLabel = null;
155     // 自分がつぶやきをかく領域
156     private JTextPane tweetBoxPane = null;
157     //自分がつぶやきを書く領域のスクロールペーン
158     private JPanel tweetBoxRegionPane = null;
159     // tweet情報などを表示するタブ
160     private JTabbedPane tweetMainTab = null;
161     // Tweet管理
162     private TweetManager tweetManager = null;
163     // tweetを表示するTextPane
164     private JEditorPane tweetMessageBox = null;
165     // つぶやくことができる文字数を表示するラベル
166     private JLabel tweetMessageCountLabel = null;
167     private int uncheckedDirectMessageCount = 0;
168     private int uncheckedMentionTweetCount = 0;
169
170     //Tweetの詳細情報を表示する部分
171     private JLabel userImageLabel = null;
172     private JLabel userNameLabel = null;
173     private JLabel updateTimeLabel = null;
174     private JLabel followerLabel = null;
175     private JLabel followingLabel = null;
176     private JLabel locationLabel = null;
177     private JEditorPane clientNameLabel = null;
178     private JLabel updateLabel = null;
179     private JEditorPane userIntroBox = null;
180     private JEditorPane userWebBox = null;
181
182     //checkbox関係
183     private javax.swing.JToggleButton timelineToggleButton;
184     private javax.swing.JToggleButton mentionToggleButton;
185     private javax.swing.JToggleButton dmToggleButton;
186     private javax.swing.JToggleButton sendDMToggleButton;
187
188     private javax.swing.JCheckBoxMenuItem timelineCheckBoxMenuItem;
189     private javax.swing.JCheckBoxMenuItem mentionCheckBoxMenuItem;
190     private javax.swing.JCheckBoxMenuItem dmCheckBoxMenuItem;
191     private javax.swing.JCheckBoxMenuItem sendCheckBoxMenuItem;
192
193     // 新しく取得したtweetでまだ参照していない数
194     private int uncheckedTimelineTweetCount = 0;
195     private AboutDialog aboutDialog = null;
196     //アカウント情報表示ダイアログ
197     private AccountDialog accountDialog;
198     //ツイートを表示するテーブル管理
199     private List<TweetTabbedTable> tweetTabbedTableList = new ArrayList<TweetTabbedTable>();
200     //ツイートテーブルの情報を一定間隔で更新するクラスを作成
201     private TweetTaskManager tweetTaskManager = new TweetTaskManager();
202
203     //リストダイアログ
204     private UserListDialog userListDialog = null;
205
206     //情報更新間隔[sec]
207     private int getTimelinePeriod = 60;
208     private int getMentionPeriod = 60 * 3;
209     private int getDirectMessagePeriod = 60 * 15;
210     private int getSendDirectMessagePeriod = 60 * 30;
211
212     /**
213      *
214      * @param mainFrame
215      * @param tweetManager
216      * @param statusBarLabel
217      * @param tweetTableModel
218      * @param mentionTableModel
219      * @param directMessageTableModel
220      * @param sendDirectMessageTableModel
221      * @param mainTweetTable
222      * @param mentionTable
223      * @param directMessageTable
224      * @param sendDirectMessageTable
225      * @param tweetBoxPane
226      * @param tweetBoxScrollPane
227      * @param tweetMessageCountLabel
228      * @param detailInfoPanel
229      * @param tweetMainTab
230      * @param tweetMessageBox
231      * @param userImageLabel
232      * @param userNameLabel
233      * @param updateTimeLabel
234      * @param followerLabel
235      * @param followingLabel
236      * @param locationLabel
237      * @param clientNameLabel
238      * @param updateLabel
239      * @param userIntroBox
240      * @param userWebBox
241      */
242     public TweetMainAction(JFrame mainFrame,
243             TweetManager tweetManager,
244             JLabel statusBarLabel,
245             JTextPane tweetBoxPane,
246             JPanel tweetBoxScrollPane,
247             JLabel tweetMessageCountLabel,
248             JPanel detailInfoPanel,
249             JTabbedPane tweetMainTab,
250             JEditorPane tweetMessageBox,
251             JLabel userImageLabel,
252             JLabel userNameLabel,
253             JLabel updateTimeLabel,
254             JLabel followerLabel,
255             JLabel followingLabel,
256             JLabel locationLabel,
257             JEditorPane clientNameLabel,
258             JLabel updateLabel,
259             JEditorPane userIntroBox,
260             JEditorPane userWebBox,
261             JToggleButton timelineToggleButton,
262             JToggleButton mentionToggleButton,
263             JToggleButton dmToggleButton,
264             JToggleButton sendToggleButton,
265             JCheckBoxMenuItem timelineCheckBoxMenuItem,
266             JCheckBoxMenuItem mentionCheckBoxMenuItem,
267             JCheckBoxMenuItem dmCheckBoxMenuItem,
268             JCheckBoxMenuItem sendCheckBoxMenuItem) {
269         this.mainFrame = mainFrame;
270         this.tweetManager = tweetManager;
271         this.statusBarLabel = statusBarLabel;
272         this.tweetBoxPane = tweetBoxPane;
273         this.tweetMessageCountLabel = tweetMessageCountLabel;
274         this.detailInfoPanel = detailInfoPanel;
275         this.tweetMainTab = tweetMainTab;
276         this.tweetMessageBox = tweetMessageBox;
277         this.tweetBoxRegionPane = tweetBoxScrollPane;
278
279         //詳細情報部分
280         this.userImageLabel = userImageLabel;
281         this.userNameLabel = userNameLabel;
282         this.updateTimeLabel = updateTimeLabel;
283         this.userIntroBox = userIntroBox;
284         this.followerLabel = followerLabel;
285         this.followingLabel = followingLabel;
286         this.locationLabel = locationLabel;
287         this.userWebBox = userWebBox;
288         this.clientNameLabel = clientNameLabel;
289         this.updateLabel = updateLabel;
290
291         this.timelineCheckBoxMenuItem = timelineCheckBoxMenuItem;
292         this.timelineToggleButton = timelineToggleButton;
293         this.mentionCheckBoxMenuItem = mentionCheckBoxMenuItem;
294         this.mentionToggleButton = mentionToggleButton;
295         this.dmCheckBoxMenuItem = dmCheckBoxMenuItem;
296         this.dmToggleButton = dmToggleButton;
297         this.sendCheckBoxMenuItem = sendCheckBoxMenuItem;
298         this.sendDMToggleButton = sendToggleButton;
299
300         //罰ボタンを押した時のイベントを追加
301         if( this.tweetMainTab instanceof DnDTabbedPane ) {
302             ((DnDTabbedPane)this.tweetMainTab).setMainAction(this);
303         }
304
305         // 設定ファイルの読み込み
306         try {
307             loadProperties();
308         } catch (FileNotFoundException e) {
309             e.printStackTrace();
310         } catch (IOException e) {
311             e.printStackTrace();
312         }
313         // フォント情報を反映
314         updateFontInformationToComponent();
315
316         //フレームの大きさを反映
317         mainFrame.setSize(this.mainFrameWidth, this.mainFrameHeight);
318         mainFrame.setPreferredSize(new Dimension(this.mainFrameWidth, this.mainFrameHeight));
319     }
320
321     /**
322      * チェックボックスの状態を更新
323      */
324     public void updateCheckboxInformation() {
325         boolean timeline = this.isExistTimelineTab();
326         boolean mention = this.isExistMentionTab();
327         boolean dm = this.isExistDirectMessageTab();
328         boolean send = this.isExistSendDirectMessageTab();
329         
330         this.timelineCheckBoxMenuItem.setSelected( timeline );
331         this.timelineToggleButton.setSelected(timeline);
332         this.mentionCheckBoxMenuItem.setSelected(mention);
333         this.mentionToggleButton.setSelected(mention);
334         this.dmCheckBoxMenuItem.setSelected(dm);
335         this.dmToggleButton.setSelected(dm);
336         this.sendCheckBoxMenuItem.setSelected(send);
337         this.sendDMToggleButton.setSelected(send);
338     }
339
340     /**
341      * Timeline, Mention , DM, SendDMの情報更新間隔を取得し,その情報をテーブルに反映
342      */
343     public void updatePeriodInformationToComponent() {
344         //すべてのテーブルにフォント情報を反映
345         for (TweetTabbedTable t : this.tweetTabbedTableList) {
346             String timerID = t.getTimerID();
347             if( timerID.equals( TimerID.createTimelineID() ) ) {
348                 //TLの周期情報更新
349                 this.tweetTaskManager.updateTaskPeriod(timerID, this.getGetTimelinePeriod(), false);
350             }else if( timerID.equals( TimerID.createMentionID() ) ) {
351                 //Mentionの周期情報更新
352                 this.tweetTaskManager.updateTaskPeriod(timerID, this.getGetMentionPeriod(), false );
353             }else if( timerID.equals( TimerID.createDirectMessageID() ) ) {
354                 //DMの周期情報更新
355                 this.tweetTaskManager.updateTaskPeriod(timerID, this.getGetDirectMessagePeriod(), false);
356             }else if( timerID.equals( TimerID.createSendDirectMessageID() ) ) {
357                 //SendDMの周期情報更新
358                 this.tweetTaskManager.updateTaskPeriod(timerID, this.getGetSendDirectMessagePeriod(), false);
359             }
360         }
361     }
362
363     // フォント情報をコンポーネントに反映
364     public void updateFontInformationToComponent() {
365         try {
366             Font tlFont = null;
367             if (this.tlFontName != null) {
368                 tlFont = new Font(this.tlFontName, Font.PLAIN, this.tlFontSize);
369             }
370             Font detailFont = null;
371             if (this.detailFontName != null) {
372                 detailFont = new Font(this.detailFontName, Font.PLAIN,
373                         this.detailFontSize);
374             }
375
376             //すべてのテーブルにフォント情報を反映
377             for( TweetTabbedTable t : this.tweetTabbedTableList) {
378                 t.getTable().setFont(tlFont);
379             }
380
381             // tweetメッセージボックスのフォントはhtmlレベルで変更する必要がある
382             this.tweetMessageBox.setFont(detailFont);
383             // htmlフォント変更
384             HTMLDocument doc = (HTMLDocument) this.tweetMessageBox.getDocument();
385             StyleSheet[] style = doc.getStyleSheet().getStyleSheets();
386             for (int i = style.length - 1; i >= 0; i--) {
387                 Style body = style[i].getStyle("body");
388                 if (body != null) {
389                     StyleConstants.setFontFamily(body, detailFont.getFontName());
390                     StyleConstants.setFontSize(body, detailFont.getSize());
391                 }
392             }
393
394         } catch (Exception e) {
395             e.printStackTrace();
396         }
397     }
398
399     /**
400      * 新しいタブを追加
401      * @param timerID TimerIDクラスで生成したタイマーID
402      * @param period 情報更新間隔[sec]
403      * @param tweetGetter 実行するアクション
404      * @param tabTitle 追加するタブのタイトル
405      */
406     public void actionAddTab(String timerID, int period, TweetGetter tweetGetter, String tabTitle) {
407         //周期的に情報を更新する
408         if( period > 0 ) {
409             try {
410                 //テーブルを作成
411                 final TweetTabbedTable table = new TweetTabbedTable(tweetGetter, tabTitle,
412                         this.tweetMainTab, 
413                         this.tableElementHeight, this.tweetManager,
414                         this, newTableColor, TABLE_ELEMENT_MAX_SIZE, timerID);
415
416                 this.tweetTaskManager.addTask(timerID, new TweetUpdateTask() {
417
418                     @Override
419                     public void runTask() throws TweetTaskException {
420                         //ツイート情報を一定間隔で更新
421                         table.updateTweetTable();
422                     }
423                 });
424                 //更新開始
425                 this.tweetTaskManager.startTask(timerID, period * 1000L);
426
427                 //タブにテーブルを追加
428                 table.addTableToTab();
429                 //タブリストに追加
430                 this.tweetTabbedTableList.add(table);
431                 //searchTable.updateTweetTable();
432                 //フォーカスを新しいタブに移す
433                 this.actionRequestForusToLastTab();
434             } catch (TweetTaskException ex) {
435                 Logger.getLogger(TweetMainAction.class.getName()).log(Level.SEVERE, null, ex);
436             }
437         }
438
439         //フォント情報を更新
440         this.updateFontInformationToComponent();
441         //テーブルの高さをすべて更新
442         this.updateTableHeight( this.getTableElementHeight() );
443     }
444
445     /**
446      * mentionタブを追加する
447      * @param period 情報更新間隔[sec]
448      */
449     public void actionAddMentionTab(int period) {
450         TimerID timerID = TimerID.getInstance();
451         String id = TimerID.createMentionID();
452         try {
453             //既にIDが存在していたらここで例外発生
454             timerID.addID(id);
455             //検索結果を表示するタブを生成
456             actionAddTab(id, period, new TweetMentionGetter(tweetManager),
457                     TweetMainAction.TAB_MENTION_STRING);
458         } catch (ExistTimerIDException ex) {
459             JOptionPane.showMessageDialog(null, "そのタブは既に存在しています",
460                     "Error", JOptionPane.ERROR_MESSAGE);
461         }
462     }
463
464     /**
465      * お気に入りタブを追加
466      * @param screenName nullで自分自身を取得,指定するとscreenNameのFav取得
467      */
468     public void actionAddFavoriteTab(String screenName) {
469         TimerID timerID = TimerID.getInstance();
470         String id = TimerID.createFavoriteID(screenName);
471         try {
472             //既にIDが存在していたらここで例外発生
473             timerID.addID(id);
474             String favTitle;
475             if( screenName == null ) {
476                 favTitle = "お気に入り";
477             }else {
478                 favTitle = screenName + "のお気に入り";
479             }
480             //検索結果を表示するタブを生成
481             actionAddTab(id, Integer.MAX_VALUE, new TweetFavoriteGetter(tweetManager, screenName),
482                     favTitle);
483         } catch (ExistTimerIDException ex) {
484             JOptionPane.showMessageDialog(null, "そのタブは既に存在しています",
485                     "Error", JOptionPane.ERROR_MESSAGE);
486         }
487     }
488
489     /**
490      * timelineタブを追加する
491      * @param period[sec]
492      */
493     public void actionAddTimelineTab(int period) {
494         TimerID timerID = TimerID.getInstance();
495         String id = TimerID.createTimelineID();
496         try {
497             //既にIDが存在していたらここで例外発生
498             timerID.addID(id);
499             //検索結果を表示するタブを生成
500             actionAddTab(id, period, new TweetTimelineGetter(tweetManager),
501                     TweetMainAction.TAB_TIMELINE_STRING);
502         } catch (ExistTimerIDException ex) {
503             JOptionPane.showMessageDialog(null, "そのタブは既に存在しています",
504                     "Error", JOptionPane.ERROR_MESSAGE);
505         }
506     }
507
508     /**
509      * ダイレクトメッセージタブを追加する
510      * @param period 更新間隔[sec]
511      */
512     public void actionAddDirectMessageTab(int period) {
513         TimerID timerID = TimerID.getInstance();
514         String id = TimerID.createDirectMessageID();
515         try {
516             //既にIDが存在していたらここで例外発生
517             timerID.addID(id);
518             //検索結果を表示するタブを生成
519             actionAddTab(id, period, new TweetDirectMessageGetter(tweetManager),
520                     TweetMainAction.TAB_DIRECT_MESSAGE_STRING);
521         } catch (ExistTimerIDException ex) {
522             JOptionPane.showMessageDialog(null, "そのタブは既に存在しています",
523                     "Error", JOptionPane.ERROR_MESSAGE);
524         }
525     }
526
527     /**
528      * SendDMタブを追加する
529      * @param period
530      */
531     public void actionAddSendDirectMessageTab(int period) {
532         TimerID timerID = TimerID.getInstance();
533         String id = TimerID.createSendDirectMessageID();
534         try {
535             //既にIDが存在していたらここで例外発生
536             timerID.addID(id);
537             //検索結果を表示するタブを生成
538             actionAddTab(id, period, new TweetSendDirectMessageGetter(tweetManager),
539                     TweetMainAction.TAB_SEND_DIRECT_MESSAGE_STRING);
540         } catch (ExistTimerIDException ex) {
541             JOptionPane.showMessageDialog(null, "そのタブは既に存在しています",
542                     "Error", JOptionPane.ERROR_MESSAGE);
543         }
544     }
545
546
547     /**
548      * ツイート検索結果を表示するタブを新しく追加
549      * @param searchWord
550      * @param period 更新周期[sec] 0以下の場合は更新しない
551      */
552     public void actionAddNewSearchResultTab(String searchWord, int period) {
553         TimerID timerID = TimerID.getInstance();
554         String id = TimerID.createSearchTimerID(searchWord);
555         try {
556             //既にIDが存在していたらここで例外発生
557             timerID.addID(id);
558             //検索結果を表示するタブを生成
559             actionAddTab(id, period, new TweetSearchResultGetter(this.tweetManager, searchWord), searchWord);
560         } catch (ExistTimerIDException ex) {
561             JOptionPane.showMessageDialog(null, "そのタブは既に存在しています",
562                     "Error", JOptionPane.ERROR_MESSAGE);
563         }
564     }
565
566     /**
567      * 指定したユーザの発言を表示
568      * @param username タブのタイトルにつけるユーザ名
569      * @param userID ユーザID
570      * @param period 更新周期[sec]
571      */
572     public void actionAddUserTimelineTab(String username, int userID, int period) {
573         TimerID timerID = TimerID.getInstance();
574         String id = TimerID.createUserTimelineID(userID);
575         try {
576             //既にIDが存在していたらここで例外発生
577             timerID.addID(id);
578             //検索結果を表示するタブを生成
579             actionAddTab(id, period, new TweetUserTimelineGetter(tweetManager, userID),
580                     username + "の発言");
581         } catch (ExistTimerIDException ex) {
582             JOptionPane.showMessageDialog(null, "そのタブは既に存在しています",
583                     "Error", JOptionPane.ERROR_MESSAGE);
584         }
585     }
586
587     /**
588      * タイムラインタブが存在しているか
589      * @return
590      */
591     public boolean isExistTimelineTab() {
592         TimerID timerID = TimerID.getInstance();
593         String id = TimerID.createTimelineID();
594         return timerID.contains(id);
595     }
596
597     /**
598      * Mentionタブが存在するか
599      * @return
600      */
601     public boolean isExistMentionTab() {
602         TimerID timerID = TimerID.getInstance();
603         String id = TimerID.createMentionID();
604         return timerID.contains(id);
605     }
606
607     /**
608      * DMタブが存在するか
609      * @return
610      */
611     public boolean isExistDirectMessageTab() {
612         TimerID timerID = TimerID.getInstance();
613         String id = TimerID.createDirectMessageID();
614         return timerID.contains(id);
615     }
616
617     /**
618      * 送信済みDMタブが存在するか
619      * @return
620      */
621     public boolean isExistSendDirectMessageTab() {
622         TimerID timerID = TimerID.getInstance();
623         String id = TimerID.createSendDirectMessageID();
624         return timerID.contains(id);
625     }
626
627     /**
628      * 基本設定ダイアログを開く
629      */
630     public void actionBasicSettingDialog() {
631         // ダイレクトメッセージ送信用ダイアログを開く
632         Point loc = getConfigurationDialog().getLocation();
633         loc.translate(20, 20);
634         ConfigurationDialog dialog = getConfigurationDialog();
635         dialog.setLocation(loc);
636         dialog.setVisible(true);
637     }
638
639     /**
640      * reply設定
641      */
642     public void actionSetReplyStatusToTweetBoxPane() {
643         //選択した部分
644         this.setReplyStatus( currentStatus );
645
646         Status s = this.getCurrentStatus();
647         if( s.isRetweet() ) {
648             s = s.getRetweetedStatus();
649         }
650         // コメントしたユーザ名
651         String username = s.getUser().getScreenName();
652         this.tweetBoxPane.setText("@" + username + " ");
653
654         //情報表示
655         this.information(username + "さんに返信");
656     }
657
658     /**
659      * reply All設定
660      */
661     public void actionSetReplyAllStatusToTweetBoxPane() {
662         //選択し多分
663         this.setReplyStatus(null);
664
665         Status s = this.getCurrentStatus();
666         if( s.isRetweet() ) {
667             s = s.getRetweetedStatus();
668         }
669         // コメントしたユーザ名
670         String username = s.getUser().getScreenName();
671         this.tweetBoxPane.setText("@" + username + " ");
672
673         //情報表示
674         this.information(username + "さんに返信");
675     }
676
677     /**
678      * 引用Tweet
679      */
680     public void actionSetQuoteStatusToTweetBoxPane() {
681         //選択した部分
682         this.setReplyStatus( currentStatus );
683         Status s = this.getCurrentStatus();
684         if( s.isRetweet() ) {
685             s = s.getRetweetedStatus();
686         }
687         // コメントしたユーザ名
688         String username = s.getUser().getScreenName();
689         // コメント
690         String message = s.getText();
691         this.tweetBoxPane.setText("QT @" + username + ": " + message);
692
693         //情報表示
694         this.information(username + "さんのメッセージを引用ツイート");
695     }
696
697     /**
698      * 選択したtweetを非公式RT
699      */
700     public void actionCopySelectedStatusToTweetBoxPane() {
701         Status s = this.getCurrentStatus();
702         if( s.isRetweet() ) {
703             s = s.getRetweetedStatus();
704         }
705         // コメントしたユーザ名
706         String username = s.getUser().getScreenName();
707         // コメント
708         String message = s.getText();
709         this.tweetBoxPane.setText("RT @" + username + ": " + message);
710     }
711
712     /**
713      * 詳細情報表示ボタンを押した時の動作
714      *
715      * @param e
716      */
717     public void actionDetailInfoButton(ActionEvent e) {
718         if (detailInfoPanel.isVisible()) {
719             detailInfoPanel.setVisible(false);
720         } else {
721             detailInfoPanel.setVisible(true);
722         }
723     }
724
725     /**
726      * 詳細情報ボタンが表示されているか
727      * @return
728      */
729     public boolean isDetailInfoPanelVisible() {
730         return detailInfoPanel.isVisible();
731     }
732
733     /**
734      * 書き込みメッセージボックスの表示ONOFFボタンを押した時の動作
735      * @param e
736      */
737     public void actionShowTweetboxButton(ActionEvent e) {
738         if( this.tweetBoxRegionPane.isVisible() ) {
739             this.tweetBoxRegionPane.setVisible(false);
740         }else {
741             this.tweetBoxRegionPane.setVisible(true);
742         }
743     }
744
745     /**
746      * 書き込みメッセージボックス領域が表示されているか
747      */
748     public boolean isShowTweetBoxVisible() {
749         return this.tweetBoxRegionPane.isVisible();
750     }
751
752     /**
753      * 選択しているタブを削除
754      */
755     public void actionRemoveFocusedTabbedTable() {
756         int selected = this.tweetMainTab.getSelectedIndex();
757         actionRemoveTabbedTable(selected);
758     }
759
760     /**
761      * 指定したIDのタブを削除
762      * @param timerID
763      */
764     public void actionRemoveTabbedTable(String timerID) {
765         int deleteTabIndex = -1;
766         
767         for(int i=0 ; i < tweetTabbedTableList.size(); i++ ) {
768             TweetTabbedTable table = tweetTabbedTableList.get(i);
769             if( table.getTimerID().equals(timerID) ) {
770                 //消したいタブが見つかった
771                 deleteTabIndex = i;
772                 break;
773             }
774         }
775
776         if( deleteTabIndex >= 0 ) {
777             int selected = this.tweetTabbedTableList.get(deleteTabIndex).getTabSetNum();
778             //タブを削除
779             this.tweetMainTab.remove(selected);
780             //削除
781             this.tweetTabbedTableList.remove(deleteTabIndex);
782             //自動更新しているタブを削除
783             this.tweetTaskManager.shutdownTask( timerID );
784             //ID削除
785             TimerID idManager = TimerID.getInstance();
786             idManager.removeID(timerID);
787
788             //checkboxの状態更新
789             this.updateCheckboxInformation();
790         }
791     }
792
793     /**
794      * 指定した場所にあるタブを削除
795      * @param removeTabIndex
796      */
797     public void actionRemoveTabbedTable(int removeTabIndex) {
798         int selected = removeTabIndex;
799         //タブの何番目に消したいテーブルがあるのかと,tweetTabbedTableListの何番目に消したいテーブルがあるのかは違う
800         //これを探してくる必要がある
801
802         //選択したタブのテーブルを取得
803         int deleteTabIndex = -1;
804         for(int i=0 ; i < tweetTabbedTableList.size(); i++ ) {
805             TweetTabbedTable table = tweetTabbedTableList.get(i);
806             if( selected == table.getTabSetNum() ) {
807                 //消したいタブが見つかった
808                 deleteTabIndex = i;
809                 break;
810             }
811         }
812
813         if( deleteTabIndex >= 0 ) {
814             //タブを削除
815             this.tweetMainTab.remove(selected);
816             //タブのタイマーID
817             String timerID = this.tweetTabbedTableList.get(deleteTabIndex).getTimerID();
818             //削除
819             this.tweetTabbedTableList.remove(deleteTabIndex);
820             //自動更新しているタブを削除
821             this.tweetTaskManager.shutdownTask( timerID );
822             //ID削除
823             TimerID idManager = TimerID.getInstance();
824             idManager.removeID(timerID);
825
826             //checkboxの状態更新
827             this.updateCheckboxInformation();
828         }
829     }
830
831     /**
832      * 終了ボタンを押した時の動作
833      *
834      * @param e
835      */
836     public void actionExitButton(ActionEvent e) {
837         System.exit(0);
838     }
839
840     /**
841      * 選択した発言をブラウザで開く
842      */
843     public void actionOpenStatusURL() {
844         try {
845             // ユーザ名
846             String userName = this.getCurrentStatus().getUser().getScreenName();
847             // 発言のstatusID
848             long statusID = this.getCurrentStatus().getId();
849             Desktop.getDesktop().browse(
850                     new URI(TWITTER_URL + userName + "/statuses/" + statusID));
851         } catch (Exception ex) {
852             ex.printStackTrace();
853             JOptionPane.showMessageDialog(null, "エラーによりブラウザを起動できませんでした.",
854                     "Error", JOptionPane.ERROR_MESSAGE);
855         }
856     }
857
858     /**
859      * 選択したユーザのFavを開く
860      */
861     public void actionOpenUserFav() {
862         try {
863             Status s = this.getCurrentStatus();
864             if( s.isRetweet() ) {
865                 s = s.getRetweetedStatus();
866             }
867             String userName = s.getUser().getScreenName();
868             this.actionAddFavoriteTab(userName);
869         } catch (Exception ex) {
870             ex.printStackTrace();
871         }
872     }
873
874     /**
875      * 選択したユーザ情報をブラウザで開く
876      */
877     public void actionOpenUserURL() {
878         try {
879             Status s = this.getCurrentStatus();
880             if( s.isRetweet() ) {
881                 s = s.getRetweetedStatus();
882             }
883             String userName = s.getUser().getScreenName();
884             Desktop.getDesktop().browse(new URI(TWITTER_URL + userName));
885         } catch (Exception ex) {
886             ex.printStackTrace();
887             JOptionPane.showMessageDialog(null, "エラーによりブラウザを起動できませんでした.",
888                     "Error", JOptionPane.ERROR_MESSAGE);
889         }
890     }
891
892     /**
893      * Tweet取得時間情報を更新
894      */
895     public void actionRefreshTime() {
896         //タブに存在する時間情報を更新
897         for(TweetTabbedTable t : this.tweetTabbedTableList ) {
898             TweetTableModel model = t.getModel();
899             if( model != null ) {
900                 model.refreshTime();
901             }
902         }
903     }
904
905     /**
906      * TweetMessageBox内にある#ハッシュタグ の部分をa hrefリンクに変換
907      *
908      * @param message
909      */
910     public String actionReplaceTweetMessageBoxHashTab(String message) {
911         // #で始まる情報
912         Pattern userPtn = Pattern.compile("#[0-9A-Z_]+",
913                 Pattern.CASE_INSENSITIVE);
914         Matcher matcher = userPtn.matcher(message);
915         
916         // #で始まる情報一覧を抜き出す
917         Set<String> findList = new TreeSet<String>();
918         while (matcher.find()) {
919             findList.add(matcher.group(0));
920         }
921         // 指定した情報をすべてリンクへ変更
922         for (String f : findList) {
923             try {
924                 message = message.replaceAll(
925                           f + "$|"
926                         + f + "\\s"
927                         ,
928                         "<a href=\""
929                         + SEARCH_TWITTER_URL + SEARCH_QUERY
930                         + URLEncoder.encode(f, DEFAULT_CHARACTER_ENCODING)
931                         + "\">" + "$0</a>");
932             } catch (UnsupportedEncodingException e) {
933                 e.printStackTrace();
934             }
935         }
936         return message;
937     }
938
939     /**
940      * TweetMessageBox内にあるリンクをa hrefリンクに変換
941      *
942      * @param message
943      */
944     public String actionReplaceTweetMessageBoxURLLink(String message) {
945         Matcher matcher = convURLLinkPtn.matcher(message);
946         return matcher.replaceAll("<a href=\"$0\">$0</a>");
947     }
948
949     /**
950      * @ユーザ名の部分をa hrefリンクに変換
951      * @param message
952      */
953     public String actionReplaceTweetMessageBoxUserInfo(String message) {
954         // @で始まる情報
955         Pattern userPtn = Pattern.compile("@[0-9A-Z_]+",
956                 Pattern.CASE_INSENSITIVE);
957         Matcher matcher = userPtn.matcher(message);
958         // @で始まるユーザ名一覧を抜き出す
959         Set<String> findList = new TreeSet<String>();
960         while (matcher.find()) {
961             findList.add(matcher.group(0));
962         }
963         // 指定したユーザ名をすべてリンクへ変更
964         for (String f : findList) {
965             message = message.replaceAll(f, "<a href=\"" + TWITTER_URL
966                     + f.substring(1) + "\">" + f + "</a>");
967         }
968         return message;
969     }
970
971     /**
972      * まだ見ていないdirectMessage数を0にする
973      */
974     public void actionResetUncheckedDirectMessageCount() {
975         uncheckedDirectMessageCount = 0;
976         tweetMainTab.setTitleAt(2, TAB_DIRECT_MESSAGE_STRING);
977     }
978
979     /**
980      * まだ見ていないmention数を0にする
981      */
982     public void actionResetUncheckedMentionTweetCount() {
983         uncheckedMentionTweetCount = 0;
984         tweetMainTab.setTitleAt(1, TAB_MENTION_STRING);
985     }
986
987     /**
988      * まだ見ていないtweet数を0にする
989      */
990     public void actionResetUncheckedTimelineTweetCount() {
991         uncheckedTimelineTweetCount = 0;
992         tweetMainTab.setTitleAt(0, TAB_TIMELINE_STRING);
993     }
994
995     /**
996      * 選択したユーザの発言を開く
997      */
998     public void actionSelectedUserTimeline() {
999         Status status = null;
1000         if( this.getCurrentStatus().isRetweet() ) {
1001             status = this.getCurrentStatus().getRetweetedStatus();
1002         }else {
1003             status = this.getCurrentStatus();
1004         }
1005         String username = status.getUser().getScreenName();
1006         int userID = status.getUser().getId();
1007         //ユーザ
1008         actionAddUserTimelineTab(username, userID, this.getGetTimelinePeriod());
1009     }
1010
1011     /**
1012      * 選択しているツイートをお気に入りに追加
1013      */
1014     public void actionCreateFavorite() {
1015         Status status = null;
1016         if( this.getCurrentStatus().isRetweet() ) {
1017             status = this.getCurrentStatus().getRetweetedStatus();
1018         }else {
1019             status = this.getCurrentStatus();
1020         }
1021         // 選択しているtweetのstatus id
1022         long statusID = status.getId();
1023         // コメントしたユーザ名
1024         String username = status.getUser().getScreenName();
1025         // コメント
1026         String message = status.getText();
1027         // 発言が長すぎる場合,後半をカット
1028         if (message.length() > 30) {
1029             message = message.substring(0, 30) + " ...(以下略)";
1030         }
1031         // Retweetしていいかどうかの確認
1032         int ret = JOptionPane.showConfirmDialog(mainFrame, username + " さんの発言:"
1033                 + message + "\nをお気に入りに追加しますか?", "Favの確認",
1034                 JOptionPane.YES_NO_OPTION);
1035         if (ret == JOptionPane.YES_OPTION) {
1036             try {
1037                 // Retweetを行う
1038                 this.tweetManager.createFavorite(statusID);
1039             } catch (TwitterException e) {
1040                 JOptionPane.showMessageDialog(null, "エラーによりお気に入りに追加できませんでした.",
1041                         "Fav Error", JOptionPane.ERROR_MESSAGE);
1042             }
1043         }
1044     }
1045
1046     /**
1047      * 選択しているツイートをお気に入りから外す
1048      */
1049     public void actionDestroyFavorite() {
1050         Status status = null;
1051         if( this.getCurrentStatus().isRetweet() ) {
1052             status = this.getCurrentStatus().getRetweetedStatus();
1053         }else {
1054             status = this.getCurrentStatus();
1055         }
1056         // 選択しているtweetのstatus id
1057         long statusID = status.getId();
1058         // コメントしたユーザ名
1059         String username = status.getUser().getScreenName();
1060         // コメント
1061         String message = status.getText();
1062         // 発言が長すぎる場合,後半をカット
1063         if (message.length() > 30) {
1064             message = message.substring(0, 30) + " ...(以下略)";
1065         }
1066         // Retweetしていいかどうかの確認
1067         int ret = JOptionPane.showConfirmDialog(mainFrame, username + " さんの発言:"
1068                 + message + "\nをお気に入りから削除しますか?", "Favの確認",
1069                 JOptionPane.YES_NO_OPTION);
1070         if (ret == JOptionPane.YES_OPTION) {
1071             try {
1072                 // Retweetを行う
1073                 this.tweetManager.destroyFavorite(statusID);
1074             } catch (TwitterException e) {
1075                 JOptionPane.showMessageDialog(null, "エラーによりお気に入りから削除できませんでした.",
1076                         "Fav Error", JOptionPane.ERROR_MESSAGE);
1077             }
1078         }
1079     }
1080
1081     /**
1082      * 現在選択しているステータスを公式Retweet
1083      */
1084     public void actionRetweet() {
1085         Status status = null;
1086         if( this.getCurrentStatus().isRetweet() ) {
1087             status = this.getCurrentStatus().getRetweetedStatus();
1088         }else {
1089             status = this.getCurrentStatus();
1090         }
1091
1092         // 選択しているtweetのstatus id
1093         long statusID = status.getId();
1094         // コメントしたユーザ名
1095         String username = status.getUser().getScreenName();
1096         // コメント
1097         String message = status.getText();
1098         // 発言が長すぎる場合,後半をカット
1099         if (message.length() > 30) {
1100             message = message.substring(0, 30) + " ...(以下略)";
1101         }
1102         // Retweetしていいかどうかの確認
1103         int ret = JOptionPane.showConfirmDialog(mainFrame, username + " さんの発言:"
1104                 + message + "\nをRetweetしますか?", "Retweetの確認",
1105                 JOptionPane.YES_NO_OPTION);
1106         if (ret == JOptionPane.YES_OPTION) {
1107             try {
1108                 // Retweetを行う
1109                 this.tweetManager.retweet(statusID);
1110             } catch (TwitterException e) {
1111                 JOptionPane.showMessageDialog(null, "エラーによりRetweetできませんでした.",
1112                         "Retweet Error", JOptionPane.ERROR_MESSAGE);
1113             }
1114         }
1115     }
1116
1117     /**
1118      * テーブルの高さを更新
1119      *
1120      * @param height
1121      */
1122     public void updateTableHeight(int height) {
1123         this.tableElementHeight = height;
1124         for( TweetTabbedTable t : this.tweetTabbedTableList) {
1125             t.getTable().setRowHeight(tableElementHeight);
1126         }
1127     }
1128
1129     /**
1130      * ダイレクトメッセージダイアログ表示
1131      */
1132     public void actionShowDirectMessageDialog() {
1133         // ダイレクトメッセージ送信用ダイアログを開く
1134         Point loc = getDirectMessageDialog().getLocation();
1135         //loc.translate(20, 20);
1136         DirectMessageDialog dialog = getDirectMessageDialog();
1137         //dialog.setLocation(loc);
1138         dialog.setLocationRelativeTo(null);
1139         dialog.setVisible(true);
1140         dialog.setUserInformation(this.selectedUsername,
1141                 this.selectedUserImageURL, this.tweetManager);
1142     }
1143
1144     /**
1145      * Aboutダイアログを表示
1146      */
1147     public void actionShowAboutDialog() {
1148         Point loc = getDirectMessageDialog().getLocation();
1149         //loc.translate(20, 20);
1150         AboutDialog dialog = getAboutDialog();
1151         dialog.setLocationRelativeTo(null);
1152         //dialog.setLocation(loc);
1153         dialog.setVisible(true);
1154     }
1155
1156     /**
1157      * アカウントダイアログを表示
1158      */
1159     public void actionShowAccountDialog() {
1160         Point loc = getDirectMessageDialog().getLocation();
1161         //loc.translate(20, 20);
1162         AccountDialog dialog = getAccountDialog();
1163         dialog.setLocationRelativeTo(null);
1164        // dialog.setLocation(loc);
1165         dialog.setVisible(true);
1166     }
1167
1168     /**
1169      * Twitter全体からキーワード検索ダイアログを表示
1170      */
1171     public void actionShowKeywordSearchDialog() {
1172         Point loc = getDirectMessageDialog().getLocation();
1173         KeywordSearchDialog dialog = getKeywordSearchDialog();
1174         dialog.setSearchWord("");
1175         dialog.setLocationRelativeTo(null);
1176         dialog.setVisible(true);
1177     }
1178
1179     /**
1180      * Twitter全体からキーワード検索ダイアログを表示
1181      * @param searchWord searchwordボックスに予め設定するワード
1182      */
1183     public void actionShowKeywordSearchDialog(String searchWord) {
1184         Point loc = getDirectMessageDialog().getLocation();
1185         KeywordSearchDialog dialog = getKeywordSearchDialog();
1186         dialog.setSearchWord(searchWord);
1187         dialog.setLocationRelativeTo(null);
1188         dialog.setVisible(true);
1189     }
1190
1191     /**
1192      * ハッシュタグ検索ダイアログを表示
1193      */
1194     public void actionShowHashtagSearchDialog() {
1195         Point loc = getDirectMessageDialog().getLocation();
1196         HashtagSearchDialog dialog = getHashtagSearchDialog();
1197         dialog.setLocationRelativeTo(null);
1198         dialog.setVisible(true);
1199     }
1200
1201     /**
1202      * リストダイアログを表示
1203      * @param listUserName リストを保持しているユーザの名前
1204      * @param selection CREATED: 指定したユーザが作成したリスト
1205      *  SUBSCRIPTION: 指定したユーザがフォローしているリスト
1206      *  MEMBERSHIPS:  指定したユーザが追加されているリスト
1207      */
1208     public void actionShowUserListDialog(String listUserName, ListGetterSelection selection) {
1209         UserListDialog dialog = getUserListDialog( listUserName, selection );
1210         Point loc = dialog.getLocation();
1211         dialog.setLocationRelativeTo(null);
1212         dialog.setVisible(true);
1213     }
1214
1215     /**
1216      * tweetBoxPaneに書かれた文字をつぶやく
1217      */
1218     public void actionTweet() {
1219         if( this.replyStatus != null ) {
1220             tweetManager.replyTweet(tweetBoxPane.getText(), this.replyStatus.getId());
1221         }else {
1222             tweetManager.tweet(tweetBoxPane.getText());
1223         }
1224         //ツイートした旨を表示
1225         this.information("メッセージをつぶやきました. 発言:" + tweetBoxPane.getText());
1226         
1227         tweetBoxPane.setText(""); // テキストをクリア
1228         
1229     }
1230
1231     /**
1232      * Tweet情報を更新
1233      *
1234      * @param e
1235      */
1236     public void actionUpdateButton(java.awt.event.ActionEvent e) {
1237         try {
1238             //タブ上に存在するテーブルの情報を更新
1239             for(TweetTabbedTable t : this.tweetTabbedTableList ) {
1240                 String timerID = t.getTimerID();
1241                 this.tweetTaskManager.resetTask(timerID, true);
1242             }
1243
1244             // API残り回数を取得
1245             int remainingHits = tweetManager.getRateLimitStatus().getRemainingHits();
1246             // 取得したコメント数をステータスバーに表示
1247             information("新しいツイートを取得しました. (APIリクエスト残数は" + remainingHits
1248                     + "回です)");
1249         } catch (Exception e1) {
1250             e1.printStackTrace();
1251         }
1252     }
1253
1254     /**
1255      * 新しく追加したタブにフォーカスを移す
1256      */
1257     public void actionRequestForusToLastTab() {
1258         int lasttab = this.tweetMainTab.getTabCount() - 1;
1259         if( lasttab >= 0 ) {
1260             this.tweetMainTab.setSelectedIndex(lasttab);
1261         }
1262     }
1263
1264     /**
1265      * 指定した番号のタブにフォーカスを移す
1266      * @param index
1267      */
1268     public void actionRequestFocusToTab(int index) {
1269         if( index >= 0 ) {
1270             this.tweetMainTab.setSelectedIndex(index);
1271         }
1272     }
1273
1274     /**
1275      * 選択しているタブにあるテーブル情報だけを更新
1276      */
1277     public void actionFocusedTableUpdate() {
1278         int selected = this.tweetMainTab.getSelectedIndex();
1279         try {
1280             if( selected >= 0 ) {
1281                 //タブ上に存在するテーブルの情報を更新
1282                 TweetTabbedTable t = this.tweetTabbedTableList.get(selected);
1283                 String timerID = t.getTimerID();
1284                 this.tweetTaskManager.resetTask(timerID, true);
1285                 // API残り回数を取得
1286                 int remainingHits = tweetManager.getRateLimitStatus().getRemainingHits();
1287                 // 取得したコメント数をステータスバーに表示
1288                 information(t.getTitle() + "タブのツイートを" + t.getUncheckedTweet()
1289                         + "件取得しました. (APIリクエスト残数は" + remainingHits
1290                         + "回です)");
1291             }
1292         } catch (Exception e1) {
1293             e1.printStackTrace();
1294         }
1295     }
1296
1297     /**
1298      * つぶやける残り文字数の更新
1299      *
1300      * @param e
1301      */
1302     public void actionUpdateTweetMessageCount() {
1303         int len = 140 - (tweetBoxPane.getText().length());
1304         if (len < 0) {
1305             len = 0;
1306         }
1307         tweetMessageCountLabel.setText(len + "");
1308
1309         //残りつぶやき数140の場合,reply状態も解除する
1310         if( len == 140 ) {
1311             this.setReplyStatus(null);
1312         }
1313     }
1314
1315     /**
1316      * 基本設定用ダイアログを取得
1317      *
1318      * @return
1319      */
1320     public ConfigurationDialog getConfigurationDialog() {
1321         if (configurationDialog == null) {
1322             configurationDialog = new ConfigurationDialog(mainFrame, true, this);
1323         }
1324         return configurationDialog;
1325     }
1326
1327     /**
1328      * リストダイアログを取得
1329      * @param listUserName リストを保持しているユーザの名前
1330      * @param selection
1331      * @return
1332      */
1333     public UserListDialog getUserListDialog(String listUserName, ListGetterSelection selection) {
1334         UserListGetter getter = null;
1335         switch( selection ) {
1336             case CREATED:
1337                 getter = new UserListSpecificUserListsGetter(tweetManager);
1338                 break;
1339             case MEMBERSHIPS:
1340                 getter = new UserListMembershipsGetter(tweetManager);
1341                 break;
1342             case SUBSCRIPTION: /* fall through */
1343             default:
1344                 getter = new UserListSubscriptionGetter(tweetManager);
1345                 break;
1346         }
1347         userListDialog = new UserListDialog(mainFrame, true, this, getter, listUserName);
1348         return userListDialog;
1349     }
1350
1351     /**
1352      * 自身のスクリーン名を取得
1353      * @return
1354      */
1355     public String getScreenName() {
1356         return tweetManager.getScreenName();
1357     }
1358
1359     /**
1360      * twitter全体からキーワード検索ダイアログを表示
1361      * @return
1362      */
1363     public KeywordSearchDialog getKeywordSearchDialog() {
1364         if( keywordSearchDialog == null ) {
1365             keywordSearchDialog = new KeywordSearchDialog(mainFrame, true, this);
1366         }
1367         return keywordSearchDialog;
1368     }
1369
1370     /**
1371      * hashtag検索ダイアログ
1372      * @return
1373      */
1374     public HashtagSearchDialog getHashtagSearchDialog() {
1375         if( hashtagSearchDialog == null ) {
1376             hashtagSearchDialog = new HashtagSearchDialog(mainFrame, true, this, tweetManager);
1377         }
1378         return hashtagSearchDialog;
1379     }
1380
1381     /**
1382      * アカウント情報設定ダイアログを取得
1383      * @return
1384      */
1385     public AccountDialog getAccountDialog() {
1386         if( accountDialog == null ) {
1387             accountDialog = new AccountDialog(mainFrame, true, tweetManager, this);
1388         }
1389         return accountDialog;
1390     }
1391
1392     /**
1393      * ダイレクトメッセージ送信用ダイアログを取得
1394      *
1395      * @return
1396      */
1397     public DirectMessageDialog getDirectMessageDialog() {
1398         if (directMessageDialog == null) {
1399             directMessageDialog = new DirectMessageDialog(mainFrame);
1400             directMessageDialog.setTitle("ダイレクトメッセージを送信");
1401         }
1402         return directMessageDialog;
1403     }
1404
1405     /**
1406      * テーブルで選択したツイートを詳細情報としてセット
1407      * @param table
1408      */
1409     public void setDetailInformationFromTable(JTable table) {
1410         int sc = table.getSelectedRowCount();
1411         String infoMessage = "";
1412
1413         //選択している行が1行だけの場合,情報を表示する
1414         if (sc == 1 && table != null) {
1415             Status st = getTweetTableInformation(table, table.getModel());
1416             //RTの場合,もとの発言を表示
1417             if( st.isRetweet() ) {
1418                 st = st.getRetweetedStatus();
1419             }
1420             infoMessage = st.getText();
1421             //メッセージのHTMLエンコードを行う
1422             infoMessage = HTMLEncode.encode(infoMessage);
1423             // tweetMessageBox内のURLをhtmlリンクへ変換
1424             infoMessage = actionReplaceTweetMessageBoxURLLink(infoMessage);
1425             // @ユーザ情報をhtmlリンクへ変換
1426             infoMessage = actionReplaceTweetMessageBoxUserInfo(infoMessage);
1427             // #ハッシュタグ情報をhtmlリンクへ変換
1428             infoMessage = actionReplaceTweetMessageBoxHashTab(infoMessage);
1429             // 詳細情報にテーブルで選択した人のツイート情報を表示
1430             tweetMessageBox.setText(infoMessage);
1431             // user icon
1432             userImageLabel.setIcon(new ImageIcon(st.getUser().getProfileImageURL()));
1433             // user name and id
1434             userNameLabel.setText(st.getUser().getName()
1435                     + " / " + st.getUser().getScreenName());
1436             // update Time
1437             updateTimeLabel.setText(DateFormat.getInstance().format( st.getCreatedAt() ));
1438             // ユーザ自己紹介文
1439             userIntroBox.setText(st.getUser().getDescription());
1440             // フォローされている数
1441             followerLabel.setText(st.getUser().getFollowersCount()
1442                     + "");
1443             // フォローしている数
1444             followingLabel.setText(st.getUser().getFriendsCount()
1445                     + "");
1446             // 現在地
1447             locationLabel.setText(st.getUser().getLocation());
1448             // Web
1449             if (st.getUser().getURL() != null) {
1450                 userWebBox.setText("<a href=\""
1451                         + st.getUser().getURL() + "\">"
1452                         + st.getUser().getScreenName()
1453                         + "のWebを開く" + "</a>");
1454             } else {
1455                 userWebBox.setText("");
1456             }
1457             // client
1458             clientNameLabel.setText(" via " + st.getSource());
1459             // Update
1460             updateLabel.setText(st.getUser().getStatusesCount()
1461                     + "");
1462         }
1463     }
1464
1465     /**
1466      *
1467      * @return
1468      */
1469     public AboutDialog getAboutDialog() {
1470         if (aboutDialog == null) {
1471             aboutDialog = new AboutDialog(mainFrame, true);
1472         }
1473         return aboutDialog;
1474     }
1475
1476     /**
1477      * テーブルで選択した場所のTweet情報を取得
1478      *
1479      * @return
1480      */
1481     public Status getTweetTableInformation(JTable table, TableModel model) {
1482         int index = table.convertRowIndexToModel(table.getSelectedRow());
1483         Status status = null;
1484         if (model instanceof TweetTableModel) {
1485             status = ((TweetTableModel) model).getTweetStatus(index);
1486             // 現在選択したセルのユーザ名を保存しておく
1487             this.selectedUsername = status.getUser().getScreenName();
1488             // 現在選択したセルのユーザURLを保存しておく
1489             this.selectedUserImageURL = status.getUser().getProfileImageURL();
1490             // 選択したStatusを保存しておく
1491             this.setCurrentStatus(status);
1492         }
1493         return status;
1494     }
1495
1496     /**
1497      * ステータスバーに情報を表示する
1498      *
1499      * @param message
1500      */
1501     public void information(String message) {
1502         statusBarLabel.setText(message);
1503     }
1504
1505     /**
1506      * 設定ファイルを読み込む
1507      *
1508      * @throws IOException
1509      * @throws FileNotFoundException
1510      */
1511     public void loadProperties() throws FileNotFoundException, IOException {
1512         if (property == null) {
1513             this.property = new Properties();
1514         }
1515         property.load(new FileInputStream("./" + PROPERTIES_DIRECTORY + "/"
1516                 + BASIC_SETTING_FILENAME));
1517         // 設定読み込み
1518         String gtp = this.property.getProperty("getTimelinePeriod");
1519         String gmp = this.property.getProperty("getMentionPeriod");
1520         String gdmp = this.property.getProperty("getDirectMessagePeriod");
1521         String gsdmp = this.property.getProperty("getSendDirectMessagePeriod");
1522
1523         String ntrgb = this.property.getProperty("newTableColorRGB");
1524
1525         this.tlFontName = this.property.getProperty("tlFontName");
1526         this.detailFontName = this.property.getProperty("detailFontName");
1527
1528         String tfs = this.property.getProperty("tlFontSize");
1529         String dfs = this.property.getProperty("detailFontSize");
1530         String teh = this.property.getProperty("tableElementHeight");
1531
1532         //メインフレームの大きさ
1533         String mfw = this.property.getProperty("mainFrameWidth");
1534         String mfh = this.property.getProperty("mainFrameHeight");
1535
1536         try {
1537             this.newTableColor = new Color(Integer.parseInt(ntrgb));
1538             this.tlFontSize = Integer.parseInt(tfs);
1539             this.detailFontSize = Integer.parseInt(dfs);
1540             this.tableElementHeight = Integer.parseInt(teh);
1541             this.mainFrameWidth = Integer.parseInt(mfw);
1542             this.mainFrameHeight = Integer.parseInt(mfh);
1543
1544             //更新間隔
1545             this.getTimelinePeriod = Integer.parseInt(gtp);
1546             this.getMentionPeriod = Integer.parseInt(gmp);
1547             this.getDirectMessagePeriod = Integer.parseInt(gdmp);
1548             this.getSendDirectMessagePeriod = Integer.parseInt(gsdmp);
1549         } catch (NumberFormatException e) {
1550             e.printStackTrace();
1551         }
1552     }
1553
1554     /**
1555      * 設定ファイルを保存する
1556      *
1557      * @throws IOException
1558      */
1559     public void saveProperties() throws IOException {
1560         // 設定ファイルディレクトリを作成
1561         File logDir = new File("./" + PROPERTIES_DIRECTORY);
1562         if (!logDir.exists()) {
1563             // ディレクトリが存在しないので作成する
1564             if (logDir.mkdir() == false) {
1565                 throw new IOException(PROPERTIES_DIRECTORY
1566                         + "ディレクトリを作成できませんでした.");
1567             }
1568         }
1569         if (property == null) {
1570             this.property = new Properties();
1571         }
1572
1573         //情報更新間隔
1574         this.property.setProperty("getTimelinePeriod", this.getTimelinePeriod + "");
1575         this.property.setProperty("getMentionPeriod", this.getMentionPeriod + "");
1576         this.property.setProperty("getDirectMessagePeriod", this.getDirectMessagePeriod + "");
1577         this.property.setProperty("getSendDirectMessagePeriod", this.getSendDirectMessagePeriod + "");
1578
1579         this.property.setProperty("newTableColorRGB", newTableColor.getRGB()
1580                 + "");
1581         this.property.setProperty("tlFontName", this.tlFontName);
1582         this.property.setProperty("tlFontSize", this.tlFontSize + "");
1583         this.property.setProperty("detailFontName", this.detailFontName);
1584         this.property.setProperty("detailFontSize", this.detailFontSize + "");
1585         this.property.setProperty("tableElementHeight", this.tableElementHeight
1586                 + "");
1587
1588         //main frame size
1589         if( this.mainFrame.getExtendedState() == JFrame.NORMAL ) {
1590             this.mainFrameWidth = this.mainFrame.getWidth();
1591             this.mainFrameHeight = this.mainFrame.getHeight();
1592         }
1593         this.property.setProperty("mainFrameWidth", this.mainFrameWidth + "");
1594         this.property.setProperty("mainFrameHeight", this.mainFrameHeight + "");
1595         // プロパティのリストを保存
1596         property.store(new FileOutputStream("./" + PROPERTIES_DIRECTORY + "/"
1597                 + BASIC_SETTING_FILENAME), null);
1598     }
1599
1600     /**
1601      * newTableColorを取得します。
1602      *
1603      * @return newTableColor
1604      */
1605     public Color getNewTableColor() {
1606         return newTableColor;
1607     }
1608
1609     /**
1610      * newTableColorを設定します。
1611      *
1612      * @param newTableColor
1613      *            newTableColor
1614      */
1615     public void setNewTableColor(Color newTableColor) {
1616         this.newTableColor = newTableColor;
1617     }
1618
1619     /**
1620      * tlFontNameを取得します。
1621      *
1622      * @return tlFontName
1623      */
1624     public String getTlFontName() {
1625         return tlFontName;
1626     }
1627
1628     /**
1629      * tlFontNameを設定します。
1630      *
1631      * @param tlFontName
1632      *            tlFontName
1633      */
1634     public void setTlFontName(String tlFontName) {
1635         this.tlFontName = tlFontName;
1636     }
1637
1638     /**
1639      * tlFontSizeを取得します。
1640      *
1641      * @return tlFontSize
1642      */
1643     public int getTlFontSize() {
1644         return tlFontSize;
1645     }
1646
1647     /**
1648      * tlFontSizeを設定します。
1649      *
1650      * @param tlFontSize
1651      *            tlFontSize
1652      */
1653     public void setTlFontSize(int tlFontSize) {
1654         this.tlFontSize = tlFontSize;
1655     }
1656
1657     /**
1658      * detailFontNameを取得します。
1659      *
1660      * @return detailFontName
1661      */
1662     public String getDetailFontName() {
1663         return detailFontName;
1664     }
1665
1666     /**
1667      * detailFontNameを設定します。
1668      *
1669      * @param detailFontName
1670      *            detailFontName
1671      */
1672     public void setDetailFontName(String detailFontName) {
1673         this.detailFontName = detailFontName;
1674     }
1675
1676     /**
1677      * detailFontSizeを取得します。
1678      *
1679      * @return detailFontSize
1680      */
1681     public int getDetailFontSize() {
1682         return detailFontSize;
1683     }
1684
1685     /**
1686      * detailFontSizeを設定します。
1687      *
1688      * @param detailFontSize
1689      *            detailFontSize
1690      */
1691     public void setDetailFontSize(int detailFontSize) {
1692         this.detailFontSize = detailFontSize;
1693     }
1694
1695     /**
1696      * tableElementHeightを取得します。
1697      *
1698      * @return tableElementHeight
1699      */
1700     public int getTableElementHeight() {
1701         return tableElementHeight;
1702     }
1703
1704     /**
1705      * tableElementHeightを設定します。
1706      *
1707      * @param tableElementHeight
1708      *            tableElementHeight
1709      */
1710     public void setTableElementHeight(int tableElementHeight) {
1711         this.tableElementHeight = tableElementHeight;
1712     }
1713
1714     /**
1715      * @return the getTimelinePeriod
1716      */
1717     public int getGetTimelinePeriod() {
1718         return getTimelinePeriod;
1719     }
1720
1721     /**
1722      * @param getTimelinePeriod the getTimelinePeriod to set
1723      */
1724     public void setGetTimelinePeriod(int getTimelinePeriod) {
1725         this.getTimelinePeriod = getTimelinePeriod;
1726     }
1727
1728     /**
1729      * @return the getMentionPeriod
1730      */
1731     public int getGetMentionPeriod() {
1732         return getMentionPeriod;
1733     }
1734
1735     /**
1736      * @param getMentionPeriod the getMentionPeriod to set
1737      */
1738     public void setGetMentionPeriod(int getMentionPeriod) {
1739         this.getMentionPeriod = getMentionPeriod;
1740     }
1741
1742     /**
1743      * @return the getDirectMessagePeriod
1744      */
1745     public int getGetDirectMessagePeriod() {
1746         return getDirectMessagePeriod;
1747     }
1748
1749     /**
1750      * @param getDirectMessagePeriod the getDirectMessagePeriod to set
1751      */
1752     public void setGetDirectMessagePeriod(int getDirectMessagePeriod) {
1753         this.getDirectMessagePeriod = getDirectMessagePeriod;
1754     }
1755
1756     /**
1757      * @return the getSendDirectMessagePeriod
1758      */
1759     public int getGetSendDirectMessagePeriod() {
1760         return getSendDirectMessagePeriod;
1761     }
1762
1763     /**
1764      * @param getSendDirectMessagePeriod the getSendDirectMessagePeriod to set
1765      */
1766     public void setGetSendDirectMessagePeriod(int getSendDirectMessagePeriod) {
1767         this.getSendDirectMessagePeriod = getSendDirectMessagePeriod;
1768     }
1769
1770     /**
1771      * @return the currentStatus
1772      */
1773     public Status getCurrentStatus() {
1774         return currentStatus;
1775     }
1776
1777     /**
1778      * @param currentStatus the currentStatus to set
1779      */
1780     public void setCurrentStatus(Status currentStatus) {
1781         this.currentStatus = currentStatus;
1782     }
1783
1784     /**
1785      * 
1786      * @return
1787      */
1788     public Status getReplyStatus() {
1789         return replyStatus;
1790     }
1791
1792     /**
1793      *
1794      * @param status
1795      * @return
1796      */
1797     public void setReplyStatus(Status status) {
1798         this.replyStatus = status;
1799     }
1800 }