OSDN Git Service

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