OSDN Git Service

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