OSDN Git Service

キーボードショートカットの追加
[tainavi/TinyBannavi.git] / TinyBannavi / src / tainavi / Viewer.java
index 34adfa4..a63189c 100644 (file)
@@ -20,14 +20,7 @@ import java.awt.Toolkit;
 import java.awt.TrayIcon;\r
 import java.awt.datatransfer.Clipboard;\r
 import java.awt.datatransfer.StringSelection;\r
-import java.awt.event.ActionEvent;\r
-import java.awt.event.ActionListener;\r
-import java.awt.event.ComponentAdapter;\r
-import java.awt.event.ComponentEvent;\r
-import java.awt.event.MouseAdapter;\r
-import java.awt.event.MouseEvent;\r
-import java.awt.event.WindowAdapter;\r
-import java.awt.event.WindowEvent;\r
+import java.awt.event.*;\r
 import java.io.File;\r
 import java.io.IOException;\r
 import java.io.UnsupportedEncodingException;\r
@@ -50,21 +43,11 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;\r
 \r
 import javax.imageio.ImageIO;\r
-import javax.swing.ImageIcon;\r
-import javax.swing.JComponent;\r
-import javax.swing.JFrame;\r
-import javax.swing.JLabel;\r
-import javax.swing.JMenuItem;\r
-import javax.swing.JOptionPane;\r
-import javax.swing.JPopupMenu;\r
-import javax.swing.SwingUtilities;\r
-import javax.swing.ToolTipManager;\r
-import javax.swing.UIManager;\r
+import javax.swing.*;\r
 import javax.swing.event.ChangeEvent;\r
 import javax.swing.event.ChangeListener;\r
 \r
 import tainavi.HDDRecorder.RecType;\r
-import tainavi.SearchKey.TargetId;\r
 import tainavi.TVProgram.ProgFlags;\r
 import tainavi.TVProgram.ProgGenre;\r
 import tainavi.TVProgram.ProgOption;\r
@@ -73,20 +56,16 @@ import tainavi.TVProgram.ProgSubtype;
 import tainavi.TVProgram.ProgType;\r
 import tainavi.VWMainWindow.MWinTab;\r
 import tainavi.VWUpdate.UpdateResult;\r
+import tainavi.plugintv.Syobocal;\r
 \r
 \r
 /**\r
  * メインな感じ\r
  */\r
-public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener {\r
+public class Viewer extends JFrame implements ChangeListener,TickTimerListener,HDDRecorderListener,CancelListener {\r
 \r
        private static final long serialVersionUID = 1L;\r
        \r
-       @Override\r
-       public void stateChanged(ChangeEvent e){\r
-               StdAppendMessage("イベント発生");\r
-       }\r
-\r
        \r
        /*\r
         * メソッド的な\r
@@ -134,7 +113,7 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
        private final TVProgramList progPlugins = new TVProgramList();                          // Web番組表プラグイン(テンプレート)\r
        private final TVProgramList tvprograms = new TVProgramList();                           // Web番組表プラグイン(実際に利用するもの)\r
        \r
-       private final VWTimer timer_now = new VWTimer();                                                        // 毎分00秒に起動して処理をキックするタイマー\r
+       private final TickTimer timer_now = new TickTimer();                                                    // 毎分00秒に起動して処理をキックするタイマー\r
        \r
        // 初期化的な\r
        private boolean logging = true;                                                                                 // ログ出力する\r
@@ -160,9 +139,13 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
        private static final int OPENING_WIAT = 500;                            // まあ起動時しか使わないんですけども\r
 \r
        private static final String MSGID = "[鯛ナビ] ";\r
-       private static final String ERRID = "[ERROR]"+MSGID;\r
+//     private static final String ERRID = "[ERROR]"+MSGID;\r
        private static final String DBGID = "[DEBUG]"+MSGID;\r
        \r
+       /*\r
+        * [メモ] enumのtoString()をoverrideすると、シリアライズの際とても困るのでやらないこと\r
+        */\r
+       \r
        /**\r
         * Web番組表のどれとどれを読めばいいのか\r
         */\r
@@ -200,8 +183,10 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
         * レコーダ情報のどれとどれを読めばいいのか\r
         */\r
        public static enum LoadRsvedFor {\r
-               SETTING         ( "設定情報のみ取得(future use.)" ),\r
-               RECORDED        ( "録画結果のみ取得" ),\r
+//             SETTING         ( "設定情報のみ取得(future use.)" ),\r
+               DETAILS         ( "予約一覧+録画詳細のみ取得" ),\r
+               RECORDED        ( "録画結果一覧のみ取得" ),\r
+               AUTORESERVE     ( "自動予約一覧のみ取得" ),\r
                ;\r
                \r
                private String name;\r
@@ -228,6 +213,7 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
         *  リスト形式のカラム定義\r
         * @deprecated しっぱいした 半年くらいしたら削除する\r
         */\r
+       @Deprecated\r
        public static enum ListedColumn {\r
                RSVMARK         ("予約",                      35),\r
                DUPMARK         ("重複",                      35),\r
@@ -278,6 +264,7 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
         *  本体予約一覧のカラム定義\r
         * @deprecated しっぱいした 半年くらいしたら削除する\r
         */\r
+       @Deprecated\r
        public static enum RsvedColumn {\r
                PATTERN         ("パタン",                   110),\r
                DUPMARK         ("重複",                      35),\r
@@ -417,6 +404,8 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                        toolBar.setBatchReservationEnabled(true);\r
                        // スナップショットを有効にする\r
                        toolBar.setSnapShotEnabled(true);\r
+                       // 新聞形式以外ではマッチ枠を無効にする\r
+                       toolBar.setBorderToggleEnabled(true, bounds.getShowReservedBackground());\r
                }\r
 \r
                @Override\r
@@ -427,17 +416,21 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                        toolBar.setBatchReservationEnabled(false);\r
                        // スナップショットを無効にする\r
                        toolBar.setSnapShotEnabled(false);\r
+                       // 新聞形式以外ではマッチ枠を無効にする\r
+                       toolBar.setBorderToggleEnabled(false, bounds.getShowReservedBackground());\r
                }\r
 \r
                @Override\r
                protected void showPopupForTraceProgram(\r
                                final JComponent comp,\r
                                final ProgDetailList tvd, final String keyword, final int threshold,\r
-                               final int x, final int y, final int h) {\r
+                               final int x, final int y) {\r
                        \r
-                       timer_now.pause();\r
-                       Viewer.this.showPopupForTraceProgram(comp, tvd, keyword, threshold, x, y, h);\r
-                       timer_now.start();\r
+                       timer_now.pause();      // 停止\r
+                       \r
+                       Viewer.this.showPopupForTraceProgram(comp, tvd, keyword, threshold, x, y, null);\r
+                       \r
+                       timer_now.start();      // 再開\r
                }\r
 \r
                @Override\r
@@ -564,7 +557,7 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                        // ジャンル別背景色を有効にする\r
                        toolBar.setPaperColorDialogEnabled(true);\r
                        // マッチ枠を有効にする\r
-                       toolBar.setBorderToggleEnabled(true);\r
+                       toolBar.setBorderToggleEnabled(true, bounds.getShowMatchedBorder());\r
                }\r
 \r
                @Override\r
@@ -576,18 +569,20 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                        // 新聞形式以外ではジャンル別背景色を無効にする\r
                        toolBar.setPaperColorDialogEnabled(false);\r
                        // 新聞形式以外ではマッチ枠を無効にする\r
-                       toolBar.setBorderToggleEnabled(false);\r
+                       toolBar.setBorderToggleEnabled(false, bounds.getShowMatchedBorder());\r
                }\r
 \r
                @Override\r
                protected void showPopupForTraceProgram(\r
                                final JComponent comp,\r
                                final ProgDetailList tvd, final String keyword, final int threshold,\r
-                               final int x, final int y, final int h) {\r
+                               final int x, final int y, final String clickedDateTime) {\r
                        \r
-                       timer_now.pause();\r
-                       Viewer.this.showPopupForTraceProgram(comp, tvd, keyword, threshold, x, y, h);\r
-                       timer_now.start();\r
+                       timer_now.pause();      // 停止\r
+                       \r
+                       Viewer.this.showPopupForTraceProgram(comp, tvd, keyword, threshold, x, y, clickedDateTime);\r
+                       \r
+                       timer_now.start();      // 再開\r
                }\r
 \r
                @Override\r
@@ -607,8 +602,6 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                protected void setSelectedTab(MWinTab tab) { mainWindow.setSelectedTab(tab); }\r
 \r
                @Override\r
-               protected String getSelectedRecorderOnToolbar() { return toolBar.getSelectedRecorder(); }\r
-               @Override\r
                protected boolean isFullScreen() { return toolBar.isFullScreen(); }\r
                @Override\r
                protected void setSelectedPagerIndex(int idx) {\r
@@ -695,17 +688,17 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                }\r
                \r
                @Override\r
-               protected JMenuItem getExecOnOffMenuItem(boolean fexec, String title,\r
-                               String chnam, String rsvId, String recId) {\r
+               protected JMenuItem getExecOnOffMenuItem(boolean fexec,\r
+                               String start, String title, String chnam, String rsvId, String recId) {\r
 \r
-                       return Viewer.this.getExecOnOffMenuItem(fexec, title, chnam, rsvId, recId, 0);\r
+                       return Viewer.this.getExecOnOffMenuItem(fexec, start, title, chnam, rsvId, recId, 0);\r
                }\r
 \r
                @Override\r
-               protected JMenuItem getRemoveRsvMenuItem(String title, String chnam,\r
-                               String rsvId, String recId) {\r
+               protected JMenuItem getRemoveRsvMenuItem(\r
+                               String start, String title, String chnam,       String rsvId, String recId) {\r
                        \r
-                       return Viewer.this.getRemoveRsvMenuItem(title, chnam, rsvId, recId, 0);\r
+                       return Viewer.this.getRemoveRsvMenuItem(start, title, chnam, rsvId, recId, 0);\r
                }\r
 \r
                @Override\r
@@ -833,88 +826,8 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                        //listed.pauseTimer();\r
                        timer_now.pause();\r
                        \r
-                       bounds.save();\r
-                       cbitems.save();\r
-                       env.save();\r
-\r
-                       // CommonUtilsの設定変更\r
-                       CommonUtils.setAdjLateNight(env.getAdjLateNight());\r
-                       CommonUtils.setExpandTo8(env.getExpandTo8());\r
-                       CommonUtils.setUseRundll32(env.getUseRundll32());\r
-                       CommonUtils.setDisplayPassedReserve(env.getDisplayPassedReserve());\r
-                       CommonUtils.setDebug(env.getDebug());\r
-                       \r
-                       SwingBackgroundWorker.setDebug(env.getDebug());\r
-\r
-                       // ほにゃらら\r
-                       toolBar.setDebug(env.getDebug());\r
-                       autores.setDebug(env.getDebug());\r
-\r
-                       // PassedProgramListの設定変更\r
-                       tvprograms.getPassed().setPassedDir(env.getPassedDir());\r
-\r
-                       // レコーダプラグインの設定変更\r
-                       for ( HDDRecorder rec : recorders ) {\r
-                               // 拡張設定だけ\r
-                               setSettingRecPluginExt(rec, env);\r
-                       }\r
-\r
-                       // Web番組表共通設定\r
-                       setSettingProgPluginCommon(env);\r
-                       \r
-                       // web番組表のリフレッシュ\r
-                       setSettingProgPluginAll(env);\r
-                       \r
-                       // リロードメニューの書き換え\r
-                       toolBar.updateReloadProgramExtention();\r
+                       Viewer.this.setEnv(reload_prog);\r
                        \r
-                       // ページャーコンボボックスの書き換え\r
-                       toolBar.setPagerItems();\r
-                       \r
-                       // 列の表示・非表示\r
-                       listed.setMarkColumnVisible(env.getSplitMarkAndTitle());\r
-                       listed.setDetailColumnVisible(env.getShowDetailOnList());\r
-                       listed.setRowHeaderVisible(env.getRowHeaderVisible());\r
-                       reserved.setRowHeaderVisible(env.getRowHeaderVisible());\r
-                       \r
-                       // 強調色\r
-                       listed.setMatchedKeywordColor(env.getMatchedKeywordColor());\r
-                       listed.setRsvdLineColor((env.getRsvdLineEnhance())?(env.getRsvdLineColor()):(null));\r
-                       listed.setPickedLineColor((env.getRsvdLineEnhance())?(env.getPickedLineColor()):(null));\r
-                       listed.setCurrentLineColor((env.getCurrentLineEnhance())?(env.getCurrentLineColor()):(null));\r
-                       \r
-                       // システムトレイアイコン\r
-                       setTrayIconVisible(env.getShowSysTray());\r
-                       setXButtonAction(env.getShowSysTray() && env.getHideToTray());\r
-                       \r
-                       // 新聞形式のツールチップの表示時間を変更する\r
-                       setTooltipDelay();\r
-                       \r
-                       // Web番組表の再構築\r
-                       mpList.setHistoryOnlyUpdateOnce(env.getHistoryOnlyUpdateOnce());\r
-                       mpList.setShowOnlyNonrepeated(env.getShowOnlyNonrepeated());\r
-                       \r
-                       // 番組情報の再取得\r
-                       if ( reload_prog ) {\r
-                               loadTVProgram(false,LoadFor.ALL);       // 部品呼び出し\r
-                       }\r
-                       \r
-                       // 新聞描画枠のリセット\r
-                       paper.clearPanel();\r
-                       paper.buildMainViewByDate();\r
-                       \r
-                       // 再度ツリーの再構築\r
-                       paper.redrawTreeByDate();\r
-                       paper.redrawTreeByPassed();\r
-                       \r
-                       listed.redrawTreeByHistory();\r
-                       listed.redrawTreeByCenter();\r
-                       \r
-                       // 再描画\r
-                       paper.reselectTree();\r
-                       listed.reselectTree();\r
-\r
-                       //listed.continueTimer();       // まあreselectTree()で再開しているはずだが\r
                        timer_now.start();\r
                }\r
        }\r
@@ -969,7 +882,7 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                        toolBar.updateRecorderComboBox();\r
                        \r
                        // 予約一覧のリフレッシュ\r
-                       loadRdReserve(false, null);             // toolBarの内容がリセットされているので recId = null で\r
+                       loadRdReservesAll(false, null);         // toolBarの内容がリセットされているので recId = null で\r
                        \r
                        // レコーダのエンコーダ表示の更新\r
                        this.redrawRecorderEncoderEntry();\r
@@ -1199,12 +1112,9 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                 */\r
                \r
                @Override\r
-               protected void searchLikeRsv(LikeReserveList likeRsvList, ProgDetailList tvd, String keyword, int threshold) {\r
-                       Viewer.this.searchLikeRsv(likeRsvList, tvd, keyword, threshold);\r
+               protected LikeReserveList findLikeReserves(ProgDetailList tvd, String keyword, int threshold) {\r
+                       return Viewer.this.findLikeReserves(tvd, keyword, threshold);\r
                }\r
-\r
-               @Override\r
-               protected String getSelectedRecorderOnToolbar() { return toolBar.getSelectedRecorder(); }\r
        }\r
        \r
        /**\r
@@ -1326,7 +1236,12 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                                reserved.redrawListByKeywordFilter(search, kStr);\r
                        }\r
                        else if ( mainWindow.getSelectedTab() == MWinTab.RECED ) {\r
-                               recorded.redrawListByKeywordFilter(search, kStr);\r
+                               if ( ! doFilter ) {\r
+                                       recorded.redrawListByKeyword(search, kStr);\r
+                               }\r
+                               else {\r
+                                       recorded.redrawListByErrorFilter();\r
+                               }\r
                        }\r
                        else {\r
                                if ( search != null ) {\r
@@ -1379,7 +1294,7 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                @Override\r
                protected boolean jumpToPassed(String passed) {\r
                        timer_now.pause();\r
-                       boolean b = paper.jumpToBangumi(null,passed);\r
+                       boolean b = paper.jumpToPassed(passed);\r
                        timer_now.start();\r
                        return b;\r
                }\r
@@ -1393,9 +1308,14 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                }\r
 \r
                @Override\r
-               protected void toggleMatchBorder() {\r
+               protected void toggleMatchBorder(boolean b) {\r
                        timer_now.pause();\r
-                       paper.toggleMatchBorder();\r
+                       if ( mainWindow.isTabSelected(MWinTab.LISTED) ) {\r
+                               listed.toggleReservedBackground(b);\r
+                       }\r
+                       else if ( mainWindow.isTabSelected(MWinTab.PAPER) ) {\r
+                               paper.toggleMatchBorder(b);\r
+                       }\r
                        timer_now.start();\r
                }\r
 \r
@@ -1431,10 +1351,12 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                                recorded.redrawRecordedList();\r
                        }\r
                        \r
+                       /*\r
                        // 新聞形式の予約枠を書き換えるかもよ?\r
                        if (env.getEffectComboToPaper()) {\r
                                paper.updateReserveBorder(null);\r
                        }\r
+                       */\r
                        \r
                        timer_now.start();\r
                        \r
@@ -1446,52 +1368,9 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                        \r
                        timer_now.pause();\r
                        \r
-                       try {\r
-                               String fname;\r
-                               if ( mainWindow.isTabSelected(MWinTab.LISTED) ) {\r
-                                       fname = String.format("snapshot.%s",env.getSnapshotFmt().getExtension());\r
-                                       CommonSwingUtils.saveComponentAsJPEG(listed.getCurrentView(), listed.getTableHeader(), null, listed.getTableBody(), fname, env.getSnapshotFmt(), Viewer.this);\r
-                               }\r
-                               else if ( mainWindow.isTabSelected(MWinTab.PAPER) ){\r
-                                       if ( env.getDrawcacheEnable() || ! env.isPagerEnabled() ) {\r
-                                               fname = String.format("snapshot.%s",env.getSnapshotFmt().getExtension());\r
-                                       }\r
-                                       else {\r
-                                               int pcur = getSelectedPagerIndex();\r
-                                               int pmax = getPagerCount();\r
-                                               if ( env.getAllPageSnapshot() ) {\r
-                                                       for ( int i=0; i<pmax; i++ ) {\r
-                                                               if ( i != pcur ) {\r
-                                                                       setSelectedPagerIndex(i);\r
-                                                                       fname = String.format("snapshot%02d.%s",i+1,env.getSnapshotFmt().getExtension());\r
-                                                                       CommonSwingUtils.saveComponentAsJPEG(paper.getCurrentView(), paper.getCenterPane(), paper.getTimebarPane(), paper.getCurrentPane(), fname, env.getSnapshotFmt(), Viewer.this);\r
-                                                               }\r
-                                                       }\r
-                                               }\r
-                                               fname = String.format("snapshot%02d.%s",pcur+1,env.getSnapshotFmt().getExtension());\r
-                                               setSelectedPagerIndex(pcur);\r
-                                       }\r
-                                       CommonSwingUtils.saveComponentAsJPEG(paper.getCurrentView(), paper.getCenterPane(), paper.getTimebarPane(), paper.getCurrentPane(), fname, env.getSnapshotFmt(), Viewer.this);\r
-                               }\r
-                               else {\r
-                                       return; // おかしーよ\r
-                               }\r
-                               Desktop desktop = Desktop.getDesktop();\r
-                               if (env.getPrintSnapshot()) {\r
-                                       desktop.print(new File(fname));\r
-                               }\r
-                               else {\r
-                                       String emsg = CommonUtils.openFile(fname);\r
-                                       if (emsg != null) {\r
-                                               mwin.appendError(emsg);\r
-                                       }\r
-                               }\r
-                       } catch (IOException e1) {\r
-                               e1.printStackTrace();\r
-                       }\r
-                       finally {\r
-                               timer_now.start();\r
-                       }\r
+                       Viewer.this.getSnapshot(getSelectedPagerIndex(),getPagerCount());\r
+                       \r
+                       timer_now.start();\r
                }\r
 \r
                @Override\r
@@ -1505,11 +1384,6 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                }\r
 \r
                @Override\r
-               protected void toggleSettingTabVisible() {\r
-                       mainWindow.toggleShowSettingTabs();\r
-               }\r
-\r
-               @Override\r
                protected boolean isTabSelected(MWinTab tab) {\r
                        return mainWindow.isTabSelected(tab);\r
                }\r
@@ -1522,7 +1396,7 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                        AbsKeywordDialog kD = new VWKeywordDialog();\r
                        CommonSwingUtils.setLocationCenter(Viewer.this,kD);\r
                        \r
-                       kD.open(search.getLabel(), search, srKeys, srGrps);\r
+                       kD.open(search.getLabel(), srKeys, srGrps, search);\r
                        kD.setVisible(true);\r
                        \r
                        if (kD.isRegistered()) {\r
@@ -1542,31 +1416,99 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                }\r
 \r
                @Override\r
-               protected boolean reLoadTVProgram(LoadFor lf) {\r
+               protected boolean doLoadTVProgram(String selected) {\r
                        timer_now.pause();\r
-                       boolean b = Viewer.this.reLoadTVProgram(lf);\r
-                       timer_now.start();\r
-                       return b;\r
-               }\r
+                       \r
+                       LoadFor lf = (selected != null) ? LoadFor.get(selected) : LoadFor.ALL;\r
+                       boolean b = Viewer.this.doLoadTVProgram(true, lf);\r
+                       \r
+                       if ( b && lf == LoadFor.CSwSD ) {\r
+                               // ロード後シャットダウン\r
+                               CommonUtils.executeCommand(env.getShutdownCmd());\r
+                       }\r
+\r
+                       Viewer.this.doRedrawTVProgram();        // か き な お し\r
 \r
-               @Override\r
-               protected boolean reLoadRdReserve(String myself) {\r
-                       timer_now.pause();\r
-                       boolean b = Viewer.this.reLoadRdReserve(myself);\r
                        timer_now.start();\r
                        return b;\r
                }\r
 \r
                @Override\r
-               protected boolean reLoadRdRecorded(String myself) {\r
+               protected boolean doLoadRdRecorder(String selected) {\r
                        timer_now.pause();\r
-                       boolean b = Viewer.this.reLoadRdRecorded(myself);\r
+                       \r
+                       LoadRsvedFor lrf = (selected != null) ? LoadRsvedFor.get(selected) : null;\r
+                       boolean b = Viewer.this.doLoadRdRecorder(lrf);\r
+                       \r
                        timer_now.start();\r
                        return b;\r
                }\r
+       }\r
+       \r
+       /*******************************************************************************\r
+        * ハンドラ―メソッド\r
+        ******************************************************************************/\r
+\r
+       /**\r
+        * なんかよくわからないもの\r
+        */\r
+       @Override\r
+       public void stateChanged(ChangeEvent e){\r
+               StdAppendMessage("イベント発生");\r
+       }\r
+\r
+       /**\r
+        * ツールバーでレコーダの選択イベントが発生\r
+        */\r
+       @Override\r
+       public void valueChanged(HDDRecorderSelectionEvent e) {\r
+               // 選択中のレコーダ情報を保存する\r
+               src_recsel = (HDDRecorderSelectable) e.getSource();\r
+       }\r
+       \r
+       private String getSelectedMySelf() {\r
+               return ( src_recsel!=null ? src_recsel.getSelectedMySelf() : null );\r
+       }\r
+       \r
+       private HDDRecorderList getSelectedRecorderList() {\r
+               return ( src_recsel!=null ? src_recsel.getSelectedList() : null );\r
+       }\r
+       \r
+       private HDDRecorderSelectable src_recsel;\r
 \r
+       /**\r
+        * レコーダ情報の変更イベントが発生\r
+        */\r
+       @Override\r
+       public void stateChanged(HDDRecorderChangeEvent e) {\r
+               // 未実装\r
+       }\r
+       \r
+       /**\r
+        * \r
+        */\r
+       @Override\r
+       public void cancelRised(CancelEvent e) {\r
+               if ( mainWindow.isTabSelected(MWinTab.RSVED) ) {\r
+                       if ( e.getCause() == CancelEvent.Cause.TOOLBAR_SEARCH ) {\r
+                               reserved.redrawListByKeywordFilter(null,null);\r
+                       }\r
+               }\r
+               else if ( mainWindow.isTabSelected(MWinTab.RECED) ) {\r
+                       if ( e.getCause() == CancelEvent.Cause.TOOLBAR_SEARCH ) {\r
+                               recorded.redrawListByKeyword(null,null);\r
+                       }\r
+               }\r
        }\r
        \r
+       /**\r
+        * タイマーイベントが発生\r
+        */\r
+       @Override\r
+       public void timerRised(TickTimerRiseEvent e) {\r
+               if (env.getDebug()) System.out.println("Timer Rised: now="+CommonUtils.getDateTimeYMDx(e.getCalendar()));\r
+               setTitleBar();\r
+       }\r
        \r
        \r
        /*******************************************************************************\r
@@ -1576,102 +1518,29 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
        /**\r
         * 類似予約をさがす\r
         */\r
-       private void searchLikeRsv(LikeReserveList likeRsvList, ProgDetailList tvd, String keyword, int threshold) {\r
+       private LikeReserveList findLikeReserves(ProgDetailList tvd, String keyword, int threshold) {\r
                \r
-               likeRsvList.clear();\r
-               \r
-               // 曖昧検索のための初期化\r
-               String keywordPop = null;\r
+               String keywordVal = null;\r
                int thresholdVal = 0;\r
-               if (threshold > 0) {\r
-                       // キーワード指定がある場合\r
-                       keywordPop = TraceProgram.replacePop(keyword);\r
-                       thresholdVal = threshold;\r
-               }\r
-               else {\r
-                       // キーワード指定がない場合\r
-                       keywordPop = tvd.titlePop;\r
-                       thresholdVal = env.getDefaultFazzyThreshold();\r
-               }\r
-\r
-               // 検索範囲\r
-               long rangeLikeRsv = env.getRangeLikeRsv()*3600000;\r
                \r
-               HashMap<String,Boolean> misCN = new HashMap<String, Boolean>();\r
-               for ( HDDRecorder recorder : recorders ) {\r
-                       \r
-                       // 終了した予約を整理する\r
-                       recorder.refreshReserves();\r
-                       \r
-                       for ( ReserveList r : recorder.getReserves() ) {\r
-                               \r
-                               // タイトルのマッチング\r
-                               boolean isExist = false;\r
-                               if (env.getDisableFazzySearch() == false) {\r
-                                       // 双方向の比較を行う・正引き\r
-                                       int fazScore = TraceProgram.sumScore(keywordPop, r.getTitlePop());\r
-                                       if ( fazScore >= thresholdVal) {\r
-                                               isExist = true;\r
-                                       }\r
-                                       else if ( ! env.getDisableFazzySearchReverse()) {\r
-                                               // 逆引き\r
-                                               fazScore = TraceProgram.sumScore(r.getTitlePop(), keywordPop);\r
-                                               if ( fazScore >= thresholdVal) {\r
-                                                       isExist = true;\r
-                                               }\r
-                                       }\r
-                               }\r
-                               else {\r
-                                       if (r.getTitlePop().equals(tvd.titlePop)) {\r
-                                               isExist = true;\r
-                                       }\r
-                               }\r
-                               if ( ! isExist) {\r
-                                       continue;\r
-                               }\r
-                               \r
-                               // 放送局のマッチング\r
-                               if (r.getCh_name() == null) {\r
-                                       if(r.getChannel().length() > 0) {\r
-                                               misCN.put(r.getChannel(),true);\r
-                                       }\r
-                                       continue;\r
-                               }\r
-                               if ( ! r.getCh_name().equals(tvd.center)) {\r
-                                       continue;\r
-                               }\r
-                               \r
-                               // 近接時間チェック\r
-                               boolean inRange = true;\r
-                               if (rangeLikeRsv > 0) {\r
-                                       \r
-                                       inRange = false;\r
-                                       \r
-                                       ArrayList<String> starts = new ArrayList<String>();\r
-                                       ArrayList<String> ends = new ArrayList<String>();\r
-                                       CommonUtils.getStartEndList(starts, ends, r);\r
-                                       for (int j=0; j<starts.size(); j++) {\r
-                                               long d = CommonUtils.getDiffDateTime(tvd.startDateTime, starts.get(j));\r
-                                               //StdAppendMessage(String.format("%s %s %d", tvd.startDateTime, starts.get(j),d));\r
-                                               if (d <= rangeLikeRsv) {\r
-                                                       inRange = true;\r
-                                                       break;\r
-                                               }\r
-                                       }\r
-                               }\r
-                               if ( ! inRange) {\r
-                                       continue;\r
-                               }\r
-                               \r
-                               // 類似予約あり!\r
-                               likeRsvList.add(new LikeReserveItem(recorder, r));\r
+               // 曖昧検索のための初期化\r
+               if ( ! env.getDisableFazzySearch() ) {\r
+                       if ( threshold > 0 ) {\r
+                               // キーワード指定がある場合\r
+                               keywordVal = TraceProgram.replacePop(keyword);\r
+                               thresholdVal = threshold;\r
+                       }\r
+                       else {\r
+                               // キーワード指定がない場合\r
+                               keywordVal = tvd.titlePop;\r
+                               thresholdVal = env.getDefaultFazzyThreshold();\r
                        }\r
                }\r
-               \r
-               return;\r
+\r
+               // 検索実行\r
+               return recorders.findLikeReserves(tvd, keywordVal, thresholdVal, env.getRangeLikeRsv(), ! env.getDisableFazzySearchReverse());\r
        }\r
        \r
-       \r
        /***\r
         * \r
         * リスト・新聞形式共通\r
@@ -1684,10 +1553,29 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
        public void showPopupForTraceProgram(\r
                        final JComponent comp,\r
                        final ProgDetailList tvd, final String keyword, final int threshold,\r
-                       final int x, final int y, final int h)\r
+                       final int x, final int y, final String clickedDateTime)\r
        {\r
                JPopupMenu pop = new JPopupMenu();\r
+               \r
+               String myself = toolBar.getSelectedRecorder();\r
        \r
+               // 類似予約検索\r
+               LikeReserveList likeRsvList;\r
+               if ( env.getDisableFazzySearch() ) {\r
+                       likeRsvList = recorders.findLikeReserves(tvd, null, 0, env.getRangeLikeRsv(), false);\r
+               }\r
+               else {\r
+                       likeRsvList = recorders.findLikeReserves(tvd, tvd.titlePop, env.getDefaultFazzyThreshold(), env.getRangeLikeRsv(), ! env.getDisableFazzySearchReverse());\r
+               }\r
+               \r
+               // 重複予約検索\r
+               LikeReserveList overlapRsvList = recorders.findOverlapReserves(tvd, null, true, env.getOverlapUp());\r
+               \r
+               // 類似と重複で被るものを重複から除外\r
+               for ( LikeReserveItem item : likeRsvList ) {\r
+                       overlapRsvList.removeDup(item);\r
+               }\r
+               \r
                // 予約する\r
                if ( tvd.type == ProgType.PASSED ||\r
                                (tvd.type == ProgType.PROG && tvd.subtype == ProgSubtype.RADIO) ||\r
@@ -1695,7 +1583,21 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                        // 過去ログは処理対象外です\r
                }\r
                else {\r
-                       JMenuItem menuItem = new JMenuItem("予約する【"+tvd.title+" ("+tvd.center+")】");\r
+                       String target;\r
+                       LikeReserveItem item = likeRsvList.getClosest(myself);\r
+                       if ( env.getGivePriorityToReserved() && item != null && item.isCandidate(env.getOverlapUp()) ) {\r
+                               target = "予約を編集する";\r
+                       }\r
+                       else {\r
+                               target = "新規予約を登録する";\r
+                       }\r
+                       \r
+                       JMenuItem menuItem = new JMenuItem(String.format("%s【%s %s - %s(%s)】",target,tvd.accurateDate,tvd.start,tvd.title,tvd.center));\r
+                       {\r
+                               menuItem.setForeground(Color.BLUE);\r
+                               Font f = menuItem.getFont();\r
+                               menuItem.setFont(f.deriveFont(f.getStyle()|Font.BOLD));\r
+                       }\r
                        \r
                        menuItem.addActionListener(new ActionListener() {\r
                                public void actionPerformed(ActionEvent e) {\r
@@ -1710,7 +1612,7 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                                        }\r
                                        \r
                                        //\r
-                                       if (rdialog.isReserved()) {\r
+                                       if (rdialog.isSucceededReserve()) {\r
                                                listed.updateReserveMark();\r
                                                paper.updateReserveBorder(tvd.center);\r
                                                reserved.redrawReservedList();\r
@@ -1720,28 +1622,44 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                        pop.add(menuItem);\r
                }\r
                \r
-               pop.addSeparator();\r
-               \r
-               // 類似予約検索\r
-               LikeReserveList likeRsvList = new LikeReserveList();\r
-               searchLikeRsv(likeRsvList, tvd, "", 0);\r
-               \r
-               // 重複予約検索\r
-               LikeReserveList overlapRsvList = new LikeReserveList();\r
-               searchOverlapRsv(overlapRsvList, tvd, h);\r
-               \r
-               // 類似と重複で被るものを重複から除外\r
-               for ( LikeReserveItem ll : likeRsvList ) {\r
-                       int i=0;\r
-                       for ( ; i<overlapRsvList.size(); i++ ) {\r
-                               if ( ll.getRsv() == overlapRsvList.getRsv(i) ) {\r
-                                       break;\r
+               // 隣接予約を編集する\r
+               {\r
+                       for ( final LikeReserveItem item : overlapRsvList ) {\r
+                               \r
+                               if ( ! item.getRec().Myself().equals(toolBar.getSelectedRecorder()) ) {\r
+                                       continue;       // 選択中のレコーダ以外はスルーで\r
+                               }\r
+                               \r
+                               {\r
+                                       ReserveList rsv = item.getRsv();\r
+                                       String start = CommonUtils.getDateTimeW(CommonUtils.getCalendar(rsv.getStartDateTime()));\r
+                                       JMenuItem menuItem = new JMenuItem(String.format("隣接予約を上書する【%s - %s(%s)】",start,rsv.getTitle(),rsv.getCh_name()));\r
+                                       \r
+                                       menuItem.addActionListener(new ActionListener() {\r
+                                               public void actionPerformed(ActionEvent e) {\r
+\r
+                                                       CommonSwingUtils.setLocationCenter(mainWindow,rdialog);\r
+\r
+                                                       if ( rdialog.open(tvd,item) ) {\r
+                                                               rdialog.setVisible(true);\r
+                                                       }\r
+                                                       else {\r
+                                                               rdialog.setVisible(false);\r
+                                                       }\r
+                                                       \r
+                                                       //\r
+                                                       if (rdialog.isSucceededReserve()) {\r
+                                                               listed.updateReserveMark();\r
+                                                               paper.updateReserveBorder(tvd.center);\r
+                                                               reserved.redrawReservedList();\r
+                                                       }\r
+                                               }\r
+                                       });\r
+                                       pop.add(menuItem);\r
                                }\r
-                       }\r
-                       if ( i < overlapRsvList.size() ) {\r
-                               overlapRsvList.remove(i);\r
                        }\r
                }\r
+               pop.addSeparator();\r
                \r
                // 予約実行ON・OFF\r
                if ( tvd.type != ProgType.PASSED )\r
@@ -1756,15 +1674,16 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                                        rsvList = overlapRsvList;\r
                                }\r
                                \r
-                               for ( int i=0; i<rsvList.size(); i++ ) {\r
+                               for ( LikeReserveItem rsvItem : rsvList ) {\r
                                        \r
-                                       final boolean fexec = rsvList.getRsv(i).getExec();\r
-                                       final String title = rsvList.getRsv(i).getTitle();\r
-                                       final String chnam = rsvList.getRsv(i).getCh_name();\r
-                                       final String rsvId = rsvList.getRsv(i).getId();\r
-                                       final String recId = rsvList.getRec(i).Myself();\r
+                                       final boolean fexec = rsvItem.getRsv().getExec();\r
+                                       final String start = rsvItem.getRsv().getAhh()+":"+rsvItem.getRsv().getAmm();\r
+                                       final String title = rsvItem.getRsv().getTitle();\r
+                                       final String chnam = rsvItem.getRsv().getCh_name();\r
+                                       final String rsvId = rsvItem.getRsv().getId();\r
+                                       final String recId = rsvItem.getRec().Myself();\r
                                        \r
-                                       pop.add(getExecOnOffMenuItem(fexec,title,chnam,rsvId,recId,n));\r
+                                       pop.add(getExecOnOffMenuItem(fexec,start,title,chnam,rsvId,recId,n));\r
                                }\r
                                \r
                                pop.addSeparator();\r
@@ -1786,14 +1705,15 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                                        rsvList = overlapRsvList;\r
                                }\r
                                \r
-                               for (int i=0; i<rsvList.size(); i++) {\r
+                               for ( LikeReserveItem rsvItem : rsvList ) {\r
                                        \r
-                                       final String title = rsvList.getRsv(i).getTitle();\r
-                                       final String chnam = rsvList.getRsv(i).getCh_name();\r
-                                       final String rsvId = rsvList.getRsv(i).getId();\r
-                                       final String recId = rsvList.getRec(i).Myself();\r
+                                       final String start = rsvItem.getRsv().getAhh()+":"+rsvItem.getRsv().getAmm();\r
+                                       final String title = rsvItem.getRsv().getTitle();\r
+                                       final String chnam = rsvItem.getRsv().getCh_name();\r
+                                       final String rsvId = rsvItem.getRsv().getId();\r
+                                       final String recId = rsvItem.getRec().Myself();\r
                                        \r
-                                       pop.add(getRemoveRsvMenuItem(title,chnam,rsvId,recId,n));\r
+                                       pop.add(getRemoveRsvMenuItem(start, title,chnam,rsvId,recId,n));\r
                                }\r
                                \r
                                pop.addSeparator();\r
@@ -1807,7 +1727,7 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                // ジャンプする\r
                {\r
                        if ( mainWindow.isTabSelected(MWinTab.LISTED) ) {\r
-                               pop.add(getJumpMenuItem(tvd.title,tvd.center,tvd.startDateTime));\r
+                               pop.add(getJumpMenuItem(tvd.title,tvd.center,tvd.accurateDate+" "+tvd.start));\r
                        }\r
                        if ( mainWindow.isTabSelected(MWinTab.LISTED) || mainWindow.isTabSelected(MWinTab.PAPER) ) {\r
                                JMenuItem mi = getJumpToLastWeekMenuItem(tvd.title,tvd.center,tvd.startDateTime);\r
@@ -1821,29 +1741,18 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                \r
                // 番組追跡へ追加する\r
                {\r
-                       final String label = tvd.title+" ("+tvd.center+")";\r
+                       final String label = TraceProgram.getNewLabel(tvd.title, tvd.center);\r
                        JMenuItem menuItem = new JMenuItem("番組追跡への追加【"+label+"】");\r
                        menuItem.addActionListener(new ActionListener() {\r
                                public void actionPerformed(ActionEvent e) {\r
                                        //\r
-                                       for (TraceKey tr : trKeys.getTraceKeys()) {\r
-                                               if (tr.getLabel().equals(label)) {\r
-                                                       mwin.appendMessage("【警告】すでに番組追跡に登録されています:"+label);\r
-                                                       ringBeep();\r
-                                                       return;\r
-                                               }\r
-                                       }\r
-                                       \r
-                                       //\r
-                                       trKeys.add(label, tvd.title, tvd.center, env.getDefaultFazzyThreshold());\r
-\r
                                        VWTraceKeyDialog tD = new VWTraceKeyDialog(0,0);\r
                                        CommonSwingUtils.setLocationCenter(mainWindow,tD);\r
                                        \r
-                                       tD.reopen(label, trKeys);\r
+                                       tD.open(trKeys, tvd, env.getDefaultFazzyThreshold());\r
                                        tD.setVisible(true);\r
                                        \r
-                                       if (tD.isRegistered()) { \r
+                                       if (tD.isRegistered()) {\r
                                                //\r
                                                trKeys.save();\r
                                                \r
@@ -1874,51 +1783,28 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                        JMenuItem menuItem = new JMenuItem("キーワード検索への追加【"+label+"】");\r
                        menuItem.addActionListener(new ActionListener(){\r
                                public void actionPerformed(ActionEvent e){\r
-                                       //\r
-                                       for (SearchKey sr : srKeys.getSearchKeys()) {\r
-                                               if (sr.getLabel().equals(tvd.title)) {\r
-                                                       ringBeep();\r
-                                                       String msg = "すでにキーワード検索に登録されています: "+tvd.title;\r
-                                                       mwin.appendMessage(msg);\r
-                                                       JOptionPane.showConfirmDialog(null, msg, "警告", JOptionPane.CLOSED_OPTION);                                                  // キーワード検索の追加ではダイアログで修正できるので止めない\r
-                                                       //return;\r
-                                               }\r
-                                       }\r
+                                       \r
                                        // 「キーワード検索の設定」ウィンドウを開く\r
-                                       SearchKey search = new SearchKey();\r
-                                       {\r
-                                               search.setCondition("0");\r
-                                               search.alTarget.add(TargetId.TITLE);\r
-                                               search.alContain.add("0");\r
-                                               search.alKeyword.add(tvd.title);\r
-                                       }\r
-                                       {\r
-                                               search.setCondition("0");\r
-                                               search.alTarget.add(TargetId.CHANNEL);\r
-                                               search.alContain.add("0");\r
-                                               search.alKeyword.add(tvd.center);\r
-                                       }\r
-                                       {\r
-                                               AbsKeywordDialog kD = new VWKeywordDialog();\r
-                                               CommonSwingUtils.setLocationCenter(mainWindow,kD);\r
-                                               \r
-                                               kD.open(tvd.title, search, srKeys, srGrps);\r
-                                               kD.setVisible(true);\r
+                                       \r
+                                       AbsKeywordDialog kD = new VWKeywordDialog();\r
+                                       CommonSwingUtils.setLocationCenter(mainWindow,kD);\r
+                                       \r
+                                       kD.open(srKeys, srGrps, tvd);\r
+                                       kD.setVisible(true);\r
+                                       \r
+                                       if (kD.isRegistered()) {\r
+                                               // 検索結果の再構築\r
+                                               mpList.clear(env.getDisableFazzySearch(), env.getDisableFazzySearchReverse());\r
+                                               mpList.build(tvprograms, trKeys.getTraceKeys(), srKeys.getSearchKeys());\r
                                                \r
-                                               if (kD.isRegistered()) {\r
-                                                       // 検索結果の再構築\r
-                                                       mpList.clear(env.getDisableFazzySearch(), env.getDisableFazzySearchReverse());\r
-                                                       mpList.build(tvprograms, trKeys.getTraceKeys(), srKeys.getSearchKeys());\r
-                                                       \r
-                                                       // ツリーに反映する\r
-                                                       listed.redrawTreeByKeyword();\r
+                                               // ツリーに反映する\r
+                                               listed.redrawTreeByKeyword();\r
 \r
-                                                       // 表示を更新する\r
-                                                       paper.updateBangumiColumns();\r
-                                                       listed.reselectTree();\r
-                                                       \r
-                                                       mwin.appendMessage("キーワード検索へ追加しました【"+label+"】");\r
-                                               }\r
+                                               // 表示を更新する\r
+                                               paper.updateBangumiColumns();\r
+                                               listed.reselectTree();\r
+                                               \r
+                                               mwin.appendMessage("キーワード検索へ追加しました【"+label+"】");\r
                                        }\r
                                }\r
                        });\r
@@ -1940,8 +1826,8 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                        \r
                        if ( ! isRemoveItem )   // 過去ログは処理対象外です\r
                        {\r
-                               final String label = tvd.title+" ("+tvd.center+")";\r
-                               JMenuItem menuItem = new JMenuItem("ピックアップへの追加【"+label+"】");\r
+                               final String label = String.format("%s(%s)",tvd.title,tvd.center);\r
+                               JMenuItem menuItem = new JMenuItem(String.format("ピックアップへの追加【%s %s - %s】",tvd.accurateDate,tvd.start,label));\r
                                menuItem.addActionListener(new ActionListener() {\r
                                        public void actionPerformed(ActionEvent e) {\r
                                                //\r
@@ -2357,10 +2243,17 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
        /**\r
         *  予約を削除するメニューアイテム\r
         */\r
-       private JMenuItem getRemoveRsvMenuItem(final String title, final String chnam, final String rsvId, final String recId, int n) {\r
+       private JMenuItem getRemoveRsvMenuItem(final String start, final String title, final String chnam, final String rsvId, final String recId, int n) {\r
                //\r
-               JMenuItem menuItem = new JMenuItem(((n==0)?"予約を削除する【":"隣接予約を削除する【")+title+"("+chnam+")/"+recId+"】");\r
+               JMenuItem menuItem = new JMenuItem();\r
+               \r
+               String mode = "削除";\r
                menuItem.setForeground(Color.RED);\r
+               \r
+               String target = ( n==0 ) ? "予約" : "隣接予約";\r
+\r
+               menuItem.setText(String.format("%sを%sする【%s - %s(%s)/%s】",target,mode,start,title,chnam,recId));\r
+               \r
                if ( recId.equals(toolBar.getSelectedRecorder()) ) {\r
                        // 選択中のレコーダのものは太字に\r
                        Font f = menuItem.getFont();\r
@@ -2440,12 +2333,12 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                                        \r
                                        @Override\r
                                        protected void doFinally() {\r
-                                               stwin.setVisible(false);\r
+                                               StWinSetVisible(false);\r
                                        }\r
                                }.execute();\r
                                \r
                                CommonSwingUtils.setLocationCenter(Viewer.this, stwin);\r
-                               stwin.setVisible(true);\r
+                               StWinSetVisible(true);\r
                                \r
                                // 予約状況を更新\r
                                listed.updateReserveMark();\r
@@ -2473,11 +2366,12 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                \r
                String mode = (fexec ? "ON" : "OFF");\r
                \r
-               if ( rdialog.open(recId,rsvId) ) {\r
-                       rdialog.setOnlyUpdateExec(fexec);\r
+               // 予約ON・OFFのみ\r
+               if ( rdialog.open(recId,rsvId,fexec) ) {\r
+                       \r
                        rdialog.doUpdate();\r
                        \r
-                       if (rdialog.isReserved()) {\r
+                       if (rdialog.isSucceededReserve()) {\r
                                // 予約状況を更新\r
                                listed.updateReserveMark();\r
                                paper.updateReserveBorder(chnam);\r
@@ -2499,7 +2393,7 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
        /**\r
         *  予約実行をONOFFするメニューアイテム\r
         */\r
-       private JMenuItem getExecOnOffMenuItem(final boolean fexec, final String title, final String chnam, final String rsvId, final String recId, int n) {\r
+       private JMenuItem getExecOnOffMenuItem(final boolean fexec, final String start, final String title, final String chnam, final String rsvId, final String recId, int n) {\r
                \r
                JMenuItem menuItem = new JMenuItem();\r
                \r
@@ -2510,9 +2404,12 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                }\r
                else {\r
                        mode = "OFF";\r
+                       menuItem.setForeground(Color.BLACK);\r
                }\r
-               \r
-               menuItem.setText(((n==0)?"予約を":"隣接予約を")+mode+"にする【"+title+"("+chnam+")/"+recId+")】");\r
+\r
+               String target = ( n==0 ) ? "予約" : "隣接予約";\r
+\r
+               menuItem.setText(String.format("%sを%sにする【%s - %s(%s)/%s】",target,mode,start,title,chnam,recId));\r
                \r
                if ( recId.equals(toolBar.getSelectedRecorder()) ) {\r
                        // 選択中のレコーダのものは太字に\r
@@ -2524,15 +2421,14 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                menuItem.addActionListener(new ActionListener() {\r
                        public void actionPerformed(ActionEvent e) {\r
                                \r
-                               //VWReserveDialog rD = new VWReserveDialog(0, 0, env, tvprograms, recorders, avs, chavs, stwin);\r
-                               //rdialog.clear();\r
                                CommonSwingUtils.setLocationCenter(mainWindow,rdialog);\r
                                \r
-                               if ( rdialog.open(recId,rsvId) ) {\r
-                                       rdialog.setOnlyUpdateExec( ! fexec);\r
+                               // 予約ON・OFFのみ\r
+                               if ( rdialog.open(recId,rsvId, ! fexec) ) {\r
+                                       \r
                                        rdialog.doUpdate();\r
                                        \r
-                                       if (rdialog.isReserved()) {\r
+                                       if (rdialog.isSucceededReserve()) {\r
                                                // 予約状況を更新\r
                                                listed.updateReserveMark();\r
                                                paper.updateReserveBorder(chnam);\r
@@ -2558,7 +2454,7 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
         *  新聞形式へジャンプするメニューアイテム\r
         */\r
        private JMenuItem getJumpMenuItem(final String title, final String chnam, final String startDT) {\r
-               JMenuItem menuItem = new JMenuItem("番組欄へジャンプする【"+title+" ("+chnam+")】");\r
+               JMenuItem menuItem = new JMenuItem(String.format("番組欄へジャンプする【%s - %s(%s)】",startDT,title,chnam));\r
                menuItem.addActionListener(new ActionListener() {\r
                        public void actionPerformed(ActionEvent e) {\r
                                paper.jumpToBangumi(chnam,startDT);\r
@@ -2566,15 +2462,18 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                });\r
                return menuItem;\r
        }\r
-       private JMenuItem getJumpToLastWeekMenuItem(final String title, final String chnam, final String startDT) {\r
+       private JMenuItem getJumpToLastWeekMenuItem( final String title, final String chnam, final String startDT) {\r
                GregorianCalendar cal = CommonUtils.getCalendar(startDT);\r
+               \r
                if ( cal != null ) {\r
-                       JMenuItem menuItem = new JMenuItem("先週の番組欄へジャンプする【"+title+" ("+chnam+")】");\r
                        cal.add(Calendar.DATE, -7);\r
-                       final String lastweek = CommonUtils.getDateTime(cal);\r
-                       menuItem.addActionListener(new ActionListener() {\r
+                       final String lastdatetime = CommonUtils.getDateTimeW(cal);\r
+                       \r
+                       JMenuItem menuItem = new JMenuItem(String.format("先週の番組欄へジャンプする【%s - (%s)】",lastdatetime,chnam));\r
+                       \r
+                       menuItem.addActionListener(new ActionListener() {\r
                                public void actionPerformed(ActionEvent e) {\r
-                                       paper.jumpToBangumi(chnam,lastweek);\r
+                                       paper.jumpToBangumi(chnam,lastdatetime);\r
                                }\r
                        });\r
                        return menuItem;\r
@@ -2582,114 +2481,45 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                return null;\r
        }\r
        \r
-       // カーソル位置にかかる予約枠の検索\r
-       private void searchOverlapRsv(LikeReserveList overlapRsvList, ProgDetailList tvd, int h)\r
-       {\r
-               String clicked = "";\r
-               if ( h >= 0 && tvd.start.length() != 0 ) {\r
-                       // 新聞形式ならクリック位置の日時を算出する\r
-                       GregorianCalendar cala = CommonUtils.getCalendar(tvd.startDateTime);\r
-                       if ( CommonUtils.isLateNight(cala.get(Calendar.HOUR_OF_DAY)) ) {\r
-                               cala.set(Calendar.HOUR_OF_DAY, TIMEBAR_START);\r
-                               cala.set(Calendar.MINUTE, 0);\r
-                       }\r
-                       cala.add(Calendar.MINUTE, Math.round(h/bounds.getPaperHeightMultiplier()));\r
-                       clicked = CommonUtils.getDateTime(cala);\r
-                       //StdAppendError("clicked:"+clicked);\r
-               }\r
-               \r
-               HashMap<String,Boolean> misCN = new HashMap<String, Boolean>();\r
-               for ( HDDRecorder recorder : recorders ) {\r
-                       \r
-                       // 終了した予約を整理する\r
-                       recorder.refreshReserves();\r
-                       \r
-                       for ( ReserveList r : recorder.getReserves() ) {\r
-                               \r
-                               // 放送局のマッチング\r
-                               if (r.getCh_name() == null) {\r
-                                       if ( r.getChannel() == null ) {\r
-                                               System.err.println(ERRID+"予約情報にCHコードが設定されていません。バグの可能性があります。 recid="+recorder.Myself()+" chname="+r.getCh_name());\r
-                                               continue;\r
-                                       }\r
-                                       if(r.getChannel().length() > 0) {\r
-                                               misCN.put(r.getChannel(),true);\r
-                                       }\r
-                                       continue;\r
-                               }\r
-                               if ( ! r.getCh_name().equals(tvd.center)) {\r
-                                       continue;\r
-                               }\r
-                               \r
-                               // 重複時間チェック\r
-                               boolean inRange = false;\r
-                               {\r
-                                       ArrayList<String> starts = new ArrayList<String>();\r
-                                       ArrayList<String> ends = new ArrayList<String>();\r
-                                       CommonUtils.getStartEndList(starts, ends, r);\r
-                                       if ( h >= 0 ) {\r
-                                               // 新聞形式はピンポイント(マウスポインタのある位置の時刻)\r
-                                               for (int j=0; j<starts.size(); j++) {\r
-                                                       if ( clicked.compareTo(starts.get(j)) >= 0 && clicked.compareTo(ends.get(j)) <= 0 ) {\r
-                                                               inRange = true;\r
-                                                               break;\r
-                                                       }\r
-                                               }\r
-                                       }\r
-                                       else {\r
-                                               // リスト形式は幅がある(開始~終了までの間のいずれかの時刻)\r
-                                               for (int j=0; j<starts.size(); j++) {\r
-                                                       if ( CommonUtils.isOverlap(tvd.startDateTime, tvd.endDateTime, starts.get(j), ends.get(j), false) ) {\r
-                                                               inRange = true;\r
-                                                               break;\r
-                                                       }\r
-                                               }\r
-                                       }\r
-                               }\r
-                               if ( ! inRange) {\r
-                                       continue;\r
-                               }\r
-                               \r
-                               // 類似予約あり!\r
-                               overlapRsvList.add(new LikeReserveItem(recorder, r));\r
-                       }\r
-               }\r
                \r
-               return;\r
-       }\r
-       \r
-       \r
        /*******************************************************************************\r
-        * ã\82¿ã\82¤ã\83\9eã\83¼é\96¢é\80£\r
+        * ã\83¬ã\82³ã\83¼ã\83\80ã\81®äº\88ç´\84æ\83\85å ±ã\82\92DLã\81\99ã\82\8b\r
         ******************************************************************************/\r
        \r
+       /***************************************\r
+        * ツールバートリガーによる\r
+        **************************************/\r
+\r
+       /**\r
+        *  レコーダの予約情報をDLする\r
+        */\r
+       private boolean doLoadRdRecorder(LoadRsvedFor lrf) {\r
                \r
-       /*******************************************************************************\r
-        * ここからおおむね初期化処理にかかわるメソッド群\r
-        ******************************************************************************/\r
-       \r
-       // レコーダから取得したエンコーダ情報で、登録済みレコーダ一覧を更新する\r
-       private void setEncoderInfo2RecorderList(HDDRecorder recorder) {\r
-               for (RecorderInfo ri : recInfoList ) {\r
-                       //if (rl.getRecorderEncoderList().size() == 0)\r
-                       {\r
-                               String mySelf = ri.getRecorderIPAddr()+":"+ri.getRecorderPortNo()+":"+ri.getRecorderId();\r
-                               String myMail = "MAIL"+":"+ri.getRecorderMacAddr()+":"+ri.getRecorderId();\r
-                               if (recorder.isMyself(mySelf) || recorder.isMyself(myMail)) {\r
-                                       ri.clearEncoders();\r
-                                       for (TextValueSet enc : recorder.getEncoderList()) {\r
-                                               ri.addEncoder(enc.getText());\r
-                                       }\r
-                                       break;\r
-                               }\r
+               if ( lrf == null ) {\r
+                       return doLoadRdRecorderAll();\r
+               }\r
+               else {\r
+                       switch (lrf) {\r
+                       case DETAILS:\r
+                               return doLoadRdReserveDetails();\r
+                       case RECORDED:\r
+                               return doLoadRdRecorded();\r
+                       case AUTORESERVE:\r
+                               return doLoadRdAutoReserves();\r
+                       default:\r
+                               break;\r
                        }\r
                }\r
+               return false;\r
        }\r
        \r
        /**\r
-        *  レコーダの予約情報をDLする\r
+        * レコーダの情報を全部DLする(ステータスウィンドウは自前で用意        する)\r
         */\r
-       private boolean reLoadRdReserve(final String recId) {\r
+       private boolean doLoadRdRecorderAll() {\r
+               \r
+               final String myself = getSelectedMySelf();\r
+               \r
                //\r
                StWinClear();\r
                \r
@@ -2700,7 +2530,8 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                                \r
                                TatCount tc = new TatCount();\r
                                \r
-                               loadRdReserve(true, recId);\r
+                               // 読み出せ!\r
+                               _loadRdRecorderAll(true,myself);\r
                                \r
                                // エンコーダ情報が更新されるかもしれないので、一覧のエンコーダ表示にも反映する\r
                                recsetting.redrawRecorderEncoderEntry();\r
@@ -2726,14 +2557,27 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                \r
                return true;\r
        }\r
-       private void loadRdReserve(final boolean force, final String myself) {\r
-\r
+       \r
+       \r
+       /**\r
+        * 予約一覧+予約詳細をDLする\r
+        */\r
+       private boolean doLoadRdReserveDetails() {\r
+               \r
+               final String myself = getSelectedMySelf();\r
+               \r
                //\r
-               new SwingBackgroundWorker(true) {\r
+               StWinClear();\r
+               \r
+               new SwingBackgroundWorker(false) {\r
                        \r
                        @Override\r
                        protected Object doWorks() throws Exception {\r
                                \r
+                               TatCount tc = new TatCount();\r
+                       \r
+                               boolean succeeded = true;\r
+                               \r
                                HDDRecorderList recs;\r
                                if ( myself != null ) {\r
                                        recs = recorders.findInstance(myself);\r
@@ -2742,142 +2586,139 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                                        recs = recorders;\r
                                }\r
                                for ( HDDRecorder recorder : recs ) {\r
-                                       switch ( recorder.getType() ) {\r
-                                       case RECORDER:\r
-                                       case EPG:\r
-                                       case MAIL:\r
-                                       case NULL:\r
-                                       case TUNER:\r
-                                               loadRdReserveOnce(recorder, force);\r
-                                               break;\r
-                                       default:\r
-                                               break;\r
+                                       \r
+                                       if ( ! recorder.isReserveListSupported() ) {\r
+                                               continue;\r
+                                       }\r
+                                       \r
+                                       // 各種設定の取得\r
+                                       if ( ! recorder.GetRdSettings(true) ) {\r
+                                               succeeded = false;\r
+                                               continue;\r
+                                       }\r
+                                       \r
+                                       // 予約一覧の取得\r
+                                       if ( ! recorder.GetRdReserve(true) ) {\r
+                                               succeeded = false;\r
+                                               continue;\r
+                                       }\r
+                                       \r
+                                       // レコーダから取得したエンコーダ情報で、登録済みレコーダ一覧を更新する\r
+                                       setEncoderInfo2RecorderList(recorder,true);\r
+                                       \r
+                                       // 予約詳細の取得\r
+                                       if ( recorder.isThereAdditionalDetails() ) {\r
+                                               if ( ! recorder.GetRdReserveDetails() ) {\r
+                                                       succeeded = false;\r
+                                                       continue;\r
+                                               }\r
+                                       }\r
+                                       \r
+                                       // レコーダの放送局名をWeb番組表の放送局名に置き換え\r
+                                       checkChNameIsRight(recorder);\r
+                                       \r
+                                       // 録画結果一覧を予約一覧に反映\r
+                                       if ( recorder.isRecordedListSupported() ) {\r
+                                               recorder.GetRdRecorded(false);\r
                                        }\r
                                }\r
                                \r
+                               if ( succeeded ) {\r
+                                       reserved.redrawReservedList();\r
+                                       recorded.redrawRecordedList();\r
+                                       \r
+                                       mwin.appendMessage(String.format("【予約詳細の取得処理が完了しました】 所要時間: %.2f秒",tc.end()));\r
+                               }\r
+                               else {\r
+                                       ringBeep();\r
+                                       mwin.appendMessage(String.format("【予約詳細の取得処理に失敗しました】 所要時間: %.2f秒",tc.end()));\r
+                               }\r
                                return null;\r
                        }\r
                        \r
                        @Override\r
                        protected void doFinally() {\r
+                               StWinSetVisible(false);\r
                        }\r
                }.execute();\r
+               \r
+               StWinSetLocationCenter(this);\r
+               StWinSetVisible(true);\r
+               \r
+               return true;\r
        }\r
        \r
-       private boolean loadRdReserveOnce(HDDRecorder recorder, boolean force) {\r
+       \r
+       /**\r
+        * 録画結果一覧をDLする\r
+        */\r
+       private boolean doLoadRdRecorded() {\r
                \r
-               mwin.appendMessage("【レコーダ情報取得】レコーダから情報を取得します: "+recorder.getRecorderId()+"("+recorder.getIPAddr()+":"+recorder.getPortNo()+")");\r
-               if ( recorder.isThereAdditionalDetails() && ! env.getForceGetRdReserveDetails() ) {\r
-                       mwin.appendMessage("<<<注意!>>>このレコーダでは予約詳細の個別取得を実行しないと正確な情報を得られない場合があります。");\r
-               }\r
+               final String myself = getSelectedMySelf();\r
                \r
-               try {\r
-                       \r
-                       // 各種設定の取得\r
-                       if ( ! recorder.GetRdSettings(force) ) {\r
-                               // 取得に失敗\r
-                               mwin.appendError(recorder.getErrmsg()+" "+recorder.getIPAddr()+":"+recorder.getPortNo()+":"+recorder.getRecorderId());\r
-                               ringBeep();\r
-                               return false;\r
-                       }\r
+               //\r
+               StWinClear();\r
+               \r
+               new SwingBackgroundWorker(false) {\r
                        \r
-                       // 予約一覧の取得\r
-                       if ( ! recorder.GetRdReserve(force) ) {\r
-                               // 取得に失敗\r
-                               mwin.appendError(recorder.getErrmsg()+" "+recorder.getIPAddr()+":"+recorder.getPortNo()+":"+recorder.getRecorderId());\r
-                               ringBeep();\r
-                               return false;\r
-                       }\r
+                       @Override\r
+                       protected Object doWorks() throws Exception {\r
+                               \r
+                               TatCount tc = new TatCount();\r
                        \r
-                       // レコーダから取得したエンコーダ情報で、登録済みレコーダ一覧を更新する\r
-                       setEncoderInfo2RecorderList(recorder);\r
-                       if ( force ) {\r
-                               recInfoList.save();\r
-                       }\r
-                       \r
-                       // 予約詳細の取得\r
-                       if ( env.getNeverGetRdReserveDetails() ) {\r
-                               mwin.appendMessage("【!】予約詳細情報の取得はスキップされました");\r
-                       }\r
-                       else if ( force && recorder.isThereAdditionalDetails() ) {\r
-                               boolean getDetails = true;\r
-                               if ( ! env.getForceGetRdReserveDetails() ) {\r
-                                       int ret = JOptOptionPane.showConfirmDialog(null, "詳細情報を取得しますか?(時間がかかります)", "今回の選択を既定の動作とする", "確認", JOptionPane.YES_NO_OPTION);\r
-                                       getDetails = (ret == JOptOptionPane.YES_OPTION);\r
-                                       if ( JOptOptionPane.isSelected() ) {\r
-                                               // 今回の選択を既定の動作とする\r
-                                               env.setForceGetRdReserveDetails(getDetails);\r
-                                               env.setNeverGetRdReserveDetails( ! getDetails);\r
-                                               env.save();\r
-                                               setting.updateSelections();\r
-                                       }\r
-                               }\r
-                               if ( ! getDetails ) {\r
-                                       mwin.appendMessage("【!】予約詳細情報の取得はスキップされました");\r
+                               boolean succeeded = true;\r
+                               \r
+                               HDDRecorderList recs;\r
+                               if ( myself != null ) {\r
+                                       recs = recorders.findInstance(myself);\r
                                }\r
                                else {\r
-                                       if ( ! recorder.GetRdReserveDetails()) {\r
-                                               // 取得に失敗\r
-                                               mwin.appendError(recorder.getErrmsg()+" "+recorder.getIPAddr()+":"+recorder.getPortNo()+":"+recorder.getRecorderId());\r
-                                               ringBeep();\r
-                                       }\r
+                                       recs = recorders;\r
                                }\r
-                       }\r
-                       \r
-                       // レコーダの放送局名をWeb番組表の放送局名に置き換え\r
-                       {       \r
-                               HashMap<String,String> misCN = new HashMap<String,String>();\r
-                               for ( ReserveList r : recorder.getReserves() ) {\r
-                                       if ( r.getCh_name() == null ) {\r
-                                               misCN.put(r.getChannel(),recorder.getRecorderId());\r
+                               for ( HDDRecorder recorder : recs ) {\r
+                                       if ( ! recorder.isRecordedListSupported() ) {\r
+                                               succeeded = false;\r
+                                               continue;\r
                                        }\r
-                               }\r
-                               if ( misCN.size() > 0 ) {\r
-                                       for ( String cn : misCN.keySet() ) {\r
-                                               String msg = "【警告(予約一覧)】 <"+misCN.get(cn)+"> \"レコーダの放送局名\"を\"Web番組表の放送局名\"に変換できません。CHコード設定に設定を追加してください:\"レコーダの放送局名\"="+cn;\r
-                                               mwin.appendMessage(msg);\r
+\r
+                                       if ( ! recorder.GetRdRecorded(true) ) {\r
+                                               succeeded = false;\r
                                        }\r
-                                       ringBeep();\r
                                }\r
-                       }\r
-                       \r
-                       // 自動予約一覧の取得\r
-                       if ( recorder.isEditAutoReserveSupported() ) {\r
-                               if ( ! recorder.GetRdAutoReserve(force) ) {\r
-                                       // 取得に失敗\r
-                                       mwin.appendError(recorder.getErrmsg()+" "+recorder.getIPAddr()+":"+recorder.getPortNo()+":"+recorder.getRecorderId());\r
-                                       ringBeep();\r
-                                       return false;\r
+                               \r
+                               if ( succeeded ) {\r
+                                       reserved.redrawReservedList();\r
+                                       recorded.redrawRecordedList();\r
+                                       \r
+                                       mwin.appendMessage(String.format("【録画結果一覧の取得処理が完了しました】 所要時間: %.2f秒",tc.end()));\r
                                }\r
-                       }\r
-                       \r
-                       // 録画結果一覧の取得\r
-                       if ( env.getSkipGetRdRecorded() ) {\r
-                               mwin.appendMessage("【!】録画結果一覧の取得はスキップされました");\r
-                       }\r
-                       else {\r
-                               if ( ! recorder.GetRdRecorded(force) ) {\r
-                                       // 取得に失敗\r
-                                       mwin.appendError(recorder.getErrmsg()+" "+recorder.getIPAddr()+":"+recorder.getPortNo()+":"+recorder.getRecorderId());\r
+                               else {\r
                                        ringBeep();\r
-                                       return false;\r
+                                       mwin.appendMessage(String.format("【録画結果一覧の取得処理に失敗しました】 所要時間: %.2f秒",tc.end()));\r
                                }\r
+                               return null;\r
                        }\r
                        \r
-               }\r
-               catch (Exception e) {\r
-                       e.printStackTrace();\r
-                       mwin.appendError("【致命的エラー】予約一覧の取得で例外が発生 "+recorder.getIPAddr()+":"+recorder.getPortNo()+":"+recorder.getRecorderId());\r
-                       ringBeep();\r
-                       return false;\r
-               }\r
+                       @Override\r
+                       protected void doFinally() {\r
+                               StWinSetVisible(false);\r
+                       }\r
+               }.execute();\r
+               \r
+               StWinSetLocationCenter(this);\r
+               StWinSetVisible(true);\r
+               \r
                return true;\r
        }\r
 \r
+\r
        /**\r
         * 録画結果一覧をDLする\r
         */\r
-       private boolean reLoadRdRecorded(final String myself) {\r
+       private boolean doLoadRdAutoReserves() {\r
+               \r
+               final String myself = getSelectedMySelf();\r
+               \r
                //\r
                StWinClear();\r
                \r
@@ -2898,33 +2739,23 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                                        recs = recorders;\r
                                }\r
                                for ( HDDRecorder recorder : recs ) {\r
-                                       switch ( recorder.getType() ) {\r
-                                       case RECORDER:\r
-                                       case EPG:\r
-                                       case MAIL:\r
-                                       case NULL:\r
-                                       case TUNER:\r
-                                               if ( ! recorder.GetRdSettings(true) ) {\r
-                                                       succeeded = false;\r
-                                               }\r
-                                               if ( ! recorder.GetRdRecorded(true) ) {\r
-                                                       succeeded = false;\r
-                                               }\r
-                                               break;\r
-                                       default:\r
-                                               break;\r
+                                       if ( ! recorder.isEditAutoReserveSupported() ) {\r
+                                               succeeded = false;\r
+                                               continue;\r
+                                       }\r
+                                       \r
+                                       if ( ! recorder.GetRdAutoReserve(true) ) {\r
+                                               succeeded = false;\r
                                        }\r
                                }\r
                                \r
                                if ( succeeded ) {\r
-                                       reserved.redrawReservedList();\r
-                                       recorded.redrawRecordedList();\r
-                                       \r
-                                       mwin.appendMessage(String.format("【録画結果一覧の取得処理が完了しました】 所要時間: %.2f秒",tc.end()));\r
+                                       // 再描画はここじゃないよ\r
+                                       mwin.appendMessage(String.format("【自動予約一覧の取得処理が完了しました】 所要時間: %.2f秒",tc.end()));\r
                                }\r
                                else {\r
                                        ringBeep();\r
-                                       mwin.appendMessage(String.format("【録画結果一覧の取得処理に失敗しました】 所要時間: %.2f秒",tc.end()));\r
+                                       mwin.appendMessage(String.format("【自動予約一覧の取得処理に失敗しました】 所要時間: %.2f秒",tc.end()));\r
                                }\r
                                return null;\r
                        }\r
@@ -2940,13 +2771,296 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                \r
                return true;\r
        }\r
+       \r
+       /***************************************\r
+        * 自クラス内呼び出しによる\r
+        **************************************/\r
+       \r
+       /**\r
+        * レコーダの情報を全部DLする(ステータスウィンドウは呼び出し元が準備する)\r
+        */\r
+       private void loadRdReservesAll(final boolean force, final String myself) {\r
+\r
+               new SwingBackgroundWorker(true) {\r
+                       \r
+                       @Override\r
+                       protected Object doWorks() throws Exception {\r
+                               \r
+                               _loadRdRecorderAll(force,myself);\r
+                               \r
+                               return null;\r
+                       }\r
+                       \r
+                       @Override\r
+                       protected void doFinally() {\r
+                       }\r
+               }.execute();\r
+       }\r
+       \r
+       /***************************************\r
+        * レコーダの情報を取得する部品群\r
+        **************************************/\r
+       \r
+       private boolean _loadRdRecorderAll(final boolean force, final String myself) {\r
+\r
+               HDDRecorderList recs;\r
+               if ( myself != null ) {\r
+                       recs = recorders.findInstance(myself);\r
+               }\r
+               else {\r
+                       recs = recorders;\r
+               }\r
+               \r
+               boolean success = true;\r
+               \r
+               for ( HDDRecorder recorder : recs ) {\r
+                       if ( recorder.isReserveListSupported() ) {\r
+                               success = success & _loadRdRecorder(recorder, force);\r
+                       }\r
+               }\r
+               \r
+               return success;\r
+       }\r
+       \r
+       private boolean _loadRdRecorder(HDDRecorder recorder, boolean force) {\r
+               \r
+               mwin.appendMessage("【レコーダ情報取得】情報を取得します: "+recorder.Myself());\r
+               if ( recorder.isThereAdditionalDetails() && env.getForceLoadReserveDetails() == 2 ) {\r
+                       mwin.appendMessage("<<<注意!>>>このレコーダでは予約詳細の個別取得を実行しないと正確な情報を得られない場合があります。");\r
+               }\r
+               \r
+               try {\r
+                       \r
+                       // 各種設定の取得\r
+                       if ( ! _loadRdSettings(recorder,force) ) {\r
+                               return false;\r
+                       }\r
+                       \r
+                       // 予約一覧の取得\r
+                       if ( ! _loadRdReserves(recorder,force) ) {\r
+                               return false;\r
+                       }\r
+                       \r
+                       // レコーダから取得したエンコーダ情報で、登録済みレコーダ一覧を更新する\r
+                       setEncoderInfo2RecorderList(recorder,force);\r
+                       \r
+                       // 予約詳細の取得(強制取得じゃなければ処理不要)\r
+                       if ( force && ! _loadRdReserveDetails(recorder,force) ) {\r
+                               return false;\r
+                       }\r
+                       \r
+                       // レコーダの放送局名をWeb番組表の放送局名に置き換え\r
+                       checkChNameIsRight(recorder);\r
+                       \r
+                       // 自動予約一覧の取得\r
+                       if ( ! _loadRdAutoReserves(recorder,force) ) {\r
+                               return false;\r
+                       }\r
+                       \r
+                       // 録画結果一覧の取得\r
+                       if ( ! _loadRdRecorded(recorder,force) ) {\r
+                               return false;\r
+                       }\r
+               }\r
+               catch (Exception e) {\r
+                       e.printStackTrace();\r
+                       mwin.appendError("【致命的エラー】予約一覧の取得で例外が発生 "+recorder.getIPAddr()+":"+recorder.getPortNo()+":"+recorder.getRecorderId());\r
+                       ringBeep();\r
+                       return false;\r
+               }\r
+               return true;\r
+       }\r
+       \r
+       \r
+       /***************************************\r
+        * レコーダの情報を取得する部品群\r
+        **************************************/\r
+       \r
+       private boolean _loadRdSettings(HDDRecorder recorder, boolean force) {\r
+               if ( recorder.GetRdSettings(force) ) {\r
+                       return true;\r
+               }\r
+               \r
+               mwin.appendError(recorder.getErrmsg()+" "+recorder.Myself());   // 取得に失敗\r
+               ringBeep();\r
+               return false;\r
+       }\r
+       \r
+       private boolean _loadRdReserves(HDDRecorder recorder, boolean force) {\r
+               if ( recorder.GetRdReserve(force) ) {\r
+                       return true;\r
+               }\r
+               \r
+               mwin.appendError(recorder.getErrmsg()+" "+recorder.Myself());   // 取得に失敗\r
+               ringBeep();\r
+               return false;\r
+       }\r
+       \r
+       private boolean _loadRdReserveDetails(HDDRecorder recorder, boolean force) {\r
+               \r
+               if ( ! recorder.isThereAdditionalDetails() ) {\r
+                       return true;    // 非対応レコーダ\r
+               }\r
+               \r
+               boolean skip = false;\r
+               if ( force && env.getForceLoadReserveDetails() == 2 ) {\r
+                       skip = true;\r
+               }\r
+               else if ( force && env.getForceLoadReserveDetails() == 0 ) {\r
+                       int ret = JOptOptionPane.showConfirmDialog(stwin, "<HTML>詳細情報を取得しますか?(時間がかかります)<BR><BR>"+recorder.Myself()+"</HTML>", "今回の選択を既定の動作とする", "※既定動作は各種設定で変更できます", "確認", JOptionPane.YES_NO_OPTION);\r
+                       skip = (ret != JOptOptionPane.YES_OPTION);\r
+                       \r
+                       if ( JOptOptionPane.isSelected() ) {\r
+                               // 今回の選択を既定の動作とする\r
+                               env.setForceLoadReserveDetails(skip ? 2 : 1);\r
+                               env.save();\r
+                               if (setting!=null) setting.updateSelections();\r
+                       }\r
+               }\r
+               if ( skip ) {\r
+                       mwin.appendMessage("【!】予約詳細情報の取得はスキップされました");\r
+                       return true;\r
+               }\r
+               \r
+               if ( recorder.GetRdReserveDetails()) {\r
+                       return true;    // 取得成功\r
+               }\r
+               \r
+               mwin.appendError(recorder.getErrmsg()+" "+recorder.Myself());\r
+               ringBeep();\r
+               return false;           // 取得失敗\r
+       }\r
+\r
+       private boolean _loadRdAutoReserves(HDDRecorder recorder, boolean force) {\r
+\r
+               if ( ! recorder.isEditAutoReserveSupported() ) {\r
+                       return true;\r
+               }\r
+               \r
+               boolean skip = false;\r
+               if ( force && env.getForceLoadAutoReserves() == 2 ) {\r
+                       skip = true;\r
+               }\r
+               else if ( force && env.getForceLoadAutoReserves() == 0 ) {\r
+                       int ret = JOptOptionPane.showConfirmDialog(stwin, "<HTML>自動予約一覧を取得しますか?(時間がかかります)<BR><BR>"+recorder.Myself()+"</HTML>", "今回の選択を既定の動作とする", "※既定動作は各種設定で変更できます", "確認", JOptionPane.YES_NO_OPTION);\r
+                       skip = (ret != JOptOptionPane.YES_OPTION);\r
+                       \r
+                       if ( JOptOptionPane.isSelected() ) {\r
+                               // 今回の選択を既定の動作とする\r
+                               env.setForceLoadAutoReserves(skip ? 2 : 1);\r
+                               env.save();\r
+                               if (setting!=null) setting.updateSelections();\r
+                       }\r
+               }\r
+               if ( skip ) {\r
+                       mwin.appendMessage("【!】自動予約一覧の取得はスキップされました");\r
+                       return true;\r
+               }\r
+\r
+               if ( recorder.GetRdAutoReserve(force) ) {\r
+                       return true;\r
+               }\r
+               \r
+               mwin.appendError(recorder.getErrmsg()+" "+recorder.Myself());\r
+               ringBeep();\r
+               return false;\r
+       }\r
+       \r
+       private boolean _loadRdRecorded(HDDRecorder recorder, boolean force) {\r
+               \r
+               if ( ! recorder.isRecordedListSupported() ) {\r
+                       return true;\r
+               }\r
+               \r
+               boolean skip = false;\r
+               if ( force && env.getForceLoadRecorded() == 2 ) {\r
+                       skip = true;\r
+               }\r
+               if ( force && env.getForceLoadRecorded() == 0 ) {\r
+                       int ret = JOptOptionPane.showConfirmDialog(stwin, "<HTML>録画結果一覧を取得しますか?(時間がかかります)<BR><BR>"+recorder.Myself()+"</HTML>", "今回の選択を既定の動作とする", "※既定動作は各種設定で変更できます", "確認", JOptionPane.YES_NO_OPTION);\r
+                       skip = (ret != JOptOptionPane.YES_OPTION);\r
+                       \r
+                       if ( JOptOptionPane.isSelected() ) {\r
+                               // 今回の選択を既定の動作とする\r
+                               env.setForceLoadRecorded(skip ? 2 : 1);\r
+                               env.save();\r
+                               if (setting!=null) setting.updateSelections();\r
+                       }\r
+               }\r
+               if ( skip ) {\r
+                       mwin.appendMessage("【!】録画結果一覧の取得はスキップされました");\r
+                       return true;\r
+               }\r
+               \r
+               if ( recorder.GetRdRecorded(force) ) {\r
+                       return true;\r
+               }\r
+               \r
+               mwin.appendError(recorder.getErrmsg()+" "+recorder.Myself());\r
+               ringBeep();\r
+               return false;\r
+       }\r
 \r
        /**\r
-        * Web番組表をDLする\r
+        * レコーダから取得したエンコーダ情報で、登録済みレコーダ一覧を更新する\r
+        * @param recorder\r
+        */\r
+       private void setEncoderInfo2RecorderList(HDDRecorder recorder, boolean force) {\r
+               for (RecorderInfo ri : recInfoList ) {\r
+                       //if (rl.getRecorderEncoderList().size() == 0)\r
+                       {\r
+                               //String mySelf = ri.getRecorderIPAddr()+":"+ri.getRecorderPortNo()+":"+ri.getRecorderId();\r
+                               //String myMail = "MAIL"+":"+ri.getRecorderMacAddr()+":"+ri.getRecorderId();\r
+                               //if (recorder.isMyself(mySelf) || recorder.isMyself(myMail)) {\r
+                               if ( recorder.isMyself(ri.MySelf()) ) {\r
+                                       ri.clearEncoders();\r
+                                       for (TextValueSet enc : recorder.getEncoderList()) {\r
+                                               ri.addEncoder(enc.getText());\r
+                                       }\r
+                                       \r
+                                       if ( force ) {\r
+                                               recInfoList.save();\r
+                                       }\r
+                                       break;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+       \r
+       /**\r
+        * 予約一覧の放送局名が正しい形式であるかどうかのチェック\r
+        */\r
+       private void checkChNameIsRight(HDDRecorder recorder) {\r
+               HashMap<String,String> misCN = new HashMap<String,String>();\r
+               for ( ReserveList r : recorder.getReserves() ) {\r
+                       if ( r.getCh_name() == null ) {\r
+                               misCN.put(r.getChannel(),recorder.getRecorderId());\r
+                       }\r
+               }\r
+               if ( misCN.size() > 0 ) {\r
+                       for ( String cn : misCN.keySet() ) {\r
+                               String msg = "【警告(予約一覧)】 <"+misCN.get(cn)+"> \"レコーダの放送局名\"を\"Web番組表の放送局名\"に変換できません。CHコード設定に設定を追加してください:\"レコーダの放送局名\"="+cn;\r
+                               mwin.appendMessage(msg);\r
+                       }\r
+                       ringBeep();\r
+               }\r
+       }\r
+       \r
+       /*******************************************************************************\r
+        * Web番組表をDLする\r
+        ******************************************************************************/\r
+       \r
+       /***************************************\r
+        * ツールバートリガー(と、各種設定変更トリガー)による\r
+        **************************************/\r
+       \r
+       /**\r
+        * Web番組表をDL→再描画まで\r
         * <P>単体実行の場合はこちらを呼び出す\r
         * <P>部品実行の場合はこちらを呼び出す:{@link #loadTVProgram(boolean, LoadFor)}\r
+        * @see #doRedrawTVProgram()\r
         */\r
-       private boolean reLoadTVProgram(final LoadFor lf) {\r
+       private boolean doLoadTVProgram(final boolean force, final LoadFor lf) {\r
                //\r
                StWinClear();\r
                \r
@@ -2957,18 +3071,7 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                                \r
                                TatCount tc = new TatCount();\r
                                \r
-                               loadTVProgram(true, lf);\r
-                               \r
-                               // 新聞描画枠のリセット\r
-                               paper.clearPanel();\r
-                               paper.buildMainViewByDate();\r
-                               \r
-                               // サイドツリーの再構築\r
-                               paper.redrawTreeByPassed();\r
-                               \r
-                               // 再描画\r
-                               paper.reselectTree();\r
-                               listed.reselectTree();\r
+                               loadTVProgram(force, lf);\r
                                \r
                                mwin.appendMessage(String.format("[Web番組表取得] 【完了しました】 所要時間: %.2f秒",tc.end()));\r
                                return null;\r
@@ -2985,124 +3088,142 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                \r
                return true;\r
        }\r
+\r
+       /**\r
+        * \r
+        * @see #doLoadTVProgram(boolean, LoadFor)\r
+        */\r
+       private void doRedrawTVProgram() {\r
+               \r
+               // 新聞描画枠のリセット\r
+               paper.clearPanel();\r
+               paper.buildMainViewByDate();\r
+               \r
+               // サイドツリーの再構築\r
+               paper.redrawTreeByDate();\r
+               paper.redrawTreeByPassed();\r
+               \r
+               listed.redrawTreeByHistory();\r
+               listed.redrawTreeByCenter();\r
+               \r
+               // 再描画\r
+               paper.reselectTree();\r
+               listed.reselectTree();\r
+       }\r
+       \r
+       /***************************************\r
+        * 自クラス内呼び出しによる\r
+        **************************************/\r
        \r
        /**\r
         * Web番組表をDLする\r
-        * <P>単体実行の場合はこちらを呼び出す:{@link #reLoadTVProgram(LoadFor)}\r
+        * <P>単体実行の場合はこちらを呼び出す:{@link #doLoadTVProgram(boolean, tainavi.Viewer.LoadFor)}\r
         * <P>部品実行の場合はこちらを呼び出す\r
         */\r
-       private void loadTVProgram(final boolean b, final LoadFor lf) {\r
+       private boolean loadTVProgram(final boolean force, final LoadFor lf) {\r
                \r
                final String FUNCID = "[Web番組表取得] ";\r
-               final String ERRID = "[ERROR]"+FUNCID;\r
-               //\r
-               new SwingBackgroundWorker(true) {\r
-                       \r
-                       @Override\r
-                       protected Object doWorks() throws Exception {\r
-                               try {\r
-                                       String msg;\r
-                                       TVProgram tvp;\r
-                                       \r
-                                       tvp = tvprograms.getTvProgPlugin(null);\r
-                                       if ( tvp != null )\r
-                                       {\r
-                                               String sType = "地上波&BS番組表";\r
-                                               if (lf == LoadFor.ALL || lf == LoadFor.TERRA) {\r
-                                                       loadTVProgramOnce(tvp, sType, tvp.getSelectedArea(), false, b);\r
-                                               }\r
-                                               else {\r
-                                                       stwin.appendMessage(FUNCID+sType+"へのアクセスはスキップされました: "+tvp.getTVProgramId());\r
-                                               }\r
-                                       }\r
-                                       \r
-                                       tvp = tvprograms.getCsProgPlugin(null);\r
-                                       if ( tvp != null )\r
-                                       {\r
-                                               String sType = "CS番組表[プライマリ]";\r
-                                               if (lf == LoadFor.ALL || lf == LoadFor.CS || lf == LoadFor.CSo1) {\r
-                                                       loadTVProgramOnce(tvp, sType, tvp.getSelectedArea(), false, b);\r
-                                               }\r
-                                               else {\r
-                                                       stwin.appendMessage(FUNCID+sType+"へのアクセスはスキップされました: "+tvp.getTVProgramId());\r
-                                               }\r
-                                       }\r
-                                       \r
-                                       tvp = tvprograms.getCs2ProgPlugin(null);\r
-                                       if ( tvp != null )\r
-                                       {\r
-                                               String sType = "CS番組表[セカンダリ]";\r
-                                               if (lf == LoadFor.ALL || lf == LoadFor.CS || lf == LoadFor.CSo2) {\r
-                                                       loadTVProgramOnce(tvp, sType, tvp.getSelectedArea(), false, b);\r
-                                               }\r
-                                               else {\r
-                                                       stwin.appendMessage(FUNCID+sType+"へのアクセスはスキップされました: "+tvp.getTVProgramId());\r
-                                               }\r
-                                       }\r
-                                       \r
-                                       tvp = tvprograms.getSyobo();\r
-                                       if ( tvp != null ) {\r
-                                               String sType = "しょぼかる";\r
-                                               if ( (lf == LoadFor.ALL || lf == LoadFor.SYOBO) && enableWebAccess && env.getUseSyobocal()) {\r
-                                                       tvp.loadCenter(tvp.getSelectedCode(), b);       // しょぼかるには放送局リストを取得するイベントが他にないので\r
-                                                       loadTVProgramOnce(tvp, sType, null, true, b);\r
-                                               }\r
-                                               else {\r
-                                                       stwin.appendMessage(FUNCID+sType+"へのアクセスはスキップされました.");\r
-                                               }\r
-                                               \r
-                                               // しょぼかるの新番組マークを引き継ぐ\r
-                                               attachSyoboNew();\r
-                                       }\r
-                               \r
-                                       PickedProgram pickup = tvprograms.getPickup();\r
-                                       if ( tvp != null ) {\r
-                                               pickup.refresh();\r
-                                               //pickup.save();\r
-                                       }\r
-                                       \r
-                                       // 番組タイトルを整形する\r
-                                       fixTitle();\r
-                                       fixDetail();\r
-                                       \r
-                                       // 検索結果の再構築\r
-                                       stwin.appendMessage(FUNCID+"検索結果を生成します.");\r
-                                       mpList.clear(env.getDisableFazzySearch(), env.getDisableFazzySearchReverse());\r
-                                       mpList.build(tvprograms, trKeys.getTraceKeys(), srKeys.getSearchKeys());\r
-                                       \r
-                                       // 過去ローグ\r
-                                       if ( env.getUsePassedProgram() ) {\r
-                                               TatCount tc = new TatCount();\r
-                                               stwin.appendMessage(FUNCID+"過去ログを生成します.");\r
-                                               if ( tvprograms.getPassed().save(tvprograms.getIterator(), chsort.getClst(), env.getPrepPassedProgramCount()) ) {\r
-                                                       msg = String.format(FUNCID+"過去ログを生成しました [%.2f秒].",tc.end());\r
-                                                       StdAppendMessage(msg);\r
-                                               }\r
-                                               //PassedProgramList.getDateList(env.getPassedLogLimit());\r
-                                       }\r
-                                       else {\r
-                                               stwin.appendMessage(FUNCID+"過去ログは記録されません.");\r
-                                       }\r
+               final String ERRID = "[ERROR]"+FUNCID;\r
+               \r
+               try {\r
+                       String msg;\r
+                       TVProgram tvp;\r
+                       \r
+                       tvp = tvprograms.getTvProgPlugin(null);\r
+                       if ( tvp != null )\r
+                       {\r
+                               String sType = "地上波&BS番組表";\r
+                               if (lf == LoadFor.ALL || lf == LoadFor.TERRA) {\r
+                                       loadTVProgramOnce(tvp, sType, tvp.getSelectedArea(), false, force);\r
                                }\r
-                               catch (Exception e) {\r
-                                       e.printStackTrace();\r
-                                       mwin.appendError(ERRID+"番組情報の取得で例外が発生");\r
-                                       ringBeep();\r
-                                       return null;\r
+                               else {\r
+                                       stwin.appendMessage(FUNCID+sType+"へのアクセスはスキップされました: "+tvp.getTVProgramId());\r
                                }\r
-                               return null;\r
                        }\r
                        \r
-                       @Override\r
-                       protected void doFinally() {\r
+                       tvp = tvprograms.getCsProgPlugin(null);\r
+                       if ( tvp != null )\r
+                       {\r
+                               String sType = "CS番組表[プライマリ]";\r
+                               if (lf == LoadFor.ALL || lf == LoadFor.CS || lf == LoadFor.CSo1 || lf == LoadFor.CSwSD) {\r
+                                       loadTVProgramOnce(tvp, sType, tvp.getSelectedArea(), false, force);\r
+                               }\r
+                               else {\r
+                                       stwin.appendMessage(FUNCID+sType+"へのアクセスはスキップされました: "+tvp.getTVProgramId());\r
+                               }\r
                        }\r
-               }.execute();\r
+                       \r
+                       tvp = tvprograms.getCs2ProgPlugin(null);\r
+                       if ( tvp != null )\r
+                       {\r
+                               String sType = "CS番組表[セカンダリ]";\r
+                               if (lf == LoadFor.ALL || lf == LoadFor.CS || lf == LoadFor.CSo2 || lf == LoadFor.CSwSD) {\r
+                                       loadTVProgramOnce(tvp, sType, tvp.getSelectedArea(), false, force);\r
+                               }\r
+                               else {\r
+                                       stwin.appendMessage(FUNCID+sType+"へのアクセスはスキップされました: "+tvp.getTVProgramId());\r
+                               }\r
+                       }\r
+                       \r
+                       tvp = tvprograms.getSyobo();\r
+                       if ( tvp != null ) {\r
+                               String sType = "しょぼかる";\r
+                               if ( (lf == LoadFor.ALL || lf == LoadFor.SYOBO) && enableWebAccess && env.getUseSyobocal()) {\r
+                                       tvp.loadCenter(tvp.getSelectedCode(), force);   // しょぼかるには放送局リストを取得するイベントが他にないので\r
+                                       loadTVProgramOnce(tvp, sType, null, true, force);\r
+                               }\r
+                               else {\r
+                                       stwin.appendMessage(FUNCID+sType+"へのアクセスはスキップされました.");\r
+                               }\r
+                               \r
+                               // しょぼかるの新番組マークを引き継ぐ\r
+                               attachSyoboNew();\r
+                       }\r
+               \r
+                       PickedProgram pickup = tvprograms.getPickup();\r
+                       if ( tvp != null ) {\r
+                               pickup.refresh();\r
+                               //pickup.save();\r
+                       }\r
+                       \r
+                       // 番組タイトルを整形する\r
+                       fixTitle();\r
+                       fixDetail();\r
+                       \r
+                       // 検索結果の再構築\r
+                       stwin.appendMessage(FUNCID+"検索結果を生成します.");\r
+                       mpList.clear(env.getDisableFazzySearch(), env.getDisableFazzySearchReverse());\r
+                       mpList.build(tvprograms, trKeys.getTraceKeys(), srKeys.getSearchKeys());\r
+                       \r
+                       // 過去ローグ\r
+                       if ( env.getUsePassedProgram() ) {\r
+                               TatCount tc = new TatCount();\r
+                               stwin.appendMessage(FUNCID+"過去ログを生成します.");\r
+                               if ( tvprograms.getPassed().save(tvprograms.getIterator(), chsort.getClst(), env.getPrepPassedProgramCount()) ) {\r
+                                       msg = String.format(FUNCID+"過去ログを生成しました [%.2f秒].",tc.end());\r
+                                       StdAppendMessage(msg);\r
+                               }\r
+                               //PassedProgramList.getDateList(env.getPassedLogLimit());\r
+                       }\r
+                       else {\r
+                               stwin.appendMessage(FUNCID+"過去ログは記録されません.");\r
+                       }\r
+               }\r
+               catch (Exception e) {\r
+                       e.printStackTrace();\r
+                       mwin.appendError(ERRID+"番組情報の取得で例外が発生");\r
+                       ringBeep();\r
+                       return false;\r
+               }\r
+               \r
+               return true;\r
        }\r
        \r
+       // 分割\r
        private void loadTVProgramOnce(TVProgram tvp, String sType, String aName, boolean loadonly, boolean force) {\r
                \r
                final String FUNCID = "[Web番組表取得] ";\r
-               final String ERRID = "[ERROR]"+FUNCID;\r
+//             final String ERRID = "[ERROR]"+FUNCID;\r
                \r
                // ログ\r
                String msg = FUNCID+sType+"を取得します: "+tvp.getTVProgramId();\r
@@ -3282,6 +3403,8 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
        \r
        // 番組タイトルを整形する\r
        private void fixTitle() {\r
+               // 番組追跡からサブタイトルを除外するかどうかのフラグ\r
+               ProgDetailList.tracenOnlyTitle = env.getFixTitle() && env.getTraceOnlyTitle();\r
                //\r
                if ( ! env.getFixTitle()) {\r
                        return;\r
@@ -3306,9 +3429,12 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                                                                // NHK系で先頭が「アニメ 」ではじまるものから「アニメ 」を削除する\r
                                                                tvd.title = tvd.title.replaceFirst("^アニメ[  ・]+","");\r
                                                                tvd.titlePop = TraceProgram.replacePop(tvd.title);\r
-                                                               tvd.SearchStrKeys = TraceProgram.splitKeys(tvd.titlePop);\r
                                                        }\r
-                                                       if ( (tvd.title.contains("劇場版") || tvd.detail.contains("映画")) && ! tvd.isEqualsGenre(ProgGenre.MOVIE, ProgSubgenre.MOVIE_ANIME) ) {\r
+                                                       if ( tvd.title.contains("コメンタリ") || tvd.detail.contains("コメンタリ") ) {\r
+                                                               // "コメンタリ"の記述のあるものは「副音声」扱いにする(副音声でなくても)\r
+                                                               tvd.option.add(ProgOption.MULTIVOICE);\r
+                                                       }\r
+                                                       if ( (tvd.title.contains("劇場版") || (tvd.detail.contains("映画") && ! tvd.detail.contains("映画館"))) && ! tvd.isEqualsGenre(ProgGenre.MOVIE, ProgSubgenre.MOVIE_ANIME) ) {\r
                                                                // ジャンル=アニメだがタイトルに「劇場版」が含まれるならジャンル=映画(アニメ映画)を追加する\r
                                                                if ( tvd.genrelist == null ) {\r
                                                                        tvd.genrelist = new ArrayList<ProgGenre>();\r
@@ -3328,11 +3454,6 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                                                        // ジャンル=映画でサブジャンルが複数ありアニメが優先されてないものはアニメを優先する\r
                                                        tvd.subgenre = ProgSubgenre.MOVIE_ANIME;\r
                                                }\r
-                                               \r
-                                               // サブタイトルを番組追跡の対象から外す\r
-                                               if ( env.getTraceOnlyTitle() && tvd.title != tvd.splitted_title ) {\r
-                                                       tvd.SearchStrKeys = TraceProgram.splitKeys(TraceProgram.replacePop(tvd.splitted_title));        // 番組追跡の検索用インデックスは、サブタイトルを削除したもので置き換える\r
-                                               }\r
                                        }\r
                                }\r
                        }\r
@@ -3376,6 +3497,11 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                tvd.dontoverlapdown = (tvd.center.startsWith("NHK") || tvd.center.startsWith("NHK"));\r
        }\r
        \r
+       \r
+       /*******************************************************************************\r
+        * 過去ログ検索\r
+        ******************************************************************************/\r
+       \r
        /**\r
         * <P>過去ログから検索キーワードにマッチする情報を取得する\r
         * <P>全部検索がヒットした結果がかえるのだから {@link ProgDetailList} ではなく {@link MarkedProgramList} を使うべきなのだが…\r
@@ -3457,6 +3583,157 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                return true;\r
        }\r
 \r
+       \r
+       /*******************************************************************************\r
+        * スナップ・ショット!\r
+        ******************************************************************************/\r
+       \r
+       /**\r
+        * 番組表のスナップショットをファイルに保存したり印刷したりする\r
+        */\r
+       private boolean getSnapshot(int currentpage, int numberofpages) {\r
+               \r
+               try {\r
+                       String fname;\r
+                       if ( mainWindow.isTabSelected(MWinTab.LISTED) ) {\r
+                               // リスト形式\r
+                               fname = String.format("snapshot.%s",env.getSnapshotFmt().getExtension());\r
+                               CommonSwingUtils.saveComponentAsJPEG(listed.getCurrentView(), listed.getTableHeader(), null, listed.getTableBody(), fname, env.getSnapshotFmt(), Viewer.this);\r
+                       }\r
+                       else if ( mainWindow.isTabSelected(MWinTab.PAPER) ){\r
+                               // 新聞形式\r
+                               if ( env.getDrawcacheEnable() || ! env.isPagerEnabled() ) {\r
+                                       fname = String.format("snapshot.%s",env.getSnapshotFmt().getExtension());\r
+                               }\r
+                               else {\r
+                                       if ( env.getAllPageSnapshot() ) {\r
+                                               for ( int i=0; i<numberofpages; i++ ) {\r
+                                                       if ( i != currentpage ) {\r
+                                                               // カレントページは最後にスナップる(再描画を1回で済ませるため)\r
+                                                               toolBar.setSelectedPagerIndex(i);\r
+                                                               fname = String.format("snapshot%02d.%s",i+1,env.getSnapshotFmt().getExtension());\r
+                                                               CommonSwingUtils.saveComponentAsJPEG(paper.getCurrentView(), paper.getCenterPane(), paper.getTimebarPane(), paper.getCurrentPane(), fname, env.getSnapshotFmt(), Viewer.this);\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                                       fname = String.format("snapshot%02d.%s",currentpage+1,env.getSnapshotFmt().getExtension());\r
+                                       toolBar.setSelectedPagerIndex(currentpage);\r
+                               }\r
+                               CommonSwingUtils.saveComponentAsJPEG(paper.getCurrentView(), paper.getCenterPane(), paper.getTimebarPane(), paper.getCurrentPane(), fname, env.getSnapshotFmt(), Viewer.this);\r
+                       }\r
+                       else {\r
+                               // 他のタブ\r
+                               return true;\r
+                       }\r
+                       \r
+                       Desktop desktop = Desktop.getDesktop();\r
+                       if (env.getPrintSnapshot()) {\r
+                               // 印刷\r
+                               desktop.print(new File(fname));\r
+                       }\r
+                       else {\r
+                               // ファイルに保存\r
+                               String emsg = CommonUtils.openFile(fname);\r
+                               if (emsg != null) {\r
+                                       mwin.appendError(emsg);\r
+                                       return false;\r
+                               }\r
+                       }\r
+                       \r
+                       return true;\r
+                       \r
+               } catch (IOException e) {\r
+                       e.printStackTrace();\r
+               }\r
+               \r
+               return false;\r
+       }\r
+       \r
+       \r
+       /*******************************************************************************\r
+        * ここからおおむね初期化処理にかかわるメソッド群\r
+        ******************************************************************************/\r
+\r
+       /**\r
+        * 各種設定の変更の反映\r
+        */\r
+       private boolean setEnv(final boolean reload_prog) {\r
+               \r
+               bounds.save();\r
+               cbitems.save();\r
+               env.save();\r
+\r
+               // CommonUtilsの設定変更\r
+               CommonUtils.setAdjLateNight(env.getAdjLateNight());\r
+               CommonUtils.setExpandTo8(env.getExpandTo8());\r
+               CommonUtils.setUseRundll32(env.getUseRundll32());\r
+               CommonUtils.setDisplayPassedReserve(env.getDisplayPassedReserve());\r
+               CommonUtils.setDebug(env.getDebug());\r
+               \r
+               SwingBackgroundWorker.setDebug(env.getDebug());\r
+\r
+               // ほにゃらら\r
+               toolBar.setDebug(env.getDebug());\r
+               autores.setDebug(env.getDebug());\r
+               rdialog.setDebug(env.getDebug());\r
+\r
+               // PassedProgramListの設定変更\r
+               tvprograms.getPassed().setPassedDir(env.getPassedDir());\r
+\r
+               // レコーダプラグインの設定変更\r
+               for ( HDDRecorder rec : recorders ) {\r
+                       // 拡張設定だけ\r
+                       setSettingRecPluginExt(rec, env);\r
+               }\r
+\r
+               // Web番組表共通設定\r
+               setSettingProgPluginCommon(env);\r
+               \r
+               // web番組表のリフレッシュ\r
+               setSettingProgPluginAll(env);\r
+               \r
+               // リロードメニューの書き換え\r
+               toolBar.updateReloadReservedExtension();\r
+               toolBar.updateReloadProgramExtension();\r
+               \r
+               // ページャーコンボボックスの書き換え\r
+               toolBar.setPagerItems();\r
+               \r
+               // 列の表示・非表示\r
+               listed.setMarkColumnVisible(env.getSplitMarkAndTitle());\r
+               listed.setDetailColumnVisible(env.getShowDetailOnList());\r
+               listed.setPickupColumnVisible(env.getShowRsvPickup());\r
+               listed.setDupColumnVisible(env.getShowRsvDup());\r
+               listed.setRowHeaderVisible(env.getRowHeaderVisible());\r
+               reserved.setRowHeaderVisible(env.getRowHeaderVisible());\r
+               \r
+               // 強調色\r
+               listed.setMatchedKeywordColor(env.getMatchedKeywordColor());\r
+               listed.setRsvdLineColor((env.getRsvdLineEnhance())?(env.getRsvdLineColor()):(null));\r
+               listed.setPickedLineColor((env.getRsvdLineEnhance())?(env.getPickedLineColor()):(null));\r
+               listed.setCurrentLineColor((env.getCurrentLineEnhance())?(env.getCurrentLineColor()):(null));\r
+               \r
+               // システムトレイアイコン\r
+               setTrayIconVisible(env.getShowSysTray());\r
+               setXButtonAction(env.getShowSysTray() && env.getHideToTray());\r
+               \r
+               // 新聞形式のツールチップの表示時間を変更する\r
+               setTooltipDelay();\r
+               \r
+               // 番組情報の再取得\r
+               if ( reload_prog ) {\r
+                       loadTVProgram(false, LoadFor.ALL);      // 部品呼び出し\r
+               }\r
+               \r
+               // Web番組表の再構築\r
+               mpList.setHistoryOnlyUpdateOnce(env.getHistoryOnlyUpdateOnce());\r
+               mpList.setShowOnlyNonrepeated(env.getShowOnlyNonrepeated());\r
+               \r
+               doRedrawTVProgram();    // か き な お し\r
+\r
+               return true;\r
+       }\r
+       \r
        // システムトレイ関係\r
        private void getTrayIcon() {\r
                if ( trayicon != null ) {\r
@@ -3763,7 +4040,7 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                \r
                //\r
                ArrayList<String> recIda = new ArrayList<String>();\r
-               for ( File f : new File(CommonUtils.joinPath(new String[]{"bin","tainavi"})).listFiles() ) {\r
+               for ( File f : new File(CommonUtils.joinPath(new String[]{"bin","tainavi","pluginrec"})).listFiles() ) {\r
                        Matcher ma = Pattern.compile("^(PlugIn_Rec[^$]+)[^$]*\\.class$").matcher(f.getName());\r
                        if ( ma.find() ) {\r
                                if ( ! isMailPluginEnabled && f.getName().toLowerCase().contains("mail") ) {\r
@@ -3784,7 +4061,7 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                // servicesに追記\r
                StringBuilder sb = new StringBuilder();\r
                for ( String recId : recIdd ) {\r
-                       sb.append("tainavi.");\r
+                       sb.append("tainavi.pluginrec.");\r
                        sb.append(recId);\r
                        sb.append("\n");\r
                }\r
@@ -3798,7 +4075,9 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                \r
                recPlugins.clear();\r
                for ( HDDRecorder recorder : r ) {\r
-                       if (env.getDebug()) StdAppendMessage("+追加します: "+recorder.getRecorderId());\r
+                       if (env.getDebug()) {\r
+                               StdAppendMessage("+追加します: "+recorder.getRecorderId());\r
+                       }\r
                        recPlugins.add(recorder.clone());\r
                        StdAppendMessage("+追加しました: "+recorder.getRecorderId());\r
                }\r
@@ -3932,7 +4211,7 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                 */\r
 \r
                ArrayList<String> prgIda = new ArrayList<String>();\r
-               for ( File f : new File(CommonUtils.joinPath("bin","tainavi")).listFiles() ) {\r
+               for ( File f : new File(CommonUtils.joinPath("bin","tainavi","plugintv")).listFiles() ) {\r
                        Matcher ma = Pattern.compile("^(PlugIn_(TV|CS|RAD)P[^$]+)\\.class$").matcher(f.getName());\r
                        if (ma.find()) {\r
                                prgIda.add(ma.group(1));\r
@@ -3944,7 +4223,7 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                // servicesに追記\r
                StringBuilder sb = new StringBuilder();\r
                for ( String prgId : prgIdd ) {\r
-                       sb.append("tainavi.");\r
+                       sb.append("tainavi.plugintv.");\r
                        sb.append(prgId);\r
                        sb.append("\n");\r
                }\r
@@ -4244,43 +4523,65 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
         * @return true:前回終了時の設定がある場合\r
         */\r
        private boolean buildMainWindow() {\r
-               //\r
-               mainWindow.addToolBar(toolBar);\r
-               mainWindow.addStatusArea(mwin);\r
-               \r
-               mainWindow.addTab(listed, MWinTab.LISTED);\r
-               mainWindow.addTab(paper, MWinTab.PAPER);\r
-               mainWindow.addTab(reserved, MWinTab.RSVED);\r
-               mainWindow.addTab(recorded, MWinTab.RECED);\r
-               mainWindow.addTab(autores, MWinTab.AUTORES);\r
-               mainWindow.addTab(setting, MWinTab.SETTING);\r
-               mainWindow.addTab(recsetting, MWinTab.RECSET);\r
-               mainWindow.addTab(chsetting, MWinTab.CHSET);\r
-               mainWindow.addTab(chsortsetting, MWinTab.CHSORT);\r
-               mainWindow.addTab(chconvsetting, MWinTab.CHCONV);\r
-               mainWindow.addTab(chdatsetting, MWinTab.CHDAT);\r
                \r
-               //新聞描画枠のリセット\r
-               paper.clearPanel();\r
-               paper.buildMainViewByDate();\r
+               // コンポーネント作成\r
+               {\r
+                       // メインウィンドウの作成\r
+                       mainWindow = new VWMainWindow();\r
                \r
-               // サイドツリーのデフォルトノードの選択\r
-               paper.selectTreeDefault();\r
-               listed.selectTreeDefault();\r
+                       // 内部クラスのインスタンス生成\r
+                       toolBar = new VWToolBar();\r
+                       listed = new VWListedView();\r
+                       paper = new VWPaperView();\r
+                       reserved = new VWReserveListView();\r
+                       recorded = new VWRecordedListView();\r
+                       autores = new VWAutoReserveListView();\r
+                       setting = new VWSettingView();\r
+                       recsetting = new VWRecorderSettingView();\r
+                       chsetting = new VWChannelSettingView();\r
+                       chdatsetting = new VWChannelDatSettingView();\r
+                       chsortsetting = new VWChannelSortView();\r
+                       chconvsetting = new VWChannelConvertView();\r
+               }\r
                \r
-               if ( recInfoList.size() > 0 ) {\r
-                       // 前回終了時設定が存在する場合\r
-                       \r
-                       // 開いていたタブ\r
-                       mainWindow.setShowSettingTabs(bounds.getShowSettingTabs());\r
-                       \r
-                       // ステータスエリアの高さ\r
-                       mwin.setRows(bounds.getStatusRows());\r
-                       \r
-                       return false;\r
+               // 初期値\r
+               {\r
+                       // 設定\r
+                       toolBar.setDebug(env.getDebug());\r
+                       autores.setDebug(env.getDebug());\r
+                       rdialog.setDebug(env.getDebug());\r
+       \r
+                       // ページャーの設定\r
+                       toolBar.setPagerItems();\r
                }\r
                \r
-               // 前回終了時設定が存在しない場合\r
+               // コンポーネントの組み立て\r
+               {\r
+                       // ツールバーなど\r
+                       mainWindow.addToolBar(toolBar);\r
+                       mainWindow.addStatusArea(mwin);\r
+                       \r
+                       // タブ群\r
+                       mainWindow.addTab(listed, MWinTab.LISTED);\r
+                       mainWindow.addTab(paper, MWinTab.PAPER);\r
+                       mainWindow.addTab(reserved, MWinTab.RSVED);\r
+                       mainWindow.addTab(recorded, MWinTab.RECED);\r
+                       mainWindow.addTab(autores, MWinTab.AUTORES);\r
+                       mainWindow.addTab(setting, MWinTab.SETTING);\r
+                       mainWindow.addTab(recsetting, MWinTab.RECSET);\r
+                       mainWindow.addTab(chsetting, MWinTab.CHSET);\r
+                       mainWindow.addTab(chsortsetting, MWinTab.CHSORT);\r
+                       mainWindow.addTab(chconvsetting, MWinTab.CHCONV);\r
+                       mainWindow.addTab(chdatsetting, MWinTab.CHDAT);\r
+               }\r
+               \r
+               // ステータスエリアを開く\r
+               setStatusVisible(bounds.getShowStatus());\r
+               \r
+               //新聞描画枠のリセット\r
+               paper.clearPanel();\r
+               paper.buildMainViewByDate();\r
+               \r
                return true;\r
        }\r
        \r
@@ -4295,7 +4596,8 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                }\r
                else {\r
                        // 設定が存在する場合\r
-                       mainWindow.setSelectedTab(MWinTab.getAt(bounds.getSelectedTab()));\r
+                       MWinTab tab = MWinTab.getAt(bounds.getSelectedTab());\r
+                       mainWindow.setSelectedTab(tab);\r
                }\r
        }\r
        \r
@@ -4419,12 +4721,6 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                );\r
        }\r
        \r
-       @Override\r
-       public void timerRised(VWTimerRiseEvent e) {\r
-               if (env.getDebug()) System.out.println("Timer Rised: now="+CommonUtils.getDateTimeYMDx(e.getCalendar()));\r
-               setTitleBar();\r
-       }\r
-       \r
        // 終了処理関連\r
        private void ExitOnClose() {\r
                // 座標・サイズ\r
@@ -4458,7 +4754,80 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                listed.saveTreeExpansion();\r
                paper.saveTreeExpansion();\r
        }\r
-       \r
+\r
+       private void setKeyboardShortCut() {\r
+               class ShortCut {\r
+                       final String action;\r
+                       final int key;\r
+                       final int mask;\r
+                       final Action callback;\r
+\r
+                       public ShortCut(String aAction, int aKey, int aMask, Action aCallback) {\r
+                               action = aAction;\r
+                               key = aKey;\r
+                               mask = aMask;\r
+                               callback = aCallback;\r
+                       }\r
+               }\r
+\r
+               final String FIND_ACTION = "find";\r
+               final String SELECT_ACTION_LISTTAB = "listtab";\r
+               final String SELECT_ACTION_PAPERTAB = "papertab";\r
+               final String SELECT_ACTION_RSVEDTAB = "rsvedtab";\r
+               final String SELECT_ACTION_RECEDTAB = "recedtab";\r
+               final String SELECT_ACTION_AUTORESTAB = "autorestab";\r
+\r
+               final Action find_action =  new AbstractAction() {\r
+                       @Override\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               toolBar.setFocusInSearchBox();\r
+                       }\r
+               };\r
+               final Action select_action_listtab = new AbstractAction() {\r
+                       @Override\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               mainWindow.setSelectedTab(MWinTab.LISTED);\r
+                       }\r
+               };\r
+               final Action select_action_papertab = new AbstractAction() {\r
+                       @Override\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               mainWindow.setSelectedTab(MWinTab.PAPER);\r
+                       }\r
+               };\r
+               final Action select_action_rsvedtab = new AbstractAction() {\r
+                       @Override\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               mainWindow.setSelectedTab(MWinTab.RSVED);\r
+                       }\r
+               };\r
+               final Action select_action_recedtab = new AbstractAction() {\r
+                       @Override\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               mainWindow.setSelectedTab(MWinTab.RECED);\r
+                       }\r
+               };\r
+               final Action select_action_autorestab = new AbstractAction() {\r
+                       @Override\r
+                       public void actionPerformed(ActionEvent e) {\r
+                               mainWindow.setSelectedTab(MWinTab.AUTORES);\r
+                       }\r
+               };\r
+\r
+               ArrayList<ShortCut> sca = new ArrayList<ShortCut>();\r
+               sca.add(new ShortCut(FIND_ACTION, KeyEvent.VK_F, KeyEvent.CTRL_DOWN_MASK, find_action));\r
+               sca.add(new ShortCut(SELECT_ACTION_LISTTAB, KeyEvent.VK_1, KeyEvent.ALT_DOWN_MASK, select_action_listtab));\r
+               sca.add(new ShortCut(SELECT_ACTION_PAPERTAB, KeyEvent.VK_2, KeyEvent.ALT_DOWN_MASK, select_action_papertab));\r
+               sca.add(new ShortCut(SELECT_ACTION_RSVEDTAB, KeyEvent.VK_3, KeyEvent.ALT_DOWN_MASK, select_action_rsvedtab));\r
+               sca.add(new ShortCut(SELECT_ACTION_RECEDTAB, KeyEvent.VK_4, KeyEvent.ALT_DOWN_MASK, select_action_recedtab));\r
+               sca.add(new ShortCut(SELECT_ACTION_AUTORESTAB, KeyEvent.VK_5, KeyEvent.ALT_DOWN_MASK, select_action_autorestab));\r
+\r
+               InputMap imap = getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);\r
+               for ( ShortCut sc : sca ) {\r
+                       imap.put(KeyStroke.getKeyStroke(sc.key, sc.mask), sc.action);\r
+                       getRootPane().getActionMap().put(sc.action, sc.callback);\r
+               }\r
+       }\r
 \r
        /*******************************************************************************\r
         * main()\r
@@ -4680,7 +5049,7 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                        // 放送局の並び順もロード\r
                        chsort.load();\r
                        \r
-                       loadRdReserve(runRecLoad, null);\r
+                       loadRdReservesAll(runRecLoad, null);\r
                }\r
                catch ( Exception e ) {\r
                        System.err.println("【致命的エラー】設定の初期化に失敗しました");\r
@@ -4694,37 +5063,9 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                // (新聞形式の)ツールチップの表示時間を変更する\r
                setTooltipDelay();\r
 \r
-               boolean firstRun = true;\r
+               // ウィンドウを構築\r
                try {\r
-                       // メインウィンドウの作成\r
-                       mainWindow = new VWMainWindow();\r
-               \r
-                       // 内部クラスのインスタンス生成\r
-                       toolBar = new VWToolBar();\r
-                       listed = new VWListedView();\r
-                       paper = new VWPaperView();\r
-                       reserved = new VWReserveListView();\r
-                       recorded = new VWRecordedListView();\r
-                       autores = new VWAutoReserveListView();\r
-                       setting = new VWSettingView();\r
-                       recsetting = new VWRecorderSettingView();\r
-                       chsetting = new VWChannelSettingView();\r
-                       chdatsetting = new VWChannelDatSettingView();\r
-                       chsortsetting = new VWChannelSortView();\r
-                       chconvsetting = new VWChannelConvertView();\r
-                       \r
-                       // 設定のほにゃらら\r
-                       toolBar.setDebug(env.getDebug());\r
-                       autores.setDebug(env.getDebug());\r
-\r
-                       // ページャーの設定\r
-                       toolBar.setPagerItems();\r
-                       \r
-                       // ウィンドウを構築\r
-                       firstRun = buildMainWindow();\r
-                       \r
-                       // ステータスエリアを開く\r
-                       setStatusVisible(bounds.getShowStatus());\r
+                       buildMainWindow();\r
                }\r
                catch ( Exception e ) {\r
                        System.err.println("【致命的エラー】ウィンドウの構築に失敗しました");\r
@@ -4758,41 +5099,68 @@ public class Viewer extends JFrame implements ChangeListener,VWTimerRiseListener
                        }\r
                });\r
                \r
-               // タブを選択\r
-               ShowInitTab();\r
-               \r
                // 初回起動時はレコーダの登録を促す\r
-               if (firstRun) {\r
+               if ( recorders.size() == 0 ) {\r
                        Container cp = getContentPane();\r
                        JOptionPane.showMessageDialog(cp, "レコーダが登録されていません。\n最初に登録を行ってください。\n番組表だけを使いたい場合は、\nNULLプラグインを登録してください。");\r
                }\r
                \r
+               // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
+               // イベントリスナーの登録 \r
+               // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
+               \r
+               // [ツールバー/共通] レコーダ情報変更\r
+               toolBar.addHDDRecorderChangeListener(autores);\r
+               \r
+               // [ツールバー/レコーダ選択]\r
+               toolBar.addHDDRecorderSelectionListener(this);          // 新聞形式\r
+               toolBar.addHDDRecorderSelectionListener(paper);         // 新聞形式\r
+               toolBar.addHDDRecorderSelectionListener(autores);       // 自動予約一覧\r
+               toolBar.addHDDRecorderSelectionListener(rdialog);       // 予約ダイアログ\r
+\r
+               // [ツールバー/キーワード入力] キャンセル動作\r
+               toolBar.addKeywordCancelListener(this);\r
+               \r
+               // [タイマー] タイトルバー更新/リスト形式の現在時刻ノード/新聞形式の現在時刻ノード\r
+               timer_now.addTickTimerRiseListener(this);\r
+               timer_now.addTickTimerRiseListener(listed);\r
+               timer_now.addTickTimerRiseListener(paper);\r
+\r
+               // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
+               // [Fire!] レコーダ選択\r
+               // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
+               toolBar.setSelectedRecorder(bounds.getSelectedRecorderId());\r
+               \r
+               // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
+               // [Fire!] サイドツリーのデフォルトを選択することで番組情報の描画を開始する\r
+               // ※ここ以前だとぬぽとかOOBとか出るかもよ!\r
+               // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
+               paper.selectTreeDefault();\r
+               listed.selectTreeDefault();\r
+               \r
+               // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
                // メインウィンドウをスプラッシュからコンポーネントに入れ替える\r
+               // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
                this.setVisible(false);\r
                this.setContentPane(mainWindow);\r
                setInitBounds();\r
                this.setVisible(true);\r
                \r
-               // タイトル更新\r
-               setTitleBar();\r
-               \r
-               // [ツールバー/レコーダ選択] 自動予約一覧\r
-               toolBar.addVWHDDRecorderSelectionListener(autores);\r
-               \r
-               // レコーダ選択イベントキック\r
-               toolBar.setSelectedRecorder(bounds.getSelectedRecorderId());\r
-               \r
-               // [タイマー] タイトルバー更新/リスト形式の現在時刻ノード/新聞形式の現在時刻ノード\r
-               timer_now.addVWTimerRiseListener(this);\r
-               timer_now.addVWTimerRiseListener(listed);\r
-               timer_now.addVWTimerRiseListener(paper);\r
+               setTitleBar();  // タイトルバー更新\r
                \r
-               // タイマー起動\r
+               ShowInitTab();  // 前回開いていたタブを開く\r
+\r
+               setKeyboardShortCut();\r
+\r
+               // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
+               // タイマーを起動する\r
+               // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
                timer_now.start();\r
                \r
-               // メッセージだ\r
+               // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
+               // 初期化終了\r
+               // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
                mwin.appendMessage(String.format("タイニー番組ナビゲータが起動しました (VersionInfo:%s on %s)",VersionInfo.getVersion(),VersionInfo.getEnvironment()));\r
-               \r
                initialized = true;\r
        }\r
 }\r