OSDN Git Service

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