OSDN Git Service

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