OSDN Git Service

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