OSDN Git Service

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