OSDN Git Service

予約行の背景色のトグル操作
[tainavi/TinyBannavi.git] / TinyBannavi / src / tainavi / Viewer.java
1 package tainavi;\r
2 \r
3 import java.awt.AWTException;\r
4 import java.awt.BorderLayout;\r
5 import java.awt.Color;\r
6 import java.awt.Component;\r
7 import java.awt.Container;\r
8 import java.awt.Desktop;\r
9 import java.awt.Dimension;\r
10 import java.awt.Font;\r
11 import java.awt.Frame;\r
12 import java.awt.Image;\r
13 import java.awt.Insets;\r
14 import java.awt.MenuItem;\r
15 import java.awt.Point;\r
16 import java.awt.PopupMenu;\r
17 import java.awt.Rectangle;\r
18 import java.awt.SystemTray;\r
19 import java.awt.Toolkit;\r
20 import java.awt.TrayIcon;\r
21 import java.awt.datatransfer.Clipboard;\r
22 import java.awt.datatransfer.StringSelection;\r
23 import java.awt.event.ActionEvent;\r
24 import java.awt.event.ActionListener;\r
25 import java.awt.event.ComponentAdapter;\r
26 import java.awt.event.ComponentEvent;\r
27 import java.awt.event.MouseAdapter;\r
28 import java.awt.event.MouseEvent;\r
29 import java.awt.event.WindowAdapter;\r
30 import java.awt.event.WindowEvent;\r
31 import java.io.File;\r
32 import java.io.IOException;\r
33 import java.io.UnsupportedEncodingException;\r
34 import java.lang.management.ManagementFactory;\r
35 import java.lang.management.MemoryMXBean;\r
36 import java.lang.management.MemoryUsage;\r
37 import java.lang.reflect.InvocationTargetException;\r
38 import java.net.URI;\r
39 import java.net.URISyntaxException;\r
40 import java.net.URLEncoder;\r
41 import java.security.NoSuchAlgorithmException;\r
42 import java.util.ArrayList;\r
43 import java.util.Arrays;\r
44 import java.util.Calendar;\r
45 import java.util.GregorianCalendar;\r
46 import java.util.HashMap;\r
47 import java.util.LinkedHashMap;\r
48 import java.util.ServiceLoader;\r
49 import java.util.regex.Matcher;\r
50 import java.util.regex.Pattern;\r
51 \r
52 import javax.imageio.ImageIO;\r
53 import javax.swing.ImageIcon;\r
54 import javax.swing.JComponent;\r
55 import javax.swing.JFrame;\r
56 import javax.swing.JLabel;\r
57 import javax.swing.JMenuItem;\r
58 import javax.swing.JOptionPane;\r
59 import javax.swing.JPopupMenu;\r
60 import javax.swing.SwingUtilities;\r
61 import javax.swing.ToolTipManager;\r
62 import javax.swing.UIManager;\r
63 import javax.swing.event.ChangeEvent;\r
64 import javax.swing.event.ChangeListener;\r
65 \r
66 import tainavi.HDDRecorder.RecType;\r
67 import tainavi.TVProgram.ProgFlags;\r
68 import tainavi.TVProgram.ProgGenre;\r
69 import tainavi.TVProgram.ProgOption;\r
70 import tainavi.TVProgram.ProgSubgenre;\r
71 import tainavi.TVProgram.ProgSubtype;\r
72 import tainavi.TVProgram.ProgType;\r
73 import tainavi.VWMainWindow.MWinTab;\r
74 import tainavi.VWUpdate.UpdateResult;\r
75 import tainavi.plugintv.Syobocal;\r
76 \r
77 \r
78 /**\r
79  * メインな感じ\r
80  */\r
81 public class Viewer extends JFrame implements ChangeListener,TickTimerListener,HDDRecorderListener,CancelListener {\r
82 \r
83         private static final long serialVersionUID = 1L;\r
84         \r
85         \r
86         /*\r
87          * メソッド的な\r
88          */\r
89         \r
90         private void StdAppendMessage(String message)   { System.out.println(message); }\r
91         private void StdAppendError(String message)             { System.err.println(message); }\r
92         // \r
93         private void MWinSetVisible(boolean b)                  { mwin.setVisible(b); }\r
94         // \r
95         private void StWinClear()                                               { stwin.clear(); }\r
96         private void StWinSetVisible(boolean b)                 { stwin.setVisible(b); }\r
97         private void StWinSetLocationCenter(Component frame) { CommonSwingUtils.setLocationCenter(frame, (VWStatusWindow)stwin); }\r
98         private void StWinSetLocationUnder(Component frame)  { CommonSwingUtils.setLocationUnder(frame, (VWStatusWindow)stwin); }\r
99         \r
100         private void ringBeep() { if (env!=null && ! env.getDisableBeep()) { Toolkit.getDefaultToolkit().beep(); if ( env.getDebug() ) CommonUtils.printStackTrace(); } }\r
101         \r
102         \r
103         /*\r
104          * オブジェクト的な\r
105          */\r
106         \r
107         // 設定値をいれるところ\r
108         private final Env env = new Env();                                                                                      // 主要な設定\r
109         private final Bounds bounds = new Bounds();                                                                     // ウィンドウサイズとか動的に変化するもの\r
110         private final ClipboardInfoList cbitems = new ClipboardInfoList();                      // クリップボード対応機能でどの項目をコピーするかとかの設定 \r
111         private final PaperColorsMap pColors = new PaperColorsMap();                            // 新聞形式のジャンル別背景色の設定\r
112         private final AVSetting avs = new AVSetting();                                                          // ジャンル別録画画質・音質等設定\r
113         private final CHAVSetting chavs = new CHAVSetting();                                            // CH別録画画質・音質等設定\r
114         private final ChannelSort chsort = new ChannelSort();                                           // CHソート設定\r
115         private final ChannelConvert chconv = new ChannelConvert();                                     // ChannelConvert.dat\r
116         private final MarkChar markchar = new MarkChar(env);                                            // タイトルにつけるマークを操作する\r
117         \r
118         private final MarkedProgramList mpList = new MarkedProgramList();                       // 検索結果のキャッシュ(表示高速化用)\r
119         private final TraceProgram trKeys = new TraceProgram();                                         // 番組追跡の設定\r
120         private final SearchProgram srKeys = new SearchProgram();                                       // キーワード検索の設定\r
121         private final SearchGroupList srGrps = new SearchGroupList();                           // キーワード検索グループの設定\r
122         private final ExtProgram extKeys = new ExtProgram();                                            // 延長警告管理の設定\r
123         \r
124         private final RecorderInfoList recInfoList = new RecorderInfoList();            // レコーダ一覧の設定\r
125         \r
126         private final HDDRecorderList recPlugins = new HDDRecorderList();                       // レコーダプラグイン(テンプレート)\r
127         private final HDDRecorderList recorders = new HDDRecorderList();                        // レコーダプラグイン(実際に利用するもの)\r
128         \r
129         private final TVProgramList progPlugins = new TVProgramList();                          // Web番組表プラグイン(テンプレート)\r
130         private final TVProgramList tvprograms = new TVProgramList();                           // Web番組表プラグイン(実際に利用するもの)\r
131         \r
132         private final TickTimer timer_now = new TickTimer();                                                    // 毎分00秒に起動して処理をキックするタイマー\r
133         \r
134         // 初期化的な\r
135         private boolean logging = true;                                                                                 // ログ出力する\r
136         private boolean runRecWakeup = false;                                                                           // 起動時にレコーダを起こす\r
137         private boolean runRecLoad = false;                                                                                     // 起動時にレコーダから予約一覧を取得する\r
138         private boolean enableWebAccess = true;                                                                         // 起動時のWeb番組表へのアクセスを禁止する\r
139         private boolean onlyLoadProgram = false;\r
140         private String pxaddr = null;                                                                                           // ProxyAddress指定\r
141         private String pxport = null;                                                                                           // ProxtPort指定\r
142         \r
143         \r
144         /*******************************************************************************\r
145          * 定数\r
146          ******************************************************************************/\r
147         \r
148         public static final String LOG_FILE = "log.txt";                                                        // ログファイル名\r
149         public static final String HISTORY_FILE = "05_history.txt";                             // 更新履歴だよ\r
150         \r
151         private static final String ICONFILE_SYSTRAY = "icon"+File.separator+"tainavi16.png";\r
152         private static final String ICONFILE_TAINAVI = "icon"+File.separator+"tainavi.png";\r
153         \r
154         public static final int TIMEBAR_START = 5;                                      // 新聞形式の開始時刻\r
155         private static final int OPENING_WIAT = 500;                            // まあ起動時しか使わないんですけども\r
156 \r
157         private static final String MSGID = "[鯛ナビ] ";\r
158 //      private static final String ERRID = "[ERROR]"+MSGID;\r
159         private static final String DBGID = "[DEBUG]"+MSGID;\r
160         \r
161         /*\r
162          * [メモ] enumのtoString()をoverrideすると、シリアライズの際とても困るのでやらないこと\r
163          */\r
164         \r
165         /**\r
166          * Web番組表のどれとどれを読めばいいのか\r
167          */\r
168         public static enum LoadFor {\r
169                 TERRA   ("地上波&BSのみ取得"),\r
170                 CS              ("CSのみ取得"),\r
171                 CSo1    ("CS[プライマリ]のみ取得"),\r
172                 CSo2    ("CS[セカンダリ]のみ取得"),\r
173                 CSwSD   ("CSのみ取得(取得後シャットダウン)"),\r
174                 RADIO   ("ラジオのみ取得"),\r
175                 SYOBO   ("しょぼかるのみ取得"),\r
176                 ALL             ("すべて取得");\r
177                 \r
178                 private String name;\r
179                 \r
180                 private LoadFor(String name) {\r
181                         this.name = name;\r
182                 }\r
183 \r
184                 public String getName() {\r
185                         return this.name;\r
186                 }\r
187                 \r
188                 public static LoadFor get(String s) {\r
189                         for ( LoadFor lf : LoadFor.values() ) {\r
190                                 if ( lf.name.equals(s) ) {\r
191                                         return lf;\r
192                                 }\r
193                         }\r
194                         return null;\r
195                 }\r
196         };\r
197 \r
198         /**\r
199          * レコーダ情報のどれとどれを読めばいいのか\r
200          */\r
201         public static enum LoadRsvedFor {\r
202 //              SETTING         ( "設定情報のみ取得(future use.)" ),\r
203                 DETAILS         ( "予約一覧+録画詳細のみ取得" ),\r
204                 RECORDED        ( "録画結果一覧のみ取得" ),\r
205                 AUTORESERVE     ( "自動予約一覧のみ取得" ),\r
206                 ;\r
207                 \r
208                 private String name;\r
209                 \r
210                 private LoadRsvedFor(String name) {\r
211                         this.name = name;\r
212                 }\r
213                 \r
214                 public String getName() {\r
215                         return name;\r
216                 }\r
217                 \r
218                 public static LoadRsvedFor get(String s) {\r
219                         for ( LoadRsvedFor lrf : LoadRsvedFor.values() ) {\r
220                                 if ( lrf.name.equals(s) ) {\r
221                                         return lrf;\r
222                                 }\r
223                         }\r
224                         return null;\r
225                 }\r
226         }\r
227         \r
228         /**\r
229          *  リスト形式のカラム定義\r
230          * @deprecated しっぱいした 半年くらいしたら削除する\r
231          */\r
232         @Deprecated\r
233         public static enum ListedColumn {\r
234                 RSVMARK         ("予約",                      35),\r
235                 DUPMARK         ("重複",                      35),\r
236                 CHNAME          ("チャンネル名",  100),\r
237                 TITLE           ("番組タイトル",  300),\r
238                 DETAIL          ("番組詳細",                200),\r
239                 START           ("開始時刻",                150),\r
240                 END                     ("終了",                      50),\r
241                 LENGTH          ("長さ",                      50),\r
242                 GENRE           ("ジャンル",                85),\r
243                 SITEM           ("検索アイテム名",       100),\r
244                 STAR            ("お気に入り度",  100),\r
245                 SCORE           ("スコア",                   35),\r
246                 THRESHOLD       ("閾値",                      35),\r
247                 HID_PRGID       ("PRGID",               -1),\r
248                 HID_STIME       ("STIME",               -1),\r
249                 HID_ETIME       ("ETIME",               -1),\r
250                 HID_EXFLG       ("EXFLG",               -1),\r
251                 HID_TITLE       ("TITLE",               -1),\r
252                 ;\r
253 \r
254                 @SuppressWarnings("unused")\r
255                 private String name;\r
256                 private int iniWidth;\r
257 \r
258                 private ListedColumn(String name, int iniWidth) {\r
259                         this.name = name;\r
260                         this.iniWidth = iniWidth;\r
261                 }\r
262 \r
263                 /* なんだかなー\r
264                 @Override\r
265                 public String toString() {\r
266                         return name;\r
267                 }\r
268                 */\r
269 \r
270                 public int getIniWidth() {\r
271                         return iniWidth;\r
272                 }\r
273                 \r
274                 public int getColumn() {\r
275                         return ordinal();\r
276                 }\r
277         };\r
278         \r
279         /**\r
280          *  本体予約一覧のカラム定義\r
281          * @deprecated しっぱいした 半年くらいしたら削除する\r
282          */\r
283         @Deprecated\r
284         public static enum RsvedColumn {\r
285                 PATTERN         ("パタン",                   110),\r
286                 DUPMARK         ("重複",                      35),\r
287                 EXEC            ("実行",                      35),\r
288                 TRACE           ("追跡",                      35),\r
289                 NEXTSTART       ("次回実行予定",  150),\r
290                 END                     ("終了",                      50),\r
291                 LENGTH          ("長さ",                      50),\r
292                 ENCODER         ("エンコーダ",          50),\r
293                 VRATE           ("画質",                      100),\r
294                 ARATE           ("音質",                      50),\r
295                 TITLE           ("番組タイトル",  300),\r
296                 CHNAME          ("チャンネル名",  150),\r
297                 RECORDER        ("レコーダ",                200),\r
298                 HID_INDEX       ("INDEX",               -1),\r
299                 HID_RSVID       ("RSVID",               -1),\r
300                 ;\r
301 \r
302                 @SuppressWarnings("unused")\r
303                 private String name;\r
304                 private int iniWidth;\r
305 \r
306                 private RsvedColumn(String name, int iniWidth) {\r
307                         this.name = name;\r
308                         this.iniWidth = iniWidth;\r
309                 }\r
310 \r
311                 /*\r
312                 @Override\r
313                 public String toString() {\r
314                         return name;\r
315                 }\r
316                 */\r
317 \r
318                 public int getIniWidth() {\r
319                         return iniWidth;\r
320                 }\r
321                 \r
322                 public int getColumn() {\r
323                         return ordinal();\r
324                 }\r
325         };\r
326         \r
327         \r
328         \r
329         /*\r
330          * コンポーネント\r
331          */\r
332         \r
333         // 起動時に固定で用意しておくもの\r
334         private final VWStatusWindow stwin = new VWStatusWindow();\r
335         private final VWStatusTextArea mwin = new VWStatusTextArea();\r
336         private final VWColorChooserDialog ccwin = new VWColorChooserDialog();\r
337         private final VWPaperColorsDialog pcwin = new VWPaperColorsDialog();\r
338         private final VWReserveDialog rdialog = new VWReserveDialog(0, 0);\r
339         \r
340         // 初期化処理の中で生成していくもの\r
341         private VWMainWindow mainWindow = null;\r
342         private VWToolBar toolBar = null;\r
343         private VWListedView listed = null;\r
344         private VWPaperView paper = null;\r
345         private VWReserveListView reserved = null;\r
346         private VWRecordedListView recorded = null;\r
347         private VWAutoReserveListView autores = null;\r
348         private VWSettingView setting = null;\r
349         private VWRecorderSettingView recsetting = null;\r
350         private VWChannelSettingView chsetting = null;\r
351         private VWChannelDatSettingView chdatsetting = null;\r
352         private VWChannelSortView chsortsetting = null;\r
353         private VWChannelConvertView chconvsetting = null;\r
354         private VWLookAndFeel vwlaf = null;\r
355         private VWFont vwfont = null;\r
356         \r
357         private TrayIcon trayicon = null;\r
358         \r
359         \r
360         \r
361         /*******************************************************************************\r
362          * タブやダイアログのインスタンス作成用クラス定義\r
363          ******************************************************************************/\r
364         \r
365         /***\r
366          * リスト形式の内部クラス\r
367          */\r
368         private class VWListedView extends AbsListedView {\r
369 \r
370                 private static final long serialVersionUID = 1L;\r
371 \r
372                 // 環境設定の入れ物を渡す\r
373                 @Override\r
374                 protected Env getEnv() { return env; }\r
375                 @Override\r
376                 protected Bounds getBoundsEnv() { return bounds; }\r
377                 @Override\r
378                 protected ChannelSort getChannelSort() { return chsort; }\r
379 \r
380                 @Override\r
381                 protected MarkedProgramList getMarkedProgramList() { return mpList; }\r
382                 @Override\r
383                 protected TraceProgram getTraceProgram() { return trKeys; }\r
384                 @Override\r
385                 protected SearchProgram getSearchProgram() { return srKeys; }\r
386                 @Override\r
387                 protected SearchGroupList getSearchGroupList() { return srGrps; }\r
388                 @Override\r
389                 protected ExtProgram getExtProgram() { return extKeys; }\r
390 \r
391                 @Override\r
392                 protected TVProgramList getTVProgramList() { return tvprograms; }\r
393                 @Override\r
394                 protected HDDRecorderList getRecorderList() { return recorders; }\r
395 \r
396                 // メッセージ出力関連\r
397                 @Override\r
398                 protected StatusWindow getStWin() { return stwin; }\r
399                 @Override\r
400                 protected StatusTextArea getMWin() { return mwin; }\r
401                 \r
402                 // コンポーネントを渡す\r
403                 @Override\r
404                 protected AbsReserveDialog getReserveDialog() { return rdialog; }\r
405                 @Override\r
406                 protected Component getParentComponent() { return Viewer.this; }\r
407 \r
408                 @Override\r
409                 protected void ringBeep() { Viewer.this.ringBeep(); }\r
410                 \r
411                 /*\r
412                  * AbsListedView内でのイベントから呼び出されるメソッド群\r
413                  */\r
414 \r
415                 @Override\r
416                 protected void onShown() {\r
417                         // キーワード登録ボタンはリスト形式のみ\r
418                         toolBar.setAddkeywordEnabled(true);\r
419                         // 一括予約はリスト形式のみ\r
420                         toolBar.setBatchReservationEnabled(true);\r
421                         // スナップショットを有効にする\r
422                         toolBar.setSnapShotEnabled(true);\r
423                         // 新聞形式以外ではマッチ枠を無効にする\r
424                         toolBar.setBorderToggleEnabled(true, bounds.getShowReservedBackground());\r
425                 }\r
426 \r
427                 @Override\r
428                 protected void onHidden() {\r
429                         // キーワード登録ボタンはリスト形式のみ\r
430                         toolBar.setAddkeywordEnabled(false);\r
431                         // 一括予約はリスト形式のみ\r
432                         toolBar.setBatchReservationEnabled(false);\r
433                         // スナップショットを無効にする\r
434                         toolBar.setSnapShotEnabled(false);\r
435                         // 新聞形式以外ではマッチ枠を無効にする\r
436                         toolBar.setBorderToggleEnabled(false, bounds.getShowReservedBackground());\r
437                 }\r
438 \r
439                 @Override\r
440                 protected void showPopupForTraceProgram(\r
441                                 final JComponent comp,\r
442                                 final ProgDetailList tvd, final String keyword, final int threshold,\r
443                                 final int x, final int y) {\r
444                         \r
445                         timer_now.pause();      // 停止\r
446                         \r
447                         Viewer.this.showPopupForTraceProgram(comp, tvd, keyword, threshold, x, y, null);\r
448                         \r
449                         timer_now.start();      // 再開\r
450                 }\r
451 \r
452                 @Override\r
453                 protected void updateReserveDisplay(String chname) {\r
454                         timer_now.pause();\r
455                         paper.updateReserveBorder(chname);\r
456                         reserved.redrawReservedList();\r
457                         timer_now.start();\r
458                 }\r
459 \r
460                 @Override\r
461                 protected void updateBangumiColumns() {\r
462                         timer_now.pause();\r
463                         paper.updateBangumiColumns();\r
464                         timer_now.start();\r
465                 }\r
466 \r
467                 @Override\r
468                 protected void clearPaper() {\r
469                         timer_now.pause();\r
470                         paper.clearPanel();\r
471                         timer_now.start();\r
472                 }\r
473 \r
474                 @Override\r
475                 protected void previewKeywordSearch(SearchKey search) {\r
476                         //timer_now.pause();\r
477                         if (search.alTarget.size() > 0) {\r
478                                 mainWindow.setSelectedTab(MWinTab.LISTED);\r
479                                 listed.redrawListByPreview(search);\r
480                         }\r
481                         //timer_now.start();\r
482                 }\r
483 \r
484                 @Override\r
485                 protected void jumpToPaper(String Center, String StartDateTime) {\r
486                         //timer_now.pause();\r
487                         paper.jumpToBangumi(Center,StartDateTime);\r
488                         //timer_now.start();\r
489                 }\r
490 \r
491                 @Override\r
492                 protected boolean addToPickup(ProgDetailList tvd) { return Viewer.this.addToPickup(tvd); }\r
493 \r
494                 @Override\r
495                 protected boolean isTabSelected(MWinTab tab) { return mainWindow.isTabSelected(tab); }\r
496                 @Override\r
497                 protected void setSelectedTab(MWinTab tab) { mainWindow.setSelectedTab(tab); }\r
498 \r
499                 @Override\r
500                 protected String getSelectedRecorderOnToolbar() { return toolBar.getSelectedRecorder(); }\r
501                 @Override\r
502                 protected boolean isFullScreen() { return toolBar.isFullScreen(); }\r
503                 @Override\r
504                 protected void setPagerEnabled(boolean b) { toolBar.setPagerEnabled(b); }\r
505                 @Override\r
506                 protected int getPagerCount() { return toolBar.getPagerCount(); }\r
507                 @Override\r
508                 protected int getSelectedPagerIndex() { return toolBar.getSelectedPagerIndex(); }\r
509 \r
510                 @Override\r
511                 protected void setDividerEnvs(int loc) {\r
512                         if ( ! toolBar.isFullScreen() && mainWindow.isTabSelected(MWinTab.LISTED) ) {\r
513                                 if (env.getSyncTreeWidth()) {\r
514                                         bounds.setTreeWidth(loc);\r
515                                         bounds.setTreeWidthPaper(loc);\r
516                                 }\r
517                                 else {\r
518                                         bounds.setTreeWidth(loc);\r
519                                 }\r
520                         }\r
521                 }\r
522         }\r
523         \r
524         \r
525         \r
526         /**\r
527          * 新聞形式の内部クラス\r
528          */\r
529         private class VWPaperView extends AbsPaperView {\r
530 \r
531                 private static final long serialVersionUID = 1L;\r
532 \r
533                 // 環境設定の入れ物を渡す\r
534                 @Override\r
535                 protected Env getEnv() { return env; }\r
536                 @Override\r
537                 protected Bounds getBoundsEnv() { return bounds; }\r
538                 @Override\r
539                 protected PaperColorsMap getPaperColorMap() { return pColors; }\r
540                 @Override\r
541                 protected ChannelSort getChannelSort() { return chsort; }\r
542                 \r
543                 @Override\r
544                 protected TVProgramList getTVProgramList() { return tvprograms; }\r
545                 @Override\r
546                 protected HDDRecorderList getRecorderList() { return recorders; }\r
547 \r
548                 // メッセージ出力関連\r
549                 @Override\r
550                 protected StatusWindow getStWin() { return stwin; }\r
551                 @Override\r
552                 protected StatusTextArea getMWin() { return mwin; }\r
553                 \r
554                 // コンポーネントを渡す\r
555                 @Override\r
556                 protected AbsReserveDialog getReserveDialog() { return rdialog; }\r
557                 @Override\r
558                 protected Component getParentComponent() { return Viewer.this; }\r
559 \r
560                 @Override\r
561                 protected void ringBeep() { Viewer.this.ringBeep(); }\r
562                 \r
563                 /*\r
564                  * AbsPaperView内でのイベントから呼び出されるメソッド群\r
565                  */\r
566 \r
567                 @Override\r
568                 protected void onShown() {\r
569                         // ページャーコンボボックスを有効にする(状況次第で有効にならない場合もある)(ツリーの選択次第で変わるのでもどし)\r
570                         //toolBar.setPagerEnabled(true);\r
571                         // スナップショットを有効にする\r
572                         toolBar.setSnapShotEnabled(true);\r
573                         // ジャンル別背景色を有効にする\r
574                         toolBar.setPaperColorDialogEnabled(true);\r
575                         // マッチ枠を有効にする\r
576                         toolBar.setBorderToggleEnabled(true, bounds.getShowMatchedBorder());\r
577                 }\r
578 \r
579                 @Override\r
580                 protected void onHidden() {\r
581                         // 新聞形式以外ではページャーコンボボックスを無効にする(ツリーの選択次第で変わるのでもどし)\r
582                         //toolBar.setPagerEnabled(false);\r
583                         // 新聞形式以外ではスナップショットを無効にする\r
584                         toolBar.setSnapShotEnabled(false);\r
585                         // 新聞形式以外ではジャンル別背景色を無効にする\r
586                         toolBar.setPaperColorDialogEnabled(false);\r
587                         // 新聞形式以外ではマッチ枠を無効にする\r
588                         toolBar.setBorderToggleEnabled(false, bounds.getShowMatchedBorder());\r
589                 }\r
590 \r
591                 @Override\r
592                 protected void showPopupForTraceProgram(\r
593                                 final JComponent comp,\r
594                                 final ProgDetailList tvd, final String keyword, final int threshold,\r
595                                 final int x, final int y, final String clickedDateTime) {\r
596                         \r
597                         timer_now.pause();      // 停止\r
598                         \r
599                         Viewer.this.showPopupForTraceProgram(comp, tvd, keyword, threshold, x, y, clickedDateTime);\r
600                         \r
601                         timer_now.start();      // 再開\r
602                 }\r
603 \r
604                 @Override\r
605                 protected void updateReserveDisplay() {\r
606                         timer_now.pause();\r
607                         listed.updateReserveMark();\r
608                         reserved.redrawReservedList();\r
609                         timer_now.start();\r
610                 }\r
611 \r
612                 @Override\r
613                 protected void addToPickup(ProgDetailList tvd) { Viewer.this.addToPickup(tvd); }\r
614 \r
615                 @Override\r
616                 protected boolean isTabSelected(MWinTab tab) { return mainWindow.isTabSelected(tab); }\r
617                 @Override\r
618                 protected void setSelectedTab(MWinTab tab) { mainWindow.setSelectedTab(tab); }\r
619 \r
620                 @Override\r
621                 protected boolean isFullScreen() { return toolBar.isFullScreen(); }\r
622                 @Override\r
623                 protected void setSelectedPagerIndex(int idx) {\r
624                         toolBar.setSelectedPagerIndex(idx);\r
625                 }\r
626                 @Override\r
627                 protected void setPagerEnabled(boolean b) { toolBar.setPagerEnabled(b); }\r
628                 @Override\r
629                 protected int getPagerCount() { return toolBar.getPagerCount(); }\r
630                 @Override\r
631                 protected int getSelectedPagerIndex() { return toolBar.getSelectedPagerIndex(); }\r
632                 @Override\r
633                 protected void setPagerItems(TVProgramIterator pli, int curindex) {\r
634                         toolBar.setPagerItems(pli,curindex);\r
635                 }\r
636 \r
637                 @Override\r
638                 protected String getExtensionMark(ProgDetailList tvd) { return markchar.getExtensionMark(tvd); }\r
639                 @Override\r
640                 protected String getOptionMark(ProgDetailList tvd) { return markchar.getOptionMark(tvd)+markchar.getNewLastMark(tvd); }\r
641                 @Override\r
642                 protected String getPostfixMark(ProgDetailList tvd) { return markchar.getPostfixMark(tvd); }\r
643 \r
644                 @Override\r
645                 protected void setDividerEnvs(int loc) {\r
646                         if ( ! toolBar.isFullScreen() && mainWindow.isTabSelected(MWinTab.PAPER) ) {\r
647                                 if (env.getSyncTreeWidth()) {\r
648                                         bounds.setTreeWidth(loc);\r
649                                         bounds.setTreeWidthPaper(loc);\r
650                                 }\r
651                                 else {\r
652                                         bounds.setTreeWidthPaper(loc);\r
653                                 }\r
654                         }\r
655                 }\r
656         }\r
657         \r
658         \r
659         \r
660         /**\r
661          * \r
662          * 本体予約一覧の内部クラス\r
663          * \r
664          */\r
665         private class VWReserveListView extends AbsReserveListView {\r
666 \r
667                 private static final long serialVersionUID = 1L;\r
668 \r
669                 // 環境設定の入れ物を渡す\r
670                 @Override\r
671                 protected Env getEnv() { return env; }\r
672                 @Override\r
673                 protected Bounds getBoundsEnv() { return bounds; }\r
674 \r
675                 @Override\r
676                 protected HDDRecorderList getRecorderList() { return recorders; }\r
677 \r
678                 // ログ関係はないのか\r
679                 \r
680                 // コンポーネントを渡す\r
681                 @Override\r
682                 protected AbsReserveDialog getReserveDialog() { return rdialog; }\r
683                 @Override\r
684                 protected Component getParentComponent() { return Viewer.this; }\r
685 \r
686                 @Override\r
687                 protected void ringBeep() { Viewer.this.ringBeep(); }\r
688 \r
689                 /*\r
690                  * AbsReserveListView内でのイベントから呼び出されるメソッド群\r
691                  */\r
692                 \r
693                 @Override\r
694                 protected void updateReserveDisplay(String chname) {\r
695                         timer_now.pause();\r
696                         listed.updateReserveMark();\r
697                         paper.updateReserveBorder(chname);\r
698                         timer_now.start();\r
699                 }\r
700 \r
701                 @Override\r
702                 protected boolean doExecOnOff(boolean fexec, String title, String chnam, String rsvId, String recId) {\r
703                         return Viewer.this.doExecOnOff(fexec, title, chnam, rsvId, recId);\r
704                 }\r
705                 \r
706                 @Override\r
707                 protected JMenuItem getExecOnOffMenuItem(boolean fexec,\r
708                                 String start, String title, String chnam, String rsvId, String recId) {\r
709 \r
710                         return Viewer.this.getExecOnOffMenuItem(fexec, start, title, chnam, rsvId, recId, 0);\r
711                 }\r
712 \r
713                 @Override\r
714                 protected JMenuItem getRemoveRsvMenuItem(\r
715                                 String start, String title, String chnam,       String rsvId, String recId) {\r
716                         \r
717                         return Viewer.this.getRemoveRsvMenuItem(start, title, chnam, rsvId, recId, 0);\r
718                 }\r
719 \r
720                 @Override\r
721                 protected JMenuItem getJumpMenuItem(String title, String chnam,\r
722                                 String startDT) {\r
723                         \r
724                         return Viewer.this.getJumpMenuItem(title, chnam, startDT);\r
725                 }\r
726 \r
727                 @Override\r
728                 protected JMenuItem getJumpToLastWeekMenuItem(String title,\r
729                                 String chnam, String startDT) {\r
730                         \r
731                         return Viewer.this.getJumpToLastWeekMenuItem(title, chnam, startDT);\r
732                 }\r
733 \r
734                 @Override\r
735                 protected String getSelectedRecorderOnToolbar() { return toolBar.getSelectedRecorder(); }\r
736         }\r
737         \r
738         \r
739         /**\r
740          * \r
741          * 録画結果一覧の内部クラス\r
742          * \r
743          */\r
744         private class VWRecordedListView extends AbsRecordedListView {\r
745 \r
746                 private static final long serialVersionUID = 1L;\r
747 \r
748                 // 環境設定の入れ物を渡す\r
749                 @Override\r
750                 protected Env getEnv() { return env; }\r
751                 @Override\r
752                 protected Bounds getBoundsEnv() { return bounds; }\r
753 \r
754                 @Override\r
755                 protected HDDRecorderList getRecorderList() { return recorders; }\r
756 \r
757                 // ログ関係はないのか\r
758                 \r
759                 // コンポーネントを渡す\r
760                 @Override\r
761                 protected Component getParentComponent() { return Viewer.this; }\r
762 \r
763                 @Override\r
764                 protected void ringBeep() { Viewer.this.ringBeep(); }\r
765 \r
766                 /*\r
767                  * AbsReserveListView内でのイベントから呼び出されるメソッド群\r
768                  */\r
769                 \r
770                 @Override\r
771                 protected String getSelectedRecorderOnToolbar() { return toolBar.getSelectedRecorder(); }\r
772         }\r
773         \r
774         \r
775         /**\r
776          * \r
777          * 録画結果一覧の内部クラス\r
778          * \r
779          */\r
780         private class VWAutoReserveListView extends AbsAutoReserveListView {\r
781 \r
782                 private static final long serialVersionUID = 1L;\r
783 \r
784                 // 環境設定の入れ物を渡す\r
785                 @Override\r
786                 protected Env getEnv() { return env; }\r
787                 @Override\r
788                 protected Bounds getBoundsEnv() { return bounds; }\r
789                 \r
790         }\r
791         \r
792         /***\r
793          * 各種設定の内部クラス\r
794          */\r
795         private class VWSettingView extends AbsSettingView {\r
796 \r
797                 private static final long serialVersionUID = 1L;\r
798 \r
799                 // 環境設定の入れ物を渡す\r
800                 @Override\r
801                 protected Env getEnv() { return env; }\r
802                 @Override\r
803                 protected ClipboardInfoList getCbItemEnv() { return cbitems; }\r
804                 @Override\r
805                 protected VWLookAndFeel getLAFEnv() { return vwlaf; }\r
806                 @Override\r
807                 protected VWFont getFontEnv() { return vwfont; }\r
808                 \r
809                 // メッセージ出力関連\r
810                 @Override\r
811                 protected StatusWindow getStWin() { return stwin; }\r
812                 @Override\r
813                 protected StatusTextArea getMWin() { return mwin; }\r
814                 \r
815                 // コンポーネントを渡す\r
816                 @Override\r
817                 protected Component getParentComponent() { return Viewer.this; }\r
818                 @Override\r
819                 protected VWColorChooserDialog getCcWin() { return ccwin; }\r
820 \r
821                 /*\r
822                  * AbsSettingView内でのイベントから呼び出されるメソッド群\r
823                  */\r
824                 \r
825                 @Override\r
826                 protected void lafChanged(String lafname) {\r
827                         vwlaf.update(lafname);\r
828                         Viewer.this.updateComponentTreeUI();\r
829                         StdAppendMessage("Set LookAndFeel="+lafname);\r
830                 }\r
831 \r
832                 @Override\r
833                 protected void fontChanged(String fn, int fontSize) {\r
834                         vwfont.update(fn, fontSize);\r
835                         Viewer.this.updateComponentTreeUI();\r
836                         StdAppendMessage("システムのフォントを変更しました: "+fn+", size="+fontSize);\r
837                 }\r
838 \r
839                 @Override\r
840                 protected void setEnv(final boolean reload_prog) {\r
841                         \r
842                         //listed.pauseTimer();\r
843                         timer_now.pause();\r
844                         \r
845                         Viewer.this.setEnv(reload_prog);\r
846                         \r
847                         timer_now.start();\r
848                 }\r
849         }\r
850         \r
851         /**\r
852          * レコーダ設定タブの内部クラス\r
853          * @see AbsRecorderSettingView\r
854          */\r
855         private class VWRecorderSettingView extends AbsRecorderSettingView {\r
856 \r
857                 private static final long serialVersionUID = 1L;\r
858 \r
859                 // 環境設定の入れ物を渡す\r
860                 @Override\r
861                 protected Env getEnv() { return env; }\r
862                 @Override\r
863                 protected RecorderInfoList getRecInfos() { return recInfoList; }\r
864                 @Override\r
865                 protected HDDRecorderList getRecPlugins() { return recPlugins; }\r
866 \r
867                 // ログ関連\r
868                 @Override\r
869                 protected VWStatusWindow getStWin() { return stwin; }\r
870                 @Override\r
871                 protected StatusTextArea getMWin() { return mwin; }\r
872 \r
873                 // コンポーネントを渡す\r
874                 @Override\r
875                 protected Component getParentComponent() { return Viewer.this; }\r
876                 @Override\r
877                 protected VWColorChooserDialog getCcWin() { return ccwin; }\r
878 \r
879                 @Override\r
880                 protected void ringBeep() { Viewer.this.ringBeep(); }\r
881 \r
882                 /*\r
883                  * AbsRecorderSettingView内でのイベントから呼び出されるメソッド群\r
884                  */\r
885                 \r
886                 @Override\r
887                 protected void setRecInfos() {\r
888                         \r
889                         timer_now.pause();\r
890                         \r
891                         // 設定を保存\r
892                         recInfoList.save();\r
893                         \r
894                         // レコーダプラグインのリフレッシュ\r
895                         initRecPluginAll();\r
896                         \r
897                         // レコーダ一覧をツールバーに設定\r
898                         toolBar.updateRecorderComboBox();\r
899                         \r
900                         // 予約一覧のリフレッシュ\r
901                         loadRdReservesAll(false, null);         // toolBarの内容がリセットされているので recId = null で\r
902                         \r
903                         // レコーダのエンコーダ表示の更新\r
904                         this.redrawRecorderEncoderEntry();\r
905 \r
906                         // レコーダ一覧をCHコード設定のコンボボックスに設定 \r
907                         chdatsetting.updateRecorderComboBox();\r
908                         \r
909                         // Web番組表の再構築(予約マークのリフレッシュ)\r
910                         paper.updateReserveBorder(null);\r
911                         listed.updateReserveMark();\r
912                         \r
913                         timer_now.start();\r
914                 }\r
915 \r
916         }\r
917 \r
918         \r
919         /***\r
920          * CH設定の内部クラス\r
921          */\r
922         private class VWChannelSettingView extends AbsChannelSettingView {\r
923 \r
924                 private static final long serialVersionUID = 1L;\r
925                 \r
926                 // 環境設定の入れ物を渡す\r
927                 @Override\r
928                 protected Env getEnv() { return Viewer.this.env; }\r
929                 @Override\r
930                 protected TVProgramList getProgPlugins() { return progPlugins; }\r
931 \r
932                 // ログ関連\r
933                 @Override\r
934                 protected StatusWindow getStWin() { return stwin; }\r
935                 @Override\r
936                 protected StatusTextArea getMWin() { return mwin; }\r
937 \r
938                 // コンポーネントを渡す\r
939                 @Override\r
940                 protected Component getParentComponent() { return Viewer.this; }\r
941                 @Override\r
942                 protected VWColorChooserDialog getCcWin() { return ccwin; }\r
943 \r
944                 @Override\r
945                 protected void ringBeep() {\r
946                         Viewer.this.ringBeep();\r
947                 }\r
948                 @Override\r
949                 protected void updateProgPlugin() {\r
950                         \r
951                         timer_now.pause();\r
952                         \r
953                         // 設定を保存(プラグイン内部の設定はChannelSettingPanel内で実施)\r
954                         env.save();\r
955                         \r
956                         // Web番組表プラグインのリフレッシュ\r
957                         setSelectedProgPlugin();\r
958                         initProgPluginAll();\r
959                         \r
960                         // CHソート設定に反映\r
961                         chsortsetting.updateChannelSortTable();\r
962                         \r
963                         // CHコンバート設定をリフレッシュ\r
964                         chconvsetting.updateChannelConvertTable();\r
965                         \r
966                         // CHコード設定にも反映\r
967                         chdatsetting.updateChannelDatTable();\r
968 \r
969                         // 番組情報の再取得\r
970                         loadTVProgram(false,LoadFor.ALL);       // 部品呼び出し\r
971                         \r
972                         // ツールバーに反映\r
973                         toolBar.setPagerItems();\r
974                         \r
975                         // 新聞描画枠のリセット\r
976                         paper.clearPanel();\r
977                         paper.buildMainViewByDate();\r
978                         \r
979                         // サイドツリーの再構築\r
980                         paper.redrawTreeByCenter();\r
981                         \r
982                         listed.redrawTreeByCenter();\r
983                         \r
984                         // 再構築\r
985                         paper.reselectTree();\r
986                         listed.reselectTree();\r
987                         \r
988                         timer_now.start();\r
989                 }\r
990                 \r
991         }\r
992         \r
993         /***\r
994          * CHコード設定の内部クラス\r
995          */\r
996         private class VWChannelDatSettingView extends AbsChannelDatSettingView {\r
997 \r
998                 private static final long serialVersionUID = 1L;\r
999 \r
1000                 // 環境設定の入れ物を渡す\r
1001                 @Override\r
1002                 protected Env getEnv() { return Viewer.this.env; }\r
1003                 @Override\r
1004                 protected TVProgramList getTVProgramList() { return tvprograms; }\r
1005                 @Override\r
1006                 protected ChannelSort getChannelSort() { return chsort; }\r
1007                 @Override\r
1008                 protected HDDRecorderList getHDDRecorderList() { return recorders; }\r
1009 \r
1010                 // ログ関連\r
1011                 @Override\r
1012                 protected StatusWindow getStWin() { return stwin; }\r
1013                 @Override\r
1014                 protected StatusTextArea getMWin() { return mwin; }\r
1015 \r
1016                 // コンポーネントを渡す\r
1017                 @Override\r
1018                 protected Component getParentComponent() { return Viewer.this; }\r
1019                 \r
1020                 @Override\r
1021                 protected void ringBeep() {\r
1022                         Viewer.this.ringBeep();\r
1023                 }\r
1024                 \r
1025         }\r
1026 \r
1027         /**\r
1028          * CHソート設定タブの内部クラス\r
1029          */\r
1030         private class VWChannelSortView extends AbsChannelSortView {\r
1031 \r
1032                 private static final long serialVersionUID = 1L;\r
1033 \r
1034                 @Override\r
1035                 protected Env getEnv() { return Viewer.this.env; }\r
1036                 @Override\r
1037                 protected TVProgramList getTVProgramList() { return tvprograms; }\r
1038                 @Override\r
1039                 protected ChannelSort getChannelSort() { return chsort; }\r
1040                 \r
1041                 // ログ関連\r
1042                 @Override\r
1043                 protected StatusTextArea getMWin() { return mwin; }\r
1044                 \r
1045                 @Override\r
1046                 protected void updProc() {\r
1047                         \r
1048                         timer_now.pause();\r
1049                         \r
1050                         env.save();\r
1051                         \r
1052                         toolBar.setPagerItems();\r
1053                         toolBar.setSelectedPagerIndex(toolBar.getSelectedPagerIndex());\r
1054                         \r
1055                         // 新聞描画枠のリセット\r
1056                         paper.clearPanel();\r
1057                         paper.buildMainViewByDate();\r
1058                         \r
1059                         // サイドツリーの再構築\r
1060                         paper.redrawTreeByCenter();\r
1061                         \r
1062                         listed.redrawTreeByCenter();\r
1063                         \r
1064                         // 再描画 \r
1065                         paper.reselectTree();\r
1066                         listed.reselectTree();\r
1067                         \r
1068                         timer_now.start();\r
1069                 }\r
1070         }\r
1071         \r
1072         /**\r
1073          * CHコンバート設定タブの内部クラス\r
1074          */\r
1075         private class VWChannelConvertView extends AbsChannelConvertView {\r
1076 \r
1077                 private static final long serialVersionUID = 1L;\r
1078 \r
1079                 // 環境設定の入れ物を渡す\r
1080                 @Override\r
1081                 protected Env getEnv() { return env; }\r
1082                 @Override\r
1083                 protected TVProgramList getProgPlugins() { return progPlugins; }\r
1084                 @Override\r
1085                 protected ChannelConvert getChannelConvert() { return chconv; }\r
1086                 \r
1087         }\r
1088         \r
1089         /***\r
1090          * 予約ウィンドウの内部クラス\r
1091          */\r
1092         private class VWReserveDialog extends AbsReserveDialog {\r
1093 \r
1094                 private static final long serialVersionUID = 1L;\r
1095 \r
1096                 // コンストラクタ\r
1097                 public VWReserveDialog(int x, int y) {\r
1098                         super(x, y);\r
1099                 }\r
1100 \r
1101                 // 環境設定の入れ物を渡す\r
1102                 @Override\r
1103                 protected Env getEnv() { return env; }\r
1104                 @Override\r
1105                 protected TVProgramList getTVProgramList() { return tvprograms; }\r
1106                 @Override\r
1107                 protected HDDRecorderList getRecorderList() { return recorders; }\r
1108                 @Override\r
1109                 protected AVSetting getAVSetting() { return avs; }\r
1110                 @Override\r
1111                 protected CHAVSetting getCHAVSetting() { return chavs; }\r
1112 \r
1113                 // ログ関連\r
1114                 @Override\r
1115                 protected StatusWindow getStWin() { return stwin; }\r
1116                 @Override\r
1117                 protected StatusTextArea getMWin() { return mwin; }\r
1118                 \r
1119                 // コンポーネントを渡す\r
1120                 @Override\r
1121                 protected Component getParentComponent() { return Viewer.this; }\r
1122 \r
1123                 @Override\r
1124                 protected void ringBeep() { Viewer.this.ringBeep(); }\r
1125 \r
1126                 /*\r
1127                  * ReserveDialog内でのイベントから呼び出されるメソッド群\r
1128                  */\r
1129                 \r
1130                 @Override\r
1131                 protected LikeReserveList findLikeReserves(ProgDetailList tvd, String keyword, int threshold) {\r
1132                         return Viewer.this.findLikeReserves(tvd, keyword, threshold);\r
1133                 }\r
1134         }\r
1135         \r
1136         /**\r
1137          * 新聞の表示形式を操作するダイアログ\r
1138          */\r
1139         private class VWPaperColorsDialog extends AbsPaperColorsDialog {\r
1140 \r
1141                 private static final long serialVersionUID = 1L;\r
1142 \r
1143                 @Override\r
1144                 protected Env getEnv() { return env; }\r
1145                 @Override\r
1146                 protected Bounds getBoundsEnv() { return bounds; }\r
1147                 @Override\r
1148                 protected PaperColorsMap getPaperColorMap() { return pColors; }\r
1149                 \r
1150                 @Override\r
1151                 protected VWColorChooserDialog getCCWin() { return ccwin; }\r
1152                 \r
1153                 /*\r
1154                  * PaperColorsDialog内でのイベントから呼び出されるメソッド群\r
1155                  */\r
1156                 \r
1157                 // 背景色設定の反映\r
1158                 @Override\r
1159                 protected void updatePaperColors(Env ec,PaperColorsMap pc) {\r
1160                         paper.updateColors(ec,pc);\r
1161                 }\r
1162 \r
1163                 // フォント設定の反映\r
1164                 @Override\r
1165                 protected void updatePaperFonts(Env ec) {\r
1166                         paper.updateFonts(ec);\r
1167                 }\r
1168 \r
1169                 // サイズ設定の反映\r
1170                 @Override\r
1171                 protected void updatePaperBounds(Env ec, Bounds bc) {\r
1172                         paper.updateBounds(ec,bc);\r
1173                 }\r
1174                 \r
1175                 // 再描画?\r
1176                 @Override\r
1177                 protected void updatePaperRepaint() {\r
1178                         paper.updateRepaint();\r
1179                 }\r
1180         }\r
1181         \r
1182         /**\r
1183          * キーワード検索ウィンドウの内部クラス\r
1184          */\r
1185         private class VWKeywordDialog extends AbsKeywordDialog {\r
1186 \r
1187                 private static final long serialVersionUID = 1L;\r
1188 \r
1189                 @Override\r
1190                 void preview(SearchKey search) {\r
1191                         // 検索実行\r
1192                         if (search.alTarget.size() > 0) {\r
1193                                 mainWindow.setSelectedTab(MWinTab.LISTED);\r
1194                                 listed.redrawListByPreview(search);\r
1195                         }\r
1196                 }\r
1197         }\r
1198 \r
1199         /**\r
1200          * 延長警告管理ウィンドウの内部クラス\r
1201          */\r
1202         private class VWExtensionDialog extends AbsExtensionDialog {\r
1203 \r
1204                 private static final long serialVersionUID = 1L;\r
1205 \r
1206                 @Override\r
1207                 void preview(SearchKey search) {\r
1208                         // 検索実行\r
1209                         if (search.alTarget.size() > 0) {\r
1210                                 mainWindow.setSelectedTab(MWinTab.LISTED);\r
1211                                 listed.redrawListByPreview(search);\r
1212                         }\r
1213                 }\r
1214         }\r
1215         \r
1216         /***\r
1217          * \r
1218          * ツールバーの内部クラス\r
1219          * \r
1220          */\r
1221         private class VWToolBar extends AbsToolBar {\r
1222 \r
1223                 private static final long serialVersionUID = 1L;\r
1224 \r
1225                 @Override\r
1226                 protected Env getEnv() { return env; }\r
1227                 @Override\r
1228                 protected Bounds getBoundsEnv() { return bounds; }\r
1229                 @Override\r
1230                 protected TVProgramList getTVPrograms() { return tvprograms; }\r
1231                 @Override\r
1232                 protected ChannelSort getChannelSort() { return chsort; }\r
1233                 @Override\r
1234                 protected HDDRecorderList getHDDRecorders() { return recorders; }\r
1235 \r
1236                 @Override\r
1237                 protected StatusWindow getStWin() { return stwin; }\r
1238                 @Override\r
1239                 protected StatusTextArea getMWin() { return mwin; }\r
1240                 @Override\r
1241                 protected Component getParentComponent() { return Viewer.this; }\r
1242 \r
1243                 @Override\r
1244                 protected void ringBeep() { Viewer.this.ringBeep(); }\r
1245 \r
1246                 @Override\r
1247                 protected boolean doKeywordSerach(SearchKey search, String kStr, String sStr, boolean doFilter) {\r
1248                         \r
1249                         timer_now.pause();\r
1250                         \r
1251                         if ( mainWindow.getSelectedTab() == MWinTab.RSVED ) {\r
1252                                 reserved.redrawListByKeywordFilter(search, kStr);\r
1253                         }\r
1254                         else if ( mainWindow.getSelectedTab() == MWinTab.RECED ) {\r
1255                                 recorded.redrawListByKeywordFilter(search, kStr);\r
1256                         }\r
1257                         else {\r
1258                                 if ( search != null ) {\r
1259                                         mainWindow.setSelectedTab(MWinTab.LISTED);\r
1260                                         if ( doFilter ) {\r
1261                                                 // 絞り込み検索\r
1262                                                 listed.clearSelection();\r
1263                                                 listed.redrawListByKeywordFilter(search, kStr);\r
1264                                         }\r
1265                                         else if (sStr != null) {\r
1266                                                 // 過去ログ検索\r
1267                                                 searchPassedProgram(search, sStr);\r
1268                                                 listed.clearSelection();\r
1269                                                 listed.redrawListBySearched(ProgType.PASSED, 0);\r
1270                                                 \r
1271                                                 listed.redrawTreeByHistory();\r
1272                                         }\r
1273                                         else {\r
1274                                                 // キーワード検索\r
1275                                                 listed.clearSelection();\r
1276                                                 listed.redrawListByKeywordDyn(search, kStr);\r
1277                                         }\r
1278                                 }\r
1279                         }\r
1280                         \r
1281                         timer_now.start();\r
1282                         \r
1283                         return true;\r
1284                 }\r
1285 \r
1286                 @Override\r
1287                 protected boolean doBatchReserve() {\r
1288                         timer_now.pause();\r
1289                         listed.doBatchReserve();\r
1290                         timer_now.start();\r
1291                         return true;\r
1292                 }\r
1293 \r
1294                 @Override\r
1295                 protected boolean jumpToNow() {\r
1296                         timer_now.pause();\r
1297                         if ( ! mainWindow.isTabSelected(MWinTab.PAPER) ) {\r
1298                                 mainWindow.setSelectedTab(MWinTab.PAPER);\r
1299                         }\r
1300                         paper.jumpToNow();\r
1301                         timer_now.start();\r
1302                         return true;\r
1303                 }\r
1304 \r
1305                 @Override\r
1306                 protected boolean jumpToPassed(String passed) {\r
1307                         timer_now.pause();\r
1308                         boolean b = paper.jumpToPassed(passed);\r
1309                         timer_now.start();\r
1310                         return b;\r
1311                 }\r
1312 \r
1313                 @Override\r
1314                 protected boolean redrawByPager() {\r
1315                         timer_now.pause();\r
1316                         boolean b = paper.redrawByPager();\r
1317                         timer_now.start();\r
1318                         return b;\r
1319                 }\r
1320 \r
1321                 @Override\r
1322                 protected void toggleMatchBorder(boolean b) {\r
1323                         timer_now.pause();\r
1324                         if ( mainWindow.isTabSelected(MWinTab.LISTED) ) {\r
1325                                 listed.toggleReservedBackground(b);\r
1326                         }\r
1327                         else if ( mainWindow.isTabSelected(MWinTab.PAPER) ) {\r
1328                                 paper.toggleMatchBorder(b);\r
1329                         }\r
1330                         timer_now.start();\r
1331                 }\r
1332 \r
1333                 @Override\r
1334                 protected void setPaperColorDialogVisible(boolean b) {\r
1335                         //paper.stopTimer(); xxxx\r
1336                         timer_now.pause();\r
1337                         CommonSwingUtils.setLocationCenter(Viewer.this,pcwin);\r
1338                         pcwin.setVisible(true);\r
1339                         timer_now.start();\r
1340                 }\r
1341 \r
1342                 @Override\r
1343                 protected void setPaperZoom(int n) {\r
1344                         timer_now.pause();\r
1345                         paper.setZoom(n);\r
1346                         timer_now.start();\r
1347                 }\r
1348 \r
1349                 @Override\r
1350                 protected boolean recorderSelectorChanged() {\r
1351                         \r
1352                         timer_now.pause();\r
1353                         \r
1354                         if (mainWindow.isTabSelected(MWinTab.LISTED)) {\r
1355                                 listed.updateReserveMark();\r
1356                                 listed.selectBatchTarget();\r
1357                         }\r
1358                         else if (mainWindow.isTabSelected(MWinTab.RSVED)) {\r
1359                                 reserved.redrawReservedList();\r
1360                         }\r
1361                         else if (mainWindow.isTabSelected(MWinTab.RECED)) {\r
1362                                 recorded.redrawRecordedList();\r
1363                         }\r
1364                         \r
1365                         /*\r
1366                         // 新聞形式の予約枠を書き換えるかもよ?\r
1367                         if (env.getEffectComboToPaper()) {\r
1368                                 paper.updateReserveBorder(null);\r
1369                         }\r
1370                         */\r
1371                         \r
1372                         timer_now.start();\r
1373                         \r
1374                         return true;\r
1375                 }\r
1376 \r
1377                 @Override\r
1378                 protected void takeSnapShot() {\r
1379                         \r
1380                         timer_now.pause();\r
1381                         \r
1382                         Viewer.this.getSnapshot(getSelectedPagerIndex(),getPagerCount());\r
1383                         \r
1384                         timer_now.start();\r
1385                 }\r
1386 \r
1387                 @Override\r
1388                 protected void setStatusVisible(boolean b) {\r
1389                         Viewer.this.setStatusVisible(b);\r
1390                 }\r
1391 \r
1392                 @Override\r
1393                 protected void setFullScreen(boolean b) {\r
1394                         Viewer.this.setFullScreen(b);\r
1395                 }\r
1396 \r
1397                 @Override\r
1398                 protected boolean isTabSelected(MWinTab tab) {\r
1399                         return mainWindow.isTabSelected(tab);\r
1400                 }\r
1401 \r
1402                 @Override\r
1403                 protected boolean addKeywordSearch(SearchKey search) {\r
1404                         \r
1405                         timer_now.pause();\r
1406                         \r
1407                         AbsKeywordDialog kD = new VWKeywordDialog();\r
1408                         CommonSwingUtils.setLocationCenter(Viewer.this,kD);\r
1409                         \r
1410                         kD.open(search.getLabel(), srKeys, srGrps, search);\r
1411                         kD.setVisible(true);\r
1412                         \r
1413                         if (kD.isRegistered()) {\r
1414                                 // 検索結果の再構築\r
1415                                 mpList.clear(env.getDisableFazzySearch(), env.getDisableFazzySearchReverse());\r
1416                                 mpList.build(tvprograms, trKeys.getTraceKeys(), srKeys.getSearchKeys());\r
1417                                 \r
1418                                 // ツリーに反映する\r
1419                                 listed.redrawTreeByKeyword();\r
1420                                 \r
1421                                 mainWindow.setSelectedTab(MWinTab.LISTED);\r
1422                         }\r
1423                         \r
1424                         timer_now.start();\r
1425                         \r
1426                         return true;\r
1427                 }\r
1428 \r
1429                 @Override\r
1430                 protected boolean doLoadTVProgram(String selected) {\r
1431                         timer_now.pause();\r
1432                         \r
1433                         LoadFor lf = (selected != null) ? LoadFor.get(selected) : LoadFor.ALL;\r
1434                         boolean b = Viewer.this.doLoadTVProgram(true, lf);\r
1435                         \r
1436                         if ( b && lf == LoadFor.CSwSD ) {\r
1437                                 // ロード後シャットダウン\r
1438                                 CommonUtils.executeCommand(env.getShutdownCmd());\r
1439                         }\r
1440 \r
1441                         Viewer.this.doRedrawTVProgram();        // か き な お し\r
1442 \r
1443                         timer_now.start();\r
1444                         return b;\r
1445                 }\r
1446 \r
1447                 @Override\r
1448                 protected boolean doLoadRdRecorder(String selected) {\r
1449                         timer_now.pause();\r
1450                         \r
1451                         LoadRsvedFor lrf = (selected != null) ? LoadRsvedFor.get(selected) : null;\r
1452                         boolean b = Viewer.this.doLoadRdRecorder(lrf);\r
1453                         \r
1454                         timer_now.start();\r
1455                         return b;\r
1456                 }\r
1457         }\r
1458         \r
1459         /*******************************************************************************\r
1460          * ハンドラ―メソッド\r
1461          ******************************************************************************/\r
1462 \r
1463         /**\r
1464          * なんかよくわからないもの\r
1465          */\r
1466         @Override\r
1467         public void stateChanged(ChangeEvent e){\r
1468                 StdAppendMessage("イベント発生");\r
1469         }\r
1470 \r
1471         /**\r
1472          * ツールバーでレコーダの選択イベントが発生\r
1473          */\r
1474         @Override\r
1475         public void valueChanged(HDDRecorderSelectionEvent e) {\r
1476                 // 選択中のレコーダ情報を保存する\r
1477                 src_recsel = (HDDRecorderSelectable) e.getSource();\r
1478         }\r
1479         \r
1480         private String getSelectedMySelf() {\r
1481                 return ( src_recsel!=null ? src_recsel.getSelectedMySelf() : null );\r
1482         }\r
1483         \r
1484         private HDDRecorderList getSelectedRecorderList() {\r
1485                 return ( src_recsel!=null ? src_recsel.getSelectedList() : null );\r
1486         }\r
1487         \r
1488         private HDDRecorderSelectable src_recsel;\r
1489 \r
1490         /**\r
1491          * レコーダ情報の変更イベントが発生\r
1492          */\r
1493         @Override\r
1494         public void stateChanged(HDDRecorderChangeEvent e) {\r
1495                 // 未実装\r
1496         }\r
1497         \r
1498         /**\r
1499          * \r
1500          */\r
1501         @Override\r
1502         public void cancelRised(CancelEvent e) {\r
1503                 if ( mainWindow.isTabSelected(MWinTab.RSVED) ) {\r
1504                         if ( e.getCause() == CancelEvent.Cause.TOOLBAR_SEARCH ) {\r
1505                                 reserved.redrawListByKeywordFilter(null,null);\r
1506                         }\r
1507                 }\r
1508                 else if ( mainWindow.isTabSelected(MWinTab.RECED) ) {\r
1509                         if ( e.getCause() == CancelEvent.Cause.TOOLBAR_SEARCH ) {\r
1510                                 recorded.redrawListByKeywordFilter(null,null);\r
1511                         }\r
1512                 }\r
1513         }\r
1514         \r
1515         /**\r
1516          * タイマーイベントが発生\r
1517          */\r
1518         @Override\r
1519         public void timerRised(TickTimerRiseEvent e) {\r
1520                 if (env.getDebug()) System.out.println("Timer Rised: now="+CommonUtils.getDateTimeYMDx(e.getCalendar()));\r
1521                 setTitleBar();\r
1522         }\r
1523         \r
1524         \r
1525         /*******************************************************************************\r
1526          * 共通メソッド群\r
1527          ******************************************************************************/\r
1528         \r
1529         /**\r
1530          * 類似予約をさがす\r
1531          */\r
1532         private LikeReserveList findLikeReserves(ProgDetailList tvd, String keyword, int threshold) {\r
1533                 \r
1534                 String keywordVal = null;\r
1535                 int thresholdVal = 0;\r
1536                 \r
1537                 // 曖昧検索のための初期化\r
1538                 if ( ! env.getDisableFazzySearch() ) {\r
1539                         if ( threshold > 0 ) {\r
1540                                 // キーワード指定がある場合\r
1541                                 keywordVal = TraceProgram.replacePop(keyword);\r
1542                                 thresholdVal = threshold;\r
1543                         }\r
1544                         else {\r
1545                                 // キーワード指定がない場合\r
1546                                 keywordVal = tvd.titlePop;\r
1547                                 thresholdVal = env.getDefaultFazzyThreshold();\r
1548                         }\r
1549                 }\r
1550 \r
1551                 // 検索実行\r
1552                 return recorders.findLikeReserves(tvd, keywordVal, thresholdVal, env.getRangeLikeRsv(), ! env.getDisableFazzySearchReverse());\r
1553         }\r
1554         \r
1555         /***\r
1556          * \r
1557          * リスト・新聞形式共通\r
1558          * \r
1559          */\r
1560 \r
1561         /**\r
1562          *  番組追跡への追加とgoogle検索\r
1563          */\r
1564         public void showPopupForTraceProgram(\r
1565                         final JComponent comp,\r
1566                         final ProgDetailList tvd, final String keyword, final int threshold,\r
1567                         final int x, final int y, final String clickedDateTime)\r
1568         {\r
1569                 JPopupMenu pop = new JPopupMenu();\r
1570                 \r
1571                 String myself = toolBar.getSelectedRecorder();\r
1572         \r
1573                 // 類似予約検索\r
1574                 LikeReserveList likeRsvList;\r
1575                 if ( env.getDisableFazzySearch() ) {\r
1576                         likeRsvList = recorders.findLikeReserves(tvd, null, 0, env.getRangeLikeRsv(), false);\r
1577                 }\r
1578                 else {\r
1579                         likeRsvList = recorders.findLikeReserves(tvd, tvd.titlePop, env.getDefaultFazzyThreshold(), env.getRangeLikeRsv(), ! env.getDisableFazzySearchReverse());\r
1580                 }\r
1581                 \r
1582                 // 重複予約検索\r
1583                 LikeReserveList overlapRsvList = recorders.findOverlapReserves(tvd, null, true, env.getOverlapUp());\r
1584                 \r
1585                 // 類似と重複で被るものを重複から除外\r
1586                 for ( LikeReserveItem item : likeRsvList ) {\r
1587                         overlapRsvList.removeDup(item);\r
1588                 }\r
1589                 \r
1590                 // 予約する\r
1591                 if ( tvd.type == ProgType.PASSED ||\r
1592                                 (tvd.type == ProgType.PROG && tvd.subtype == ProgSubtype.RADIO) ||\r
1593                                 recorders.size() == 0 ) {\r
1594                         // 過去ログは処理対象外です\r
1595                 }\r
1596                 else {\r
1597                         String target;\r
1598                         LikeReserveItem item = likeRsvList.getClosest(myself);\r
1599                         if ( env.getGivePriorityToReserved() && item != null && item.isCandidate(env.getOverlapUp()) ) {\r
1600                                 target = "予約を編集する";\r
1601                         }\r
1602                         else {\r
1603                                 target = "新規予約を登録する";\r
1604                         }\r
1605                         \r
1606                         JMenuItem menuItem = new JMenuItem(String.format("%s【%s %s - %s(%s)】",target,tvd.accurateDate,tvd.start,tvd.title,tvd.center));\r
1607                         {\r
1608                                 menuItem.setForeground(Color.BLUE);\r
1609                                 Font f = menuItem.getFont();\r
1610                                 menuItem.setFont(f.deriveFont(f.getStyle()|Font.BOLD));\r
1611                         }\r
1612                         \r
1613                         menuItem.addActionListener(new ActionListener() {\r
1614                                 public void actionPerformed(ActionEvent e) {\r
1615 \r
1616                                         CommonSwingUtils.setLocationCenter(mainWindow,rdialog);\r
1617 \r
1618                                         if ( rdialog.open(tvd) ) {\r
1619                                                 rdialog.setVisible(true);\r
1620                                         }\r
1621                                         else {\r
1622                                                 rdialog.setVisible(false);\r
1623                                         }\r
1624                                         \r
1625                                         //\r
1626                                         if (rdialog.isSucceededReserve()) {\r
1627                                                 listed.updateReserveMark();\r
1628                                                 paper.updateReserveBorder(tvd.center);\r
1629                                                 reserved.redrawReservedList();\r
1630                                         }\r
1631                                 }\r
1632                         });\r
1633                         pop.add(menuItem);\r
1634                 }\r
1635                 \r
1636                 // 隣接予約を編集する\r
1637                 {\r
1638                         for ( final LikeReserveItem item : overlapRsvList ) {\r
1639                                 \r
1640                                 if ( ! item.getRec().Myself().equals(toolBar.getSelectedRecorder()) ) {\r
1641                                         continue;       // 選択中のレコーダ以外はスルーで\r
1642                                 }\r
1643                                 \r
1644                                 {\r
1645                                         ReserveList rsv = item.getRsv();\r
1646                                         String start = CommonUtils.getDateTimeW(CommonUtils.getCalendar(rsv.getStartDateTime()));\r
1647                                         JMenuItem menuItem = new JMenuItem(String.format("隣接予約を上書する【%s - %s(%s)】",start,rsv.getTitle(),rsv.getCh_name()));\r
1648                                         \r
1649                                         menuItem.addActionListener(new ActionListener() {\r
1650                                                 public void actionPerformed(ActionEvent e) {\r
1651 \r
1652                                                         CommonSwingUtils.setLocationCenter(mainWindow,rdialog);\r
1653 \r
1654                                                         if ( rdialog.open(tvd,item) ) {\r
1655                                                                 rdialog.setVisible(true);\r
1656                                                         }\r
1657                                                         else {\r
1658                                                                 rdialog.setVisible(false);\r
1659                                                         }\r
1660                                                         \r
1661                                                         //\r
1662                                                         if (rdialog.isSucceededReserve()) {\r
1663                                                                 listed.updateReserveMark();\r
1664                                                                 paper.updateReserveBorder(tvd.center);\r
1665                                                                 reserved.redrawReservedList();\r
1666                                                         }\r
1667                                                 }\r
1668                                         });\r
1669                                         pop.add(menuItem);\r
1670                                 }\r
1671                         }\r
1672                 }\r
1673                 pop.addSeparator();\r
1674                 \r
1675                 // 予約実行ON・OFF\r
1676                 if ( tvd.type != ProgType.PASSED )\r
1677                 {\r
1678                         for ( int n=0; n<2; n++ ) {\r
1679                                 \r
1680                                 LikeReserveList rsvList = null;\r
1681                                 if ( n == 0 ) {\r
1682                                         rsvList = likeRsvList;\r
1683                                 }\r
1684                                 else {\r
1685                                         rsvList = overlapRsvList;\r
1686                                 }\r
1687                                 \r
1688                                 for ( LikeReserveItem rsvItem : rsvList ) {\r
1689                                         \r
1690                                         final boolean fexec = rsvItem.getRsv().getExec();\r
1691                                         final String start = rsvItem.getRsv().getAhh()+":"+rsvItem.getRsv().getAmm();\r
1692                                         final String title = rsvItem.getRsv().getTitle();\r
1693                                         final String chnam = rsvItem.getRsv().getCh_name();\r
1694                                         final String rsvId = rsvItem.getRsv().getId();\r
1695                                         final String recId = rsvItem.getRec().Myself();\r
1696                                         \r
1697                                         pop.add(getExecOnOffMenuItem(fexec,start,title,chnam,rsvId,recId,n));\r
1698                                 }\r
1699                                 \r
1700                                 pop.addSeparator();\r
1701                         }\r
1702                 }\r
1703                 \r
1704                 pop.addSeparator();\r
1705                 \r
1706                 // 削除する\r
1707                 if ( tvd.type != ProgType.PASSED )      // 過去ログは処理対象外です\r
1708                 {\r
1709                         for ( int n=0; n<2; n++ ) {\r
1710                                 \r
1711                                 LikeReserveList rsvList = null;\r
1712                                 if ( n == 0 ) {\r
1713                                         rsvList = likeRsvList;\r
1714                                 }\r
1715                                 else {\r
1716                                         rsvList = overlapRsvList;\r
1717                                 }\r
1718                                 \r
1719                                 for ( LikeReserveItem rsvItem : rsvList ) {\r
1720                                         \r
1721                                         final String start = rsvItem.getRsv().getAhh()+":"+rsvItem.getRsv().getAmm();\r
1722                                         final String title = rsvItem.getRsv().getTitle();\r
1723                                         final String chnam = rsvItem.getRsv().getCh_name();\r
1724                                         final String rsvId = rsvItem.getRsv().getId();\r
1725                                         final String recId = rsvItem.getRec().Myself();\r
1726                                         \r
1727                                         pop.add(getRemoveRsvMenuItem(start, title,chnam,rsvId,recId,n));\r
1728                                 }\r
1729                                 \r
1730                                 pop.addSeparator();\r
1731                         }\r
1732                 }\r
1733                 else {\r
1734                         pop.addSeparator();\r
1735                         pop.addSeparator();\r
1736                 }\r
1737                 \r
1738                 // ジャンプする\r
1739                 {\r
1740                         if ( mainWindow.isTabSelected(MWinTab.LISTED) ) {\r
1741                                 pop.add(getJumpMenuItem(tvd.title,tvd.center,tvd.accurateDate+" "+tvd.start));\r
1742                         }\r
1743                         if ( mainWindow.isTabSelected(MWinTab.LISTED) || mainWindow.isTabSelected(MWinTab.PAPER) ) {\r
1744                                 JMenuItem mi = getJumpToLastWeekMenuItem(tvd.title,tvd.center,tvd.startDateTime);\r
1745                                 if ( mi != null ) {\r
1746                                         pop.add(mi);\r
1747                                 }\r
1748                         }\r
1749                 }\r
1750                 \r
1751                 pop.addSeparator();\r
1752                 \r
1753                 // 番組追跡へ追加する\r
1754                 {\r
1755                         final String label = TraceProgram.getNewLabel(tvd.title, tvd.center);\r
1756                         JMenuItem menuItem = new JMenuItem("番組追跡への追加【"+label+"】");\r
1757                         menuItem.addActionListener(new ActionListener() {\r
1758                                 public void actionPerformed(ActionEvent e) {\r
1759                                         //\r
1760                                         VWTraceKeyDialog tD = new VWTraceKeyDialog(0,0);\r
1761                                         CommonSwingUtils.setLocationCenter(mainWindow,tD);\r
1762                                         \r
1763                                         tD.open(trKeys, tvd, env.getDefaultFazzyThreshold());\r
1764                                         tD.setVisible(true);\r
1765                                         \r
1766                                         if (tD.isRegistered()) {\r
1767                                                 //\r
1768                                                 trKeys.save();\r
1769                                                 \r
1770                                                 // 検索結果の再構築\r
1771                                                 mpList.clear(env.getDisableFazzySearch(), env.getDisableFazzySearchReverse());\r
1772                                                 mpList.build(tvprograms, trKeys.getTraceKeys(), srKeys.getSearchKeys());\r
1773                                                 \r
1774                                                 // ツリーに反映する\r
1775                                                 listed.redrawTreeByTrace();\r
1776 \r
1777                                                 // 表示を更新する\r
1778                                                 paper.updateBangumiColumns();\r
1779                                                 listed.reselectTree();\r
1780                                                 \r
1781                                                 mwin.appendMessage("番組追跡へ追加しました【"+label+"】");\r
1782                                         }\r
1783                                         else {\r
1784                                                 trKeys.remove(label);\r
1785                                         }\r
1786                                 }\r
1787                         });\r
1788                         pop.add(menuItem);\r
1789                 }\r
1790                 \r
1791                 // キーワード検索へ追加する\r
1792                 {\r
1793                         final String label = tvd.title+" ("+tvd.center+")";\r
1794                         JMenuItem menuItem = new JMenuItem("キーワード検索への追加【"+label+"】");\r
1795                         menuItem.addActionListener(new ActionListener(){\r
1796                                 public void actionPerformed(ActionEvent e){\r
1797                                         \r
1798                                         // 「キーワード検索の設定」ウィンドウを開く\r
1799                                         \r
1800                                         AbsKeywordDialog kD = new VWKeywordDialog();\r
1801                                         CommonSwingUtils.setLocationCenter(mainWindow,kD);\r
1802                                         \r
1803                                         kD.open(srKeys, srGrps, tvd);\r
1804                                         kD.setVisible(true);\r
1805                                         \r
1806                                         if (kD.isRegistered()) {\r
1807                                                 // 検索結果の再構築\r
1808                                                 mpList.clear(env.getDisableFazzySearch(), env.getDisableFazzySearchReverse());\r
1809                                                 mpList.build(tvprograms, trKeys.getTraceKeys(), srKeys.getSearchKeys());\r
1810                                                 \r
1811                                                 // ツリーに反映する\r
1812                                                 listed.redrawTreeByKeyword();\r
1813 \r
1814                                                 // 表示を更新する\r
1815                                                 paper.updateBangumiColumns();\r
1816                                                 listed.reselectTree();\r
1817                                                 \r
1818                                                 mwin.appendMessage("キーワード検索へ追加しました【"+label+"】");\r
1819                                         }\r
1820                                 }\r
1821                         });\r
1822                         pop.add(menuItem);\r
1823                 }\r
1824                 \r
1825                 // ピックアップへ追加する\r
1826                 {\r
1827                         boolean isRemoveItem = false;\r
1828                         if ( mainWindow.isTabSelected(MWinTab.LISTED) && tvd.type == ProgType.PICKED ) {\r
1829                                 isRemoveItem = true;\r
1830                         }\r
1831                         else {\r
1832                                 PickedProgram tvp = tvprograms.getPickup();\r
1833                                 if ( tvp != null ) {\r
1834                                         isRemoveItem = tvp.remove(tvd, tvd.center, tvd.accurateDate, false);\r
1835                                 }\r
1836                         }\r
1837                         \r
1838                         if ( ! isRemoveItem )   // 過去ログは処理対象外です\r
1839                         {\r
1840                                 final String label = String.format("%s(%s)",tvd.title,tvd.center);\r
1841                                 JMenuItem menuItem = new JMenuItem(String.format("ピックアップへの追加【%s %s - %s】",tvd.accurateDate,tvd.start,label));\r
1842                                 menuItem.addActionListener(new ActionListener() {\r
1843                                         public void actionPerformed(ActionEvent e) {\r
1844                                                 //\r
1845                                                 PickedProgram tvp = tvprograms.getPickup();\r
1846                                                 if ( tvp != null ) {\r
1847                                                         tvp.refresh();\r
1848                                                         tvp.add(tvd);\r
1849                                                         tvp.save();\r
1850                                                         /*\r
1851                                                         if ( listed.isNodeSelected(ListedTreeNode.PICKUP) ) {\r
1852                                                                 // ピックアップノードが選択されていたらリストを更新する\r
1853                                                                 listed.reselectTree();\r
1854                                                         }\r
1855                                                         */\r
1856                                                         listed.updateReserveMark();\r
1857                                                         listed.refocus();\r
1858                                                         paper.updateReserveBorder(tvd.center);\r
1859                                                         mwin.appendMessage("【ピックアップ】追加しました: "+tvd.title+" ("+tvd.center+")");\r
1860                                                         return;\r
1861                                                 }\r
1862                                         }\r
1863                                 });\r
1864                                 pop.add(menuItem);\r
1865                         }\r
1866                         else {\r
1867                                 final String label = tvd.title+" ("+tvd.center+")";\r
1868                                 JMenuItem menuItem = new JMenuItem("ピックアップからの削除【"+label+"】");\r
1869                                 menuItem.setForeground(Color.RED);\r
1870                                 menuItem.addActionListener(new ActionListener() {\r
1871                                         public void actionPerformed(ActionEvent e) {\r
1872                                                 //\r
1873                                                 PickedProgram tvp = tvprograms.getPickup();\r
1874                                                 if ( tvp != null ) {\r
1875                                                         tvp.refresh();\r
1876                                                         tvp.remove(tvd, tvd.center, tvd.accurateDate, true);\r
1877                                                         tvp.save();\r
1878                                                         /*\r
1879                                                         if ( listed.isNodeSelected(ListedTreeNode.PICKUP) || listed.isNodeSelected(ListedTreeNode.STANDBY) ) {\r
1880                                                                 // ピックアップノードが選択されていたらリストを更新する\r
1881                                                                 listed.reselectTree();\r
1882                                                         }\r
1883                                                         */\r
1884                                                         listed.updateReserveMark();\r
1885                                                         paper.updateReserveBorder(tvd.center);\r
1886                                                         mwin.appendMessage("【ピックアップ】削除しました: "+tvd.title+" ("+tvd.center+")");\r
1887                                                         return;\r
1888                                                 }\r
1889                                         }\r
1890                                 });\r
1891                                 pop.add(menuItem);\r
1892                         }\r
1893                 }\r
1894 \r
1895                 pop.addSeparator();\r
1896                 \r
1897                 // googleで検索する\r
1898                 {\r
1899                         for (final TextValueSet tv : env.getTvCommand()) {\r
1900                                 JMenuItem menuItem = new JMenuItem(tv.getText());\r
1901                                 String escepedTitle = "";\r
1902                                 String escepedChName = "";\r
1903                                 String escepedDetail = "";\r
1904                                 try {\r
1905                                         escepedTitle = URLEncoder.encode(tvd.title,"UTF-8");\r
1906                                         escepedDetail = URLEncoder.encode(tvd.detail,"UTF-8");\r
1907                                         escepedChName = URLEncoder.encode(tvd.center,"UTF-8");\r
1908                                 } catch (UnsupportedEncodingException e2) {\r
1909                                         //\r
1910                                 }\r
1911                                 \r
1912                                 String cmd = tv.getValue();\r
1913                                 if ( cmd.matches(".*%DETAILURL%.*") ) {\r
1914                                         if ( tvd.link == null || tvd.link.length() == 0 ) {\r
1915                                                 // このメニューは利用できません!\r
1916                                                 menuItem.setEnabled(false);\r
1917                                                 menuItem.setForeground(Color.lightGray);\r
1918                                         }\r
1919                                 }\r
1920                                 cmd = cmd.replaceAll("%ENCTITLE%", escepedTitle);\r
1921                                 cmd = cmd.replaceAll("%ENCDETAIL%", escepedDetail);\r
1922                                 cmd = cmd.replaceAll("%ENCCHNAME%", escepedChName);\r
1923                                 cmd = cmd.replaceAll("%TITLE%", tvd.title);\r
1924                                 cmd = cmd.replaceAll("%DETAIL%", tvd.detail);\r
1925                                 cmd = cmd.replaceAll("%CHNAME%", tvd.center);\r
1926                                 cmd = cmd.replaceAll("%DATE%", tvd.accurateDate);\r
1927                                 cmd = cmd.replaceAll("%START%", tvd.start);\r
1928                                 cmd = cmd.replaceAll("%END%", tvd.end);\r
1929                                 cmd = cmd.replaceAll("%DETAILURL%", tvd.link); \r
1930                                 \r
1931                                 // CHAN-TORU対応\r
1932                                 if ( cmd.matches(".*%TVKAREACODE%.*") && cmd.matches(".*%TVKPID%.*") ) {\r
1933                                         Center cr = null;\r
1934                                         for ( TVProgram tvp : progPlugins ) {\r
1935                                                 if ( tvp.getTVProgramId().startsWith("Gガイド.テレビ王国") ) {\r
1936                                                         for ( Center tempcr : tvp.getCRlist() ) {\r
1937                                                                 // CH設定が完了している必要がある\r
1938                                                                 if ( tvp.getSubtype() == ProgSubtype.TERRA && tvp.getSelectedCode().equals(TVProgram.allCode) && ! tempcr.getAreaCode().equals(TVProgram.bsCode) ) {\r
1939                                                                         // 地域が全国の地デジの場合のみ、有効局かどうかを確認する必要がある\r
1940                                                                         if ( tempcr.getCenter().equals(tvd.center) && tempcr.getOrder() > 0 ) {\r
1941                                                                                 // このメニューは利用できます!\r
1942                                                                                 cr = tempcr;\r
1943                                                                                 break;\r
1944                                                                         }\r
1945                                                                 }\r
1946                                                                 else {\r
1947                                                                         if ( tempcr.getCenter().equals(tvd.center) ) {\r
1948                                                                                 // このメニューは利用できます!\r
1949                                                                                 cr = tempcr;\r
1950                                                                                 break;\r
1951                                                                         }\r
1952                                                                 }\r
1953                                                         }\r
1954                                                         \r
1955                                                         if ( cr != null ) {\r
1956                                                                 break;\r
1957                                                         }\r
1958                                                 }\r
1959                                         }\r
1960                                         if ( cr != null ) {\r
1961                                                 String areacode = null;\r
1962                                                 String centercode = cr.getLink();\r
1963                                                 String cat = cr.getLink().substring(0,1);\r
1964                                                 if ( cat.equals("1") ) {\r
1965                                                         areacode = cr.getAreaCode();\r
1966                                                 }\r
1967                                                 else {\r
1968                                                         if ( cat.equals("4") ) {\r
1969                                                                 cat = "5";\r
1970                                                         }\r
1971                                                         else if ( cat.equals("5") ) {\r
1972                                                                 cat = "4";\r
1973                                                         }\r
1974                                                         areacode = "10";\r
1975                                                 }\r
1976                                                 \r
1977                                                 cmd = cmd.replaceAll("%TVKAREACODE%", areacode);\r
1978                                                 cmd = cmd.replaceAll("%TVKCAT%", cat);\r
1979                                                 cmd = cmd.replaceAll("%TVKPID%", centercode+CommonUtils.getDateTimeYMD(CommonUtils.getCalendar(tvd.startDateTime)).replaceFirst("..$", ""));\r
1980                                                 System.out.println("[DEBUG] "+cmd);\r
1981                                                 \r
1982                                                 menuItem.setEnabled(true);\r
1983                                                 menuItem.setForeground(Color.BLACK);\r
1984                                         }\r
1985                                         else {\r
1986                                                 menuItem.setEnabled(false);\r
1987                                                 menuItem.setForeground(Color.lightGray);\r
1988                                         }\r
1989                                 }\r
1990                                 \r
1991                                 final String run = cmd;\r
1992                                 \r
1993                                 menuItem.addActionListener(new ActionListener() {\r
1994                                         @Override\r
1995                                         public void actionPerformed(ActionEvent e) {\r
1996                                                 try {\r
1997                                                         if (run.indexOf("http") == 0) {\r
1998                                                                 Desktop desktop = Desktop.getDesktop();\r
1999                                                                 desktop.browse(new URI(run));\r
2000                                                         }\r
2001                                                         else {\r
2002                                                                 CommonUtils.executeCommand(run);\r
2003                                                         }\r
2004                                                 } catch (IOException e1) {\r
2005                                                         e1.printStackTrace();\r
2006                                                 } catch (URISyntaxException e1) {\r
2007                                                         e1.printStackTrace();\r
2008                                                 }\r
2009                                         }\r
2010                                 });\r
2011 \r
2012                                 pop.add(menuItem);\r
2013                         }\r
2014                 }\r
2015                 \r
2016                 pop.addSeparator();\r
2017                 \r
2018                 // クリップボードへコピーする\r
2019                 {\r
2020                         JMenuItem menuItem = new JMenuItem("番組名をコピー【"+tvd.title+"】");\r
2021                         menuItem.addActionListener(new ActionListener() {\r
2022                                 public void actionPerformed(ActionEvent e) {\r
2023                                         String msg = tvd.title;\r
2024                                         Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();\r
2025                                         StringSelection s = new StringSelection(msg);\r
2026                                         cb.setContents(s, null);\r
2027                                 }\r
2028                         });\r
2029                         pop.add(menuItem);\r
2030                 }\r
2031                 {\r
2032                         JMenuItem menuItem = new JMenuItem("番組名と詳細をコピー【"+tvd.title+"】");\r
2033                         menuItem.addActionListener(new ActionListener() {\r
2034                                 public void actionPerformed(ActionEvent e) {\r
2035                                         String msg = tvd.title+System.getProperty("line.separator")+tvd.detail+"\0"+tvd.getAddedDetail();\r
2036                                         Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();\r
2037                                         StringSelection s = new StringSelection(msg);\r
2038                                         cb.setContents(s, null);\r
2039                                 }\r
2040                         });\r
2041                         pop.add(menuItem);\r
2042                 }\r
2043                 {\r
2044                         JMenuItem menuItem = new JMenuItem("番組情報をコピー【"+tvd.title+"】");\r
2045                         menuItem.addActionListener(new ActionListener() {\r
2046                                 public void actionPerformed(ActionEvent e) {\r
2047                                         String msg = "";\r
2048                                         int preId = 0;\r
2049                                         for (ClipboardInfo cb : cbitems) {\r
2050                                                 if (cb.getB()) {\r
2051                                                         switch (cb.getId()) {\r
2052                                                         case 1:\r
2053                                                                 msg += tvd.title+"\t";\r
2054                                                                 break;\r
2055                                                         case 2:\r
2056                                                                 msg += tvd.center+"\t";\r
2057                                                                 break;\r
2058                                                         case 3:\r
2059                                                                 msg += tvd.accurateDate+"\t";\r
2060                                                                 break;\r
2061                                                         case 4:\r
2062                                                                 msg += tvd.start+"\t";\r
2063                                                                 break;\r
2064                                                         case 5:\r
2065                                                                 if (preId == 4) {\r
2066                                                                         msg = msg.substring(0,msg.length()-1)+"-";\r
2067                                                                 }\r
2068                                                                 msg += tvd.end+"\t";\r
2069                                                                 break;\r
2070                                                         case 6:\r
2071                                                                 msg += tvd.genre+"\t";\r
2072                                                                 break;\r
2073                                                         case 7:\r
2074                                                                 msg += tvd.detail+"\0"+tvd.getAddedDetail()+"\t";\r
2075                                                                 break;\r
2076                                                         }\r
2077                                                 }\r
2078                                                 preId = cb.getId();\r
2079                                         }\r
2080                                         if (msg.length() > 0) {\r
2081                                                 msg = msg.substring(0,msg.length()-1);\r
2082                                         }\r
2083                                         Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();\r
2084                                         StringSelection s = new StringSelection(msg);\r
2085                                         cb.setContents(s, null);\r
2086                                 }\r
2087                         });\r
2088                         pop.add(menuItem);\r
2089                 }\r
2090 \r
2091                 pop.addSeparator();\r
2092                 \r
2093                 // 延長感染源へ追加する\r
2094                 if (\r
2095                                 tvd.type == ProgType.SYOBO ||\r
2096                                 tvd.type == ProgType.PASSED ||\r
2097                                 tvd.type == ProgType.PICKED ||\r
2098                                 (tvd.type == ProgType.PROG && tvd.subtype != ProgSubtype.RADIO) )       // ラジオは処理対象外です\r
2099                 {\r
2100                         JMenuItem menuItem = new JMenuItem("延長感染源にしない【"+tvd.title+" ("+tvd.center+")】");\r
2101                         menuItem.addActionListener(new ActionListener() {\r
2102                                 public void actionPerformed(ActionEvent e) {\r
2103                                         //\r
2104                                         mwin.appendMessage("延長感染源を隔離します【"+tvd.title+"("+tvd.center+")】");\r
2105                                         //\r
2106                                         AbsExtensionDialog eD = new VWExtensionDialog();\r
2107                                         CommonSwingUtils.setLocationCenter(mainWindow,eD);\r
2108                                         \r
2109                                         eD.open(tvd.title,tvd.center,false,extKeys);\r
2110                                         eD.setVisible(true);\r
2111                                         \r
2112                                         if (eD.isRegistered()) {\r
2113                                                 // 番組表の状態を更新する\r
2114                                                 for (TVProgram tvp : tvprograms) {\r
2115                                                         if (tvp.getType() == ProgType.PROG) {\r
2116                                                                 tvp.setExtension(null, null, false, extKeys.getSearchKeys());\r
2117                                                         }\r
2118                                                 }\r
2119                                                 \r
2120                                                 // ツリーに反映する\r
2121                                                 listed.redrawTreeByExtension();\r
2122                                                 \r
2123                                                 mainWindow.setSelectedTab(MWinTab.LISTED);\r
2124                                         }\r
2125                                 }\r
2126                         });\r
2127                         pop.add(menuItem);\r
2128                 }\r
2129                 if ( tvd.type == ProgType.PASSED || (tvd.type == ProgType.PROG && tvd.subtype != ProgSubtype.RADIO) )   // ラジオは処理対象外です\r
2130                 {\r
2131                         JMenuItem menuItem = new JMenuItem("延長感染源にする【"+tvd.title+" ("+tvd.center+")】");\r
2132                         menuItem.addActionListener(new ActionListener() {\r
2133                                 public void actionPerformed(ActionEvent e) {\r
2134                                         //\r
2135                                         AbsExtensionDialog eD = new VWExtensionDialog();\r
2136                                         CommonSwingUtils.setLocationCenter(mainWindow,eD);\r
2137                                         \r
2138                                         eD.open(tvd.title,tvd.center,true,extKeys);\r
2139                                         eD.setVisible(true);\r
2140                                         \r
2141                                         if (eD.isRegistered()) {\r
2142                                                 // 番組表の状態を更新する\r
2143                                                 for (TVProgram tvp : tvprograms) {\r
2144                                                         if (tvp.getType() == ProgType.PROG) {\r
2145                                                                 tvp.setExtension(null, null, false, extKeys.getSearchKeys());\r
2146                                                         }\r
2147                                                 }\r
2148                                                 \r
2149                                                 // ツリーに反映する\r
2150                                                 listed.redrawTreeByExtension();\r
2151                                                 \r
2152                                                 mainWindow.setSelectedTab(MWinTab.LISTED);\r
2153                                         }\r
2154                                 }\r
2155                         });\r
2156                         pop.add(menuItem);\r
2157                 }\r
2158                 \r
2159                 pop.addSeparator();\r
2160                 \r
2161                 // 視聴する\r
2162                 if ( tvd.type == ProgType.PROG && tvd.subtype != ProgSubtype.RADIO)     // ラジオは処理対象外です\r
2163                 {\r
2164                         for (HDDRecorder recorder : recorders ) {\r
2165                                 \r
2166                                 if (recorder.ChangeChannel(null) == false) {\r
2167                                         continue;\r
2168                                 }\r
2169                                 \r
2170                                 final String recorderName = recorder.Myself();\r
2171                                 JMenuItem menuItem = new JMenuItem("【"+recorderName+"】で【"+tvd.center+"】を視聴する");\r
2172                                 \r
2173                                 menuItem.addActionListener(new ActionListener() {\r
2174                                         public void actionPerformed(ActionEvent e) {\r
2175                                                 for (HDDRecorder recorder : recorders ) {\r
2176                                                         if (recorder.isMyself(recorderName)) {\r
2177                                                                 if (recorder.ChangeChannel(tvd.center) == false) {\r
2178                                                                         ringBeep();\r
2179                                                                         mwin.appendError("【警告】チャンネルを変更できませんでした:"+recorder.getErrmsg());\r
2180                                                                 }\r
2181                                                                 else if (recorder.getErrmsg() !=null && recorder.getErrmsg().length() > 0) {\r
2182                                                                         mwin.appendError("[追加情報] "+recorder.getErrmsg());\r
2183                                                                 }\r
2184                                                         }\r
2185                                                 }\r
2186                                         }\r
2187                                 });\r
2188                                 \r
2189                                 menuItem.setEnabled(recorder.getUseChChange());\r
2190                                 \r
2191                                 pop.add(menuItem);\r
2192                         }\r
2193                 }\r
2194                 \r
2195                 pop.show(comp, x, y);\r
2196         }\r
2197         \r
2198         // ピックアップへ追加する\r
2199         public boolean addToPickup(final ProgDetailList tvd) {\r
2200                 \r
2201                 if (tvd.start.equals("")) {\r
2202                         // 番組情報がありません\r
2203                         return false;\r
2204                 }\r
2205                 \r
2206                 PickedProgram tvp = tvprograms.getPickup();\r
2207                 if ( tvp == null ) {\r
2208                         // ピックアップ先がありません\r
2209                         return true;\r
2210                 }\r
2211                 \r
2212                 // 削除かな?\r
2213                 if ( tvp.remove(tvd, tvd.center, tvd.accurateDate, true) ) {\r
2214                         tvp.save();\r
2215                         if ( listed.isNodeSelected(JTreeLabel.Nodes.PICKUP) || listed.isNodeSelected(JTreeLabel.Nodes.STANDBY) ) {\r
2216                                 // ピックアップノードor予約待機ノードが選択されていたらリストを更新する\r
2217                                 listed.reselectTree();\r
2218                                 //listed.updateReserveMark();\r
2219                         }\r
2220                         else {\r
2221                                 // 予約マークだけ変えておけばいいよね\r
2222                                 listed.updateReserveMark();\r
2223                                 listed.refocus();\r
2224                         }\r
2225                         paper.updateReserveBorder(tvd.center);\r
2226                         mwin.appendMessage("【ピックアップ】削除しました: "+tvd.title+" ("+tvd.center+")");\r
2227                         return false;\r
2228                 }\r
2229                 \r
2230                 // 追加です\r
2231                 if ( tvd.endDateTime.compareTo(CommonUtils.getDateTime(0)) > 0 ) {\r
2232                         tvp.refresh();\r
2233                         tvp.add(tvd);\r
2234                         tvp.save();\r
2235                         if ( listed.isNodeSelected(JTreeLabel.Nodes.PICKUP) ) {\r
2236                                 // ピックアップノードが選択されていたらリストを更新する\r
2237                                 listed.reselectTree();\r
2238                                 //listed.updateReserveMark();\r
2239                         }\r
2240                         else {\r
2241                                 listed.updateReserveMark();\r
2242                                 listed.refocus();\r
2243                         }\r
2244                         paper.updateReserveBorder(tvd.center);\r
2245                         mwin.appendMessage("【ピックアップ】追加しました: "+tvd.title+" ("+tvd.center+")");\r
2246                         return true;\r
2247                 }\r
2248 \r
2249                 // 過去ログは登録できないよ\r
2250                 mwin.appendMessage("【ピックアップ】過去情報はピックアップできません.");\r
2251                 return false;\r
2252         }\r
2253         \r
2254         /**\r
2255          *  予約を削除するメニューアイテム\r
2256          */\r
2257         private JMenuItem getRemoveRsvMenuItem(final String start, final String title, final String chnam, final String rsvId, final String recId, int n) {\r
2258                 //\r
2259                 JMenuItem menuItem = new JMenuItem();\r
2260                 \r
2261                 String mode = "削除";\r
2262                 menuItem.setForeground(Color.RED);\r
2263                 \r
2264                 String target = ( n==0 ) ? "予約" : "隣接予約";\r
2265 \r
2266                 menuItem.setText(String.format("%sを%sする【%s - %s(%s)/%s】",target,mode,start,title,chnam,recId));\r
2267                 \r
2268                 if ( recId.equals(toolBar.getSelectedRecorder()) ) {\r
2269                         // 選択中のレコーダのものは太字に\r
2270                         Font f = menuItem.getFont();\r
2271                         menuItem.setFont(f.deriveFont(f.getStyle()|Font.BOLD));\r
2272                 }\r
2273                 \r
2274                 menuItem.addActionListener(new ActionListener() {\r
2275                         public void actionPerformed(ActionEvent e) {\r
2276                                 \r
2277                                 if (env.getShowWarnDialog()) {\r
2278                                         Container cp = getContentPane();\r
2279                                         int ret = JOptionPane.showConfirmDialog(cp, "削除しますか?【"+title+"("+chnam+")】("+recId+")", "確認", JOptionPane.YES_NO_OPTION);\r
2280                                         if (ret != JOptionPane.YES_OPTION) {\r
2281                                                 return;\r
2282                                         }\r
2283                                 }\r
2284                                 \r
2285                                 stwin.clear();\r
2286                                 \r
2287                                 // 削除本体\r
2288                                 new SwingBackgroundWorker(false) {\r
2289                                         \r
2290                                         @Override\r
2291                                         protected Object doWorks() throws Exception {\r
2292                                                 \r
2293                                                 for (HDDRecorder recorder : recorders) {\r
2294                                                         if (recorder.isMyself(recId)) { // IPAddr:PortNo:RecorderIdで比較\r
2295                                                                 \r
2296                                                                 String title = "";\r
2297                                                                 for (ReserveList r : recorder.getReserves()) {\r
2298                                                                         if (r.getId().equals(rsvId)) {\r
2299                                                                                 title = r.getTitle();\r
2300                                                                                 break;\r
2301                                                                         }\r
2302                                                                 }\r
2303                                                                 \r
2304                                                                 stwin.appendMessage("予約を削除します:"+title+"("+rsvId+")");\r
2305                                                                 //recorder.setProgressArea(stwin);\r
2306                                                                 ReserveList r = recorder.RemoveRdEntry(rsvId);  // Noで検索\r
2307                                                                 if (r != null) {\r
2308                                                                         mwin.appendMessage("正常に削除できました:"+r.getTitle()+"("+r.getCh_name()+")");\r
2309                                                                         \r
2310                                                                         if ( ! r.getTitle().equals(title) || ! r.getId().equals(rsvId)) {\r
2311                                                                                 mwin.appendError("【警告】削除結果が一致しません!:"+title+"/"+r.getTitle());\r
2312                                                                         }\r
2313                                                                         \r
2314                                                                         if ( recorder.getUseCalendar()) {\r
2315                                                                                 // カレンダーから削除する\r
2316                                                                                 for ( HDDRecorder calendar : recorders ) {\r
2317                                                                                         if (calendar.getType() == RecType.CALENDAR) {\r
2318                                                                                                 stwin.appendMessage("カレンダーから予約情報を削除します");\r
2319                                                                                                 //calendar.setProgressArea(stwin);\r
2320                                                                                                 if ( ! calendar.UpdateRdEntry(r, null)) {\r
2321                                                                                                         mwin.appendError("【カレンダー】"+calendar.getErrmsg());\r
2322                                                                                                         ringBeep();\r
2323                                                                                                 }\r
2324                                                                                         }\r
2325                                                                                 }\r
2326                                                                         }\r
2327                                                                         \r
2328                                                                         r = null;\r
2329                                                                 }\r
2330                                                                 else {\r
2331                                                                         mwin.appendError("削除に失敗しました:"+title);\r
2332                                                                 }\r
2333                                                                 \r
2334                                                                 //\r
2335                                                                 if ( ! recorder.getErrmsg().equals("")) {\r
2336                                                                         mwin.appendError("【追加情報】"+recorder.getErrmsg());\r
2337                                                                         ringBeep();\r
2338                                                                 }\r
2339                                                                 break;\r
2340                                                         }\r
2341                                                 }\r
2342                                                 return null;\r
2343                                         }\r
2344                                         \r
2345                                         @Override\r
2346                                         protected void doFinally() {\r
2347                                                 StWinSetVisible(false);\r
2348                                         }\r
2349                                 }.execute();\r
2350                                 \r
2351                                 CommonSwingUtils.setLocationCenter(Viewer.this, stwin);\r
2352                                 StWinSetVisible(true);\r
2353                                 \r
2354                                 // 予約状況を更新\r
2355                                 listed.updateReserveMark();\r
2356                                 paper.updateReserveBorder(chnam);\r
2357                                 reserved.redrawReservedList();\r
2358                         }\r
2359                 });\r
2360                 \r
2361                 return menuItem;\r
2362         }\r
2363         \r
2364         \r
2365         \r
2366         \r
2367         /*\r
2368          * 他のクラスに分離できなかったというか、しなかったというか、そんなメソッド群\r
2369          */\r
2370         \r
2371         /**\r
2372          * \r
2373          */\r
2374         private boolean doExecOnOff(final boolean fexec, final String title, final String chnam, final String rsvId, final String recId) {\r
2375                 \r
2376                 CommonSwingUtils.setLocationCenter(mainWindow,rdialog);\r
2377                 \r
2378                 String mode = (fexec ? "ON" : "OFF");\r
2379                 \r
2380                 // 予約ON・OFFのみ\r
2381                 if ( rdialog.open(recId,rsvId,fexec) ) {\r
2382                         \r
2383                         rdialog.doUpdate();\r
2384                         \r
2385                         if (rdialog.isSucceededReserve()) {\r
2386                                 // 予約状況を更新\r
2387                                 listed.updateReserveMark();\r
2388                                 paper.updateReserveBorder(chnam);\r
2389                                 reserved.redrawReservedList();\r
2390                                 \r
2391                                 {\r
2392                                         String msg = "予約を"+mode+"にしました【"+title+"("+chnam+")/"+recId+"】";\r
2393                                         //StdAppendMessage(msg);\r
2394                                         mwin.appendMessage(msg);\r
2395                                 }\r
2396                                 \r
2397                                 return true;\r
2398                         }\r
2399                 }\r
2400                 \r
2401                 return false;\r
2402         }\r
2403         \r
2404         /**\r
2405          *  予約実行をONOFFするメニューアイテム\r
2406          */\r
2407         private JMenuItem getExecOnOffMenuItem(final boolean fexec, final String start, final String title, final String chnam, final String rsvId, final String recId, int n) {\r
2408                 \r
2409                 JMenuItem menuItem = new JMenuItem();\r
2410                 \r
2411                 String mode;\r
2412                 if ( ! fexec ) {\r
2413                         mode = "ON";\r
2414                         menuItem.setForeground(Color.BLUE);\r
2415                 }\r
2416                 else {\r
2417                         mode = "OFF";\r
2418                         menuItem.setForeground(Color.BLACK);\r
2419                 }\r
2420 \r
2421                 String target = ( n==0 ) ? "予約" : "隣接予約";\r
2422 \r
2423                 menuItem.setText(String.format("%sを%sにする【%s - %s(%s)/%s】",target,mode,start,title,chnam,recId));\r
2424                 \r
2425                 if ( recId.equals(toolBar.getSelectedRecorder()) ) {\r
2426                         // 選択中のレコーダのものは太字に\r
2427                         Font f = menuItem.getFont();\r
2428                         menuItem.setFont(f.deriveFont(f.getStyle()|Font.BOLD));\r
2429                 }\r
2430 \r
2431                 final String xmode = mode;\r
2432                 menuItem.addActionListener(new ActionListener() {\r
2433                         public void actionPerformed(ActionEvent e) {\r
2434                                 \r
2435                                 CommonSwingUtils.setLocationCenter(mainWindow,rdialog);\r
2436                                 \r
2437                                 // 予約ON・OFFのみ\r
2438                                 if ( rdialog.open(recId,rsvId, ! fexec) ) {\r
2439                                         \r
2440                                         rdialog.doUpdate();\r
2441                                         \r
2442                                         if (rdialog.isSucceededReserve()) {\r
2443                                                 // 予約状況を更新\r
2444                                                 listed.updateReserveMark();\r
2445                                                 paper.updateReserveBorder(chnam);\r
2446                                                 reserved.redrawReservedList();\r
2447                                                 \r
2448                                                 {\r
2449                                                         String msg = "予約を"+xmode+"にしました【"+title+"("+chnam+")/"+recId+"】";\r
2450                                                         StdAppendMessage(msg);\r
2451                                                         mwin.appendMessage(msg);\r
2452                                                 }\r
2453                                         }\r
2454                                 }\r
2455                                 else {\r
2456                                         //rdialog.setVisible(false);\r
2457                                 }\r
2458                         }\r
2459                 });\r
2460                 \r
2461                 return menuItem;\r
2462         }\r
2463         \r
2464         /**\r
2465          *  新聞形式へジャンプするメニューアイテム\r
2466          */\r
2467         private JMenuItem getJumpMenuItem(final String title, final String chnam, final String startDT) {\r
2468                 JMenuItem menuItem = new JMenuItem(String.format("番組欄へジャンプする【%s - %s(%s)】",startDT,title,chnam));\r
2469                 menuItem.addActionListener(new ActionListener() {\r
2470                         public void actionPerformed(ActionEvent e) {\r
2471                                 paper.jumpToBangumi(chnam,startDT);\r
2472                         }\r
2473                 });\r
2474                 return menuItem;\r
2475         }\r
2476         private JMenuItem getJumpToLastWeekMenuItem( final String title, final String chnam, final String startDT) {\r
2477                 GregorianCalendar cal = CommonUtils.getCalendar(startDT);\r
2478                 \r
2479                 if ( cal != null ) {\r
2480                         cal.add(Calendar.DATE, -7);\r
2481                         final String lastdatetime = CommonUtils.getDateTimeW(cal);\r
2482                         \r
2483                         JMenuItem menuItem = new JMenuItem(String.format("先週の番組欄へジャンプする【%s - (%s)】",lastdatetime,chnam));\r
2484                         \r
2485                         menuItem.addActionListener(new ActionListener() {\r
2486                                 public void actionPerformed(ActionEvent e) {\r
2487                                         paper.jumpToBangumi(chnam,lastdatetime);\r
2488                                 }\r
2489                         });\r
2490                         return menuItem;\r
2491                 }\r
2492                 return null;\r
2493         }\r
2494         \r
2495                 \r
2496         /*******************************************************************************\r
2497          * レコーダの予約情報をDLする\r
2498          ******************************************************************************/\r
2499         \r
2500         /***************************************\r
2501          * ツールバートリガーによる\r
2502          **************************************/\r
2503 \r
2504         /**\r
2505          *  レコーダの予約情報をDLする\r
2506          */\r
2507         private boolean doLoadRdRecorder(LoadRsvedFor lrf) {\r
2508                 \r
2509                 if ( lrf == null ) {\r
2510                         return doLoadRdRecorderAll();\r
2511                 }\r
2512                 else {\r
2513                         switch (lrf) {\r
2514                         case DETAILS:\r
2515                                 return doLoadRdReserveDetails();\r
2516                         case RECORDED:\r
2517                                 return doLoadRdRecorded();\r
2518                         case AUTORESERVE:\r
2519                                 return doLoadRdAutoReserves();\r
2520                         default:\r
2521                                 break;\r
2522                         }\r
2523                 }\r
2524                 return false;\r
2525         }\r
2526         \r
2527         /**\r
2528          * レコーダの情報を全部DLする(ステータスウィンドウは自前で用意        する)\r
2529          */\r
2530         private boolean doLoadRdRecorderAll() {\r
2531                 \r
2532                 final String myself = getSelectedMySelf();\r
2533                 \r
2534                 //\r
2535                 StWinClear();\r
2536                 \r
2537                 new SwingBackgroundWorker(false) {\r
2538                         \r
2539                         @Override\r
2540                         protected Object doWorks() throws Exception {\r
2541                                 \r
2542                                 TatCount tc = new TatCount();\r
2543                                 \r
2544                                 // 読み出せ!\r
2545                                 _loadRdRecorderAll(true,myself);\r
2546                                 \r
2547                                 // エンコーダ情報が更新されるかもしれないので、一覧のエンコーダ表示にも反映する\r
2548                                 recsetting.redrawRecorderEncoderEntry();\r
2549                                 \r
2550                                 // 各タブに反映する\r
2551                                 paper.updateReserveBorder(null);\r
2552                                 listed.updateReserveMark();\r
2553                                 reserved.redrawReservedList();\r
2554                                 recorded.redrawRecordedList();\r
2555                                 \r
2556                                 mwin.appendMessage(String.format("【予約一覧の取得処理が完了しました】 所要時間: %.2f秒",tc.end()));\r
2557                                 return null;\r
2558                         }\r
2559                         \r
2560                         @Override\r
2561                         protected void doFinally() {\r
2562                                 StWinSetVisible(false);\r
2563                         }\r
2564                 }.execute();\r
2565                 \r
2566                 StWinSetLocationCenter(this);\r
2567                 StWinSetVisible(true);\r
2568                 \r
2569                 return true;\r
2570         }\r
2571         \r
2572         \r
2573         /**\r
2574          * 予約一覧+予約詳細をDLする\r
2575          */\r
2576         private boolean doLoadRdReserveDetails() {\r
2577                 \r
2578                 final String myself = getSelectedMySelf();\r
2579                 \r
2580                 //\r
2581                 StWinClear();\r
2582                 \r
2583                 new SwingBackgroundWorker(false) {\r
2584                         \r
2585                         @Override\r
2586                         protected Object doWorks() throws Exception {\r
2587                                 \r
2588                                 TatCount tc = new TatCount();\r
2589                         \r
2590                                 boolean succeeded = true;\r
2591                                 \r
2592                                 HDDRecorderList recs;\r
2593                                 if ( myself != null ) {\r
2594                                         recs = recorders.findInstance(myself);\r
2595                                 }\r
2596                                 else {\r
2597                                         recs = recorders;\r
2598                                 }\r
2599                                 for ( HDDRecorder recorder : recs ) {\r
2600                                         \r
2601                                         if ( ! recorder.isReserveListSupported() ) {\r
2602                                                 continue;\r
2603                                         }\r
2604                                         \r
2605                                         // 各種設定の取得\r
2606                                         if ( ! recorder.GetRdSettings(true) ) {\r
2607                                                 succeeded = false;\r
2608                                                 continue;\r
2609                                         }\r
2610                                         \r
2611                                         // 予約一覧の取得\r
2612                                         if ( ! recorder.GetRdReserve(true) ) {\r
2613                                                 succeeded = false;\r
2614                                                 continue;\r
2615                                         }\r
2616                                         \r
2617                                         // レコーダから取得したエンコーダ情報で、登録済みレコーダ一覧を更新する\r
2618                                         setEncoderInfo2RecorderList(recorder,true);\r
2619                                         \r
2620                                         // 予約詳細の取得\r
2621                                         if ( recorder.isThereAdditionalDetails() ) {\r
2622                                                 if ( ! recorder.GetRdReserveDetails() ) {\r
2623                                                         succeeded = false;\r
2624                                                         continue;\r
2625                                                 }\r
2626                                         }\r
2627                                         \r
2628                                         // レコーダの放送局名をWeb番組表の放送局名に置き換え\r
2629                                         checkChNameIsRight(recorder);\r
2630                                         \r
2631                                         // 録画結果一覧を予約一覧に反映\r
2632                                         if ( recorder.isRecordedListSupported() ) {\r
2633                                                 recorder.GetRdRecorded(false);\r
2634                                         }\r
2635                                 }\r
2636                                 \r
2637                                 if ( succeeded ) {\r
2638                                         reserved.redrawReservedList();\r
2639                                         recorded.redrawRecordedList();\r
2640                                         \r
2641                                         mwin.appendMessage(String.format("【予約詳細の取得処理が完了しました】 所要時間: %.2f秒",tc.end()));\r
2642                                 }\r
2643                                 else {\r
2644                                         ringBeep();\r
2645                                         mwin.appendMessage(String.format("【予約詳細の取得処理に失敗しました】 所要時間: %.2f秒",tc.end()));\r
2646                                 }\r
2647                                 return null;\r
2648                         }\r
2649                         \r
2650                         @Override\r
2651                         protected void doFinally() {\r
2652                                 StWinSetVisible(false);\r
2653                         }\r
2654                 }.execute();\r
2655                 \r
2656                 StWinSetLocationCenter(this);\r
2657                 StWinSetVisible(true);\r
2658                 \r
2659                 return true;\r
2660         }\r
2661         \r
2662         \r
2663         /**\r
2664          * 録画結果一覧をDLする\r
2665          */\r
2666         private boolean doLoadRdRecorded() {\r
2667                 \r
2668                 final String myself = getSelectedMySelf();\r
2669                 \r
2670                 //\r
2671                 StWinClear();\r
2672                 \r
2673                 new SwingBackgroundWorker(false) {\r
2674                         \r
2675                         @Override\r
2676                         protected Object doWorks() throws Exception {\r
2677                                 \r
2678                                 TatCount tc = new TatCount();\r
2679                         \r
2680                                 boolean succeeded = true;\r
2681                                 \r
2682                                 HDDRecorderList recs;\r
2683                                 if ( myself != null ) {\r
2684                                         recs = recorders.findInstance(myself);\r
2685                                 }\r
2686                                 else {\r
2687                                         recs = recorders;\r
2688                                 }\r
2689                                 for ( HDDRecorder recorder : recs ) {\r
2690                                         if ( ! recorder.isRecordedListSupported() ) {\r
2691                                                 succeeded = false;\r
2692                                                 continue;\r
2693                                         }\r
2694 \r
2695                                         if ( ! recorder.GetRdRecorded(true) ) {\r
2696                                                 succeeded = false;\r
2697                                         }\r
2698                                 }\r
2699                                 \r
2700                                 if ( succeeded ) {\r
2701                                         reserved.redrawReservedList();\r
2702                                         recorded.redrawRecordedList();\r
2703                                         \r
2704                                         mwin.appendMessage(String.format("【録画結果一覧の取得処理が完了しました】 所要時間: %.2f秒",tc.end()));\r
2705                                 }\r
2706                                 else {\r
2707                                         ringBeep();\r
2708                                         mwin.appendMessage(String.format("【録画結果一覧の取得処理に失敗しました】 所要時間: %.2f秒",tc.end()));\r
2709                                 }\r
2710                                 return null;\r
2711                         }\r
2712                         \r
2713                         @Override\r
2714                         protected void doFinally() {\r
2715                                 StWinSetVisible(false);\r
2716                         }\r
2717                 }.execute();\r
2718                 \r
2719                 StWinSetLocationCenter(this);\r
2720                 StWinSetVisible(true);\r
2721                 \r
2722                 return true;\r
2723         }\r
2724 \r
2725 \r
2726         /**\r
2727          * 録画結果一覧をDLする\r
2728          */\r
2729         private boolean doLoadRdAutoReserves() {\r
2730                 \r
2731                 final String myself = getSelectedMySelf();\r
2732                 \r
2733                 //\r
2734                 StWinClear();\r
2735                 \r
2736                 new SwingBackgroundWorker(false) {\r
2737                         \r
2738                         @Override\r
2739                         protected Object doWorks() throws Exception {\r
2740                                 \r
2741                                 TatCount tc = new TatCount();\r
2742                         \r
2743                                 boolean succeeded = true;\r
2744                                 \r
2745                                 HDDRecorderList recs;\r
2746                                 if ( myself != null ) {\r
2747                                         recs = recorders.findInstance(myself);\r
2748                                 }\r
2749                                 else {\r
2750                                         recs = recorders;\r
2751                                 }\r
2752                                 for ( HDDRecorder recorder : recs ) {\r
2753                                         if ( ! recorder.isEditAutoReserveSupported() ) {\r
2754                                                 succeeded = false;\r
2755                                                 continue;\r
2756                                         }\r
2757                                         \r
2758                                         if ( ! recorder.GetRdAutoReserve(true) ) {\r
2759                                                 succeeded = false;\r
2760                                         }\r
2761                                 }\r
2762                                 \r
2763                                 if ( succeeded ) {\r
2764                                         // 再描画はここじゃないよ\r
2765                                         mwin.appendMessage(String.format("【自動予約一覧の取得処理が完了しました】 所要時間: %.2f秒",tc.end()));\r
2766                                 }\r
2767                                 else {\r
2768                                         ringBeep();\r
2769                                         mwin.appendMessage(String.format("【自動予約一覧の取得処理に失敗しました】 所要時間: %.2f秒",tc.end()));\r
2770                                 }\r
2771                                 return null;\r
2772                         }\r
2773                         \r
2774                         @Override\r
2775                         protected void doFinally() {\r
2776                                 StWinSetVisible(false);\r
2777                         }\r
2778                 }.execute();\r
2779                 \r
2780                 StWinSetLocationCenter(this);\r
2781                 StWinSetVisible(true);\r
2782                 \r
2783                 return true;\r
2784         }\r
2785         \r
2786         /***************************************\r
2787          * 自クラス内呼び出しによる\r
2788          **************************************/\r
2789         \r
2790         /**\r
2791          * レコーダの情報を全部DLする(ステータスウィンドウは呼び出し元が準備する)\r
2792          */\r
2793         private void loadRdReservesAll(final boolean force, final String myself) {\r
2794 \r
2795                 new SwingBackgroundWorker(true) {\r
2796                         \r
2797                         @Override\r
2798                         protected Object doWorks() throws Exception {\r
2799                                 \r
2800                                 _loadRdRecorderAll(force,myself);\r
2801                                 \r
2802                                 return null;\r
2803                         }\r
2804                         \r
2805                         @Override\r
2806                         protected void doFinally() {\r
2807                         }\r
2808                 }.execute();\r
2809         }\r
2810         \r
2811         /***************************************\r
2812          * レコーダの情報を取得する部品群\r
2813          **************************************/\r
2814         \r
2815         private boolean _loadRdRecorderAll(final boolean force, final String myself) {\r
2816 \r
2817                 HDDRecorderList recs;\r
2818                 if ( myself != null ) {\r
2819                         recs = recorders.findInstance(myself);\r
2820                 }\r
2821                 else {\r
2822                         recs = recorders;\r
2823                 }\r
2824                 \r
2825                 boolean success = true;\r
2826                 \r
2827                 for ( HDDRecorder recorder : recs ) {\r
2828                         if ( recorder.isReserveListSupported() ) {\r
2829                                 success = success & _loadRdRecorder(recorder, force);\r
2830                         }\r
2831                 }\r
2832                 \r
2833                 return success;\r
2834         }\r
2835         \r
2836         private boolean _loadRdRecorder(HDDRecorder recorder, boolean force) {\r
2837                 \r
2838                 mwin.appendMessage("【レコーダ情報取得】情報を取得します: "+recorder.Myself());\r
2839                 if ( recorder.isThereAdditionalDetails() && env.getForceLoadReserveDetails() == 2 ) {\r
2840                         mwin.appendMessage("<<<注意!>>>このレコーダでは予約詳細の個別取得を実行しないと正確な情報を得られない場合があります。");\r
2841                 }\r
2842                 \r
2843                 try {\r
2844                         \r
2845                         // 各種設定の取得\r
2846                         if ( ! _loadRdSettings(recorder,force) ) {\r
2847                                 return false;\r
2848                         }\r
2849                         \r
2850                         // 予約一覧の取得\r
2851                         if ( ! _loadRdReserves(recorder,force) ) {\r
2852                                 return false;\r
2853                         }\r
2854                         \r
2855                         // レコーダから取得したエンコーダ情報で、登録済みレコーダ一覧を更新する\r
2856                         setEncoderInfo2RecorderList(recorder,force);\r
2857                         \r
2858                         // 予約詳細の取得(強制取得じゃなければ処理不要)\r
2859                         if ( force && ! _loadRdReserveDetails(recorder,force) ) {\r
2860                                 return false;\r
2861                         }\r
2862                         \r
2863                         // レコーダの放送局名をWeb番組表の放送局名に置き換え\r
2864                         checkChNameIsRight(recorder);\r
2865                         \r
2866                         // 自動予約一覧の取得\r
2867                         if ( ! _loadRdAutoReserves(recorder,force) ) {\r
2868                                 return false;\r
2869                         }\r
2870                         \r
2871                         // 録画結果一覧の取得\r
2872                         if ( ! _loadRdRecorded(recorder,force) ) {\r
2873                                 return false;\r
2874                         }\r
2875                 }\r
2876                 catch (Exception e) {\r
2877                         e.printStackTrace();\r
2878                         mwin.appendError("【致命的エラー】予約一覧の取得で例外が発生 "+recorder.getIPAddr()+":"+recorder.getPortNo()+":"+recorder.getRecorderId());\r
2879                         ringBeep();\r
2880                         return false;\r
2881                 }\r
2882                 return true;\r
2883         }\r
2884         \r
2885         \r
2886         /***************************************\r
2887          * レコーダの情報を取得する部品群\r
2888          **************************************/\r
2889         \r
2890         private boolean _loadRdSettings(HDDRecorder recorder, boolean force) {\r
2891                 if ( recorder.GetRdSettings(force) ) {\r
2892                         return true;\r
2893                 }\r
2894                 \r
2895                 mwin.appendError(recorder.getErrmsg()+" "+recorder.Myself());   // 取得に失敗\r
2896                 ringBeep();\r
2897                 return false;\r
2898         }\r
2899         \r
2900         private boolean _loadRdReserves(HDDRecorder recorder, boolean force) {\r
2901                 if ( recorder.GetRdReserve(force) ) {\r
2902                         return true;\r
2903                 }\r
2904                 \r
2905                 mwin.appendError(recorder.getErrmsg()+" "+recorder.Myself());   // 取得に失敗\r
2906                 ringBeep();\r
2907                 return false;\r
2908         }\r
2909         \r
2910         private boolean _loadRdReserveDetails(HDDRecorder recorder, boolean force) {\r
2911                 \r
2912                 if ( ! recorder.isThereAdditionalDetails() ) {\r
2913                         return true;    // 非対応レコーダ\r
2914                 }\r
2915                 \r
2916                 boolean skip = false;\r
2917                 if ( force && env.getForceLoadReserveDetails() == 2 ) {\r
2918                         skip = true;\r
2919                 }\r
2920                 else if ( force && env.getForceLoadReserveDetails() == 0 ) {\r
2921                         int ret = JOptOptionPane.showConfirmDialog(stwin, "<HTML>詳細情報を取得しますか?(時間がかかります)<BR><BR>"+recorder.Myself()+"</HTML>", "今回の選択を既定の動作とする", "※既定動作は各種設定で変更できます", "確認", JOptionPane.YES_NO_OPTION);\r
2922                         skip = (ret != JOptOptionPane.YES_OPTION);\r
2923                         \r
2924                         if ( JOptOptionPane.isSelected() ) {\r
2925                                 // 今回の選択を既定の動作とする\r
2926                                 env.setForceLoadReserveDetails(skip ? 2 : 1);\r
2927                                 env.save();\r
2928                                 if (setting!=null) setting.updateSelections();\r
2929                         }\r
2930                 }\r
2931                 if ( skip ) {\r
2932                         mwin.appendMessage("【!】予約詳細情報の取得はスキップされました");\r
2933                         return true;\r
2934                 }\r
2935                 \r
2936                 if ( recorder.GetRdReserveDetails()) {\r
2937                         return true;    // 取得成功\r
2938                 }\r
2939                 \r
2940                 mwin.appendError(recorder.getErrmsg()+" "+recorder.Myself());\r
2941                 ringBeep();\r
2942                 return false;           // 取得失敗\r
2943         }\r
2944 \r
2945         private boolean _loadRdAutoReserves(HDDRecorder recorder, boolean force) {\r
2946 \r
2947                 if ( ! recorder.isEditAutoReserveSupported() ) {\r
2948                         return true;\r
2949                 }\r
2950                 \r
2951                 boolean skip = false;\r
2952                 if ( force && env.getForceLoadAutoReserves() == 2 ) {\r
2953                         skip = true;\r
2954                 }\r
2955                 else if ( force && env.getForceLoadAutoReserves() == 0 ) {\r
2956                         int ret = JOptOptionPane.showConfirmDialog(stwin, "<HTML>自動予約一覧を取得しますか?(時間がかかります)<BR><BR>"+recorder.Myself()+"</HTML>", "今回の選択を既定の動作とする", "※既定動作は各種設定で変更できます", "確認", JOptionPane.YES_NO_OPTION);\r
2957                         skip = (ret != JOptOptionPane.YES_OPTION);\r
2958                         \r
2959                         if ( JOptOptionPane.isSelected() ) {\r
2960                                 // 今回の選択を既定の動作とする\r
2961                                 env.setForceLoadAutoReserves(skip ? 2 : 1);\r
2962                                 env.save();\r
2963                                 if (setting!=null) setting.updateSelections();\r
2964                         }\r
2965                 }\r
2966                 if ( skip ) {\r
2967                         mwin.appendMessage("【!】自動予約一覧の取得はスキップされました");\r
2968                         return true;\r
2969                 }\r
2970 \r
2971                 if ( recorder.GetRdAutoReserve(force) ) {\r
2972                         return true;\r
2973                 }\r
2974                 \r
2975                 mwin.appendError(recorder.getErrmsg()+" "+recorder.Myself());\r
2976                 ringBeep();\r
2977                 return false;\r
2978         }\r
2979         \r
2980         private boolean _loadRdRecorded(HDDRecorder recorder, boolean force) {\r
2981                 \r
2982                 if ( ! recorder.isRecordedListSupported() ) {\r
2983                         return true;\r
2984                 }\r
2985                 \r
2986                 boolean skip = false;\r
2987                 if ( force && env.getForceLoadRecorded() == 2 ) {\r
2988                         skip = true;\r
2989                 }\r
2990                 if ( force && env.getForceLoadRecorded() == 0 ) {\r
2991                         int ret = JOptOptionPane.showConfirmDialog(stwin, "<HTML>録画結果一覧を取得しますか?(時間がかかります)<BR><BR>"+recorder.Myself()+"</HTML>", "今回の選択を既定の動作とする", "※既定動作は各種設定で変更できます", "確認", JOptionPane.YES_NO_OPTION);\r
2992                         skip = (ret != JOptOptionPane.YES_OPTION);\r
2993                         \r
2994                         if ( JOptOptionPane.isSelected() ) {\r
2995                                 // 今回の選択を既定の動作とする\r
2996                                 env.setForceLoadRecorded(skip ? 2 : 1);\r
2997                                 env.save();\r
2998                                 if (setting!=null) setting.updateSelections();\r
2999                         }\r
3000                 }\r
3001                 if ( skip ) {\r
3002                         mwin.appendMessage("【!】録画結果一覧の取得はスキップされました");\r
3003                         return true;\r
3004                 }\r
3005                 \r
3006                 if ( recorder.GetRdRecorded(force) ) {\r
3007                         return true;\r
3008                 }\r
3009                 \r
3010                 mwin.appendError(recorder.getErrmsg()+" "+recorder.Myself());\r
3011                 ringBeep();\r
3012                 return false;\r
3013         }\r
3014 \r
3015         /**\r
3016          * レコーダから取得したエンコーダ情報で、登録済みレコーダ一覧を更新する\r
3017          * @param recorder\r
3018          */\r
3019         private void setEncoderInfo2RecorderList(HDDRecorder recorder, boolean force) {\r
3020                 for (RecorderInfo ri : recInfoList ) {\r
3021                         //if (rl.getRecorderEncoderList().size() == 0)\r
3022                         {\r
3023                                 //String mySelf = ri.getRecorderIPAddr()+":"+ri.getRecorderPortNo()+":"+ri.getRecorderId();\r
3024                                 //String myMail = "MAIL"+":"+ri.getRecorderMacAddr()+":"+ri.getRecorderId();\r
3025                                 //if (recorder.isMyself(mySelf) || recorder.isMyself(myMail)) {\r
3026                                 if ( recorder.isMyself(ri.MySelf()) ) {\r
3027                                         ri.clearEncoders();\r
3028                                         for (TextValueSet enc : recorder.getEncoderList()) {\r
3029                                                 ri.addEncoder(enc.getText());\r
3030                                         }\r
3031                                         \r
3032                                         if ( force ) {\r
3033                                                 recInfoList.save();\r
3034                                         }\r
3035                                         break;\r
3036                                 }\r
3037                         }\r
3038                 }\r
3039         }\r
3040         \r
3041         /**\r
3042          * 予約一覧の放送局名が正しい形式であるかどうかのチェック\r
3043          */\r
3044         private void checkChNameIsRight(HDDRecorder recorder) {\r
3045                 HashMap<String,String> misCN = new HashMap<String,String>();\r
3046                 for ( ReserveList r : recorder.getReserves() ) {\r
3047                         if ( r.getCh_name() == null ) {\r
3048                                 misCN.put(r.getChannel(),recorder.getRecorderId());\r
3049                         }\r
3050                 }\r
3051                 if ( misCN.size() > 0 ) {\r
3052                         for ( String cn : misCN.keySet() ) {\r
3053                                 String msg = "【警告(予約一覧)】 <"+misCN.get(cn)+"> \"レコーダの放送局名\"を\"Web番組表の放送局名\"に変換できません。CHコード設定に設定を追加してください:\"レコーダの放送局名\"="+cn;\r
3054                                 mwin.appendMessage(msg);\r
3055                         }\r
3056                         ringBeep();\r
3057                 }\r
3058         }\r
3059         \r
3060         /*******************************************************************************\r
3061          * Web番組表をDLする\r
3062          ******************************************************************************/\r
3063         \r
3064         /***************************************\r
3065          * ツールバートリガー(と、各種設定変更トリガー)による\r
3066          **************************************/\r
3067         \r
3068         /**\r
3069          * Web番組表をDL→再描画まで\r
3070          * <P>単体実行の場合はこちらを呼び出す\r
3071          * <P>部品実行の場合はこちらを呼び出す:{@link #loadTVProgram(boolean, LoadFor)}\r
3072          * @see #doRedrawTVProgram()\r
3073          */\r
3074         private boolean doLoadTVProgram(final boolean force, final LoadFor lf) {\r
3075                 //\r
3076                 StWinClear();\r
3077                 \r
3078                 new SwingBackgroundWorker(false) {\r
3079                         \r
3080                         @Override\r
3081                         protected Object doWorks() throws Exception {\r
3082                                 \r
3083                                 TatCount tc = new TatCount();\r
3084                                 \r
3085                                 loadTVProgram(force, lf);\r
3086                                 \r
3087                                 mwin.appendMessage(String.format("[Web番組表取得] 【完了しました】 所要時間: %.2f秒",tc.end()));\r
3088                                 return null;\r
3089                         }\r
3090                         \r
3091                         @Override\r
3092                         protected void doFinally() {\r
3093                                 StWinSetVisible(false);\r
3094                         }\r
3095                 }.execute();\r
3096                 \r
3097                 StWinSetLocationCenter(this);\r
3098                 StWinSetVisible(true);\r
3099                 \r
3100                 return true;\r
3101         }\r
3102 \r
3103         /**\r
3104          * \r
3105          * @see #doLoadTVProgram(boolean, LoadFor)\r
3106          */\r
3107         private void doRedrawTVProgram() {\r
3108                 \r
3109                 // 新聞描画枠のリセット\r
3110                 paper.clearPanel();\r
3111                 paper.buildMainViewByDate();\r
3112                 \r
3113                 // サイドツリーの再構築\r
3114                 paper.redrawTreeByDate();\r
3115                 paper.redrawTreeByPassed();\r
3116                 \r
3117                 listed.redrawTreeByHistory();\r
3118                 listed.redrawTreeByCenter();\r
3119                 \r
3120                 // 再描画\r
3121                 paper.reselectTree();\r
3122                 listed.reselectTree();\r
3123         }\r
3124         \r
3125         /***************************************\r
3126          * 自クラス内呼び出しによる\r
3127          **************************************/\r
3128         \r
3129         /**\r
3130          * Web番組表をDLする\r
3131          * <P>単体実行の場合はこちらを呼び出す:{@link #doLoadTVProgram(boolean, tainavi.Viewer.LoadFor)}\r
3132          * <P>部品実行の場合はこちらを呼び出す\r
3133          */\r
3134         private boolean loadTVProgram(final boolean force, final LoadFor lf) {\r
3135                 \r
3136                 final String FUNCID = "[Web番組表取得] ";\r
3137                 final String ERRID = "[ERROR]"+FUNCID;\r
3138                 \r
3139                 try {\r
3140                         String msg;\r
3141                         TVProgram tvp;\r
3142                         \r
3143                         tvp = tvprograms.getTvProgPlugin(null);\r
3144                         if ( tvp != null )\r
3145                         {\r
3146                                 String sType = "地上波&BS番組表";\r
3147                                 if (lf == LoadFor.ALL || lf == LoadFor.TERRA) {\r
3148                                         loadTVProgramOnce(tvp, sType, tvp.getSelectedArea(), false, force);\r
3149                                 }\r
3150                                 else {\r
3151                                         stwin.appendMessage(FUNCID+sType+"へのアクセスはスキップされました: "+tvp.getTVProgramId());\r
3152                                 }\r
3153                         }\r
3154                         \r
3155                         tvp = tvprograms.getCsProgPlugin(null);\r
3156                         if ( tvp != null )\r
3157                         {\r
3158                                 String sType = "CS番組表[プライマリ]";\r
3159                                 if (lf == LoadFor.ALL || lf == LoadFor.CS || lf == LoadFor.CSo1 || lf == LoadFor.CSwSD) {\r
3160                                         loadTVProgramOnce(tvp, sType, tvp.getSelectedArea(), false, force);\r
3161                                 }\r
3162                                 else {\r
3163                                         stwin.appendMessage(FUNCID+sType+"へのアクセスはスキップされました: "+tvp.getTVProgramId());\r
3164                                 }\r
3165                         }\r
3166                         \r
3167                         tvp = tvprograms.getCs2ProgPlugin(null);\r
3168                         if ( tvp != null )\r
3169                         {\r
3170                                 String sType = "CS番組表[セカンダリ]";\r
3171                                 if (lf == LoadFor.ALL || lf == LoadFor.CS || lf == LoadFor.CSo2 || lf == LoadFor.CSwSD) {\r
3172                                         loadTVProgramOnce(tvp, sType, tvp.getSelectedArea(), false, force);\r
3173                                 }\r
3174                                 else {\r
3175                                         stwin.appendMessage(FUNCID+sType+"へのアクセスはスキップされました: "+tvp.getTVProgramId());\r
3176                                 }\r
3177                         }\r
3178                         \r
3179                         tvp = tvprograms.getSyobo();\r
3180                         if ( tvp != null ) {\r
3181                                 String sType = "しょぼかる";\r
3182                                 if ( (lf == LoadFor.ALL || lf == LoadFor.SYOBO) && enableWebAccess && env.getUseSyobocal()) {\r
3183                                         tvp.loadCenter(tvp.getSelectedCode(), force);   // しょぼかるには放送局リストを取得するイベントが他にないので\r
3184                                         loadTVProgramOnce(tvp, sType, null, true, force);\r
3185                                 }\r
3186                                 else {\r
3187                                         stwin.appendMessage(FUNCID+sType+"へのアクセスはスキップされました.");\r
3188                                 }\r
3189                                 \r
3190                                 // しょぼかるの新番組マークを引き継ぐ\r
3191                                 attachSyoboNew();\r
3192                         }\r
3193                 \r
3194                         PickedProgram pickup = tvprograms.getPickup();\r
3195                         if ( tvp != null ) {\r
3196                                 pickup.refresh();\r
3197                                 //pickup.save();\r
3198                         }\r
3199                         \r
3200                         // 番組タイトルを整形する\r
3201                         fixTitle();\r
3202                         fixDetail();\r
3203                         \r
3204                         // 検索結果の再構築\r
3205                         stwin.appendMessage(FUNCID+"検索結果を生成します.");\r
3206                         mpList.clear(env.getDisableFazzySearch(), env.getDisableFazzySearchReverse());\r
3207                         mpList.build(tvprograms, trKeys.getTraceKeys(), srKeys.getSearchKeys());\r
3208                         \r
3209                         // 過去ローグ\r
3210                         if ( env.getUsePassedProgram() ) {\r
3211                                 TatCount tc = new TatCount();\r
3212                                 stwin.appendMessage(FUNCID+"過去ログを生成します.");\r
3213                                 if ( tvprograms.getPassed().save(tvprograms.getIterator(), chsort.getClst(), env.getPrepPassedProgramCount()) ) {\r
3214                                         msg = String.format(FUNCID+"過去ログを生成しました [%.2f秒].",tc.end());\r
3215                                         StdAppendMessage(msg);\r
3216                                 }\r
3217                                 //PassedProgramList.getDateList(env.getPassedLogLimit());\r
3218                         }\r
3219                         else {\r
3220                                 stwin.appendMessage(FUNCID+"過去ログは記録されません.");\r
3221                         }\r
3222                 }\r
3223                 catch (Exception e) {\r
3224                         e.printStackTrace();\r
3225                         mwin.appendError(ERRID+"番組情報の取得で例外が発生");\r
3226                         ringBeep();\r
3227                         return false;\r
3228                 }\r
3229                 \r
3230                 return true;\r
3231         }\r
3232         \r
3233         // 分割\r
3234         private void loadTVProgramOnce(TVProgram tvp, String sType, String aName, boolean loadonly, boolean force) {\r
3235                 \r
3236                 final String FUNCID = "[Web番組表取得] ";\r
3237 //              final String ERRID = "[ERROR]"+FUNCID;\r
3238                 \r
3239                 // ログ\r
3240                 String msg = FUNCID+sType+"を取得します: "+tvp.getTVProgramId();\r
3241                 stwin.appendMessage(msg);\r
3242                 if (aName!=null) stwin.appendMessage(FUNCID+"+選択されているエリア="+aName);\r
3243                 \r
3244                 // 読み込み\r
3245                 //tvp.setProgressArea(stwin);\r
3246                 tvp.loadProgram(tvp.getSelectedCode(), force);\r
3247                 \r
3248                 if (loadonly) {\r
3249                         return;\r
3250                 }\r
3251                 \r
3252                 // 延長警告\r
3253                 tvp.setExtension(null, null, false, extKeys.getSearchKeys());   // 最初の3引数は盲腸。ダミー\r
3254                 // NGワード\r
3255                 tvp.abon(env.getNgword());\r
3256                 // 抜けチェック\r
3257                 String errmsg = tvp.chkComplete(); \r
3258                 if (errmsg != null) {\r
3259                         stwin.appendError(FUNCID+"取得した情報が不正です:"+errmsg);\r
3260                         if (mainWindow!=null) mwin.appendMessage(msg);\r
3261                         ringBeep();\r
3262                 }\r
3263         }\r
3264         \r
3265         // しょぼかるの番組詳細を番組表に反映する\r
3266         private void attachSyoboNew() {\r
3267                 TVProgram syobo = tvprograms.getSyobo();\r
3268                 if (syobo == null) {\r
3269                         return;\r
3270                 }\r
3271                 \r
3272                 for ( TVProgram tvp : tvprograms ) {\r
3273                         \r
3274                         if ( tvp.getType() != ProgType.PROG ) {\r
3275                                 continue;\r
3276                         }\r
3277                         if ( ! (tvp.getSubtype() == ProgSubtype.TERRA || tvp.getSubtype() == ProgSubtype.CS || tvp.getSubtype() == ProgSubtype.CS2) ) {\r
3278                                 continue;\r
3279                         }\r
3280                         \r
3281                         for ( ProgList tvpl : tvp.getCenters() ) {\r
3282                                 if ( ! tvpl.enabled) {\r
3283                                         continue;\r
3284                                 }\r
3285                                 for ( ProgList svpl : syobo.getCenters() ) {\r
3286                                         if ( ! tvpl.Center.equals(svpl.Center)) {\r
3287                                                 continue;\r
3288                                         }\r
3289                                         for ( ProgDateList tvc : tvpl.pdate ) {\r
3290                                                 \r
3291                                                 ProgDateList mSvc = null;\r
3292                                                 for ( ProgDateList svc : svpl.pdate ) {\r
3293                                                         if (tvc.Date.equals(svc.Date) ) {\r
3294                                                                 mSvc = svc;\r
3295                                                                 break;\r
3296                                                         }\r
3297                                                 }\r
3298                                                 if (mSvc == null) {\r
3299                                                         // しょぼかる側に該当する日付自体ないので全部フラグを立てっぱなしでいい\r
3300                                                         for ( ProgDetailList tvd : tvc.pdetail ) {\r
3301                                                                 if ( tvd.isEqualsGenre(ProgGenre.ANIME, null) ) {\r
3302                                                                         tvd.addOption(ProgOption.NOSYOBO);\r
3303                                                                 }\r
3304                                                         }\r
3305                                                 }\r
3306                                                 else {\r
3307                                                         // しょぼかる側に該当する日付があるのでマッチング。アニメと映画と音楽\r
3308                                                         for ( ProgDetailList tvd : tvc.pdetail ) {\r
3309                                                                 \r
3310                                                                 // アニメはいったんフラグを立てる\r
3311                                                                 if ( tvd.isEqualsGenre(ProgGenre.ANIME, null) ) {\r
3312                                                                         tvd.addOption(ProgOption.NOSYOBO);\r
3313                                                                 }\r
3314                                                                 \r
3315                                                                 boolean isFind = false;\r
3316                                                                 for ( ProgDetailList svd : mSvc.pdetail ) {\r
3317                                                                         if ( tvd.start.equals(svd.start) ) {\r
3318                                                                                 \r
3319                                                                                 // 番組ID\r
3320                                                                                 {\r
3321                                                                                         //svd.progid = tvd.progid;\r
3322                                                                                         svd.setContentIdStr();\r
3323                                                                                 }\r
3324                                                                                 \r
3325                                                                                 boolean isAnime = tvd.isEqualsGenre(ProgGenre.ANIME, null);\r
3326                                                                                 if ( ! isAnime && ! tvd.isEqualsGenre(ProgGenre.MOVIE, null) && ! tvd.isEqualsGenre(ProgGenre.MUSIC, null) ) {\r
3327                                                                                         break;\r
3328                                                                                 }\r
3329                                                                                 \r
3330                                                                                 // みつけた\r
3331                                                                                 isFind = true;\r
3332                                                                                 \r
3333                                                                                 // しょぼかるとWeb番組表の両方に存在する\r
3334                                                                                 svd.nosyobo = true;\r
3335                         \r
3336                                                                                 // 各種フラグ\r
3337                                                                                 {\r
3338                                                                                         boolean isAttached = false;\r
3339                                                                                         \r
3340                                                                                         // 新番組フラグ\r
3341                                                                                         if ( svd.flag == ProgFlags.NEW && tvd.flag != ProgFlags.NEW ) {\r
3342                                                                                                 tvd.flag = ProgFlags.NEW;\r
3343                                                                                                 isAttached = true;\r
3344                                                                                         }\r
3345                                                                                         \r
3346                                                                                         // 最終回フラグ\r
3347                                                                                         if ( svd.flag == ProgFlags.LAST && tvd.flag != ProgFlags.LAST ) {\r
3348                                                                                                 tvd.flag = ProgFlags.LAST;\r
3349                                                                                                 isAttached = true;\r
3350                                                                                         }\r
3351                                                                                         \r
3352                                                                                         // ジャンル\r
3353                                                                                         if ( tvd.isEqualsGenre(ProgGenre.MOVIE, null) && ! tvd.isEqualsGenre(ProgGenre.MOVIE, ProgSubgenre.MOVIE_ANIME) ) {\r
3354                                                                                                 if ( tvd.genrelist == null ) {\r
3355                                                                                                         tvd.genrelist = new ArrayList<ProgGenre>();\r
3356                                                                                                         tvd.genrelist.add(tvd.genre);\r
3357                                                                                                         tvd.genrelist.add(ProgGenre.MOVIE);\r
3358                                                                                                         tvd.subgenrelist = new ArrayList<ProgSubgenre>();\r
3359                                                                                                         tvd.subgenrelist.add(tvd.subgenre);\r
3360                                                                                                         tvd.subgenrelist.add(ProgSubgenre.MOVIE_ANIME);\r
3361                                                                                                 }\r
3362                                                                                                 else {\r
3363                                                                                                         tvd.genrelist.add(ProgGenre.MOVIE);\r
3364                                                                                                         tvd.subgenrelist.add(ProgSubgenre.MOVIE_ANIME);\r
3365                                                                                                 }\r
3366                                                                                                 isAttached = true;\r
3367                                                                                         }\r
3368                                                                                         \r
3369                                                                                         // その他のフラグ\r
3370                                                                                         for ( ProgOption sopt : svd.getOption() ) {\r
3371                                                                                                 if ( tvd.addOption(sopt) && isAttached == false ) {\r
3372                                                                                                         isAttached = true;\r
3373                                                                                                 }\r
3374                                                                                         }\r
3375                                                                                         \r
3376                                                                                         // ログ\r
3377                                                                                         if (isAttached && env.getDebug()) {\r
3378                                                                                                 StdAppendMessage("しょぼかるのフラグを引き継ぎました: ("+tvpl.Center+") "+tvd.title);\r
3379                                                                                         }\r
3380                                                                                 }\r
3381                                                                                 \r
3382                                                                                 // 番組詳細\r
3383                                                                                 if ( tvd.detail.length() < svd.detail.length() ) {\r
3384                                                                                         tvd.detail = svd.detail;\r
3385                                                                                 }\r
3386                                                                                 else {\r
3387                                                                                         int idx = svd.detail.indexOf("<!");\r
3388                                                                                         if (idx != -1) {\r
3389                                                                                                 tvd.detail += svd.detail.substring(idx);\r
3390                                                                                         }\r
3391                                                                                 }\r
3392                                                                                 \r
3393                                                                                 // 「しょぼかるにのみ存在」フラグの上げ下げ(これはアニメ限定)\r
3394                                                                                 if ( isAnime ) {\r
3395                                                                                         if ( isFind ) {\r
3396                                                                                                 tvd.removeOption(ProgOption.NOSYOBO);   // NOSYOBOって…\r
3397                                                                                         }\r
3398                                                                                         else {\r
3399                                                                                                 //tvd.addOption(ProgOption.NOSYOBO);\r
3400                                                                                         }\r
3401                                                                                 }\r
3402                                                                                 \r
3403                                                                                 break;\r
3404                                                                         }\r
3405                                                                 }\r
3406                                                         }\r
3407                                                 }\r
3408                                         }\r
3409                                         break;\r
3410                                 }\r
3411                         }\r
3412                 }\r
3413         }\r
3414         \r
3415         // 番組タイトルを整形する\r
3416         private void fixTitle() {\r
3417                 // 番組追跡からサブタイトルを除外するかどうかのフラグ\r
3418                 ProgDetailList.tracenOnlyTitle = env.getFixTitle() && env.getTraceOnlyTitle();\r
3419                 //\r
3420                 if ( ! env.getFixTitle()) {\r
3421                         return;\r
3422                 }\r
3423                 //\r
3424                 for ( TVProgram tvp : tvprograms ) {\r
3425                         //if ( ! (tvp.getType() == ProgType.PROG && tvp.getSubtype() == ProgSubtype.TERRA) ) {\r
3426                         if ( tvp.getType() != ProgType.PROG ) {\r
3427                                 continue;\r
3428                         }\r
3429                         //\r
3430                         for ( ProgList pl : tvp.getCenters() ) {\r
3431                                 if ( ! pl.enabled ) {\r
3432                                         continue;\r
3433                                 }\r
3434 \r
3435                                 for ( ProgDateList pcl : pl.pdate ) {\r
3436                                         //\r
3437                                         for ( ProgDetailList tvd : pcl.pdetail ) {\r
3438                                                 if ( tvd.isEqualsGenre(ProgGenre.ANIME, null) ) {\r
3439                                                         if ( pl.Center.startsWith("NHK") || pl.Center.startsWith("NHK") ) {\r
3440                                                                 // NHK系で先頭が「アニメ 」ではじまるものから「アニメ 」を削除する\r
3441                                                                 tvd.title = tvd.title.replaceFirst("^アニメ[  ・]+","");\r
3442                                                                 tvd.titlePop = TraceProgram.replacePop(tvd.title);\r
3443                                                         }\r
3444                                                         if ( tvd.title.contains("コメンタリ") || tvd.detail.contains("コメンタリ") ) {\r
3445                                                                 // "コメンタリ"の記述のあるものは「副音声」扱いにする(副音声でなくても)\r
3446                                                                 tvd.option.add(ProgOption.MULTIVOICE);\r
3447                                                         }\r
3448                                                         if ( (tvd.title.contains("劇場版") || (tvd.detail.contains("映画") && ! tvd.detail.contains("映画館"))) && ! tvd.isEqualsGenre(ProgGenre.MOVIE, ProgSubgenre.MOVIE_ANIME) ) {\r
3449                                                                 // ジャンル=アニメだがタイトルに「劇場版」が含まれるならジャンル=映画(アニメ映画)を追加する\r
3450                                                                 if ( tvd.genrelist == null ) {\r
3451                                                                         tvd.genrelist = new ArrayList<ProgGenre>();\r
3452                                                                         tvd.genrelist.add(tvd.genre);\r
3453                                                                         tvd.genrelist.add(ProgGenre.MOVIE);\r
3454                                                                         tvd.subgenrelist = new ArrayList<ProgSubgenre>();\r
3455                                                                         tvd.subgenrelist.add(tvd.subgenre);\r
3456                                                                         tvd.subgenrelist.add(ProgSubgenre.MOVIE_ANIME);\r
3457                                                                 }\r
3458                                                                 else {\r
3459                                                                         tvd.genrelist.add(ProgGenre.MOVIE);\r
3460                                                                         tvd.subgenrelist.add(ProgSubgenre.MOVIE_ANIME);\r
3461                                                                 }\r
3462                                                         }\r
3463                                                 }\r
3464                                                 else if ( tvd.isEqualsGenre(ProgGenre.MOVIE, ProgSubgenre.MOVIE_ANIME) && tvd.subgenre != ProgSubgenre.MOVIE_ANIME ) {\r
3465                                                         // ジャンル=映画でサブジャンルが複数ありアニメが優先されてないものはアニメを優先する\r
3466                                                         tvd.subgenre = ProgSubgenre.MOVIE_ANIME;\r
3467                                                 }\r
3468                                         }\r
3469                                 }\r
3470                         }\r
3471                 }\r
3472         }\r
3473         \r
3474         /**\r
3475          * {@link ProgDetailList} の情報を整形する\r
3476          */\r
3477         private void fixDetail() {\r
3478                 for ( TVProgram tvp : tvprograms ) {\r
3479                         for ( ProgList pl : tvp.getCenters() ) {\r
3480                                 if ( ! pl.enabled ) {\r
3481                                         continue;\r
3482                                 }\r
3483                                 for ( ProgDateList pcl : pl.pdate ) {\r
3484                                         for ( ProgDetailList tvd : pcl.pdetail ) {\r
3485                                                 if ( tvd.start == null || tvd.start.length() == 0 ) {\r
3486                                                         continue;\r
3487                                                 }\r
3488                                                 \r
3489                                                 fixDetailSub(tvp, pl, tvd);\r
3490                                         }\r
3491                                 }\r
3492                         }\r
3493                 }\r
3494         }\r
3495         \r
3496         private void fixDetailSub(TVProgram tvp, ProgList pl, ProgDetailList tvd) {\r
3497                 tvd.type = tvp.getType();\r
3498                 tvd.subtype = tvp.getSubtype();\r
3499                 tvd.center = pl.Center;\r
3500                 \r
3501                 tvd.recmin = CommonUtils.getRecMinVal(tvd.startDateTime, tvd.endDateTime);\r
3502                 \r
3503                 tvd.extension_mark = markchar.getExtensionMark(tvd);\r
3504                 tvd.prefix_mark = markchar.getOptionMark(tvd);\r
3505                 tvd.newlast_mark = markchar.getNewLastMark(tvd);\r
3506                 tvd.postfix_mark = markchar.getPostfixMark(tvd);\r
3507                 \r
3508                 tvd.dontoverlapdown = (tvd.center.startsWith("NHK") || tvd.center.startsWith("NHK"));\r
3509         }\r
3510         \r
3511         \r
3512         /*******************************************************************************\r
3513          * 過去ログ検索\r
3514          ******************************************************************************/\r
3515         \r
3516         /**\r
3517          * <P>過去ログから検索キーワードにマッチする情報を取得する\r
3518          * <P>全部検索がヒットした結果がかえるのだから {@link ProgDetailList} ではなく {@link MarkedProgramList} を使うべきなのだが…\r
3519          */\r
3520         private boolean searchPassedProgram(final SearchKey sKey, final String target) {\r
3521                 \r
3522                 Matcher ma = Pattern.compile("^(\\d\\d\\d\\d/\\d\\d/\\d\\d)-(\\d\\d\\d\\d/\\d\\d/\\d\\d)$").matcher(target);\r
3523                 if ( ! ma.find() ) {\r
3524                         return false;\r
3525                 }\r
3526                 \r
3527                 final GregorianCalendar s = CommonUtils.getCalendar(ma.group(1));\r
3528                 final GregorianCalendar e = CommonUtils.getCalendar(ma.group(2));\r
3529                 final long dDays = (e.getTimeInMillis() - s.getTimeInMillis())/86400000 + 1;\r
3530 \r
3531                 final ArrayList<ProgDetailList> srchpdl = tvprograms.getSearched().getResultBuffer(sKey.getLabel()) ;\r
3532 \r
3533                 stwin.clear();\r
3534                 \r
3535                 // 検索実行(時間がかかるので状況表示する)\r
3536                 new SwingBackgroundWorker(false) {\r
3537                         \r
3538                         @Override\r
3539                         protected Object doWorks() throws Exception {\r
3540                                 \r
3541                                 TatCount tc = new TatCount();\r
3542                                 \r
3543                                 // 検索中\r
3544                                 int resultCnt = 0;\r
3545                                 for (int cnt=1; cnt<=dDays; cnt++) {\r
3546                                         \r
3547                                         String passdt = CommonUtils.getDate(e);\r
3548                                         stwin.appendMessage(String.format("[過去ログ検索] 検索中:(%d/%d) %s", cnt, dDays, passdt));\r
3549                                         \r
3550                                         PassedProgram tvp = new PassedProgram();\r
3551                                         if ( tvp.loadAllCenters(passdt) ) {\r
3552                                                 for ( ProgList pl : tvp.getCenters() ) {\r
3553                                                         if ( ! pl.enabled ) {\r
3554                                                                 continue;\r
3555                                                         }\r
3556                                                         \r
3557                                                         for ( ProgDateList pcl : pl.pdate ) {\r
3558                                                                 for ( ProgDetailList tvd : pcl.pdetail ) {\r
3559                                                                         if ( tvd.start == null || tvd.start.length() == 0 ) {\r
3560                                                                                 continue;\r
3561                                                                         }\r
3562                                                                         \r
3563                                                                         if ( SearchProgram.isMatchKeyword(sKey, pl.Center, tvd) ) {\r
3564                                                                                 tvd.dynKey = sKey;\r
3565                                                                                 tvd.dynMatched = SearchProgram.getMatchedString();\r
3566                                                                                 fixDetailSub(tvp, pl, tvd);\r
3567                                                                                 srchpdl.add(tvd);\r
3568                                                                                 if ( ++resultCnt >= env.getSearchResultMax() ) {\r
3569                                                                                         mwin.appendMessage(String.format("[過去ログ検索] 検索件数の上限に到達しました。所要時間: %.2f秒",tc.end()));\r
3570                                                                                         return null;\r
3571                                                                                 }\r
3572                                                                         }\r
3573                                                                 }\r
3574                                                         }\r
3575                                                 }\r
3576                                         }\r
3577                                         \r
3578                                         e.add(Calendar.DATE,-1);\r
3579                                 }\r
3580 \r
3581                                 mwin.appendMessage(String.format("[過去ログ検索] 検索完了。所要時間: %.2f秒",tc.end()));\r
3582                                 return null;\r
3583                         }\r
3584                         \r
3585                         @Override\r
3586                         protected void doFinally() {\r
3587                                 StWinSetVisible(false);\r
3588                         }\r
3589                 }.execute();\r
3590                 \r
3591                 StWinSetLocationCenter(this);\r
3592                 StWinSetVisible(true);\r
3593 \r
3594                 return true;\r
3595         }\r
3596 \r
3597         \r
3598         /*******************************************************************************\r
3599          * スナップ・ショット!\r
3600          ******************************************************************************/\r
3601         \r
3602         /**\r
3603          * 番組表のスナップショットをファイルに保存したり印刷したりする\r
3604          */\r
3605         private boolean getSnapshot(int currentpage, int numberofpages) {\r
3606                 \r
3607                 try {\r
3608                         String fname;\r
3609                         if ( mainWindow.isTabSelected(MWinTab.LISTED) ) {\r
3610                                 // リスト形式\r
3611                                 fname = String.format("snapshot.%s",env.getSnapshotFmt().getExtension());\r
3612                                 CommonSwingUtils.saveComponentAsJPEG(listed.getCurrentView(), listed.getTableHeader(), null, listed.getTableBody(), fname, env.getSnapshotFmt(), Viewer.this);\r
3613                         }\r
3614                         else if ( mainWindow.isTabSelected(MWinTab.PAPER) ){\r
3615                                 // 新聞形式\r
3616                                 if ( env.getDrawcacheEnable() || ! env.isPagerEnabled() ) {\r
3617                                         fname = String.format("snapshot.%s",env.getSnapshotFmt().getExtension());\r
3618                                 }\r
3619                                 else {\r
3620                                         if ( env.getAllPageSnapshot() ) {\r
3621                                                 for ( int i=0; i<numberofpages; i++ ) {\r
3622                                                         if ( i != currentpage ) {\r
3623                                                                 // カレントページは最後にスナップる(再描画を1回で済ませるため)\r
3624                                                                 toolBar.setSelectedPagerIndex(i);\r
3625                                                                 fname = String.format("snapshot%02d.%s",i+1,env.getSnapshotFmt().getExtension());\r
3626                                                                 CommonSwingUtils.saveComponentAsJPEG(paper.getCurrentView(), paper.getCenterPane(), paper.getTimebarPane(), paper.getCurrentPane(), fname, env.getSnapshotFmt(), Viewer.this);\r
3627                                                         }\r
3628                                                 }\r
3629                                         }\r
3630                                         fname = String.format("snapshot%02d.%s",currentpage+1,env.getSnapshotFmt().getExtension());\r
3631                                         toolBar.setSelectedPagerIndex(currentpage);\r
3632                                 }\r
3633                                 CommonSwingUtils.saveComponentAsJPEG(paper.getCurrentView(), paper.getCenterPane(), paper.getTimebarPane(), paper.getCurrentPane(), fname, env.getSnapshotFmt(), Viewer.this);\r
3634                         }\r
3635                         else {\r
3636                                 // 他のタブ\r
3637                                 return true;\r
3638                         }\r
3639                         \r
3640                         Desktop desktop = Desktop.getDesktop();\r
3641                         if (env.getPrintSnapshot()) {\r
3642                                 // 印刷\r
3643                                 desktop.print(new File(fname));\r
3644                         }\r
3645                         else {\r
3646                                 // ファイルに保存\r
3647                                 String emsg = CommonUtils.openFile(fname);\r
3648                                 if (emsg != null) {\r
3649                                         mwin.appendError(emsg);\r
3650                                         return false;\r
3651                                 }\r
3652                         }\r
3653                         \r
3654                         return true;\r
3655                         \r
3656                 } catch (IOException e) {\r
3657                         e.printStackTrace();\r
3658                 }\r
3659                 \r
3660                 return false;\r
3661         }\r
3662         \r
3663         \r
3664         /*******************************************************************************\r
3665          * ここからおおむね初期化処理にかかわるメソッド群\r
3666          ******************************************************************************/\r
3667 \r
3668         /**\r
3669          * 各種設定の変更の反映\r
3670          */\r
3671         private boolean setEnv(final boolean reload_prog) {\r
3672                 \r
3673                 bounds.save();\r
3674                 cbitems.save();\r
3675                 env.save();\r
3676 \r
3677                 // CommonUtilsの設定変更\r
3678                 CommonUtils.setAdjLateNight(env.getAdjLateNight());\r
3679                 CommonUtils.setExpandTo8(env.getExpandTo8());\r
3680                 CommonUtils.setUseRundll32(env.getUseRundll32());\r
3681                 CommonUtils.setDisplayPassedReserve(env.getDisplayPassedReserve());\r
3682                 CommonUtils.setDebug(env.getDebug());\r
3683                 \r
3684                 SwingBackgroundWorker.setDebug(env.getDebug());\r
3685 \r
3686                 // ほにゃらら\r
3687                 toolBar.setDebug(env.getDebug());\r
3688                 autores.setDebug(env.getDebug());\r
3689                 rdialog.setDebug(env.getDebug());\r
3690 \r
3691                 // PassedProgramListの設定変更\r
3692                 tvprograms.getPassed().setPassedDir(env.getPassedDir());\r
3693 \r
3694                 // レコーダプラグインの設定変更\r
3695                 for ( HDDRecorder rec : recorders ) {\r
3696                         // 拡張設定だけ\r
3697                         setSettingRecPluginExt(rec, env);\r
3698                 }\r
3699 \r
3700                 // Web番組表共通設定\r
3701                 setSettingProgPluginCommon(env);\r
3702                 \r
3703                 // web番組表のリフレッシュ\r
3704                 setSettingProgPluginAll(env);\r
3705                 \r
3706                 // リロードメニューの書き換え\r
3707                 toolBar.updateReloadReservedExtension();\r
3708                 toolBar.updateReloadProgramExtension();\r
3709                 \r
3710                 // ページャーコンボボックスの書き換え\r
3711                 toolBar.setPagerItems();\r
3712                 \r
3713                 // 列の表示・非表示\r
3714                 listed.setMarkColumnVisible(env.getSplitMarkAndTitle());\r
3715                 listed.setDetailColumnVisible(env.getShowDetailOnList());\r
3716                 listed.setPickupColumnVisible(env.getShowRsvPickup());\r
3717                 listed.setDupColumnVisible(env.getShowRsvDup());\r
3718                 listed.setRowHeaderVisible(env.getRowHeaderVisible());\r
3719                 reserved.setRowHeaderVisible(env.getRowHeaderVisible());\r
3720                 \r
3721                 // 強調色\r
3722                 listed.setMatchedKeywordColor(env.getMatchedKeywordColor());\r
3723                 listed.setRsvdLineColor((env.getRsvdLineEnhance())?(env.getRsvdLineColor()):(null));\r
3724                 listed.setPickedLineColor((env.getRsvdLineEnhance())?(env.getPickedLineColor()):(null));\r
3725                 listed.setCurrentLineColor((env.getCurrentLineEnhance())?(env.getCurrentLineColor()):(null));\r
3726                 \r
3727                 // システムトレイアイコン\r
3728                 setTrayIconVisible(env.getShowSysTray());\r
3729                 setXButtonAction(env.getShowSysTray() && env.getHideToTray());\r
3730                 \r
3731                 // 新聞形式のツールチップの表示時間を変更する\r
3732                 setTooltipDelay();\r
3733                 \r
3734                 // 番組情報の再取得\r
3735                 if ( reload_prog ) {\r
3736                         loadTVProgram(false, LoadFor.ALL);      // 部品呼び出し\r
3737                 }\r
3738                 \r
3739                 // Web番組表の再構築\r
3740                 mpList.setHistoryOnlyUpdateOnce(env.getHistoryOnlyUpdateOnce());\r
3741                 mpList.setShowOnlyNonrepeated(env.getShowOnlyNonrepeated());\r
3742                 \r
3743                 doRedrawTVProgram();    // か き な お し\r
3744 \r
3745                 return true;\r
3746         }\r
3747         \r
3748         // システムトレイ関係\r
3749         private void getTrayIcon() {\r
3750                 if ( trayicon != null ) {\r
3751                         return;\r
3752                 }\r
3753                 \r
3754                 try {\r
3755                         Image image = ImageIO.read(new File(ICONFILE_SYSTRAY));\r
3756                         trayicon = new TrayIcon(image,"Tainavi");\r
3757                         \r
3758                         final Viewer thisClass = this;\r
3759                         \r
3760                         // メニューの追加\r
3761                         PopupMenu popup = new PopupMenu();\r
3762                         {\r
3763                                 MenuItem item = new MenuItem("開く");\r
3764                                 item.addActionListener(new ActionListener() {\r
3765                                         @Override\r
3766                                         public void actionPerformed(ActionEvent e) {\r
3767                                                 thisClass.setVisible(true);\r
3768                                                 thisClass.setState(Frame.NORMAL);\r
3769                                         }\r
3770                                 });\r
3771                                 popup.add(item);\r
3772                         }\r
3773                         {\r
3774                                 MenuItem item = new MenuItem("終了する");\r
3775                                 item.addActionListener(new ActionListener() {\r
3776                                         @Override\r
3777                                         public void actionPerformed(ActionEvent e) {\r
3778                                                 ExitOnClose();\r
3779                                                 System.exit(0);\r
3780                                         }\r
3781                                 });\r
3782                                 popup.add(item);\r
3783                         }\r
3784                         trayicon.setPopupMenu(popup);\r
3785                         \r
3786                         // 左クリックで復帰\r
3787                         trayicon.addMouseListener(new MouseAdapter() {\r
3788                                 //\r
3789                                 public void mouseClicked(MouseEvent e) {\r
3790                                         if (e.getButton() == MouseEvent.BUTTON1) {\r
3791                                                 thisClass.setVisible(true);\r
3792                                                 thisClass.setState(Frame.NORMAL);\r
3793                                         }\r
3794                                 }\r
3795                         });\r
3796                 \r
3797                 } catch (IOException e) {\r
3798                         StdAppendError("アイコンファイルが読み込めませんでした: "+ICONFILE_SYSTRAY);\r
3799                         e.printStackTrace();\r
3800                 }\r
3801         }\r
3802         private void setTrayIconVisible(boolean b) {\r
3803                 \r
3804                 if ( ! SystemTray.isSupported() || trayicon == null ) {\r
3805                         return;\r
3806                 }\r
3807                 \r
3808                 try {\r
3809                         if ( b ) {\r
3810                                 // システムトレイに追加\r
3811                                 SystemTray.getSystemTray().remove(trayicon);\r
3812                                 SystemTray.getSystemTray().add(trayicon);\r
3813                         }\r
3814                         else {\r
3815                                 // システムトレイから削除\r
3816                                 SystemTray.getSystemTray().remove(trayicon);\r
3817                         }\r
3818                 } catch (AWTException e) {\r
3819                         e.printStackTrace();\r
3820                 }\r
3821         }\r
3822         private void HideToTray() {\r
3823                 if ( SystemTray.isSupported() && trayicon != null && (env.getShowSysTray() && env.getHideToTray()) ) {\r
3824                         this.setVisible(false);\r
3825                 }\r
3826         }\r
3827         private void setXButtonAction(boolean b) {\r
3828                 if ( b ) {\r
3829                         this.setDefaultCloseOperation(JFrame.ICONIFIED);\r
3830                 }\r
3831                 else {\r
3832                         this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);\r
3833                 }\r
3834         }\r
3835         \r
3836         // コマンドライン引数の処理\r
3837         private void procArgs(String[] args) {\r
3838                 int flag = 0;\r
3839                 for (String arg : args) {\r
3840                         switch (flag) {\r
3841                         case 0:\r
3842                                 if (arg.compareTo("-L") == 0) {\r
3843                                         // -l : ロギング\r
3844                                         //logging = false;\r
3845                                 }\r
3846                                 else if (arg.compareTo("-L") == 0) {\r
3847                                         // -L : ロギング不可\r
3848                                         logging = false;\r
3849                                 }\r
3850                                 else if (arg.compareTo("-w") == 0) {\r
3851                                         // -w : レコーダ起動\r
3852                                         runRecWakeup = true;\r
3853                                 }\r
3854                                 else if (arg.compareTo("-nowebaccess") == 0) {\r
3855                                         // -nowebaccess : 起動時のWeb番組表へのアクセス無効\r
3856                                         enableWebAccess = false;\r
3857                                 }\r
3858                                 else if (arg.compareTo("-proxy") == 0) {\r
3859                                         // -proxy : Web番組表へのアクセスにProxy経由を強制する\r
3860                                         flag = 1;\r
3861                                 }\r
3862                                 else if (arg.compareTo("-loadrec") == 0) {\r
3863                                         // -loadrec : 起動時にレコーダにアクセスする\r
3864                                         runRecLoad = true;\r
3865                                 }\r
3866                                 else if (arg.compareTo("-onlyLoadProgram") == 0) {\r
3867                                         // -onlyLoadProgram : 番組表の取得だけ行う\r
3868                                         onlyLoadProgram = true;\r
3869                                 }\r
3870                                 break;\r
3871                         case 1:\r
3872                                 String[] dat = arg.split(":");\r
3873                                 if (dat.length == 1 ) {\r
3874                                         pxaddr = dat[0];\r
3875                                         pxport = "8080";\r
3876                                 } if (dat.length >= 2 ) {\r
3877                                         pxaddr = dat[0];\r
3878                                         pxport = dat[1];\r
3879                                 }\r
3880                                 flag = 0;\r
3881                                 break;\r
3882                         }\r
3883                 }\r
3884         }\r
3885         \r
3886         // メインの環境設定ファイルを読みだす\r
3887         private void loadEnvfile() {\r
3888                 StdAppendMessage("【環境設定】環境設定ファイルを読み込みます.");\r
3889                 env.load();\r
3890         }\r
3891         \r
3892         // 引き続きその他の環境設定ファイルも読みだす\r
3893         private void procEnvs() {\r
3894                 \r
3895                 StdAppendMessage("【環境設定】環境設定ファイル類を読み込みます.");\r
3896 \r
3897                 // 各種設定\r
3898                 env.makeEnvDir();\r
3899                 \r
3900                 // レコーダ一覧\r
3901                 recInfoList.load();\r
3902 \r
3903                 // Proxyサーバ\r
3904                 if (pxaddr != null) {\r
3905                         env.setUseProxy(true);\r
3906                         env.setProxyAddr(pxaddr);\r
3907                         env.setProxyPort(pxport);\r
3908                 }\r
3909                 \r
3910                 // Cookieの処理を入れようとしたけど無理だった\r
3911                 /*\r
3912                 {\r
3913                         CookieManager manager = new CookieManager();\r
3914                         manager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);\r
3915                         CookieHandler.setDefault(manager);\r
3916                 }\r
3917                 */\r
3918                 \r
3919                 // ジャンル別背景色\r
3920                 pColors.load();\r
3921                 \r
3922                 // 深夜の帯予約の補正(一日前にずらす)\r
3923                 // 可能なら番組表を8日分取得する\r
3924                 // 【WIN】ファイルオープンにrundll32を使用する\r
3925                 CommonUtils.setAdjLateNight(env.getAdjLateNight());\r
3926                 CommonUtils.setExpandTo8(env.getExpandTo8());\r
3927                 CommonUtils.setUseRundll32(env.getUseRundll32());\r
3928                 CommonUtils.setDisplayPassedReserve(env.getDisplayPassedReserve());\r
3929                 CommonUtils.setDebug(env.getDebug());\r
3930                 \r
3931                 SwingBackgroundWorker.setDebug(env.getDebug());\r
3932                 \r
3933                 // クリップボードアイテム\r
3934                 cbitems.load();\r
3935                 \r
3936                 // サイズ・位置情報取得\r
3937                 bounds.setLoaded(bounds.load());\r
3938                 \r
3939                 // 番組追跡キーワード取得\r
3940                 trKeys.load();\r
3941                 \r
3942                 // 検索キーワード取得\r
3943                 srKeys.load();\r
3944                 \r
3945                 // 検索キーワードグループ取得\r
3946                 srGrps.load();\r
3947                 \r
3948                 // 延長警告源設定取得\r
3949                 extKeys.load();\r
3950                 \r
3951                 // デフォルトAV設定取得\r
3952                 avs.load();\r
3953                 chavs.load();\r
3954 \r
3955                 // スポーツ延長警告のデフォルト設定のコードはもういらないので削除(3.15.4β) \r
3956                 \r
3957                 // 簡易描画はもういらないので削除\r
3958                 \r
3959                 // ChannelConvert\r
3960                 chconv.load();\r
3961         }\r
3962         \r
3963         // 二重起動チェック\r
3964         private void chkDualBoot() {\r
3965                 if ( ! env.getOnlyOneInstance() ) {\r
3966                         return;\r
3967                 }\r
3968                 \r
3969                 if ( ! CommonUtils.getLock() ) {\r
3970                         // 既にロックされている\r
3971                         ringBeep();\r
3972                         System.exit(1);\r
3973                 }\r
3974                 \r
3975                 Runtime.getRuntime().addShutdownHook(new Thread() {\r
3976                         public void run() {\r
3977                                 // 鯛ナビ終了時にロックを解除する\r
3978                                 CommonUtils.getUnlock();\r
3979                         }\r
3980                 });\r
3981         }\r
3982         \r
3983         // アップデートの有無チェック\r
3984         private void chkVerUp() {\r
3985                 if ( ! enableWebAccess || onlyLoadProgram ) {\r
3986                         stwin.appendError("【オンラインアップデート】オンラインアップデートは無効です");\r
3987                         return;\r
3988                 }\r
3989                 \r
3990                 VWUpdate vu = new VWUpdate(stwin);\r
3991                 if ( ! vu.isExpired(env.getUpdateMethod()) ) {\r
3992                         // メッセージはVWUpdate内で出力されます\r
3993                         return;\r
3994                 }\r
3995                 if ( doVerUp(vu) ) {\r
3996                         System.exit(0);\r
3997                 }\r
3998         }\r
3999         \r
4000         private boolean doVerUp(VWUpdate vu) {\r
4001                 UpdateResult res = vu.checkUpdate(VersionInfo.getVersion());\r
4002                 switch ( res ) {\r
4003                 case DONE:\r
4004                         // 成功\r
4005                         // 履歴は更新しない(連続アップデートがあるかも知れないので)\r
4006                         LogViewer lv = new LogViewer(HISTORY_FILE);\r
4007                         lv.setModal(true);\r
4008                         lv.setCaretPosition(0);\r
4009                         lv.setVisible(true);\r
4010                         return true;\r
4011                 case PASS:\r
4012                         // キャンセル\r
4013                         // 履歴は更新しない(次回に持ち越し)\r
4014                         break;\r
4015                 case NOUPDATE:\r
4016                         // アップデートなし\r
4017                         vu.updateHistory();\r
4018                         break;\r
4019                 default:\r
4020                         // 失敗\r
4021                         // 履歴は更新しない(次回再挑戦)\r
4022                         break;\r
4023                 }\r
4024                 return false;\r
4025         }\r
4026         \r
4027         /**\r
4028          *  レコーダプラグインをすべて読み込みます。\r
4029          */\r
4030         private boolean loadRecPlugins() {\r
4031                 \r
4032                 stwin.appendMessage("【レコーダプラグイン】プラグインを読み込みます.");\r
4033                 \r
4034                 boolean isMailPluginEnabled = false;\r
4035                 try {\r
4036                         Class.forName("javax.mail.Session");\r
4037                         isMailPluginEnabled = true;\r
4038                 }\r
4039                 catch ( Exception e ) {\r
4040                         System.err.println("【レコーダプラグイン】メール系プラグイン用の外部ライブラリがみつかりません: "+e.toString());\r
4041                 }\r
4042 \r
4043                 boolean isCalendarPluginEnabled = false;\r
4044                 try {\r
4045                         Class.forName("com.google.gdata.client.calendar.CalendarService");\r
4046                         isCalendarPluginEnabled = true;\r
4047                 }\r
4048                 catch ( Exception e ) {\r
4049                         System.err.println("【レコーダプラグイン】カレンダー系プラグイン用の外部ライブラリがみつかりません: "+e.toString());\r
4050                 }\r
4051                 \r
4052                 //\r
4053                 ArrayList<String> recIda = new ArrayList<String>();\r
4054                 for ( File f : new File(CommonUtils.joinPath(new String[]{"bin","tainavi","pluginrec"})).listFiles() ) {\r
4055                         Matcher ma = Pattern.compile("^(PlugIn_Rec[^$]+)[^$]*\\.class$").matcher(f.getName());\r
4056                         if ( ma.find() ) {\r
4057                                 if ( ! isMailPluginEnabled && f.getName().toLowerCase().contains("mail") ) {\r
4058                                         System.out.println("【レコーダプラグイン】メール系プラグインは無効です: "+f.getName());\r
4059                                         continue;\r
4060                                 }\r
4061                                 if ( ! isCalendarPluginEnabled && f.getName().toLowerCase().contains("calendar") ) {\r
4062                                         System.out.println("【レコーダプラグイン】カレンダー系プラグインは無効です: "+f.getName());\r
4063                                         continue;\r
4064                                 }\r
4065                                 \r
4066                                 recIda.add(ma.group(1));\r
4067                         }\r
4068                 }\r
4069                 String[] recIdd = recIda.toArray(new String[0]);\r
4070                 Arrays.sort(recIdd);\r
4071                 \r
4072                 // servicesに追記\r
4073                 StringBuilder sb = new StringBuilder();\r
4074                 for ( String recId : recIdd ) {\r
4075                         sb.append("tainavi.pluginrec.");\r
4076                         sb.append(recId);\r
4077                         sb.append("\n");\r
4078                 }\r
4079                 if ( ! CommonUtils.write2file(CommonUtils.joinPath(new String[] {"bin","META-INF","services","tainavi.HDDRecorder"}), sb.toString()) ) {\r
4080                         stwin.appendError("【レコーダプラグイン】プラグインの読み込みに失敗しました: ");\r
4081                         return false;\r
4082                 }\r
4083 \r
4084                 // ここで例外が起きてもトラップできない、スレッドが落ちる\r
4085                 ServiceLoader<HDDRecorder> r = ServiceLoader.load(HDDRecorder.class);\r
4086                 \r
4087                 recPlugins.clear();\r
4088                 for ( HDDRecorder recorder : r ) {\r
4089                         if (env.getDebug()) {\r
4090                                 StdAppendMessage("+追加します: "+recorder.getRecorderId());\r
4091                         }\r
4092                         recPlugins.add(recorder.clone());\r
4093                         StdAppendMessage("+追加しました: "+recorder.getRecorderId());\r
4094                 }\r
4095                 \r
4096                 return true;\r
4097         }\r
4098         \r
4099         /**\r
4100          * レコーダ設定をもとにレコーダプラグインから実レコーダのインスタンスを生成します。\r
4101          */\r
4102         private void initRecPluginAll() {\r
4103                 //\r
4104                 recorders.clear();\r
4105                 for ( RecorderInfo ri : recInfoList ) {\r
4106                         ArrayList<HDDRecorder> rl = recPlugins.findPlugin(ri.getRecorderId());\r
4107                         if ( rl.size() == 0 ) {\r
4108                                 stwin.appendError("【レコーダプラグイン】プラグインがみつかりません: "+ri.getRecorderId()+"("+ri.getRecorderIPAddr()+":"+ri.getRecorderPortNo()+")");\r
4109                         }\r
4110                         else { \r
4111                                 stwin.appendMessage("【レコーダプラグイン】プラグインを初期化します: "+ri.getRecorderId()+"("+ri.getRecorderIPAddr()+":"+ri.getRecorderPortNo()+")");\r
4112                                 for ( HDDRecorder rPlugin : rl ) {\r
4113                                         initRecPlugin(rPlugin, ri);\r
4114                                 }\r
4115                         }\r
4116                 }\r
4117         }\r
4118         protected HDDRecorder initRecPlugin(HDDRecorder rPlugin, RecorderInfo ri) {\r
4119                 HDDRecorder rec = rPlugin.clone();\r
4120                 recorders.add(rec);\r
4121                 \r
4122                 rec.getChCode().load(true);     // true : ログ出力あり\r
4123                 setSettingRecPluginBase(rec, ri);\r
4124                 setSettingRecPluginExt(rec,env);\r
4125                 rec.setProgressArea(stwin);\r
4126                 return rec;\r
4127         }\r
4128         protected void setSettingRecPluginBase(HDDRecorder to, RecorderInfo from) {\r
4129                 to.setIPAddr(from.getRecorderIPAddr());\r
4130                 to.setPortNo(from.getRecorderPortNo());\r
4131                 to.setUser(from.getRecorderUser());\r
4132                 to.setPasswd(from.getRecorderPasswd());\r
4133                 to.setMacAddr(from.getRecorderMacAddr());\r
4134                 to.setBroadcast(from.getRecorderBroadcast());\r
4135                 to.setUseCalendar(from.getUseCalendar());\r
4136                 to.setUseChChange(from.getUseChChange());\r
4137                 to.setRecordedCheckScope(from.getRecordedCheckScope());\r
4138                 to.setTunerNum(from.getTunerNum());\r
4139                 to.setColor(from.getRecorderColor());\r
4140         }\r
4141         protected void setSettingRecPluginExt(HDDRecorder recorder, Env nEnv) {\r
4142                 recorder.setUserAgent(nEnv.getUserAgent());\r
4143                 recorder.setDebug(nEnv.getDebug());\r
4144                 recorder.setAdjNotRep(nEnv.getAdjoiningNotRepetition());\r
4145                 recorder.setRecordedSaveScope(nEnv.getRecordedSaveScope());\r
4146         }\r
4147         \r
4148         //\r
4149         protected void doRecWakeup() {\r
4150                 for ( HDDRecorder rec : recorders ) {\r
4151                         if ( ! rec.getMacAddr().equals("") && ! rec.getBroadcast().equals("") ) {\r
4152                                 rec.wakeup();\r
4153                         }\r
4154                 }\r
4155         }\r
4156         \r
4157         /**\r
4158          * 一時間は再実行させないんだ\r
4159          */\r
4160         private boolean isOLPExpired(int expire) {\r
4161                 String fname = "env"+File.separator+"olp.history";\r
4162                 if ( ! new File(fname).exists() || ! new File(fname).canWrite() ) {\r
4163                         stwin.appendError("【警告】実行履歴ファイルがないから実行させないよ!");\r
4164                         ringBeep();\r
4165                         return false;\r
4166                 }\r
4167                 String dat = CommonUtils.read4file(fname, true);\r
4168                 if ( dat == null ) {\r
4169                         stwin.appendError("【警告】実行履歴を取得できなかったから実行させないよ!");\r
4170                         ringBeep();\r
4171                         return false;\r
4172                 }\r
4173                 GregorianCalendar ca = null;\r
4174                 dat = EncryptPassword.dec(b64.dec(dat));\r
4175                 if ( dat != null ) {\r
4176                         ca = CommonUtils.getCalendar(dat);\r
4177                 }\r
4178                 if ( ca == null ) {\r
4179                         stwin.appendError("【警告】実行履歴の内容が不正だったから実行させないよ! "+dat);\r
4180                         ringBeep();\r
4181                         return false;\r
4182                 }\r
4183                 if ( CommonUtils.getCompareDateTime(ca, CommonUtils.getCalendar(-expire*3600)) >= 0 ) {\r
4184                         ca.add(Calendar.HOUR,expire);\r
4185                         stwin.appendError("【警告】"+expire+"時間以内の再実行は許さないよ!"+CommonUtils.getDateTime(ca)+"まで待って!");\r
4186                         ringBeep();\r
4187                         return false;\r
4188                 }\r
4189                 if ( ! CommonUtils.write2file(fname, b64.enc(EncryptPassword.enc(CommonUtils.getDateTime(0)))) ) {\r
4190                         stwin.appendError("【警告】実行履歴を保存できなかったから実行させないよ!");\r
4191                         ringBeep();\r
4192                         return false;\r
4193                 }\r
4194                 \r
4195                 return true;\r
4196         }\r
4197         \r
4198         /**\r
4199          *  Web番組表プラグインをすべて読み込みます。\r
4200          */\r
4201         private boolean loadProgPlugins() {\r
4202         \r
4203                 final String FUNCID = "[Web番組表プラグイン組込] ";\r
4204                 final String ERRID = "[ERROR]"+FUNCID;\r
4205                 \r
4206                 // Web番組表プラグインの処理\r
4207                 stwin.appendMessage(FUNCID+"プラグインを読み込みます.");\r
4208                 \r
4209                 // Web番組表共通設定\r
4210                 setSettingProgPluginCommon(env);\r
4211                 \r
4212                 /*\r
4213                  * 重要 - ここから\r
4214                  */\r
4215                 \r
4216                 // TVProgramListのインスタンスは別途初期化が必要\r
4217                 progPlugins.clear();\r
4218                 tvprograms.clear();\r
4219 \r
4220                 /*\r
4221                  * 重要 - ここまで\r
4222                  */\r
4223 \r
4224                 ArrayList<String> prgIda = new ArrayList<String>();\r
4225                 for ( File f : new File(CommonUtils.joinPath("bin","tainavi","plugintv")).listFiles() ) {\r
4226                         Matcher ma = Pattern.compile("^(PlugIn_(TV|CS|RAD)P[^$]+)\\.class$").matcher(f.getName());\r
4227                         if (ma.find()) {\r
4228                                 prgIda.add(ma.group(1));\r
4229                         }\r
4230                 }\r
4231                 String[] prgIdd = prgIda.toArray(new String[0]);\r
4232                 Arrays.sort(prgIdd);\r
4233                 \r
4234                 // servicesに追記\r
4235                 StringBuilder sb = new StringBuilder();\r
4236                 for ( String prgId : prgIdd ) {\r
4237                         sb.append("tainavi.plugintv.");\r
4238                         sb.append(prgId);\r
4239                         sb.append("\n");\r
4240                 }\r
4241                 if ( ! CommonUtils.write2file(CommonUtils.joinPath("bin","META-INF","services","tainavi.TVProgram"), sb.toString()) ) {\r
4242                         stwin.appendError(ERRID+"プラグインの読み込みに失敗しました: ");\r
4243                         return false;\r
4244                 }\r
4245                 \r
4246                 ServiceLoader<TVProgram> p = ServiceLoader.load(TVProgram.class);\r
4247 \r
4248                 // 実際必要ないのだが、プラグインのインスタンスはclone()して使う\r
4249                 for ( TVProgram pg : p ) {\r
4250                         TVProgram prog = pg.clone();\r
4251                         \r
4252                         stwin.appendMessage("+追加しました: "+prog.getTVProgramId());\r
4253                         \r
4254                         // CH設定タブではプラグイン側のインスタンスを使うので情報を追加してやる必要があるのであった\r
4255                         setSettingProgPlugin(prog, env);\r
4256                         \r
4257                         progPlugins.add(prog);\r
4258                 }\r
4259                 \r
4260                 p = null;\r
4261                 \r
4262                 return true;\r
4263         }\r
4264         \r
4265         /**\r
4266          *  設定にあわせてWeb番組表プラグインを絞り込みます。\r
4267          */\r
4268         private void setSelectedProgPlugin() {\r
4269                 \r
4270                 // この3つは保存しておく\r
4271                 Syobocal syobo = tvprograms.getSyobo();\r
4272                 PassedProgram passed = tvprograms.getPassed();\r
4273                 PickedProgram pickup = tvprograms.getPickup();\r
4274                 SearchResult searched = tvprograms.getSearched();\r
4275                 \r
4276                 tvprograms.clear();\r
4277                 \r
4278                 {\r
4279                         TVProgram tvp = progPlugins.getTvProgPlugin(env.getTVProgramSite());\r
4280                         if ( tvp == null ) {\r
4281                                 // デフォルトもなければ先頭にあるもの\r
4282                                 tvp = progPlugins.getTvProgPlugin(null);\r
4283                         }\r
4284                         if ( tvp == null ) {\r
4285                                 // てか一個もなくね?\r
4286                                 StdAppendError("【Web番組表選択】地上波&BS番組表が選択されていません: "+env.getTVProgramSite());\r
4287                         }\r
4288                         else {\r
4289                                 StdAppendMessage("【Web番組表選択】地上波&BS番組表が選択されました: "+tvp.getTVProgramId());\r
4290                                 tvprograms.add(tvp.clone());\r
4291                         }\r
4292                 }\r
4293                 {\r
4294                         TVProgram tvp = progPlugins.getCsProgPlugin(env.getCSProgramSite());\r
4295                         if ( tvp == null ) {\r
4296                                 tvp = progPlugins.getCsProgPlugin(null);\r
4297                         }\r
4298                         if ( tvp == null ) {\r
4299                                 StdAppendError("【Web番組表選択】CS番組表[プライマリ]が選択されていません: "+env.getCSProgramSite());\r
4300                         }\r
4301                         else {\r
4302                                 StdAppendMessage("【Web番組表選択】CS番組表[プライマリ]が選択されました: "+tvp.getTVProgramId());\r
4303                                 tvprograms.add(tvp.clone());\r
4304                         }\r
4305                 }\r
4306                 {\r
4307                         TVProgram tvp = progPlugins.getCs2ProgPlugin(env.getCS2ProgramSite());\r
4308                         if ( tvp == null ) {\r
4309                                 tvp = progPlugins.getCs2ProgPlugin(null);\r
4310                         }\r
4311                         if ( tvp == null ) {\r
4312                                 StdAppendError("【Web番組表選択】CS番組表[プライマリ]が選択されていません: "+env.getCS2ProgramSite());\r
4313                         }\r
4314                         else {\r
4315                                 StdAppendMessage("【Web番組表選択】CS番組表[プライマリ]が選択されました: "+tvp.getTVProgramId());\r
4316                                 tvprograms.add(tvp.clone());\r
4317                         }\r
4318                 }\r
4319                 /*\r
4320                 if ( progPlugins.getRadioProgPlugins().size() > 0 )\r
4321                 {\r
4322                         TVProgram tvp = progPlugins.getCsProgPlugin(env.getRadioProgramSite());\r
4323                         if ( tvp == null ) {\r
4324                                 tvp = progPlugins.getCsProgPlugin(null);\r
4325                         }\r
4326                         if ( tvp == null ) {\r
4327                                 StdAppendError("【Web番組表選択】ラジオ番組表が選択されていません: "+env.getRadioProgramSite());\r
4328                         }\r
4329                         else {\r
4330                                 StdAppendMessage("【Web番組表選択】ラジオ番組表が選択されました: "+tvp.getTVProgramId());\r
4331                                 tvprograms.add(tvp.clone());\r
4332                         }\r
4333                 }\r
4334                 */\r
4335                 \r
4336                 {\r
4337                         if ( syobo == null ) {\r
4338                                 syobo = new Syobocal();\r
4339                         }\r
4340                         tvprograms.add(syobo);\r
4341                 }\r
4342                 {\r
4343                         if ( passed == null ) {\r
4344                                 passed = new PassedProgram();\r
4345                         }\r
4346                         tvprograms.add(passed);\r
4347                 }\r
4348                 {\r
4349                         if ( pickup == null ) {\r
4350                                 pickup = new PickedProgram();\r
4351                                 pickup.loadProgram(null, false);\r
4352                         }\r
4353                         tvprograms.add(pickup);\r
4354                 }\r
4355                 {\r
4356                         if ( searched == null ) {\r
4357                                 searched = new SearchResult();\r
4358                         }\r
4359                         tvprograms.add(searched);\r
4360                 }\r
4361         }\r
4362         \r
4363         /**\r
4364          * Web番組表設定をもとにレコーダプラグインのインスタンスを生成します。\r
4365          */\r
4366         private void initProgPluginAll() {\r
4367 \r
4368                 final String FUNCID = "[Web番組表プラグイン初期化] ";\r
4369                 final LinkedHashMap<ArrayList<TVProgram>,String> map = new LinkedHashMap<ArrayList<TVProgram>, String>();\r
4370                 map.put(tvprograms.getTvProgPlugins(), "地上波&BS番組表");\r
4371                 map.put(tvprograms.getCsProgPlugins(), "CS番組表[プライマリ]");\r
4372                 map.put(tvprograms.getCs2ProgPlugins(), "CS番組表[セカンダリ]");\r
4373                 //map.put(progPlugins.getRadioProgPlugins(), "ラジオ番組表");\r
4374                 \r
4375                 new SwingBackgroundWorker(true) {\r
4376                         \r
4377                         @Override\r
4378                         protected Object doWorks() throws Exception {\r
4379 \r
4380                                 for ( ArrayList<TVProgram> tvpa : map.keySet() ) {\r
4381                                         stwin.appendMessage(FUNCID+map.get(tvpa)+"のベース情報(放送局リストなど)を取得します.");\r
4382                                         for ( TVProgram p : tvpa ) {\r
4383                                                 stwin.appendMessage(FUNCID+"プラグインを初期化します: "+p.getTVProgramId());\r
4384                                                 \r
4385                                                 try {\r
4386                                                         // 個別設定(2) …(1)と(2)の順番が逆だったので前に移動してきました(3.17.3β)\r
4387                                                         setSettingProgPlugin(p,env);                            // 他からも呼び出される部分だけ分離\r
4388                                                         \r
4389                                                         // 個別設定(1)\r
4390                                                         p.setOptString(null);                                           // フリーオプション初期化\r
4391                                                         p.loadAreaCode();                                                       // 放送エリア情報取得\r
4392                                                         p.loadCenter(p.getSelectedCode(),false);        // 放送局情報取得\r
4393                                                         p.setSortedCRlist();                                            // 有効放送局だけよりわける\r
4394                                                 }\r
4395                                                 catch (Exception e) {\r
4396                                                         stwin.appendError(FUNCID+"ベース情報の取得に失敗しました.");\r
4397                                                         e.printStackTrace();\r
4398                                                 }\r
4399                                         }\r
4400                                 }\r
4401                                 \r
4402                                 // 共通設定部分の一斉更新\r
4403                                 //setSettingProgPluginAll(env);\r
4404                                 \r
4405                                 if ( env.getUseSyobocal() ) {\r
4406                                         TVProgram syobo = tvprograms.getSyobo();\r
4407                                         if ( syobo != null ) {\r
4408                                                 stwin.appendMessage(FUNCID+"しょぼかるを初期化します.");\r
4409                                                 setSettingProgPlugin(syobo,env);                                // 他からも呼び出される部分だけ分離\r
4410                                                 syobo.setUserAgent("tainavi");\r
4411                                                 syobo.setOptString(null);                                               // フリーオプション初期化\r
4412                                                 syobo.loadCenter(syobo.getSelectedCode(), false);\r
4413                                         }\r
4414                                 }\r
4415                                 \r
4416                                 return null;\r
4417                         }\r
4418                         \r
4419                         @Override\r
4420                         protected void doFinally() {\r
4421                         }\r
4422                 }.execute();\r
4423         }\r
4424         protected void setSettingProgPluginAll(Env nEnv) {\r
4425                 // 通常\r
4426                 setSettingProgPlugin(tvprograms.getTvProgPlugin(null),nEnv);\r
4427                 setSettingProgPlugin(tvprograms.getCsProgPlugin(null),nEnv);\r
4428                 setSettingProgPlugin(tvprograms.getCs2ProgPlugin(null),nEnv);\r
4429                 //setSettingProgPlugin(tvprograms.getRadioProgPlugin(null),nEnv);\r
4430                 setSettingProgPlugin(tvprograms.getSyobo(),nEnv);\r
4431                 \r
4432                 // しょぼかるは特殊\r
4433                 tvprograms.getSyobo().setUserAgent("tainavi");\r
4434                 // 検索結果も特殊\r
4435                 tvprograms.getSearched().setResultBufferMax(nEnv.getSearchResultBufferMax());\r
4436         }\r
4437         protected void setSettingProgPlugin(TVProgram p, Env nEnv) {\r
4438                 if ( p == null ) {\r
4439                         return;\r
4440                 }               \r
4441                 p.setUserAgent(nEnv.getUserAgent());\r
4442                 p.setProgDir(nEnv.getProgDir());\r
4443                 p.setCacheExpired((enableWebAccess)?(nEnv.getCacheTimeLimit()):(0));\r
4444                 p.setContinueTomorrow(nEnv.getContinueTomorrow());\r
4445                 p.setExpandTo8(nEnv.getExpandTo8());\r
4446                 //p.setUseDetailCache(nEnv.getUseDetailCache());\r
4447                 p.setUseDetailCache(false);\r
4448                 p.setSplitEpno(nEnv.getSplitEpno());\r
4449         }\r
4450         \r
4451         /**\r
4452          * staticで持っている共通設定の更新\r
4453          */\r
4454         protected void setSettingProgPluginCommon(Env nEnv) {\r
4455                 \r
4456                 if ( nEnv.getUseProxy() && (nEnv.getProxyAddr().length() > 0 && nEnv.getProxyPort().length() > 0) ) {\r
4457                         stwin.appendMessage("+Web番組表へのアクセスにProxyが設定されています: "+nEnv.getProxyAddr()+":"+nEnv.getProxyPort());\r
4458                         TVProgramUtils.setProxy(nEnv.getProxyAddr(),nEnv.getProxyPort());\r
4459                 }\r
4460                 else {\r
4461                         TVProgramUtils.setProxy(null,null);\r
4462                 }\r
4463                 \r
4464                 TVProgramUtils.setProgressArea(stwin);\r
4465                 TVProgramUtils.setChConv(chconv);\r
4466         }\r
4467         \r
4468         //\r
4469         private void initMpList() {\r
4470                 //mpList = new MarkedProgramList();                     // 検索結果リスト\r
4471                 mpList.setHistoryOnlyUpdateOnce(env.getHistoryOnlyUpdateOnce());\r
4472                 mpList.setShowOnlyNonrepeated(env.getShowOnlyNonrepeated());\r
4473         }\r
4474         \r
4475         // L&FとFontを設定\r
4476         private void initLookAndFeelAndFont() {\r
4477 \r
4478                 try {\r
4479                         {\r
4480                                 vwlaf = new VWLookAndFeel();\r
4481                                 \r
4482                                 String lafname = vwlaf.update(env.getLookAndFeel());\r
4483                                 if ( lafname != null && ! lafname.equals(env.getLookAndFeel())) {\r
4484                                         env.setLookAndFeel(lafname);\r
4485                                 }\r
4486                                 \r
4487                                 if ( CommonUtils.isMac() ) {\r
4488                                         UIManager.getDefaults().put("Table.gridColor", new Color(128,128,128));\r
4489                                         //UIManager.getDefaults().put("Table.selectionBackground", new Color(182,207,229));\r
4490                                         //UIManager.getDefaults().put("Table.selectionForeground", new Color(0,0,0));\r
4491                                 }\r
4492                         }\r
4493                         \r
4494                         {\r
4495                                 vwfont = new VWFont();\r
4496                                 \r
4497                                 String fname = vwfont.update(env.getFontName(),env.getFontSize());\r
4498                                 if ( fname != null && ! fname.equals(env.getFontName())) {\r
4499                                         env.setFontName(fname);\r
4500                                 }\r
4501                         }\r
4502                 }\r
4503                 catch ( Exception e ) {\r
4504                         // 落ちられると困るからトラップしておこうぜ\r
4505                         e.printStackTrace();\r
4506                 }\r
4507         }\r
4508         \r
4509         // L&FやFontを変えたらコンポーネントに通知が必要\r
4510         protected void updateComponentTreeUI() {\r
4511                 try {\r
4512                         SwingUtilities.updateComponentTreeUI(this);\r
4513                         SwingUtilities.updateComponentTreeUI(stwin);\r
4514                         SwingUtilities.updateComponentTreeUI(mwin);\r
4515                         SwingUtilities.updateComponentTreeUI(pcwin);\r
4516                         SwingUtilities.updateComponentTreeUI(rdialog);\r
4517                         SwingUtilities.updateComponentTreeUI(ccwin);\r
4518                 }\r
4519                 catch ( Exception e ) {\r
4520                         // 落ちられると困るからトラップしておこうぜ\r
4521                         e.printStackTrace();\r
4522                 }\r
4523         }\r
4524 \r
4525         // ツールチップの表示遅延時間を設定する\r
4526         private void setTooltipDelay() {\r
4527                 ToolTipManager tp = ToolTipManager.sharedInstance();\r
4528                 tp.setInitialDelay(env.getTooltipInitialDelay()*100);\r
4529                 tp.setDismissDelay(env.getTooltipDismissDelay()*100);\r
4530         }\r
4531         \r
4532         /**\r
4533          * \r
4534          * @return true:前回終了時の設定がある場合\r
4535          */\r
4536         private boolean buildMainWindow() {\r
4537                 \r
4538                 // コンポーネント作成\r
4539                 {\r
4540                         // メインウィンドウの作成\r
4541                         mainWindow = new VWMainWindow();\r
4542                 \r
4543                         // 内部クラスのインスタンス生成\r
4544                         toolBar = new VWToolBar();\r
4545                         listed = new VWListedView();\r
4546                         paper = new VWPaperView();\r
4547                         reserved = new VWReserveListView();\r
4548                         recorded = new VWRecordedListView();\r
4549                         autores = new VWAutoReserveListView();\r
4550                         setting = new VWSettingView();\r
4551                         recsetting = new VWRecorderSettingView();\r
4552                         chsetting = new VWChannelSettingView();\r
4553                         chdatsetting = new VWChannelDatSettingView();\r
4554                         chsortsetting = new VWChannelSortView();\r
4555                         chconvsetting = new VWChannelConvertView();\r
4556                 }\r
4557                 \r
4558                 // 初期値\r
4559                 {\r
4560                         // 設定\r
4561                         toolBar.setDebug(env.getDebug());\r
4562                         autores.setDebug(env.getDebug());\r
4563                         rdialog.setDebug(env.getDebug());\r
4564         \r
4565                         // ページャーの設定\r
4566                         toolBar.setPagerItems();\r
4567                 }\r
4568                 \r
4569                 // コンポーネントの組み立て\r
4570                 {\r
4571                         // ツールバーなど\r
4572                         mainWindow.addToolBar(toolBar);\r
4573                         mainWindow.addStatusArea(mwin);\r
4574                         \r
4575                         // タブ群\r
4576                         mainWindow.addTab(listed, MWinTab.LISTED);\r
4577                         mainWindow.addTab(paper, MWinTab.PAPER);\r
4578                         mainWindow.addTab(reserved, MWinTab.RSVED);\r
4579                         mainWindow.addTab(recorded, MWinTab.RECED);\r
4580                         mainWindow.addTab(autores, MWinTab.AUTORES);\r
4581                         mainWindow.addTab(setting, MWinTab.SETTING);\r
4582                         mainWindow.addTab(recsetting, MWinTab.RECSET);\r
4583                         mainWindow.addTab(chsetting, MWinTab.CHSET);\r
4584                         mainWindow.addTab(chsortsetting, MWinTab.CHSORT);\r
4585                         mainWindow.addTab(chconvsetting, MWinTab.CHCONV);\r
4586                         mainWindow.addTab(chdatsetting, MWinTab.CHDAT);\r
4587                 }\r
4588                 \r
4589                 // ステータスエリアを開く\r
4590                 setStatusVisible(bounds.getShowStatus());\r
4591                 \r
4592                 //新聞描画枠のリセット\r
4593                 paper.clearPanel();\r
4594                 paper.buildMainViewByDate();\r
4595                 \r
4596                 return true;\r
4597         }\r
4598         \r
4599         private void ShowInitTab() {\r
4600                 \r
4601                 // いったん無選択状態にしてから\r
4602                 mainWindow.setSelectedTab(null);\r
4603                 \r
4604                 if ( recInfoList.size() <= 0 ) {\r
4605                         // 設定が存在しない場合\r
4606                         mainWindow.setSelectedTab(MWinTab.RECSET);\r
4607                 }\r
4608                 else {\r
4609                         // 設定が存在する場合\r
4610                         MWinTab tab = MWinTab.getAt(bounds.getSelectedTab());\r
4611                         mainWindow.setSelectedTab(tab);\r
4612                 }\r
4613         }\r
4614         \r
4615         //\r
4616         private void setInitBounds() {\r
4617                 // ウィンドウのサイズと表示位置を設定する\r
4618                 Rectangle window = bounds.getWinRectangle();\r
4619                 if (bounds.isLoaded()) {\r
4620                         // 設定ファイルを読み込んであったらそれを設定する\r
4621                         System.out.println(DBGID+"set bounds "+window);\r
4622                         this.setBounds(window.x, window.y, window.width, window.height);\r
4623                 }\r
4624                 else {\r
4625                         // 設定ファイルがなければ自動設定する\r
4626                         Rectangle screen = this.getGraphicsConfiguration().getBounds();\r
4627                         int x = 0;\r
4628                         int w = window.width;\r
4629                         if (window.width > screen.width) {\r
4630                                 x = 0;\r
4631                                 w = screen.width;\r
4632                         }\r
4633                         else {\r
4634                                 x = (screen.width - window.width)/2;\r
4635                         }\r
4636                         int y = 0;\r
4637                         int h = window.height;\r
4638                         if (window.height > screen.height) {\r
4639                                 y = 0;\r
4640                                 h = screen.height;\r
4641                         }\r
4642                         else {\r
4643                                 y = (screen.height - window.height)/2;\r
4644                         }\r
4645                         this.setBounds(x, y, w, h);\r
4646                 }\r
4647         }\r
4648 \r
4649         /**\r
4650          * <P>ステータスエリアを隠す\r
4651          * {@link VWMainWindow#setStatusVisible(boolean)}の置き換え\r
4652          */\r
4653         private void setStatusVisible(boolean b) {\r
4654                 \r
4655                 if (b) {\r
4656                         listed.setDetailVisible(true);\r
4657                         paper.setDetailVisible(true);\r
4658                         MWinSetVisible(true);\r
4659                 }\r
4660                 else {\r
4661                         listed.setDetailVisible(false);\r
4662                         paper.setDetailVisible(false);\r
4663                         MWinSetVisible(false);\r
4664                 }\r
4665         }\r
4666         \r
4667         // フルスクリーンモードをトグル切り替え\r
4668         private Dimension f_dim;\r
4669         private Point f_pnt;\r
4670         private int divloc_l = 0;\r
4671         private int divloc_p = 0;\r
4672         \r
4673         private void setFullScreen(boolean b) {\r
4674                 \r
4675                 if ( b == true ) {\r
4676                         // 枠の撤去\r
4677                         this.dispose();\r
4678                         this.setUndecorated(true);\r
4679                         this.setVisible(true);\r
4680                         \r
4681                         //全画面表示へ\r
4682                         Toolkit tk = getToolkit();\r
4683                         Insets in = tk.getScreenInsets(getGraphicsConfiguration());\r
4684                         Dimension d = tk.getScreenSize();\r
4685                         f_dim = this.getSize();\r
4686                         f_pnt = this.getLocation();\r
4687                         this.setBounds(in.left, in.top, d.width-(in.left+in.right), d.height-(in.top+in.bottom));\r
4688                         \r
4689                         divloc_l = bounds.getTreeWidth();\r
4690                         divloc_p = bounds.getTreeWidthPaper();\r
4691                         \r
4692                         // ツリーを閉じる\r
4693                         paper.setCollapseTree();\r
4694                         listed.setCollapseTree();\r
4695                 }\r
4696                 else {\r
4697                         if ( f_pnt != null && f_dim != null ) { // 起動直後などは値がないですしね\r
4698                                 \r
4699                                 // 枠の復帰\r
4700                                 this.dispose();\r
4701                                 this.setUndecorated(false);\r
4702                                 this.setVisible(true);\r
4703                                 \r
4704                                 //全画面表示終了\r
4705                                 this.setBounds(f_pnt.x, f_pnt.y, f_dim.width, f_dim.height);\r
4706                                 \r
4707                                 bounds.setTreeWidth(divloc_l);\r
4708                                 bounds.setTreeWidthPaper(divloc_p);\r
4709                                 \r
4710                                 // ツリーの幅を元に戻す\r
4711                                 paper.setExpandTree();\r
4712                                 listed.setExpandTree();\r
4713                         }\r
4714                 }\r
4715         }\r
4716         \r
4717         // タイトルバー\r
4718         private void setTitleBar() {\r
4719                 MemoryMXBean mbean = ManagementFactory.getMemoryMXBean();\r
4720                 MemoryUsage heapUsage = mbean.getHeapMemoryUsage();\r
4721                 \r
4722                 this.setTitle(\r
4723                                 String.format(\r
4724                                                 "%s - %s - Memory Usage Max:%dM Committed:%dM Used:%dM - FrameBuffer Status:%s",\r
4725                                                 VersionInfo.getVersion(),\r
4726                                                 CommonUtils.getDateTime(0),\r
4727                                                 heapUsage.getMax()/(1024*1024),\r
4728                                                 heapUsage.getCommitted()/(1024*1024),\r
4729                                                 heapUsage.getUsed()/(1024*1024),\r
4730                                                 (paper!=null)?(paper.getFrameBufferStatus()):("N/A")\r
4731                                 )\r
4732                 );\r
4733         }\r
4734         \r
4735         // 終了処理関連\r
4736         private void ExitOnClose() {\r
4737                 // 座標・サイズ\r
4738                 if ( ! this.toolBar.isFullScreen()) {\r
4739                         Rectangle r = this.getBounds();\r
4740                         bounds.setWinRectangle(r);\r
4741                 }\r
4742                 else {\r
4743                         Rectangle r = new Rectangle();\r
4744                         r.x = this.f_pnt.x;\r
4745                         r.y = this.f_pnt.y;\r
4746                         r.width = this.f_dim.width;\r
4747                         r.height = this.f_dim.height;\r
4748                         bounds.setWinRectangle(r);\r
4749                 }\r
4750                 listed.copyColumnWidth();\r
4751                 reserved.copyColumnWidth();\r
4752                 \r
4753                 bounds.setStatusRows(mwin.getRows());\r
4754 \r
4755                 // 動作状態\r
4756                 bounds.setSelectedTab(mainWindow.getSelectedTab().getIndex());\r
4757                 bounds.setShowSettingTabs(mainWindow.getShowSettingTabs());\r
4758                 bounds.setSelectedRecorderId(toolBar.getSelectedRecorder());\r
4759                 bounds.setShowStatus(toolBar.isStatusShown());\r
4760                 \r
4761                 // 保存する\r
4762                 bounds.save();\r
4763                 \r
4764                 // ツリーの展開状態の保存\r
4765                 listed.saveTreeExpansion();\r
4766                 paper.saveTreeExpansion();\r
4767         }\r
4768         \r
4769 \r
4770         /*******************************************************************************\r
4771          * main()\r
4772          ******************************************************************************/\r
4773         \r
4774         // 初期化が完了したら立てる\r
4775         private static boolean initialized = false;\r
4776         private static Viewer myClass = null;\r
4777         \r
4778         /**\r
4779          * めいーん\r
4780          * @param args\r
4781          * @throws NoSuchAlgorithmException\r
4782          * @version 今まで初期化を行ってからウィンドウを作成していたが<BR>\r
4783          * 途中で例外が起こるとダンマリの上にゾンビになってたりとヒドかったので<BR>\r
4784          * 先にウィンドウを作成してから初期化を行うように変えました\r
4785          * @throws InterruptedException \r
4786          * @throws InvocationTargetException \r
4787          */\r
4788         public static void main(final String[] args) throws NoSuchAlgorithmException, InvocationTargetException, InterruptedException {\r
4789                 \r
4790                 if ( myClass != null ) {\r
4791                         // 既に起動していたらフォアグラウンドにする\r
4792                         SwingUtilities.invokeAndWait(new Runnable() {\r
4793                                 @Override\r
4794                                 public void run() {\r
4795                                         // うーん、いいのかこのコード?\r
4796                                         myClass.setVisible(true);\r
4797                                         myClass.setState(Frame.NORMAL);\r
4798                                 }\r
4799                         });\r
4800                         return;\r
4801                 }\r
4802                 \r
4803                 SwingUtilities.invokeLater(new Runnable() {\r
4804                         public void run() {\r
4805                                 \r
4806                                 final Viewer thisClass = myClass = new Viewer(args);\r
4807                                 \r
4808                                 thisClass.addComponentListener(new ComponentAdapter() {\r
4809                                         @Override\r
4810                                         public void componentShown(ComponentEvent e) {\r
4811                                                 \r
4812                                                 // 一回実行したらもういらないよ\r
4813                                                 thisClass.removeComponentListener(this);\r
4814                                                 \r
4815                                                 // 初期化するよ\r
4816                                                 thisClass.initialize(args);\r
4817                                                 \r
4818                                         }\r
4819                                 });\r
4820                                 \r
4821                                 thisClass.setVisible(true);\r
4822                         }\r
4823                 });\r
4824         }\r
4825 \r
4826         \r
4827         \r
4828         /*******************************************************************************\r
4829          * コンストラクタ\r
4830          ******************************************************************************/\r
4831 \r
4832         /**\r
4833          * デフォルトコンストラクタ\r
4834          */\r
4835         public Viewer(final String[] args) {\r
4836                 \r
4837                 super();\r
4838                 \r
4839                 env.loadText();\r
4840                 bounds.loadText();\r
4841                 \r
4842                 \r
4843                 // 初期化が終わるまでは閉じられないよ → どうせステータスウィンドウにブロックされて操作できない\r
4844                 //setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);\r
4845                 //setResizable(false);\r
4846                 \r
4847                 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);\r
4848                 \r
4849                 setTitleBar();\r
4850                 \r
4851                 try {\r
4852                         Image image = ImageIO.read(new File(ICONFILE_TAINAVI));\r
4853                         setIconImage(image);\r
4854                 }\r
4855                 catch (IOException e) {\r
4856                         StdAppendError("[ERROR] アイコンが設定できない: "+e.toString());\r
4857                 }\r
4858                 \r
4859                 JLabel jLabel_splash_img = new JLabel(new ImageIcon("splash.gif"));\r
4860                 jLabel_splash_img.setPreferredSize(new Dimension(400,300));\r
4861                 //getContentPane().setLayout(new BorderLayout());\r
4862                 getContentPane().add(jLabel_splash_img, BorderLayout.CENTER);\r
4863                 pack();\r
4864                 \r
4865                 setLocationRelativeTo(null);    // 画面の真ん中に\r
4866                 \r
4867                 // SwingLocker共有設定\r
4868                 SwingLocker.setOwner(this);\r
4869                 \r
4870                 // とりあえずルックアンドフィールはリセットしておかないとだめっぽいよ\r
4871                 initLookAndFeelAndFont();\r
4872                 updateComponentTreeUI();\r
4873         }\r
4874         \r
4875         // 初期化をバックグラウンドで行う\r
4876         private void initialize(final String[] args) {\r
4877                 \r
4878                 StWinClear();\r
4879                 \r
4880                 // 初期化処理はバックグラウンドで行う\r
4881                 new SwingBackgroundWorker(false) {\r
4882                         \r
4883                         @Override\r
4884                         protected Object doWorks() throws Exception {\r
4885                                 \r
4886                                 TatCount tc = new TatCount();\r
4887                                 \r
4888                                 // 初期化処理\r
4889                                 _initialize(args);\r
4890                                 \r
4891                                 // 終わったら閉じられるようにするよ\r
4892                                 //setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);\r
4893                                 //setResizable(true);\r
4894 \r
4895                                 stwin.append("");\r
4896                                 stwin.appendMessage(String.format("【タイニー番組ナビゲータが起動しました】 所要時間: %.2f秒",tc.end()));\r
4897                                 return null;\r
4898                         }\r
4899                         \r
4900                         @Override\r
4901                         protected void doFinally() {\r
4902                                 if ( ! initialized ) System.err.println("[ERROR][鯛ナビ] 【致命的エラー】 初期化処理を行っていたスレッドが異常終了しました。");\r
4903                                 stwin.setClosingEnabled(false);\r
4904                                 CommonUtils.milSleep(OPENING_WIAT);\r
4905                                 StWinSetVisible(false);\r
4906                         }\r
4907                 }.execute();\r
4908                 \r
4909                 StWinSetLocationUnder(this);\r
4910                 StWinSetVisible(true);\r
4911         }\r
4912         \r
4913         // 初期化の本体\r
4914         private void _initialize(final String[] args) {\r
4915                 \r
4916                 // コマンドライン引数を処理する\r
4917                 procArgs(args);\r
4918                 \r
4919                 // ログ出力を設定する(Windowsの場合は文字コードをMS932にする) →DOS窓を殺したので終了\r
4920                 System.setOut(new DebugPrintStream(System.out,LOG_FILE,logging));\r
4921                 System.setErr(new DebugPrintStream(System.err,LOG_FILE,logging));\r
4922                 \r
4923                 // 起動メッセージ\r
4924                 StdAppendMessage("================================================================================");\r
4925                 StdAppendMessage("以下のメッセージは無視してください(原因調査中)");\r
4926                 StdAppendMessage("Exception occurred during event dispatching:");\r
4927                 StdAppendMessage("      java.lang.NullPointerException");\r
4928                 StdAppendMessage("              at javax.swing.plaf.basic.BasicScrollBarUI.layoutHScrollbar(Unknown Source)");\r
4929                 StdAppendMessage("              (以下略)");\r
4930                 StdAppendMessage("================================================================================");\r
4931                 stwin.appendMessage(CommonUtils.getDateTime(0));\r
4932                 stwin.appendMessage(String.format("タイニー番組ナビゲータが起動を開始しました(VersionInfo:%s on %s)",VersionInfo.getVersion(),VersionInfo.getEnvironment()));\r
4933                 \r
4934                 // 起動時にアップデートを確認する\r
4935                 chkVerUp();\r
4936                 \r
4937                 try {\r
4938                         // メインの環境設定ファイルを読み込む\r
4939                         loadEnvfile();\r
4940                         \r
4941                         // 二重起動防止\r
4942                         chkDualBoot();\r
4943                         \r
4944                         // その他の環境設定ファイルを読み込む\r
4945                         procEnvs();\r
4946                         \r
4947                         if ( onlyLoadProgram ) {\r
4948                                 if ( ! isOLPExpired(4) ) {\r
4949                                         CommonUtils.milSleep(3000);\r
4950                                         System.exit(1);\r
4951                                 }\r
4952                                 // プラグインのロード\r
4953                                 loadProgPlugins();\r
4954                                 // プラグインの初期化\r
4955                                 setSelectedProgPlugin();\r
4956                                 initProgPluginAll();\r
4957                                 // 検索結果リストの初期化(loadTVProgram()中で使うので)\r
4958                                 initMpList();\r
4959                                 // データのロード\r
4960                                 loadTVProgram(true,LoadFor.ALL);\r
4961                                 stwin.appendMessage("番組表を取得したので終了します");\r
4962                                 CommonUtils.milSleep(3000);\r
4963                                 System.exit(1);\r
4964                         }\r
4965                         \r
4966                         // プラグインのロード\r
4967                         loadProgPlugins();\r
4968                         loadRecPlugins();\r
4969 \r
4970                         // プラグインの初期化\r
4971                         setSelectedProgPlugin();\r
4972                         initProgPluginAll();\r
4973 \r
4974                         initRecPluginAll();\r
4975 \r
4976                         // WOL指定があったなら\r
4977                         if ( runRecWakeup ) {\r
4978                                 doRecWakeup();\r
4979                         }\r
4980 \r
4981                         // 検索結果リストの初期化(loadTVProgram()中で使うので)\r
4982                         initMpList();\r
4983                         \r
4984                         // データのロード\r
4985                         loadTVProgram(false,LoadFor.ALL);\r
4986                         \r
4987                         // 放送局の並び順もロード\r
4988                         chsort.load();\r
4989                         \r
4990                         loadRdReservesAll(runRecLoad, null);\r
4991                 }\r
4992                 catch ( Exception e ) {\r
4993                         System.err.println("【致命的エラー】設定の初期化に失敗しました");\r
4994                         e.printStackTrace();\r
4995                         System.exit(1);\r
4996                 }\r
4997                 \r
4998                 // 背景色設定ダイアログにフォント名の一覧を設定する\r
4999                 pcwin.setFontList(vwfont);\r
5000                 \r
5001                 // (新聞形式の)ツールチップの表示時間を変更する\r
5002                 setTooltipDelay();\r
5003 \r
5004                 // ウィンドウを構築\r
5005                 try {\r
5006                         buildMainWindow();\r
5007                 }\r
5008                 catch ( Exception e ) {\r
5009                         System.err.println("【致命的エラー】ウィンドウの構築に失敗しました");\r
5010                         e.printStackTrace();\r
5011                         System.exit(1);\r
5012                 }\r
5013                 \r
5014                 // ★★★★★★★★★★\r
5015                 //int x = 2/0;  // サブスレッドの突然死のトラップを確認するためのコード\r
5016                 // ★★★★★★★★★★\r
5017                 \r
5018                 // トレイアイコンを作る\r
5019                 getTrayIcon();\r
5020                 setTrayIconVisible(env.getShowSysTray());\r
5021                 \r
5022                 // ウィンドウを閉じたときの処理\r
5023                 setXButtonAction(env.getShowSysTray() && env.getHideToTray());\r
5024                 \r
5025                 // ウィンドウ操作のリスナー登録\r
5026                 this.addWindowListener(new WindowAdapter() {\r
5027                         // ウィンドウを最小化したときの処理\r
5028                         @Override\r
5029                         public void windowIconified(WindowEvent e) {\r
5030                                 HideToTray();\r
5031                         }\r
5032                 \r
5033                         // ウィンドウを閉じたときの処理\r
5034                         @Override\r
5035                         public void windowClosing(WindowEvent e) {\r
5036                                 ExitOnClose();\r
5037                         }\r
5038                 });\r
5039                 \r
5040                 // 初回起動時はレコーダの登録を促す\r
5041                 if ( recorders.size() == 0 ) {\r
5042                         Container cp = getContentPane();\r
5043                         JOptionPane.showMessageDialog(cp, "レコーダが登録されていません。\n最初に登録を行ってください。\n番組表だけを使いたい場合は、\nNULLプラグインを登録してください。");\r
5044                 }\r
5045                 \r
5046                 // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
5047                 // イベントリスナーの登録 \r
5048                 // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
5049                 \r
5050                 // [ツールバー/共通] レコーダ情報変更\r
5051                 toolBar.addHDDRecorderChangeListener(autores);\r
5052                 \r
5053                 // [ツールバー/レコーダ選択]\r
5054                 toolBar.addHDDRecorderSelectionListener(this);          // 新聞形式\r
5055                 toolBar.addHDDRecorderSelectionListener(paper);         // 新聞形式\r
5056                 toolBar.addHDDRecorderSelectionListener(autores);       // 自動予約一覧\r
5057                 toolBar.addHDDRecorderSelectionListener(rdialog);       // 予約ダイアログ\r
5058 \r
5059                 // [ツールバー/キーワード入力] キャンセル動作\r
5060                 toolBar.addKeywordCancelListener(this);\r
5061                 \r
5062                 // [タイマー] タイトルバー更新/リスト形式の現在時刻ノード/新聞形式の現在時刻ノード\r
5063                 timer_now.addTickTimerRiseListener(this);\r
5064                 timer_now.addTickTimerRiseListener(listed);\r
5065                 timer_now.addTickTimerRiseListener(paper);\r
5066 \r
5067                 // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
5068                 // [Fire!] レコーダ選択\r
5069                 // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
5070                 toolBar.setSelectedRecorder(bounds.getSelectedRecorderId());\r
5071                 \r
5072                 // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
5073                 // [Fire!] サイドツリーのデフォルトを選択することで番組情報の描画を開始する\r
5074                 // ※ここ以前だとぬぽとかOOBとか出るかもよ!\r
5075                 // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
5076                 paper.selectTreeDefault();\r
5077                 listed.selectTreeDefault();\r
5078                 \r
5079                 // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
5080                 // メインウィンドウをスプラッシュからコンポーネントに入れ替える\r
5081                 // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
5082                 this.setVisible(false);\r
5083                 this.setContentPane(mainWindow);\r
5084                 setInitBounds();\r
5085                 this.setVisible(true);\r
5086                 \r
5087                 setTitleBar();  // タイトルバー更新\r
5088                 \r
5089                 ShowInitTab();  // 前回開いていたタブを開く\r
5090                 \r
5091                 // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
5092                 // タイマーを起動する\r
5093                 // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
5094                 timer_now.start();\r
5095                 \r
5096                 // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
5097                 // 初期化終了\r
5098                 // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
5099                 mwin.appendMessage(String.format("タイニー番組ナビゲータが起動しました (VersionInfo:%s on %s)",VersionInfo.getVersion(),VersionInfo.getEnvironment()));\r
5100                 initialized = true;\r
5101         }\r
5102 }\r