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
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
66 import tainavi.HDDRecorder.RecType;
\r
67 import tainavi.TVProgram.ProgFlags;
\r
68 import tainavi.TVProgram.ProgGenre;
\r
69 import tainavi.TVProgram.ProgOption;
\r
70 import tainavi.TVProgram.ProgSubgenre;
\r
71 import tainavi.TVProgram.ProgSubtype;
\r
72 import tainavi.TVProgram.ProgType;
\r
73 import tainavi.VWMainWindow.MWinTab;
\r
74 import tainavi.VWUpdate.UpdateResult;
\r
75 import tainavi.plugintv.Syobocal;
\r
81 public class Viewer extends JFrame implements ChangeListener,TickTimerListener,HDDRecorderListener,CancelListener {
\r
83 private static final long serialVersionUID = 1L;
\r
90 private void StdAppendMessage(String message) { System.out.println(message); }
\r
91 private void StdAppendError(String message) { System.err.println(message); }
\r
93 private void MWinSetVisible(boolean b) { mwin.setVisible(b); }
\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
100 private void ringBeep() { if (env!=null && ! env.getDisableBeep()) { Toolkit.getDefaultToolkit().beep(); if ( env.getDebug() ) CommonUtils.printStackTrace(); } }
\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
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
124 private final RecorderInfoList recInfoList = new RecorderInfoList(); // レコーダ一覧の設定
\r
126 private final HDDRecorderList recPlugins = new HDDRecorderList(); // レコーダプラグイン(テンプレート)
\r
127 private final HDDRecorderList recorders = new HDDRecorderList(); // レコーダプラグイン(実際に利用するもの)
\r
129 private final TVProgramList progPlugins = new TVProgramList(); // Web番組表プラグイン(テンプレート)
\r
130 private final TVProgramList tvprograms = new TVProgramList(); // Web番組表プラグイン(実際に利用するもの)
\r
132 private final TickTimer timer_now = new TickTimer(); // 毎分00秒に起動して処理をキックするタイマー
\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
144 /*******************************************************************************
\r
146 ******************************************************************************/
\r
148 public static final String LOG_FILE = "log.txt"; // ログファイル名
\r
149 public static final String HISTORY_FILE = "05_history.txt"; // 更新履歴だよ
\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
154 public static final int TIMEBAR_START = 5; // 新聞形式の開始時刻
\r
155 private static final int OPENING_WIAT = 500; // まあ起動時しか使わないんですけども
\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
162 * [メモ] enumのtoString()をoverrideすると、シリアライズの際とても困るのでやらないこと
\r
166 * Web番組表のどれとどれを読めばいいのか
\r
168 public static enum LoadFor {
\r
169 TERRA ("地上波&BSのみ取得"),
\r
171 CSo1 ("CS[プライマリ]のみ取得"),
\r
172 CSo2 ("CS[セカンダリ]のみ取得"),
\r
173 CSwSD ("CSのみ取得(取得後シャットダウン)"),
\r
175 SYOBO ("しょぼかるのみ取得"),
\r
178 private String name;
\r
180 private LoadFor(String name) {
\r
184 public String getName() {
\r
188 public static LoadFor get(String s) {
\r
189 for ( LoadFor lf : LoadFor.values() ) {
\r
190 if ( lf.name.equals(s) ) {
\r
199 * レコーダ情報のどれとどれを読めばいいのか
\r
201 public static enum LoadRsvedFor {
\r
202 // SETTING ( "設定情報のみ取得(future use.)" ),
\r
203 DETAILS ( "予約一覧+録画詳細のみ取得" ),
\r
204 RECORDED ( "録画結果一覧のみ取得" ),
\r
205 AUTORESERVE ( "自動予約一覧のみ取得" ),
\r
208 private String name;
\r
210 private LoadRsvedFor(String name) {
\r
214 public String getName() {
\r
218 public static LoadRsvedFor get(String s) {
\r
219 for ( LoadRsvedFor lrf : LoadRsvedFor.values() ) {
\r
220 if ( lrf.name.equals(s) ) {
\r
230 * @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
242 GENRE ("ジャンル", 85),
\r
243 SITEM ("検索アイテム名", 100),
\r
244 STAR ("お気に入り度", 100),
\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
254 @SuppressWarnings("unused")
\r
255 private String name;
\r
256 private int iniWidth;
\r
258 private ListedColumn(String name, int iniWidth) {
\r
260 this.iniWidth = iniWidth;
\r
265 public String toString() {
\r
270 public int getIniWidth() {
\r
274 public int getColumn() {
\r
281 * @deprecated しっぱいした 半年くらいしたら削除する
\r
284 public static enum RsvedColumn {
\r
285 PATTERN ("パタン", 110),
\r
286 DUPMARK ("重複", 35),
\r
289 NEXTSTART ("次回実行予定", 150),
\r
292 ENCODER ("エンコーダ", 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
302 @SuppressWarnings("unused")
\r
303 private String name;
\r
304 private int iniWidth;
\r
306 private RsvedColumn(String name, int iniWidth) {
\r
308 this.iniWidth = iniWidth;
\r
313 public String toString() {
\r
318 public int getIniWidth() {
\r
322 public int getColumn() {
\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
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
357 private TrayIcon trayicon = null;
\r
361 /*******************************************************************************
\r
362 * タブやダイアログのインスタンス作成用クラス定義
\r
363 ******************************************************************************/
\r
368 private class VWListedView extends AbsListedView {
\r
370 private static final long serialVersionUID = 1L;
\r
374 protected Env getEnv() { return env; }
\r
376 protected Bounds getBoundsEnv() { return bounds; }
\r
378 protected ChannelSort getChannelSort() { return chsort; }
\r
381 protected MarkedProgramList getMarkedProgramList() { return mpList; }
\r
383 protected TraceProgram getTraceProgram() { return trKeys; }
\r
385 protected SearchProgram getSearchProgram() { return srKeys; }
\r
387 protected SearchGroupList getSearchGroupList() { return srGrps; }
\r
389 protected ExtProgram getExtProgram() { return extKeys; }
\r
392 protected TVProgramList getTVProgramList() { return tvprograms; }
\r
394 protected HDDRecorderList getRecorderList() { return recorders; }
\r
398 protected StatusWindow getStWin() { return stwin; }
\r
400 protected StatusTextArea getMWin() { return mwin; }
\r
404 protected AbsReserveDialog getReserveDialog() { return rdialog; }
\r
406 protected Component getParentComponent() { return Viewer.this; }
\r
409 protected void ringBeep() { Viewer.this.ringBeep(); }
\r
412 * AbsListedView内でのイベントから呼び出されるメソッド群
\r
416 protected void onShown() {
\r
417 // キーワード登録ボタンはリスト形式のみ
\r
418 toolBar.setAddkeywordEnabled(true);
\r
420 toolBar.setBatchReservationEnabled(true);
\r
422 toolBar.setSnapShotEnabled(true);
\r
423 // 新聞形式以外ではマッチ枠を無効にする
\r
424 toolBar.setBorderToggleEnabled(true, bounds.getShowReservedBackground());
\r
428 protected void onHidden() {
\r
429 // キーワード登録ボタンはリスト形式のみ
\r
430 toolBar.setAddkeywordEnabled(false);
\r
432 toolBar.setBatchReservationEnabled(false);
\r
434 toolBar.setSnapShotEnabled(false);
\r
435 // 新聞形式以外ではマッチ枠を無効にする
\r
436 toolBar.setBorderToggleEnabled(false, bounds.getShowReservedBackground());
\r
440 protected void showPopupForTraceProgram(
\r
441 final JComponent comp,
\r
442 final ProgDetailList tvd, final String keyword, final int threshold,
\r
443 final int x, final int y) {
\r
445 timer_now.pause(); // 停止
\r
447 Viewer.this.showPopupForTraceProgram(comp, tvd, keyword, threshold, x, y, null);
\r
449 timer_now.start(); // 再開
\r
453 protected void updateReserveDisplay(String chname) {
\r
455 paper.updateReserveBorder(chname);
\r
456 reserved.redrawReservedList();
\r
461 protected void updateBangumiColumns() {
\r
463 paper.updateBangumiColumns();
\r
468 protected void clearPaper() {
\r
470 paper.clearPanel();
\r
475 protected void previewKeywordSearch(SearchKey search) {
\r
476 //timer_now.pause();
\r
477 if (search.alTarget.size() > 0) {
\r
478 mainWindow.setSelectedTab(MWinTab.LISTED);
\r
479 listed.redrawListByPreview(search);
\r
481 //timer_now.start();
\r
485 protected void jumpToPaper(String Center, String StartDateTime) {
\r
486 //timer_now.pause();
\r
487 paper.jumpToBangumi(Center,StartDateTime);
\r
488 //timer_now.start();
\r
492 protected boolean addToPickup(ProgDetailList tvd) { return Viewer.this.addToPickup(tvd); }
\r
495 protected boolean isTabSelected(MWinTab tab) { return mainWindow.isTabSelected(tab); }
\r
497 protected void setSelectedTab(MWinTab tab) { mainWindow.setSelectedTab(tab); }
\r
500 protected String getSelectedRecorderOnToolbar() { return toolBar.getSelectedRecorder(); }
\r
502 protected boolean isFullScreen() { return toolBar.isFullScreen(); }
\r
504 protected void setPagerEnabled(boolean b) { toolBar.setPagerEnabled(b); }
\r
506 protected int getPagerCount() { return toolBar.getPagerCount(); }
\r
508 protected int getSelectedPagerIndex() { return toolBar.getSelectedPagerIndex(); }
\r
511 protected void setDividerEnvs(int loc) {
\r
512 if ( ! toolBar.isFullScreen() && mainWindow.isTabSelected(MWinTab.LISTED) ) {
\r
513 if (env.getSyncTreeWidth()) {
\r
514 bounds.setTreeWidth(loc);
\r
515 bounds.setTreeWidthPaper(loc);
\r
518 bounds.setTreeWidth(loc);
\r
529 private class VWPaperView extends AbsPaperView {
\r
531 private static final long serialVersionUID = 1L;
\r
535 protected Env getEnv() { return env; }
\r
537 protected Bounds getBoundsEnv() { return bounds; }
\r
539 protected PaperColorsMap getPaperColorMap() { return pColors; }
\r
541 protected ChannelSort getChannelSort() { return chsort; }
\r
544 protected TVProgramList getTVProgramList() { return tvprograms; }
\r
546 protected HDDRecorderList getRecorderList() { return recorders; }
\r
550 protected StatusWindow getStWin() { return stwin; }
\r
552 protected StatusTextArea getMWin() { return mwin; }
\r
556 protected AbsReserveDialog getReserveDialog() { return rdialog; }
\r
558 protected Component getParentComponent() { return Viewer.this; }
\r
561 protected void ringBeep() { Viewer.this.ringBeep(); }
\r
564 * AbsPaperView内でのイベントから呼び出されるメソッド群
\r
568 protected void onShown() {
\r
569 // ページャーコンボボックスを有効にする(状況次第で有効にならない場合もある)(ツリーの選択次第で変わるのでもどし)
\r
570 //toolBar.setPagerEnabled(true);
\r
572 toolBar.setSnapShotEnabled(true);
\r
574 toolBar.setPaperColorDialogEnabled(true);
\r
576 toolBar.setBorderToggleEnabled(true, bounds.getShowMatchedBorder());
\r
580 protected void onHidden() {
\r
581 // 新聞形式以外ではページャーコンボボックスを無効にする(ツリーの選択次第で変わるのでもどし)
\r
582 //toolBar.setPagerEnabled(false);
\r
583 // 新聞形式以外ではスナップショットを無効にする
\r
584 toolBar.setSnapShotEnabled(false);
\r
585 // 新聞形式以外ではジャンル別背景色を無効にする
\r
586 toolBar.setPaperColorDialogEnabled(false);
\r
587 // 新聞形式以外ではマッチ枠を無効にする
\r
588 toolBar.setBorderToggleEnabled(false, bounds.getShowMatchedBorder());
\r
592 protected void showPopupForTraceProgram(
\r
593 final JComponent comp,
\r
594 final ProgDetailList tvd, final String keyword, final int threshold,
\r
595 final int x, final int y, final String clickedDateTime) {
\r
597 timer_now.pause(); // 停止
\r
599 Viewer.this.showPopupForTraceProgram(comp, tvd, keyword, threshold, x, y, clickedDateTime);
\r
601 timer_now.start(); // 再開
\r
605 protected void updateReserveDisplay() {
\r
607 listed.updateReserveMark();
\r
608 reserved.redrawReservedList();
\r
613 protected void addToPickup(ProgDetailList tvd) { Viewer.this.addToPickup(tvd); }
\r
616 protected boolean isTabSelected(MWinTab tab) { return mainWindow.isTabSelected(tab); }
\r
618 protected void setSelectedTab(MWinTab tab) { mainWindow.setSelectedTab(tab); }
\r
621 protected boolean isFullScreen() { return toolBar.isFullScreen(); }
\r
623 protected void setSelectedPagerIndex(int idx) {
\r
624 toolBar.setSelectedPagerIndex(idx);
\r
627 protected void setPagerEnabled(boolean b) { toolBar.setPagerEnabled(b); }
\r
629 protected int getPagerCount() { return toolBar.getPagerCount(); }
\r
631 protected int getSelectedPagerIndex() { return toolBar.getSelectedPagerIndex(); }
\r
633 protected void setPagerItems(TVProgramIterator pli, int curindex) {
\r
634 toolBar.setPagerItems(pli,curindex);
\r
638 protected String getExtensionMark(ProgDetailList tvd) { return markchar.getExtensionMark(tvd); }
\r
640 protected String getOptionMark(ProgDetailList tvd) { return markchar.getOptionMark(tvd)+markchar.getNewLastMark(tvd); }
\r
642 protected String getPostfixMark(ProgDetailList tvd) { return markchar.getPostfixMark(tvd); }
\r
645 protected void setDividerEnvs(int loc) {
\r
646 if ( ! toolBar.isFullScreen() && mainWindow.isTabSelected(MWinTab.PAPER) ) {
\r
647 if (env.getSyncTreeWidth()) {
\r
648 bounds.setTreeWidth(loc);
\r
649 bounds.setTreeWidthPaper(loc);
\r
652 bounds.setTreeWidthPaper(loc);
\r
665 private class VWReserveListView extends AbsReserveListView {
\r
667 private static final long serialVersionUID = 1L;
\r
671 protected Env getEnv() { return env; }
\r
673 protected Bounds getBoundsEnv() { return bounds; }
\r
676 protected HDDRecorderList getRecorderList() { return recorders; }
\r
682 protected AbsReserveDialog getReserveDialog() { return rdialog; }
\r
684 protected Component getParentComponent() { return Viewer.this; }
\r
687 protected void ringBeep() { Viewer.this.ringBeep(); }
\r
690 * AbsReserveListView内でのイベントから呼び出されるメソッド群
\r
694 protected void updateReserveDisplay(String chname) {
\r
696 listed.updateReserveMark();
\r
697 paper.updateReserveBorder(chname);
\r
702 protected boolean doExecOnOff(boolean fexec, String title, String chnam, String rsvId, String recId) {
\r
703 return Viewer.this.doExecOnOff(fexec, title, chnam, rsvId, recId);
\r
707 protected JMenuItem getExecOnOffMenuItem(boolean fexec,
\r
708 String start, String title, String chnam, String rsvId, String recId) {
\r
710 return Viewer.this.getExecOnOffMenuItem(fexec, start, title, chnam, rsvId, recId, 0);
\r
714 protected JMenuItem getRemoveRsvMenuItem(
\r
715 String start, String title, String chnam, String rsvId, String recId) {
\r
717 return Viewer.this.getRemoveRsvMenuItem(start, title, chnam, rsvId, recId, 0);
\r
721 protected JMenuItem getJumpMenuItem(String title, String chnam,
\r
724 return Viewer.this.getJumpMenuItem(title, chnam, startDT);
\r
728 protected JMenuItem getJumpToLastWeekMenuItem(String title,
\r
729 String chnam, String startDT) {
\r
731 return Viewer.this.getJumpToLastWeekMenuItem(title, chnam, startDT);
\r
735 protected String getSelectedRecorderOnToolbar() { return toolBar.getSelectedRecorder(); }
\r
744 private class VWRecordedListView extends AbsRecordedListView {
\r
746 private static final long serialVersionUID = 1L;
\r
750 protected Env getEnv() { return env; }
\r
752 protected Bounds getBoundsEnv() { return bounds; }
\r
755 protected HDDRecorderList getRecorderList() { return recorders; }
\r
761 protected Component getParentComponent() { return Viewer.this; }
\r
764 protected void ringBeep() { Viewer.this.ringBeep(); }
\r
767 * AbsReserveListView内でのイベントから呼び出されるメソッド群
\r
771 protected String getSelectedRecorderOnToolbar() { return toolBar.getSelectedRecorder(); }
\r
780 private class VWAutoReserveListView extends AbsAutoReserveListView {
\r
782 private static final long serialVersionUID = 1L;
\r
786 protected Env getEnv() { return env; }
\r
788 protected Bounds getBoundsEnv() { return bounds; }
\r
795 private class VWSettingView extends AbsSettingView {
\r
797 private static final long serialVersionUID = 1L;
\r
801 protected Env getEnv() { return env; }
\r
803 protected ClipboardInfoList getCbItemEnv() { return cbitems; }
\r
805 protected VWLookAndFeel getLAFEnv() { return vwlaf; }
\r
807 protected VWFont getFontEnv() { return vwfont; }
\r
811 protected StatusWindow getStWin() { return stwin; }
\r
813 protected StatusTextArea getMWin() { return mwin; }
\r
817 protected Component getParentComponent() { return Viewer.this; }
\r
819 protected VWColorChooserDialog getCcWin() { return ccwin; }
\r
822 * AbsSettingView内でのイベントから呼び出されるメソッド群
\r
826 protected void lafChanged(String lafname) {
\r
827 vwlaf.update(lafname);
\r
828 Viewer.this.updateComponentTreeUI();
\r
829 StdAppendMessage("Set LookAndFeel="+lafname);
\r
833 protected void fontChanged(String fn, int fontSize) {
\r
834 vwfont.update(fn, fontSize);
\r
835 Viewer.this.updateComponentTreeUI();
\r
836 StdAppendMessage("システムのフォントを変更しました: "+fn+", size="+fontSize);
\r
840 protected void setEnv(final boolean reload_prog) {
\r
842 //listed.pauseTimer();
\r
845 Viewer.this.setEnv(reload_prog);
\r
853 * @see AbsRecorderSettingView
\r
855 private class VWRecorderSettingView extends AbsRecorderSettingView {
\r
857 private static final long serialVersionUID = 1L;
\r
861 protected Env getEnv() { return env; }
\r
863 protected RecorderInfoList getRecInfos() { return recInfoList; }
\r
865 protected HDDRecorderList getRecPlugins() { return recPlugins; }
\r
869 protected VWStatusWindow getStWin() { return stwin; }
\r
871 protected StatusTextArea getMWin() { return mwin; }
\r
875 protected Component getParentComponent() { return Viewer.this; }
\r
877 protected VWColorChooserDialog getCcWin() { return ccwin; }
\r
880 protected void ringBeep() { Viewer.this.ringBeep(); }
\r
883 * AbsRecorderSettingView内でのイベントから呼び出されるメソッド群
\r
887 protected void setRecInfos() {
\r
892 recInfoList.save();
\r
894 // レコーダプラグインのリフレッシュ
\r
895 initRecPluginAll();
\r
898 toolBar.updateRecorderComboBox();
\r
901 loadRdReservesAll(false, null); // toolBarの内容がリセットされているので recId = null で
\r
904 this.redrawRecorderEncoderEntry();
\r
906 // レコーダ一覧をCHコード設定のコンボボックスに設定
\r
907 chdatsetting.updateRecorderComboBox();
\r
909 // Web番組表の再構築(予約マークのリフレッシュ)
\r
910 paper.updateReserveBorder(null);
\r
911 listed.updateReserveMark();
\r
922 private class VWChannelSettingView extends AbsChannelSettingView {
\r
924 private static final long serialVersionUID = 1L;
\r
928 protected Env getEnv() { return Viewer.this.env; }
\r
930 protected TVProgramList getProgPlugins() { return progPlugins; }
\r
934 protected StatusWindow getStWin() { return stwin; }
\r
936 protected StatusTextArea getMWin() { return mwin; }
\r
940 protected Component getParentComponent() { return Viewer.this; }
\r
942 protected VWColorChooserDialog getCcWin() { return ccwin; }
\r
945 protected void ringBeep() {
\r
946 Viewer.this.ringBeep();
\r
949 protected void updateProgPlugin() {
\r
953 // 設定を保存(プラグイン内部の設定はChannelSettingPanel内で実施)
\r
956 // Web番組表プラグインのリフレッシュ
\r
957 setSelectedProgPlugin();
\r
958 initProgPluginAll();
\r
961 chsortsetting.updateChannelSortTable();
\r
963 // CHコンバート設定をリフレッシュ
\r
964 chconvsetting.updateChannelConvertTable();
\r
967 chdatsetting.updateChannelDatTable();
\r
970 loadTVProgram(false,LoadFor.ALL); // 部品呼び出し
\r
973 toolBar.setPagerItems();
\r
976 paper.clearPanel();
\r
977 paper.buildMainViewByDate();
\r
980 paper.redrawTreeByCenter();
\r
982 listed.redrawTreeByCenter();
\r
985 paper.reselectTree();
\r
986 listed.reselectTree();
\r
996 private class VWChannelDatSettingView extends AbsChannelDatSettingView {
\r
998 private static final long serialVersionUID = 1L;
\r
1002 protected Env getEnv() { return Viewer.this.env; }
\r
1004 protected TVProgramList getTVProgramList() { return tvprograms; }
\r
1006 protected ChannelSort getChannelSort() { return chsort; }
\r
1008 protected HDDRecorderList getHDDRecorderList() { return recorders; }
\r
1012 protected StatusWindow getStWin() { return stwin; }
\r
1014 protected StatusTextArea getMWin() { return mwin; }
\r
1018 protected Component getParentComponent() { return Viewer.this; }
\r
1021 protected void ringBeep() {
\r
1022 Viewer.this.ringBeep();
\r
1030 private class VWChannelSortView extends AbsChannelSortView {
\r
1032 private static final long serialVersionUID = 1L;
\r
1035 protected Env getEnv() { return Viewer.this.env; }
\r
1037 protected TVProgramList getTVProgramList() { return tvprograms; }
\r
1039 protected ChannelSort getChannelSort() { return chsort; }
\r
1043 protected StatusTextArea getMWin() { return mwin; }
\r
1046 protected void updProc() {
\r
1048 timer_now.pause();
\r
1052 toolBar.setPagerItems();
\r
1053 toolBar.setSelectedPagerIndex(toolBar.getSelectedPagerIndex());
\r
1056 paper.clearPanel();
\r
1057 paper.buildMainViewByDate();
\r
1060 paper.redrawTreeByCenter();
\r
1062 listed.redrawTreeByCenter();
\r
1065 paper.reselectTree();
\r
1066 listed.reselectTree();
\r
1068 timer_now.start();
\r
1073 * CHコンバート設定タブの内部クラス
\r
1075 private class VWChannelConvertView extends AbsChannelConvertView {
\r
1077 private static final long serialVersionUID = 1L;
\r
1081 protected Env getEnv() { return env; }
\r
1083 protected TVProgramList getProgPlugins() { return progPlugins; }
\r
1085 protected ChannelConvert getChannelConvert() { return chconv; }
\r
1092 private class VWReserveDialog extends AbsReserveDialog {
\r
1094 private static final long serialVersionUID = 1L;
\r
1097 public VWReserveDialog(int x, int y) {
\r
1103 protected Env getEnv() { return env; }
\r
1105 protected TVProgramList getTVProgramList() { return tvprograms; }
\r
1107 protected HDDRecorderList getRecorderList() { return recorders; }
\r
1109 protected AVSetting getAVSetting() { return avs; }
\r
1111 protected CHAVSetting getCHAVSetting() { return chavs; }
\r
1115 protected StatusWindow getStWin() { return stwin; }
\r
1117 protected StatusTextArea getMWin() { return mwin; }
\r
1121 protected Component getParentComponent() { return Viewer.this; }
\r
1124 protected void ringBeep() { Viewer.this.ringBeep(); }
\r
1127 * ReserveDialog内でのイベントから呼び出されるメソッド群
\r
1131 protected LikeReserveList findLikeReserves(ProgDetailList tvd, String keyword, int threshold) {
\r
1132 return Viewer.this.findLikeReserves(tvd, keyword, threshold);
\r
1137 * 新聞の表示形式を操作するダイアログ
\r
1139 private class VWPaperColorsDialog extends AbsPaperColorsDialog {
\r
1141 private static final long serialVersionUID = 1L;
\r
1144 protected Env getEnv() { return env; }
\r
1146 protected Bounds getBoundsEnv() { return bounds; }
\r
1148 protected PaperColorsMap getPaperColorMap() { return pColors; }
\r
1151 protected VWColorChooserDialog getCCWin() { return ccwin; }
\r
1154 * PaperColorsDialog内でのイベントから呼び出されるメソッド群
\r
1159 protected void updatePaperColors(Env ec,PaperColorsMap pc) {
\r
1160 paper.updateColors(ec,pc);
\r
1165 protected void updatePaperFonts(Env ec) {
\r
1166 paper.updateFonts(ec);
\r
1171 protected void updatePaperBounds(Env ec, Bounds bc) {
\r
1172 paper.updateBounds(ec,bc);
\r
1177 protected void updatePaperRepaint() {
\r
1178 paper.updateRepaint();
\r
1183 * キーワード検索ウィンドウの内部クラス
\r
1185 private class VWKeywordDialog extends AbsKeywordDialog {
\r
1187 private static final long serialVersionUID = 1L;
\r
1190 void preview(SearchKey search) {
\r
1192 if (search.alTarget.size() > 0) {
\r
1193 mainWindow.setSelectedTab(MWinTab.LISTED);
\r
1194 listed.redrawListByPreview(search);
\r
1200 * 延長警告管理ウィンドウの内部クラス
\r
1202 private class VWExtensionDialog extends AbsExtensionDialog {
\r
1204 private static final long serialVersionUID = 1L;
\r
1207 void preview(SearchKey search) {
\r
1209 if (search.alTarget.size() > 0) {
\r
1210 mainWindow.setSelectedTab(MWinTab.LISTED);
\r
1211 listed.redrawListByPreview(search);
\r
1221 private class VWToolBar extends AbsToolBar {
\r
1223 private static final long serialVersionUID = 1L;
\r
1226 protected Env getEnv() { return env; }
\r
1228 protected Bounds getBoundsEnv() { return bounds; }
\r
1230 protected TVProgramList getTVPrograms() { return tvprograms; }
\r
1232 protected ChannelSort getChannelSort() { return chsort; }
\r
1234 protected HDDRecorderList getHDDRecorders() { return recorders; }
\r
1237 protected StatusWindow getStWin() { return stwin; }
\r
1239 protected StatusTextArea getMWin() { return mwin; }
\r
1241 protected Component getParentComponent() { return Viewer.this; }
\r
1244 protected void ringBeep() { Viewer.this.ringBeep(); }
\r
1247 protected boolean doKeywordSerach(SearchKey search, String kStr, String sStr, boolean doFilter) {
\r
1249 timer_now.pause();
\r
1251 if ( mainWindow.getSelectedTab() == MWinTab.RSVED ) {
\r
1252 reserved.redrawListByKeywordFilter(search, kStr);
\r
1254 else if ( mainWindow.getSelectedTab() == MWinTab.RECED ) {
\r
1255 recorded.redrawListByKeywordFilter(search, kStr);
\r
1258 if ( search != null ) {
\r
1259 mainWindow.setSelectedTab(MWinTab.LISTED);
\r
1262 listed.clearSelection();
\r
1263 listed.redrawListByKeywordFilter(search, kStr);
\r
1265 else if (sStr != null) {
\r
1267 searchPassedProgram(search, sStr);
\r
1268 listed.clearSelection();
\r
1269 listed.redrawListBySearched(ProgType.PASSED, 0);
\r
1271 listed.redrawTreeByHistory();
\r
1275 listed.clearSelection();
\r
1276 listed.redrawListByKeywordDyn(search, kStr);
\r
1281 timer_now.start();
\r
1287 protected boolean doBatchReserve() {
\r
1288 timer_now.pause();
\r
1289 listed.doBatchReserve();
\r
1290 timer_now.start();
\r
1295 protected boolean jumpToNow() {
\r
1296 timer_now.pause();
\r
1297 if ( ! mainWindow.isTabSelected(MWinTab.PAPER) ) {
\r
1298 mainWindow.setSelectedTab(MWinTab.PAPER);
\r
1300 paper.jumpToNow();
\r
1301 timer_now.start();
\r
1306 protected boolean jumpToPassed(String passed) {
\r
1307 timer_now.pause();
\r
1308 boolean b = paper.jumpToPassed(passed);
\r
1309 timer_now.start();
\r
1314 protected boolean redrawByPager() {
\r
1315 timer_now.pause();
\r
1316 boolean b = paper.redrawByPager();
\r
1317 timer_now.start();
\r
1322 protected void toggleMatchBorder(boolean b) {
\r
1323 timer_now.pause();
\r
1324 if ( mainWindow.isTabSelected(MWinTab.LISTED) ) {
\r
1325 listed.toggleReservedBackground(b);
\r
1327 else if ( mainWindow.isTabSelected(MWinTab.PAPER) ) {
\r
1328 paper.toggleMatchBorder(b);
\r
1330 timer_now.start();
\r
1334 protected void setPaperColorDialogVisible(boolean b) {
\r
1335 //paper.stopTimer(); xxxx
\r
1336 timer_now.pause();
\r
1337 CommonSwingUtils.setLocationCenter(Viewer.this,pcwin);
\r
1338 pcwin.setVisible(true);
\r
1339 timer_now.start();
\r
1343 protected void setPaperZoom(int n) {
\r
1344 timer_now.pause();
\r
1346 timer_now.start();
\r
1350 protected boolean recorderSelectorChanged() {
\r
1352 timer_now.pause();
\r
1354 if (mainWindow.isTabSelected(MWinTab.LISTED)) {
\r
1355 listed.updateReserveMark();
\r
1356 listed.selectBatchTarget();
\r
1358 else if (mainWindow.isTabSelected(MWinTab.RSVED)) {
\r
1359 reserved.redrawReservedList();
\r
1361 else if (mainWindow.isTabSelected(MWinTab.RECED)) {
\r
1362 recorded.redrawRecordedList();
\r
1366 // 新聞形式の予約枠を書き換えるかもよ?
\r
1367 if (env.getEffectComboToPaper()) {
\r
1368 paper.updateReserveBorder(null);
\r
1372 timer_now.start();
\r
1378 protected void takeSnapShot() {
\r
1380 timer_now.pause();
\r
1382 Viewer.this.getSnapshot(getSelectedPagerIndex(),getPagerCount());
\r
1384 timer_now.start();
\r
1388 protected void setStatusVisible(boolean b) {
\r
1389 Viewer.this.setStatusVisible(b);
\r
1393 protected void setFullScreen(boolean b) {
\r
1394 Viewer.this.setFullScreen(b);
\r
1398 protected boolean isTabSelected(MWinTab tab) {
\r
1399 return mainWindow.isTabSelected(tab);
\r
1403 protected boolean addKeywordSearch(SearchKey search) {
\r
1405 timer_now.pause();
\r
1407 AbsKeywordDialog kD = new VWKeywordDialog();
\r
1408 CommonSwingUtils.setLocationCenter(Viewer.this,kD);
\r
1410 kD.open(search.getLabel(), srKeys, srGrps, search);
\r
1411 kD.setVisible(true);
\r
1413 if (kD.isRegistered()) {
\r
1415 mpList.clear(env.getDisableFazzySearch(), env.getDisableFazzySearchReverse());
\r
1416 mpList.build(tvprograms, trKeys.getTraceKeys(), srKeys.getSearchKeys());
\r
1419 listed.redrawTreeByKeyword();
\r
1421 mainWindow.setSelectedTab(MWinTab.LISTED);
\r
1424 timer_now.start();
\r
1430 protected boolean doLoadTVProgram(String selected) {
\r
1431 timer_now.pause();
\r
1433 LoadFor lf = (selected != null) ? LoadFor.get(selected) : LoadFor.ALL;
\r
1434 boolean b = Viewer.this.doLoadTVProgram(true, lf);
\r
1436 if ( b && lf == LoadFor.CSwSD ) {
\r
1438 CommonUtils.executeCommand(env.getShutdownCmd());
\r
1441 Viewer.this.doRedrawTVProgram(); // か き な お し
\r
1443 timer_now.start();
\r
1448 protected boolean doLoadRdRecorder(String selected) {
\r
1449 timer_now.pause();
\r
1451 LoadRsvedFor lrf = (selected != null) ? LoadRsvedFor.get(selected) : null;
\r
1452 boolean b = Viewer.this.doLoadRdRecorder(lrf);
\r
1454 timer_now.start();
\r
1459 /*******************************************************************************
\r
1461 ******************************************************************************/
\r
1467 public void stateChanged(ChangeEvent e){
\r
1468 StdAppendMessage("イベント発生");
\r
1472 * ツールバーでレコーダの選択イベントが発生
\r
1475 public void valueChanged(HDDRecorderSelectionEvent e) {
\r
1476 // 選択中のレコーダ情報を保存する
\r
1477 src_recsel = (HDDRecorderSelectable) e.getSource();
\r
1480 private String getSelectedMySelf() {
\r
1481 return ( src_recsel!=null ? src_recsel.getSelectedMySelf() : null );
\r
1484 private HDDRecorderList getSelectedRecorderList() {
\r
1485 return ( src_recsel!=null ? src_recsel.getSelectedList() : null );
\r
1488 private HDDRecorderSelectable src_recsel;
\r
1491 * レコーダ情報の変更イベントが発生
\r
1494 public void stateChanged(HDDRecorderChangeEvent e) {
\r
1502 public void cancelRised(CancelEvent e) {
\r
1503 if ( mainWindow.isTabSelected(MWinTab.RSVED) ) {
\r
1504 if ( e.getCause() == CancelEvent.Cause.TOOLBAR_SEARCH ) {
\r
1505 reserved.redrawListByKeywordFilter(null,null);
\r
1508 else if ( mainWindow.isTabSelected(MWinTab.RECED) ) {
\r
1509 if ( e.getCause() == CancelEvent.Cause.TOOLBAR_SEARCH ) {
\r
1510 recorded.redrawListByKeywordFilter(null,null);
\r
1519 public void timerRised(TickTimerRiseEvent e) {
\r
1520 if (env.getDebug()) System.out.println("Timer Rised: now="+CommonUtils.getDateTimeYMDx(e.getCalendar()));
\r
1525 /*******************************************************************************
\r
1527 ******************************************************************************/
\r
1532 private LikeReserveList findLikeReserves(ProgDetailList tvd, String keyword, int threshold) {
\r
1534 String keywordVal = null;
\r
1535 int thresholdVal = 0;
\r
1538 if ( ! env.getDisableFazzySearch() ) {
\r
1539 if ( threshold > 0 ) {
\r
1541 keywordVal = TraceProgram.replacePop(keyword);
\r
1542 thresholdVal = threshold;
\r
1546 keywordVal = tvd.titlePop;
\r
1547 thresholdVal = env.getDefaultFazzyThreshold();
\r
1552 return recorders.findLikeReserves(tvd, keywordVal, thresholdVal, env.getRangeLikeRsv(), ! env.getDisableFazzySearchReverse());
\r
1562 * 番組追跡への追加とgoogle検索
\r
1564 public void showPopupForTraceProgram(
\r
1565 final JComponent comp,
\r
1566 final ProgDetailList tvd, final String keyword, final int threshold,
\r
1567 final int x, final int y, final String clickedDateTime)
\r
1569 JPopupMenu pop = new JPopupMenu();
\r
1571 String myself = toolBar.getSelectedRecorder();
\r
1574 LikeReserveList likeRsvList;
\r
1575 if ( env.getDisableFazzySearch() ) {
\r
1576 likeRsvList = recorders.findLikeReserves(tvd, null, 0, env.getRangeLikeRsv(), false);
\r
1579 likeRsvList = recorders.findLikeReserves(tvd, tvd.titlePop, env.getDefaultFazzyThreshold(), env.getRangeLikeRsv(), ! env.getDisableFazzySearchReverse());
\r
1583 LikeReserveList overlapRsvList = recorders.findOverlapReserves(tvd, null, true, env.getOverlapUp());
\r
1585 // 類似と重複で被るものを重複から除外
\r
1586 for ( LikeReserveItem item : likeRsvList ) {
\r
1587 overlapRsvList.removeDup(item);
\r
1591 if ( tvd.type == ProgType.PASSED ||
\r
1592 (tvd.type == ProgType.PROG && tvd.subtype == ProgSubtype.RADIO) ||
\r
1593 recorders.size() == 0 ) {
\r
1598 LikeReserveItem item = likeRsvList.getClosest(myself);
\r
1599 if ( env.getGivePriorityToReserved() && item != null && item.isCandidate(env.getOverlapUp()) ) {
\r
1600 target = "予約を編集する";
\r
1603 target = "新規予約を登録する";
\r
1606 JMenuItem menuItem = new JMenuItem(String.format("%s【%s %s - %s(%s)】",target,tvd.accurateDate,tvd.start,tvd.title,tvd.center));
\r
1608 menuItem.setForeground(Color.BLUE);
\r
1609 Font f = menuItem.getFont();
\r
1610 menuItem.setFont(f.deriveFont(f.getStyle()|Font.BOLD));
\r
1613 menuItem.addActionListener(new ActionListener() {
\r
1614 public void actionPerformed(ActionEvent e) {
\r
1616 CommonSwingUtils.setLocationCenter(mainWindow,rdialog);
\r
1618 if ( rdialog.open(tvd) ) {
\r
1619 rdialog.setVisible(true);
\r
1622 rdialog.setVisible(false);
\r
1626 if (rdialog.isSucceededReserve()) {
\r
1627 listed.updateReserveMark();
\r
1628 paper.updateReserveBorder(tvd.center);
\r
1629 reserved.redrawReservedList();
\r
1633 pop.add(menuItem);
\r
1638 for ( final LikeReserveItem item : overlapRsvList ) {
\r
1640 if ( ! item.getRec().Myself().equals(toolBar.getSelectedRecorder()) ) {
\r
1641 continue; // 選択中のレコーダ以外はスルーで
\r
1645 ReserveList rsv = item.getRsv();
\r
1646 String start = CommonUtils.getDateTimeW(CommonUtils.getCalendar(rsv.getStartDateTime()));
\r
1647 JMenuItem menuItem = new JMenuItem(String.format("隣接予約を上書する【%s - %s(%s)】",start,rsv.getTitle(),rsv.getCh_name()));
\r
1649 menuItem.addActionListener(new ActionListener() {
\r
1650 public void actionPerformed(ActionEvent e) {
\r
1652 CommonSwingUtils.setLocationCenter(mainWindow,rdialog);
\r
1654 if ( rdialog.open(tvd,item) ) {
\r
1655 rdialog.setVisible(true);
\r
1658 rdialog.setVisible(false);
\r
1662 if (rdialog.isSucceededReserve()) {
\r
1663 listed.updateReserveMark();
\r
1664 paper.updateReserveBorder(tvd.center);
\r
1665 reserved.redrawReservedList();
\r
1669 pop.add(menuItem);
\r
1673 pop.addSeparator();
\r
1676 if ( tvd.type != ProgType.PASSED )
\r
1678 for ( int n=0; n<2; n++ ) {
\r
1680 LikeReserveList rsvList = null;
\r
1682 rsvList = likeRsvList;
\r
1685 rsvList = overlapRsvList;
\r
1688 for ( LikeReserveItem rsvItem : rsvList ) {
\r
1690 final boolean fexec = rsvItem.getRsv().getExec();
\r
1691 final String start = rsvItem.getRsv().getAhh()+":"+rsvItem.getRsv().getAmm();
\r
1692 final String title = rsvItem.getRsv().getTitle();
\r
1693 final String chnam = rsvItem.getRsv().getCh_name();
\r
1694 final String rsvId = rsvItem.getRsv().getId();
\r
1695 final String recId = rsvItem.getRec().Myself();
\r
1697 pop.add(getExecOnOffMenuItem(fexec,start,title,chnam,rsvId,recId,n));
\r
1700 pop.addSeparator();
\r
1704 pop.addSeparator();
\r
1707 if ( tvd.type != ProgType.PASSED ) // 過去ログは処理対象外です
\r
1709 for ( int n=0; n<2; n++ ) {
\r
1711 LikeReserveList rsvList = null;
\r
1713 rsvList = likeRsvList;
\r
1716 rsvList = overlapRsvList;
\r
1719 for ( LikeReserveItem rsvItem : rsvList ) {
\r
1721 final String start = rsvItem.getRsv().getAhh()+":"+rsvItem.getRsv().getAmm();
\r
1722 final String title = rsvItem.getRsv().getTitle();
\r
1723 final String chnam = rsvItem.getRsv().getCh_name();
\r
1724 final String rsvId = rsvItem.getRsv().getId();
\r
1725 final String recId = rsvItem.getRec().Myself();
\r
1727 pop.add(getRemoveRsvMenuItem(start, title,chnam,rsvId,recId,n));
\r
1730 pop.addSeparator();
\r
1734 pop.addSeparator();
\r
1735 pop.addSeparator();
\r
1740 if ( mainWindow.isTabSelected(MWinTab.LISTED) ) {
\r
1741 pop.add(getJumpMenuItem(tvd.title,tvd.center,tvd.accurateDate+" "+tvd.start));
\r
1743 if ( mainWindow.isTabSelected(MWinTab.LISTED) || mainWindow.isTabSelected(MWinTab.PAPER) ) {
\r
1744 JMenuItem mi = getJumpToLastWeekMenuItem(tvd.title,tvd.center,tvd.startDateTime);
\r
1745 if ( mi != null ) {
\r
1751 pop.addSeparator();
\r
1755 final String label = TraceProgram.getNewLabel(tvd.title, tvd.center);
\r
1756 JMenuItem menuItem = new JMenuItem("番組追跡への追加【"+label+"】");
\r
1757 menuItem.addActionListener(new ActionListener() {
\r
1758 public void actionPerformed(ActionEvent e) {
\r
1760 VWTraceKeyDialog tD = new VWTraceKeyDialog(0,0);
\r
1761 CommonSwingUtils.setLocationCenter(mainWindow,tD);
\r
1763 tD.open(trKeys, tvd, env.getDefaultFazzyThreshold());
\r
1764 tD.setVisible(true);
\r
1766 if (tD.isRegistered()) {
\r
1771 mpList.clear(env.getDisableFazzySearch(), env.getDisableFazzySearchReverse());
\r
1772 mpList.build(tvprograms, trKeys.getTraceKeys(), srKeys.getSearchKeys());
\r
1775 listed.redrawTreeByTrace();
\r
1778 paper.updateBangumiColumns();
\r
1779 listed.reselectTree();
\r
1781 mwin.appendMessage("番組追跡へ追加しました【"+label+"】");
\r
1784 trKeys.remove(label);
\r
1788 pop.add(menuItem);
\r
1793 final String label = tvd.title+" ("+tvd.center+")";
\r
1794 JMenuItem menuItem = new JMenuItem("キーワード検索への追加【"+label+"】");
\r
1795 menuItem.addActionListener(new ActionListener(){
\r
1796 public void actionPerformed(ActionEvent e){
\r
1798 // 「キーワード検索の設定」ウィンドウを開く
\r
1800 AbsKeywordDialog kD = new VWKeywordDialog();
\r
1801 CommonSwingUtils.setLocationCenter(mainWindow,kD);
\r
1803 kD.open(srKeys, srGrps, tvd);
\r
1804 kD.setVisible(true);
\r
1806 if (kD.isRegistered()) {
\r
1808 mpList.clear(env.getDisableFazzySearch(), env.getDisableFazzySearchReverse());
\r
1809 mpList.build(tvprograms, trKeys.getTraceKeys(), srKeys.getSearchKeys());
\r
1812 listed.redrawTreeByKeyword();
\r
1815 paper.updateBangumiColumns();
\r
1816 listed.reselectTree();
\r
1818 mwin.appendMessage("キーワード検索へ追加しました【"+label+"】");
\r
1822 pop.add(menuItem);
\r
1827 boolean isRemoveItem = false;
\r
1828 if ( mainWindow.isTabSelected(MWinTab.LISTED) && tvd.type == ProgType.PICKED ) {
\r
1829 isRemoveItem = true;
\r
1832 PickedProgram tvp = tvprograms.getPickup();
\r
1833 if ( tvp != null ) {
\r
1834 isRemoveItem = tvp.remove(tvd, tvd.center, tvd.accurateDate, false);
\r
1838 if ( ! isRemoveItem ) // 過去ログは処理対象外です
\r
1840 final String label = String.format("%s(%s)",tvd.title,tvd.center);
\r
1841 JMenuItem menuItem = new JMenuItem(String.format("ピックアップへの追加【%s %s - %s】",tvd.accurateDate,tvd.start,label));
\r
1842 menuItem.addActionListener(new ActionListener() {
\r
1843 public void actionPerformed(ActionEvent e) {
\r
1845 PickedProgram tvp = tvprograms.getPickup();
\r
1846 if ( tvp != null ) {
\r
1851 if ( listed.isNodeSelected(ListedTreeNode.PICKUP) ) {
\r
1852 // ピックアップノードが選択されていたらリストを更新する
\r
1853 listed.reselectTree();
\r
1856 listed.updateReserveMark();
\r
1858 paper.updateReserveBorder(tvd.center);
\r
1859 mwin.appendMessage("【ピックアップ】追加しました: "+tvd.title+" ("+tvd.center+")");
\r
1864 pop.add(menuItem);
\r
1867 final String label = tvd.title+" ("+tvd.center+")";
\r
1868 JMenuItem menuItem = new JMenuItem("ピックアップからの削除【"+label+"】");
\r
1869 menuItem.setForeground(Color.RED);
\r
1870 menuItem.addActionListener(new ActionListener() {
\r
1871 public void actionPerformed(ActionEvent e) {
\r
1873 PickedProgram tvp = tvprograms.getPickup();
\r
1874 if ( tvp != null ) {
\r
1876 tvp.remove(tvd, tvd.center, tvd.accurateDate, true);
\r
1879 if ( listed.isNodeSelected(ListedTreeNode.PICKUP) || listed.isNodeSelected(ListedTreeNode.STANDBY) ) {
\r
1880 // ピックアップノードが選択されていたらリストを更新する
\r
1881 listed.reselectTree();
\r
1884 listed.updateReserveMark();
\r
1885 paper.updateReserveBorder(tvd.center);
\r
1886 mwin.appendMessage("【ピックアップ】削除しました: "+tvd.title+" ("+tvd.center+")");
\r
1891 pop.add(menuItem);
\r
1895 pop.addSeparator();
\r
1899 for (final TextValueSet tv : env.getTvCommand()) {
\r
1900 JMenuItem menuItem = new JMenuItem(tv.getText());
\r
1901 String escepedTitle = "";
\r
1902 String escepedChName = "";
\r
1903 String escepedDetail = "";
\r
1905 escepedTitle = URLEncoder.encode(tvd.title,"UTF-8");
\r
1906 escepedDetail = URLEncoder.encode(tvd.detail,"UTF-8");
\r
1907 escepedChName = URLEncoder.encode(tvd.center,"UTF-8");
\r
1908 } catch (UnsupportedEncodingException e2) {
\r
1912 String cmd = tv.getValue();
\r
1913 if ( cmd.matches(".*%DETAILURL%.*") ) {
\r
1914 if ( tvd.link == null || tvd.link.length() == 0 ) {
\r
1915 // このメニューは利用できません!
\r
1916 menuItem.setEnabled(false);
\r
1917 menuItem.setForeground(Color.lightGray);
\r
1920 cmd = cmd.replaceAll("%ENCTITLE%", escepedTitle);
\r
1921 cmd = cmd.replaceAll("%ENCDETAIL%", escepedDetail);
\r
1922 cmd = cmd.replaceAll("%ENCCHNAME%", escepedChName);
\r
1923 cmd = cmd.replaceAll("%TITLE%", tvd.title);
\r
1924 cmd = cmd.replaceAll("%DETAIL%", tvd.detail);
\r
1925 cmd = cmd.replaceAll("%CHNAME%", tvd.center);
\r
1926 cmd = cmd.replaceAll("%DATE%", tvd.accurateDate);
\r
1927 cmd = cmd.replaceAll("%START%", tvd.start);
\r
1928 cmd = cmd.replaceAll("%END%", tvd.end);
\r
1929 cmd = cmd.replaceAll("%DETAILURL%", tvd.link);
\r
1932 if ( cmd.matches(".*%TVKAREACODE%.*") && cmd.matches(".*%TVKPID%.*") ) {
\r
1934 for ( TVProgram tvp : progPlugins ) {
\r
1935 if ( tvp.getTVProgramId().startsWith("Gガイド.テレビ王国") ) {
\r
1936 for ( Center tempcr : tvp.getCRlist() ) {
\r
1937 // CH設定が完了している必要がある
\r
1938 if ( tvp.getSubtype() == ProgSubtype.TERRA && tvp.getSelectedCode().equals(TVProgram.allCode) && ! tempcr.getAreaCode().equals(TVProgram.bsCode) ) {
\r
1939 // 地域が全国の地デジの場合のみ、有効局かどうかを確認する必要がある
\r
1940 if ( tempcr.getCenter().equals(tvd.center) && tempcr.getOrder() > 0 ) {
\r
1947 if ( tempcr.getCenter().equals(tvd.center) ) {
\r
1955 if ( cr != null ) {
\r
1960 if ( cr != null ) {
\r
1961 String areacode = null;
\r
1962 String centercode = cr.getLink();
\r
1963 String cat = cr.getLink().substring(0,1);
\r
1964 if ( cat.equals("1") ) {
\r
1965 areacode = cr.getAreaCode();
\r
1968 if ( cat.equals("4") ) {
\r
1971 else if ( cat.equals("5") ) {
\r
1977 cmd = cmd.replaceAll("%TVKAREACODE%", areacode);
\r
1978 cmd = cmd.replaceAll("%TVKCAT%", cat);
\r
1979 cmd = cmd.replaceAll("%TVKPID%", centercode+CommonUtils.getDateTimeYMD(CommonUtils.getCalendar(tvd.startDateTime)).replaceFirst("..$", ""));
\r
1980 System.out.println("[DEBUG] "+cmd);
\r
1982 menuItem.setEnabled(true);
\r
1983 menuItem.setForeground(Color.BLACK);
\r
1986 menuItem.setEnabled(false);
\r
1987 menuItem.setForeground(Color.lightGray);
\r
1991 final String run = cmd;
\r
1993 menuItem.addActionListener(new ActionListener() {
\r
1995 public void actionPerformed(ActionEvent e) {
\r
1997 if (run.indexOf("http") == 0) {
\r
1998 Desktop desktop = Desktop.getDesktop();
\r
1999 desktop.browse(new URI(run));
\r
2002 CommonUtils.executeCommand(run);
\r
2004 } catch (IOException e1) {
\r
2005 e1.printStackTrace();
\r
2006 } catch (URISyntaxException e1) {
\r
2007 e1.printStackTrace();
\r
2012 pop.add(menuItem);
\r
2016 pop.addSeparator();
\r
2020 JMenuItem menuItem = new JMenuItem("番組名をコピー【"+tvd.title+"】");
\r
2021 menuItem.addActionListener(new ActionListener() {
\r
2022 public void actionPerformed(ActionEvent e) {
\r
2023 String msg = tvd.title;
\r
2024 Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
\r
2025 StringSelection s = new StringSelection(msg);
\r
2026 cb.setContents(s, null);
\r
2029 pop.add(menuItem);
\r
2032 JMenuItem menuItem = new JMenuItem("番組名と詳細をコピー【"+tvd.title+"】");
\r
2033 menuItem.addActionListener(new ActionListener() {
\r
2034 public void actionPerformed(ActionEvent e) {
\r
2035 String msg = tvd.title+System.getProperty("line.separator")+tvd.detail+"\0"+tvd.getAddedDetail();
\r
2036 Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
\r
2037 StringSelection s = new StringSelection(msg);
\r
2038 cb.setContents(s, null);
\r
2041 pop.add(menuItem);
\r
2044 JMenuItem menuItem = new JMenuItem("番組情報をコピー【"+tvd.title+"】");
\r
2045 menuItem.addActionListener(new ActionListener() {
\r
2046 public void actionPerformed(ActionEvent e) {
\r
2049 for (ClipboardInfo cb : cbitems) {
\r
2051 switch (cb.getId()) {
\r
2053 msg += tvd.title+"\t";
\r
2056 msg += tvd.center+"\t";
\r
2059 msg += tvd.accurateDate+"\t";
\r
2062 msg += tvd.start+"\t";
\r
2066 msg = msg.substring(0,msg.length()-1)+"-";
\r
2068 msg += tvd.end+"\t";
\r
2071 msg += tvd.genre+"\t";
\r
2074 msg += tvd.detail+"\0"+tvd.getAddedDetail()+"\t";
\r
2078 preId = cb.getId();
\r
2080 if (msg.length() > 0) {
\r
2081 msg = msg.substring(0,msg.length()-1);
\r
2083 Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
\r
2084 StringSelection s = new StringSelection(msg);
\r
2085 cb.setContents(s, null);
\r
2088 pop.add(menuItem);
\r
2091 pop.addSeparator();
\r
2095 tvd.type == ProgType.SYOBO ||
\r
2096 tvd.type == ProgType.PASSED ||
\r
2097 tvd.type == ProgType.PICKED ||
\r
2098 (tvd.type == ProgType.PROG && tvd.subtype != ProgSubtype.RADIO) ) // ラジオは処理対象外です
\r
2100 JMenuItem menuItem = new JMenuItem("延長感染源にしない【"+tvd.title+" ("+tvd.center+")】");
\r
2101 menuItem.addActionListener(new ActionListener() {
\r
2102 public void actionPerformed(ActionEvent e) {
\r
2104 mwin.appendMessage("延長感染源を隔離します【"+tvd.title+"("+tvd.center+")】");
\r
2106 AbsExtensionDialog eD = new VWExtensionDialog();
\r
2107 CommonSwingUtils.setLocationCenter(mainWindow,eD);
\r
2109 eD.open(tvd.title,tvd.center,false,extKeys);
\r
2110 eD.setVisible(true);
\r
2112 if (eD.isRegistered()) {
\r
2114 for (TVProgram tvp : tvprograms) {
\r
2115 if (tvp.getType() == ProgType.PROG) {
\r
2116 tvp.setExtension(null, null, false, extKeys.getSearchKeys());
\r
2121 listed.redrawTreeByExtension();
\r
2123 mainWindow.setSelectedTab(MWinTab.LISTED);
\r
2127 pop.add(menuItem);
\r
2129 if ( tvd.type == ProgType.PASSED || (tvd.type == ProgType.PROG && tvd.subtype != ProgSubtype.RADIO) ) // ラジオは処理対象外です
\r
2131 JMenuItem menuItem = new JMenuItem("延長感染源にする【"+tvd.title+" ("+tvd.center+")】");
\r
2132 menuItem.addActionListener(new ActionListener() {
\r
2133 public void actionPerformed(ActionEvent e) {
\r
2135 AbsExtensionDialog eD = new VWExtensionDialog();
\r
2136 CommonSwingUtils.setLocationCenter(mainWindow,eD);
\r
2138 eD.open(tvd.title,tvd.center,true,extKeys);
\r
2139 eD.setVisible(true);
\r
2141 if (eD.isRegistered()) {
\r
2143 for (TVProgram tvp : tvprograms) {
\r
2144 if (tvp.getType() == ProgType.PROG) {
\r
2145 tvp.setExtension(null, null, false, extKeys.getSearchKeys());
\r
2150 listed.redrawTreeByExtension();
\r
2152 mainWindow.setSelectedTab(MWinTab.LISTED);
\r
2156 pop.add(menuItem);
\r
2159 pop.addSeparator();
\r
2162 if ( tvd.type == ProgType.PROG && tvd.subtype != ProgSubtype.RADIO) // ラジオは処理対象外です
\r
2164 for (HDDRecorder recorder : recorders ) {
\r
2166 if (recorder.ChangeChannel(null) == false) {
\r
2170 final String recorderName = recorder.Myself();
\r
2171 JMenuItem menuItem = new JMenuItem("【"+recorderName+"】で【"+tvd.center+"】を視聴する");
\r
2173 menuItem.addActionListener(new ActionListener() {
\r
2174 public void actionPerformed(ActionEvent e) {
\r
2175 for (HDDRecorder recorder : recorders ) {
\r
2176 if (recorder.isMyself(recorderName)) {
\r
2177 if (recorder.ChangeChannel(tvd.center) == false) {
\r
2179 mwin.appendError("【警告】チャンネルを変更できませんでした:"+recorder.getErrmsg());
\r
2181 else if (recorder.getErrmsg() !=null && recorder.getErrmsg().length() > 0) {
\r
2182 mwin.appendError("[追加情報] "+recorder.getErrmsg());
\r
2189 menuItem.setEnabled(recorder.getUseChChange());
\r
2191 pop.add(menuItem);
\r
2195 pop.show(comp, x, y);
\r
2199 public boolean addToPickup(final ProgDetailList tvd) {
\r
2201 if (tvd.start.equals("")) {
\r
2206 PickedProgram tvp = tvprograms.getPickup();
\r
2207 if ( tvp == null ) {
\r
2213 if ( tvp.remove(tvd, tvd.center, tvd.accurateDate, true) ) {
\r
2215 if ( listed.isNodeSelected(JTreeLabel.Nodes.PICKUP) || listed.isNodeSelected(JTreeLabel.Nodes.STANDBY) ) {
\r
2216 // ピックアップノードor予約待機ノードが選択されていたらリストを更新する
\r
2217 listed.reselectTree();
\r
2218 //listed.updateReserveMark();
\r
2221 // 予約マークだけ変えておけばいいよね
\r
2222 listed.updateReserveMark();
\r
2225 paper.updateReserveBorder(tvd.center);
\r
2226 mwin.appendMessage("【ピックアップ】削除しました: "+tvd.title+" ("+tvd.center+")");
\r
2231 if ( tvd.endDateTime.compareTo(CommonUtils.getDateTime(0)) > 0 ) {
\r
2235 if ( listed.isNodeSelected(JTreeLabel.Nodes.PICKUP) ) {
\r
2236 // ピックアップノードが選択されていたらリストを更新する
\r
2237 listed.reselectTree();
\r
2238 //listed.updateReserveMark();
\r
2241 listed.updateReserveMark();
\r
2244 paper.updateReserveBorder(tvd.center);
\r
2245 mwin.appendMessage("【ピックアップ】追加しました: "+tvd.title+" ("+tvd.center+")");
\r
2250 mwin.appendMessage("【ピックアップ】過去情報はピックアップできません.");
\r
2257 private JMenuItem getRemoveRsvMenuItem(final String start, final String title, final String chnam, final String rsvId, final String recId, int n) {
\r
2259 JMenuItem menuItem = new JMenuItem();
\r
2261 String mode = "削除";
\r
2262 menuItem.setForeground(Color.RED);
\r
2264 String target = ( n==0 ) ? "予約" : "隣接予約";
\r
2266 menuItem.setText(String.format("%sを%sする【%s - %s(%s)/%s】",target,mode,start,title,chnam,recId));
\r
2268 if ( recId.equals(toolBar.getSelectedRecorder()) ) {
\r
2269 // 選択中のレコーダのものは太字に
\r
2270 Font f = menuItem.getFont();
\r
2271 menuItem.setFont(f.deriveFont(f.getStyle()|Font.BOLD));
\r
2274 menuItem.addActionListener(new ActionListener() {
\r
2275 public void actionPerformed(ActionEvent e) {
\r
2277 if (env.getShowWarnDialog()) {
\r
2278 Container cp = getContentPane();
\r
2279 int ret = JOptionPane.showConfirmDialog(cp, "削除しますか?【"+title+"("+chnam+")】("+recId+")", "確認", JOptionPane.YES_NO_OPTION);
\r
2280 if (ret != JOptionPane.YES_OPTION) {
\r
2288 new SwingBackgroundWorker(false) {
\r
2291 protected Object doWorks() throws Exception {
\r
2293 for (HDDRecorder recorder : recorders) {
\r
2294 if (recorder.isMyself(recId)) { // IPAddr:PortNo:RecorderIdで比較
\r
2296 String title = "";
\r
2297 for (ReserveList r : recorder.getReserves()) {
\r
2298 if (r.getId().equals(rsvId)) {
\r
2299 title = r.getTitle();
\r
2304 stwin.appendMessage("予約を削除します:"+title+"("+rsvId+")");
\r
2305 //recorder.setProgressArea(stwin);
\r
2306 ReserveList r = recorder.RemoveRdEntry(rsvId); // Noで検索
\r
2308 mwin.appendMessage("正常に削除できました:"+r.getTitle()+"("+r.getCh_name()+")");
\r
2310 if ( ! r.getTitle().equals(title) || ! r.getId().equals(rsvId)) {
\r
2311 mwin.appendError("【警告】削除結果が一致しません!:"+title+"/"+r.getTitle());
\r
2314 if ( recorder.getUseCalendar()) {
\r
2316 for ( HDDRecorder calendar : recorders ) {
\r
2317 if (calendar.getType() == RecType.CALENDAR) {
\r
2318 stwin.appendMessage("カレンダーから予約情報を削除します");
\r
2319 //calendar.setProgressArea(stwin);
\r
2320 if ( ! calendar.UpdateRdEntry(r, null)) {
\r
2321 mwin.appendError("【カレンダー】"+calendar.getErrmsg());
\r
2331 mwin.appendError("削除に失敗しました:"+title);
\r
2335 if ( ! recorder.getErrmsg().equals("")) {
\r
2336 mwin.appendError("【追加情報】"+recorder.getErrmsg());
\r
2346 protected void doFinally() {
\r
2347 StWinSetVisible(false);
\r
2351 CommonSwingUtils.setLocationCenter(Viewer.this, stwin);
\r
2352 StWinSetVisible(true);
\r
2355 listed.updateReserveMark();
\r
2356 paper.updateReserveBorder(chnam);
\r
2357 reserved.redrawReservedList();
\r
2368 * 他のクラスに分離できなかったというか、しなかったというか、そんなメソッド群
\r
2374 private boolean doExecOnOff(final boolean fexec, final String title, final String chnam, final String rsvId, final String recId) {
\r
2376 CommonSwingUtils.setLocationCenter(mainWindow,rdialog);
\r
2378 String mode = (fexec ? "ON" : "OFF");
\r
2381 if ( rdialog.open(recId,rsvId,fexec) ) {
\r
2383 rdialog.doUpdate();
\r
2385 if (rdialog.isSucceededReserve()) {
\r
2387 listed.updateReserveMark();
\r
2388 paper.updateReserveBorder(chnam);
\r
2389 reserved.redrawReservedList();
\r
2392 String msg = "予約を"+mode+"にしました【"+title+"("+chnam+")/"+recId+"】";
\r
2393 //StdAppendMessage(msg);
\r
2394 mwin.appendMessage(msg);
\r
2405 * 予約実行をONOFFするメニューアイテム
\r
2407 private JMenuItem getExecOnOffMenuItem(final boolean fexec, final String start, final String title, final String chnam, final String rsvId, final String recId, int n) {
\r
2409 JMenuItem menuItem = new JMenuItem();
\r
2414 menuItem.setForeground(Color.BLUE);
\r
2418 menuItem.setForeground(Color.BLACK);
\r
2421 String target = ( n==0 ) ? "予約" : "隣接予約";
\r
2423 menuItem.setText(String.format("%sを%sにする【%s - %s(%s)/%s】",target,mode,start,title,chnam,recId));
\r
2425 if ( recId.equals(toolBar.getSelectedRecorder()) ) {
\r
2426 // 選択中のレコーダのものは太字に
\r
2427 Font f = menuItem.getFont();
\r
2428 menuItem.setFont(f.deriveFont(f.getStyle()|Font.BOLD));
\r
2431 final String xmode = mode;
\r
2432 menuItem.addActionListener(new ActionListener() {
\r
2433 public void actionPerformed(ActionEvent e) {
\r
2435 CommonSwingUtils.setLocationCenter(mainWindow,rdialog);
\r
2438 if ( rdialog.open(recId,rsvId, ! fexec) ) {
\r
2440 rdialog.doUpdate();
\r
2442 if (rdialog.isSucceededReserve()) {
\r
2444 listed.updateReserveMark();
\r
2445 paper.updateReserveBorder(chnam);
\r
2446 reserved.redrawReservedList();
\r
2449 String msg = "予約を"+xmode+"にしました【"+title+"("+chnam+")/"+recId+"】";
\r
2450 StdAppendMessage(msg);
\r
2451 mwin.appendMessage(msg);
\r
2456 //rdialog.setVisible(false);
\r
2465 * 新聞形式へジャンプするメニューアイテム
\r
2467 private JMenuItem getJumpMenuItem(final String title, final String chnam, final String startDT) {
\r
2468 JMenuItem menuItem = new JMenuItem(String.format("番組欄へジャンプする【%s - %s(%s)】",startDT,title,chnam));
\r
2469 menuItem.addActionListener(new ActionListener() {
\r
2470 public void actionPerformed(ActionEvent e) {
\r
2471 paper.jumpToBangumi(chnam,startDT);
\r
2476 private JMenuItem getJumpToLastWeekMenuItem( final String title, final String chnam, final String startDT) {
\r
2477 GregorianCalendar cal = CommonUtils.getCalendar(startDT);
\r
2479 if ( cal != null ) {
\r
2480 cal.add(Calendar.DATE, -7);
\r
2481 final String lastdatetime = CommonUtils.getDateTimeW(cal);
\r
2483 JMenuItem menuItem = new JMenuItem(String.format("先週の番組欄へジャンプする【%s - (%s)】",lastdatetime,chnam));
\r
2485 menuItem.addActionListener(new ActionListener() {
\r
2486 public void actionPerformed(ActionEvent e) {
\r
2487 paper.jumpToBangumi(chnam,lastdatetime);
\r
2496 /*******************************************************************************
\r
2498 ******************************************************************************/
\r
2500 /***************************************
\r
2502 **************************************/
\r
2507 private boolean doLoadRdRecorder(LoadRsvedFor lrf) {
\r
2509 if ( lrf == null ) {
\r
2510 return doLoadRdRecorderAll();
\r
2515 return doLoadRdReserveDetails();
\r
2517 return doLoadRdRecorded();
\r
2519 return doLoadRdAutoReserves();
\r
2528 * レコーダの情報を全部DLする(ステータスウィンドウは自前で用意 する)
\r
2530 private boolean doLoadRdRecorderAll() {
\r
2532 final String myself = getSelectedMySelf();
\r
2537 new SwingBackgroundWorker(false) {
\r
2540 protected Object doWorks() throws Exception {
\r
2542 TatCount tc = new TatCount();
\r
2545 _loadRdRecorderAll(true,myself);
\r
2547 // エンコーダ情報が更新されるかもしれないので、一覧のエンコーダ表示にも反映する
\r
2548 recsetting.redrawRecorderEncoderEntry();
\r
2551 paper.updateReserveBorder(null);
\r
2552 listed.updateReserveMark();
\r
2553 reserved.redrawReservedList();
\r
2554 recorded.redrawRecordedList();
\r
2556 mwin.appendMessage(String.format("【予約一覧の取得処理が完了しました】 所要時間: %.2f秒",tc.end()));
\r
2561 protected void doFinally() {
\r
2562 StWinSetVisible(false);
\r
2566 StWinSetLocationCenter(this);
\r
2567 StWinSetVisible(true);
\r
2576 private boolean doLoadRdReserveDetails() {
\r
2578 final String myself = getSelectedMySelf();
\r
2583 new SwingBackgroundWorker(false) {
\r
2586 protected Object doWorks() throws Exception {
\r
2588 TatCount tc = new TatCount();
\r
2590 boolean succeeded = true;
\r
2592 HDDRecorderList recs;
\r
2593 if ( myself != null ) {
\r
2594 recs = recorders.findInstance(myself);
\r
2599 for ( HDDRecorder recorder : recs ) {
\r
2601 if ( ! recorder.isReserveListSupported() ) {
\r
2606 if ( ! recorder.GetRdSettings(true) ) {
\r
2607 succeeded = false;
\r
2612 if ( ! recorder.GetRdReserve(true) ) {
\r
2613 succeeded = false;
\r
2617 // レコーダから取得したエンコーダ情報で、登録済みレコーダ一覧を更新する
\r
2618 setEncoderInfo2RecorderList(recorder,true);
\r
2621 if ( recorder.isThereAdditionalDetails() ) {
\r
2622 if ( ! recorder.GetRdReserveDetails() ) {
\r
2623 succeeded = false;
\r
2628 // レコーダの放送局名をWeb番組表の放送局名に置き換え
\r
2629 checkChNameIsRight(recorder);
\r
2632 if ( recorder.isRecordedListSupported() ) {
\r
2633 recorder.GetRdRecorded(false);
\r
2637 if ( succeeded ) {
\r
2638 reserved.redrawReservedList();
\r
2639 recorded.redrawRecordedList();
\r
2641 mwin.appendMessage(String.format("【予約詳細の取得処理が完了しました】 所要時間: %.2f秒",tc.end()));
\r
2645 mwin.appendMessage(String.format("【予約詳細の取得処理に失敗しました】 所要時間: %.2f秒",tc.end()));
\r
2651 protected void doFinally() {
\r
2652 StWinSetVisible(false);
\r
2656 StWinSetLocationCenter(this);
\r
2657 StWinSetVisible(true);
\r
2666 private boolean doLoadRdRecorded() {
\r
2668 final String myself = getSelectedMySelf();
\r
2673 new SwingBackgroundWorker(false) {
\r
2676 protected Object doWorks() throws Exception {
\r
2678 TatCount tc = new TatCount();
\r
2680 boolean succeeded = true;
\r
2682 HDDRecorderList recs;
\r
2683 if ( myself != null ) {
\r
2684 recs = recorders.findInstance(myself);
\r
2689 for ( HDDRecorder recorder : recs ) {
\r
2690 if ( ! recorder.isRecordedListSupported() ) {
\r
2691 succeeded = false;
\r
2695 if ( ! recorder.GetRdRecorded(true) ) {
\r
2696 succeeded = false;
\r
2700 if ( succeeded ) {
\r
2701 reserved.redrawReservedList();
\r
2702 recorded.redrawRecordedList();
\r
2704 mwin.appendMessage(String.format("【録画結果一覧の取得処理が完了しました】 所要時間: %.2f秒",tc.end()));
\r
2708 mwin.appendMessage(String.format("【録画結果一覧の取得処理に失敗しました】 所要時間: %.2f秒",tc.end()));
\r
2714 protected void doFinally() {
\r
2715 StWinSetVisible(false);
\r
2719 StWinSetLocationCenter(this);
\r
2720 StWinSetVisible(true);
\r
2729 private boolean doLoadRdAutoReserves() {
\r
2731 final String myself = getSelectedMySelf();
\r
2736 new SwingBackgroundWorker(false) {
\r
2739 protected Object doWorks() throws Exception {
\r
2741 TatCount tc = new TatCount();
\r
2743 boolean succeeded = true;
\r
2745 HDDRecorderList recs;
\r
2746 if ( myself != null ) {
\r
2747 recs = recorders.findInstance(myself);
\r
2752 for ( HDDRecorder recorder : recs ) {
\r
2753 if ( ! recorder.isEditAutoReserveSupported() ) {
\r
2754 succeeded = false;
\r
2758 if ( ! recorder.GetRdAutoReserve(true) ) {
\r
2759 succeeded = false;
\r
2763 if ( succeeded ) {
\r
2765 mwin.appendMessage(String.format("【自動予約一覧の取得処理が完了しました】 所要時間: %.2f秒",tc.end()));
\r
2769 mwin.appendMessage(String.format("【自動予約一覧の取得処理に失敗しました】 所要時間: %.2f秒",tc.end()));
\r
2775 protected void doFinally() {
\r
2776 StWinSetVisible(false);
\r
2780 StWinSetLocationCenter(this);
\r
2781 StWinSetVisible(true);
\r
2786 /***************************************
\r
2788 **************************************/
\r
2791 * レコーダの情報を全部DLする(ステータスウィンドウは呼び出し元が準備する)
\r
2793 private void loadRdReservesAll(final boolean force, final String myself) {
\r
2795 new SwingBackgroundWorker(true) {
\r
2798 protected Object doWorks() throws Exception {
\r
2800 _loadRdRecorderAll(force,myself);
\r
2806 protected void doFinally() {
\r
2811 /***************************************
\r
2813 **************************************/
\r
2815 private boolean _loadRdRecorderAll(final boolean force, final String myself) {
\r
2817 HDDRecorderList recs;
\r
2818 if ( myself != null ) {
\r
2819 recs = recorders.findInstance(myself);
\r
2825 boolean success = true;
\r
2827 for ( HDDRecorder recorder : recs ) {
\r
2828 if ( recorder.isReserveListSupported() ) {
\r
2829 success = success & _loadRdRecorder(recorder, force);
\r
2836 private boolean _loadRdRecorder(HDDRecorder recorder, boolean force) {
\r
2838 mwin.appendMessage("【レコーダ情報取得】情報を取得します: "+recorder.Myself());
\r
2839 if ( recorder.isThereAdditionalDetails() && env.getForceLoadReserveDetails() == 2 ) {
\r
2840 mwin.appendMessage("<<<注意!>>>このレコーダでは予約詳細の個別取得を実行しないと正確な情報を得られない場合があります。");
\r
2846 if ( ! _loadRdSettings(recorder,force) ) {
\r
2851 if ( ! _loadRdReserves(recorder,force) ) {
\r
2855 // レコーダから取得したエンコーダ情報で、登録済みレコーダ一覧を更新する
\r
2856 setEncoderInfo2RecorderList(recorder,force);
\r
2858 // 予約詳細の取得(強制取得じゃなければ処理不要)
\r
2859 if ( force && ! _loadRdReserveDetails(recorder,force) ) {
\r
2863 // レコーダの放送局名をWeb番組表の放送局名に置き換え
\r
2864 checkChNameIsRight(recorder);
\r
2867 if ( ! _loadRdAutoReserves(recorder,force) ) {
\r
2872 if ( ! _loadRdRecorded(recorder,force) ) {
\r
2876 catch (Exception e) {
\r
2877 e.printStackTrace();
\r
2878 mwin.appendError("【致命的エラー】予約一覧の取得で例外が発生 "+recorder.getIPAddr()+":"+recorder.getPortNo()+":"+recorder.getRecorderId());
\r
2886 /***************************************
\r
2888 **************************************/
\r
2890 private boolean _loadRdSettings(HDDRecorder recorder, boolean force) {
\r
2891 if ( recorder.GetRdSettings(force) ) {
\r
2895 mwin.appendError(recorder.getErrmsg()+" "+recorder.Myself()); // 取得に失敗
\r
2900 private boolean _loadRdReserves(HDDRecorder recorder, boolean force) {
\r
2901 if ( recorder.GetRdReserve(force) ) {
\r
2905 mwin.appendError(recorder.getErrmsg()+" "+recorder.Myself()); // 取得に失敗
\r
2910 private boolean _loadRdReserveDetails(HDDRecorder recorder, boolean force) {
\r
2912 if ( ! recorder.isThereAdditionalDetails() ) {
\r
2913 return true; // 非対応レコーダ
\r
2916 boolean skip = false;
\r
2917 if ( force && env.getForceLoadReserveDetails() == 2 ) {
\r
2920 else if ( force && env.getForceLoadReserveDetails() == 0 ) {
\r
2921 int ret = JOptOptionPane.showConfirmDialog(stwin, "<HTML>詳細情報を取得しますか?(時間がかかります)<BR><BR>"+recorder.Myself()+"</HTML>", "今回の選択を既定の動作とする", "※既定動作は各種設定で変更できます", "確認", JOptionPane.YES_NO_OPTION);
\r
2922 skip = (ret != JOptOptionPane.YES_OPTION);
\r
2924 if ( JOptOptionPane.isSelected() ) {
\r
2926 env.setForceLoadReserveDetails(skip ? 2 : 1);
\r
2928 if (setting!=null) setting.updateSelections();
\r
2932 mwin.appendMessage("【!】予約詳細情報の取得はスキップされました");
\r
2936 if ( recorder.GetRdReserveDetails()) {
\r
2937 return true; // 取得成功
\r
2940 mwin.appendError(recorder.getErrmsg()+" "+recorder.Myself());
\r
2942 return false; // 取得失敗
\r
2945 private boolean _loadRdAutoReserves(HDDRecorder recorder, boolean force) {
\r
2947 if ( ! recorder.isEditAutoReserveSupported() ) {
\r
2951 boolean skip = false;
\r
2952 if ( force && env.getForceLoadAutoReserves() == 2 ) {
\r
2955 else if ( force && env.getForceLoadAutoReserves() == 0 ) {
\r
2956 int ret = JOptOptionPane.showConfirmDialog(stwin, "<HTML>自動予約一覧を取得しますか?(時間がかかります)<BR><BR>"+recorder.Myself()+"</HTML>", "今回の選択を既定の動作とする", "※既定動作は各種設定で変更できます", "確認", JOptionPane.YES_NO_OPTION);
\r
2957 skip = (ret != JOptOptionPane.YES_OPTION);
\r
2959 if ( JOptOptionPane.isSelected() ) {
\r
2961 env.setForceLoadAutoReserves(skip ? 2 : 1);
\r
2963 if (setting!=null) setting.updateSelections();
\r
2967 mwin.appendMessage("【!】自動予約一覧の取得はスキップされました");
\r
2971 if ( recorder.GetRdAutoReserve(force) ) {
\r
2975 mwin.appendError(recorder.getErrmsg()+" "+recorder.Myself());
\r
2980 private boolean _loadRdRecorded(HDDRecorder recorder, boolean force) {
\r
2982 if ( ! recorder.isRecordedListSupported() ) {
\r
2986 boolean skip = false;
\r
2987 if ( force && env.getForceLoadRecorded() == 2 ) {
\r
2990 if ( force && env.getForceLoadRecorded() == 0 ) {
\r
2991 int ret = JOptOptionPane.showConfirmDialog(stwin, "<HTML>録画結果一覧を取得しますか?(時間がかかります)<BR><BR>"+recorder.Myself()+"</HTML>", "今回の選択を既定の動作とする", "※既定動作は各種設定で変更できます", "確認", JOptionPane.YES_NO_OPTION);
\r
2992 skip = (ret != JOptOptionPane.YES_OPTION);
\r
2994 if ( JOptOptionPane.isSelected() ) {
\r
2996 env.setForceLoadRecorded(skip ? 2 : 1);
\r
2998 if (setting!=null) setting.updateSelections();
\r
3002 mwin.appendMessage("【!】録画結果一覧の取得はスキップされました");
\r
3006 if ( recorder.GetRdRecorded(force) ) {
\r
3010 mwin.appendError(recorder.getErrmsg()+" "+recorder.Myself());
\r
3016 * レコーダから取得したエンコーダ情報で、登録済みレコーダ一覧を更新する
\r
3019 private void setEncoderInfo2RecorderList(HDDRecorder recorder, boolean force) {
\r
3020 for (RecorderInfo ri : recInfoList ) {
\r
3021 //if (rl.getRecorderEncoderList().size() == 0)
\r
3023 //String mySelf = ri.getRecorderIPAddr()+":"+ri.getRecorderPortNo()+":"+ri.getRecorderId();
\r
3024 //String myMail = "MAIL"+":"+ri.getRecorderMacAddr()+":"+ri.getRecorderId();
\r
3025 //if (recorder.isMyself(mySelf) || recorder.isMyself(myMail)) {
\r
3026 if ( recorder.isMyself(ri.MySelf()) ) {
\r
3027 ri.clearEncoders();
\r
3028 for (TextValueSet enc : recorder.getEncoderList()) {
\r
3029 ri.addEncoder(enc.getText());
\r
3033 recInfoList.save();
\r
3042 * 予約一覧の放送局名が正しい形式であるかどうかのチェック
\r
3044 private void checkChNameIsRight(HDDRecorder recorder) {
\r
3045 HashMap<String,String> misCN = new HashMap<String,String>();
\r
3046 for ( ReserveList r : recorder.getReserves() ) {
\r
3047 if ( r.getCh_name() == null ) {
\r
3048 misCN.put(r.getChannel(),recorder.getRecorderId());
\r
3051 if ( misCN.size() > 0 ) {
\r
3052 for ( String cn : misCN.keySet() ) {
\r
3053 String msg = "【警告(予約一覧)】 <"+misCN.get(cn)+"> \"レコーダの放送局名\"を\"Web番組表の放送局名\"に変換できません。CHコード設定に設定を追加してください:\"レコーダの放送局名\"="+cn;
\r
3054 mwin.appendMessage(msg);
\r
3060 /*******************************************************************************
\r
3062 ******************************************************************************/
\r
3064 /***************************************
\r
3065 * ツールバートリガー(と、各種設定変更トリガー)による
\r
3066 **************************************/
\r
3070 * <P>単体実行の場合はこちらを呼び出す
\r
3071 * <P>部品実行の場合はこちらを呼び出す:{@link #loadTVProgram(boolean, LoadFor)}
\r
3072 * @see #doRedrawTVProgram()
\r
3074 private boolean doLoadTVProgram(final boolean force, final LoadFor lf) {
\r
3078 new SwingBackgroundWorker(false) {
\r
3081 protected Object doWorks() throws Exception {
\r
3083 TatCount tc = new TatCount();
\r
3085 loadTVProgram(force, lf);
\r
3087 mwin.appendMessage(String.format("[Web番組表取得] 【完了しました】 所要時間: %.2f秒",tc.end()));
\r
3092 protected void doFinally() {
\r
3093 StWinSetVisible(false);
\r
3097 StWinSetLocationCenter(this);
\r
3098 StWinSetVisible(true);
\r
3105 * @see #doLoadTVProgram(boolean, LoadFor)
\r
3107 private void doRedrawTVProgram() {
\r
3110 paper.clearPanel();
\r
3111 paper.buildMainViewByDate();
\r
3114 paper.redrawTreeByDate();
\r
3115 paper.redrawTreeByPassed();
\r
3117 listed.redrawTreeByHistory();
\r
3118 listed.redrawTreeByCenter();
\r
3121 paper.reselectTree();
\r
3122 listed.reselectTree();
\r
3125 /***************************************
\r
3127 **************************************/
\r
3131 * <P>単体実行の場合はこちらを呼び出す:{@link #doLoadTVProgram(boolean, tainavi.Viewer.LoadFor)}
\r
3132 * <P>部品実行の場合はこちらを呼び出す
\r
3134 private boolean loadTVProgram(final boolean force, final LoadFor lf) {
\r
3136 final String FUNCID = "[Web番組表取得] ";
\r
3137 final String ERRID = "[ERROR]"+FUNCID;
\r
3143 tvp = tvprograms.getTvProgPlugin(null);
\r
3144 if ( tvp != null )
\r
3146 String sType = "地上波&BS番組表";
\r
3147 if (lf == LoadFor.ALL || lf == LoadFor.TERRA) {
\r
3148 loadTVProgramOnce(tvp, sType, tvp.getSelectedArea(), false, force);
\r
3151 stwin.appendMessage(FUNCID+sType+"へのアクセスはスキップされました: "+tvp.getTVProgramId());
\r
3155 tvp = tvprograms.getCsProgPlugin(null);
\r
3156 if ( tvp != null )
\r
3158 String sType = "CS番組表[プライマリ]";
\r
3159 if (lf == LoadFor.ALL || lf == LoadFor.CS || lf == LoadFor.CSo1 || lf == LoadFor.CSwSD) {
\r
3160 loadTVProgramOnce(tvp, sType, tvp.getSelectedArea(), false, force);
\r
3163 stwin.appendMessage(FUNCID+sType+"へのアクセスはスキップされました: "+tvp.getTVProgramId());
\r
3167 tvp = tvprograms.getCs2ProgPlugin(null);
\r
3168 if ( tvp != null )
\r
3170 String sType = "CS番組表[セカンダリ]";
\r
3171 if (lf == LoadFor.ALL || lf == LoadFor.CS || lf == LoadFor.CSo2 || lf == LoadFor.CSwSD) {
\r
3172 loadTVProgramOnce(tvp, sType, tvp.getSelectedArea(), false, force);
\r
3175 stwin.appendMessage(FUNCID+sType+"へのアクセスはスキップされました: "+tvp.getTVProgramId());
\r
3179 tvp = tvprograms.getSyobo();
\r
3180 if ( tvp != null ) {
\r
3181 String sType = "しょぼかる";
\r
3182 if ( (lf == LoadFor.ALL || lf == LoadFor.SYOBO) && enableWebAccess && env.getUseSyobocal()) {
\r
3183 tvp.loadCenter(tvp.getSelectedCode(), force); // しょぼかるには放送局リストを取得するイベントが他にないので
\r
3184 loadTVProgramOnce(tvp, sType, null, true, force);
\r
3187 stwin.appendMessage(FUNCID+sType+"へのアクセスはスキップされました.");
\r
3190 // しょぼかるの新番組マークを引き継ぐ
\r
3194 PickedProgram pickup = tvprograms.getPickup();
\r
3195 if ( tvp != null ) {
\r
3205 stwin.appendMessage(FUNCID+"検索結果を生成します.");
\r
3206 mpList.clear(env.getDisableFazzySearch(), env.getDisableFazzySearchReverse());
\r
3207 mpList.build(tvprograms, trKeys.getTraceKeys(), srKeys.getSearchKeys());
\r
3210 if ( env.getUsePassedProgram() ) {
\r
3211 TatCount tc = new TatCount();
\r
3212 stwin.appendMessage(FUNCID+"過去ログを生成します.");
\r
3213 if ( tvprograms.getPassed().save(tvprograms.getIterator(), chsort.getClst(), env.getPrepPassedProgramCount()) ) {
\r
3214 msg = String.format(FUNCID+"過去ログを生成しました [%.2f秒].",tc.end());
\r
3215 StdAppendMessage(msg);
\r
3217 //PassedProgramList.getDateList(env.getPassedLogLimit());
\r
3220 stwin.appendMessage(FUNCID+"過去ログは記録されません.");
\r
3223 catch (Exception e) {
\r
3224 e.printStackTrace();
\r
3225 mwin.appendError(ERRID+"番組情報の取得で例外が発生");
\r
3234 private void loadTVProgramOnce(TVProgram tvp, String sType, String aName, boolean loadonly, boolean force) {
\r
3236 final String FUNCID = "[Web番組表取得] ";
\r
3237 // final String ERRID = "[ERROR]"+FUNCID;
\r
3240 String msg = FUNCID+sType+"を取得します: "+tvp.getTVProgramId();
\r
3241 stwin.appendMessage(msg);
\r
3242 if (aName!=null) stwin.appendMessage(FUNCID+"+選択されているエリア="+aName);
\r
3245 //tvp.setProgressArea(stwin);
\r
3246 tvp.loadProgram(tvp.getSelectedCode(), force);
\r
3253 tvp.setExtension(null, null, false, extKeys.getSearchKeys()); // 最初の3引数は盲腸。ダミー
\r
3255 tvp.abon(env.getNgword());
\r
3257 String errmsg = tvp.chkComplete();
\r
3258 if (errmsg != null) {
\r
3259 stwin.appendError(FUNCID+"取得した情報が不正です:"+errmsg);
\r
3260 if (mainWindow!=null) mwin.appendMessage(msg);
\r
3265 // しょぼかるの番組詳細を番組表に反映する
\r
3266 private void attachSyoboNew() {
\r
3267 TVProgram syobo = tvprograms.getSyobo();
\r
3268 if (syobo == null) {
\r
3272 for ( TVProgram tvp : tvprograms ) {
\r
3274 if ( tvp.getType() != ProgType.PROG ) {
\r
3277 if ( ! (tvp.getSubtype() == ProgSubtype.TERRA || tvp.getSubtype() == ProgSubtype.CS || tvp.getSubtype() == ProgSubtype.CS2) ) {
\r
3281 for ( ProgList tvpl : tvp.getCenters() ) {
\r
3282 if ( ! tvpl.enabled) {
\r
3285 for ( ProgList svpl : syobo.getCenters() ) {
\r
3286 if ( ! tvpl.Center.equals(svpl.Center)) {
\r
3289 for ( ProgDateList tvc : tvpl.pdate ) {
\r
3291 ProgDateList mSvc = null;
\r
3292 for ( ProgDateList svc : svpl.pdate ) {
\r
3293 if (tvc.Date.equals(svc.Date) ) {
\r
3298 if (mSvc == null) {
\r
3299 // しょぼかる側に該当する日付自体ないので全部フラグを立てっぱなしでいい
\r
3300 for ( ProgDetailList tvd : tvc.pdetail ) {
\r
3301 if ( tvd.isEqualsGenre(ProgGenre.ANIME, null) ) {
\r
3302 tvd.addOption(ProgOption.NOSYOBO);
\r
3307 // しょぼかる側に該当する日付があるのでマッチング。アニメと映画と音楽
\r
3308 for ( ProgDetailList tvd : tvc.pdetail ) {
\r
3310 // アニメはいったんフラグを立てる
\r
3311 if ( tvd.isEqualsGenre(ProgGenre.ANIME, null) ) {
\r
3312 tvd.addOption(ProgOption.NOSYOBO);
\r
3315 boolean isFind = false;
\r
3316 for ( ProgDetailList svd : mSvc.pdetail ) {
\r
3317 if ( tvd.start.equals(svd.start) ) {
\r
3321 //svd.progid = tvd.progid;
\r
3322 svd.setContentIdStr();
\r
3325 boolean isAnime = tvd.isEqualsGenre(ProgGenre.ANIME, null);
\r
3326 if ( ! isAnime && ! tvd.isEqualsGenre(ProgGenre.MOVIE, null) && ! tvd.isEqualsGenre(ProgGenre.MUSIC, null) ) {
\r
3333 // しょぼかるとWeb番組表の両方に存在する
\r
3334 svd.nosyobo = true;
\r
3338 boolean isAttached = false;
\r
3341 if ( svd.flag == ProgFlags.NEW && tvd.flag != ProgFlags.NEW ) {
\r
3342 tvd.flag = ProgFlags.NEW;
\r
3343 isAttached = true;
\r
3347 if ( svd.flag == ProgFlags.LAST && tvd.flag != ProgFlags.LAST ) {
\r
3348 tvd.flag = ProgFlags.LAST;
\r
3349 isAttached = true;
\r
3353 if ( tvd.isEqualsGenre(ProgGenre.MOVIE, null) && ! tvd.isEqualsGenre(ProgGenre.MOVIE, ProgSubgenre.MOVIE_ANIME) ) {
\r
3354 if ( tvd.genrelist == null ) {
\r
3355 tvd.genrelist = new ArrayList<ProgGenre>();
\r
3356 tvd.genrelist.add(tvd.genre);
\r
3357 tvd.genrelist.add(ProgGenre.MOVIE);
\r
3358 tvd.subgenrelist = new ArrayList<ProgSubgenre>();
\r
3359 tvd.subgenrelist.add(tvd.subgenre);
\r
3360 tvd.subgenrelist.add(ProgSubgenre.MOVIE_ANIME);
\r
3363 tvd.genrelist.add(ProgGenre.MOVIE);
\r
3364 tvd.subgenrelist.add(ProgSubgenre.MOVIE_ANIME);
\r
3366 isAttached = true;
\r
3370 for ( ProgOption sopt : svd.getOption() ) {
\r
3371 if ( tvd.addOption(sopt) && isAttached == false ) {
\r
3372 isAttached = true;
\r
3377 if (isAttached && env.getDebug()) {
\r
3378 StdAppendMessage("しょぼかるのフラグを引き継ぎました: ("+tvpl.Center+") "+tvd.title);
\r
3383 if ( tvd.detail.length() < svd.detail.length() ) {
\r
3384 tvd.detail = svd.detail;
\r
3387 int idx = svd.detail.indexOf("<!");
\r
3389 tvd.detail += svd.detail.substring(idx);
\r
3393 // 「しょぼかるにのみ存在」フラグの上げ下げ(これはアニメ限定)
\r
3396 tvd.removeOption(ProgOption.NOSYOBO); // NOSYOBOって…
\r
3399 //tvd.addOption(ProgOption.NOSYOBO);
\r
3416 private void fixTitle() {
\r
3417 // 番組追跡からサブタイトルを除外するかどうかのフラグ
\r
3418 ProgDetailList.tracenOnlyTitle = env.getFixTitle() && env.getTraceOnlyTitle();
\r
3420 if ( ! env.getFixTitle()) {
\r
3424 for ( TVProgram tvp : tvprograms ) {
\r
3425 //if ( ! (tvp.getType() == ProgType.PROG && tvp.getSubtype() == ProgSubtype.TERRA) ) {
\r
3426 if ( tvp.getType() != ProgType.PROG ) {
\r
3430 for ( ProgList pl : tvp.getCenters() ) {
\r
3431 if ( ! pl.enabled ) {
\r
3435 for ( ProgDateList pcl : pl.pdate ) {
\r
3437 for ( ProgDetailList tvd : pcl.pdetail ) {
\r
3438 if ( tvd.isEqualsGenre(ProgGenre.ANIME, null) ) {
\r
3439 if ( pl.Center.startsWith("NHK") || pl.Center.startsWith("NHK") ) {
\r
3440 // NHK系で先頭が「アニメ 」ではじまるものから「アニメ 」を削除する
\r
3441 tvd.title = tvd.title.replaceFirst("^アニメ[ ・]+","");
\r
3442 tvd.titlePop = TraceProgram.replacePop(tvd.title);
\r
3444 if ( tvd.title.contains("コメンタリ") || tvd.detail.contains("コメンタリ") ) {
\r
3445 // "コメンタリ"の記述のあるものは「副音声」扱いにする(副音声でなくても)
\r
3446 tvd.option.add(ProgOption.MULTIVOICE);
\r
3448 if ( (tvd.title.contains("劇場版") || (tvd.detail.contains("映画") && ! tvd.detail.contains("映画館"))) && ! tvd.isEqualsGenre(ProgGenre.MOVIE, ProgSubgenre.MOVIE_ANIME) ) {
\r
3449 // ジャンル=アニメだがタイトルに「劇場版」が含まれるならジャンル=映画(アニメ映画)を追加する
\r
3450 if ( tvd.genrelist == null ) {
\r
3451 tvd.genrelist = new ArrayList<ProgGenre>();
\r
3452 tvd.genrelist.add(tvd.genre);
\r
3453 tvd.genrelist.add(ProgGenre.MOVIE);
\r
3454 tvd.subgenrelist = new ArrayList<ProgSubgenre>();
\r
3455 tvd.subgenrelist.add(tvd.subgenre);
\r
3456 tvd.subgenrelist.add(ProgSubgenre.MOVIE_ANIME);
\r
3459 tvd.genrelist.add(ProgGenre.MOVIE);
\r
3460 tvd.subgenrelist.add(ProgSubgenre.MOVIE_ANIME);
\r
3464 else if ( tvd.isEqualsGenre(ProgGenre.MOVIE, ProgSubgenre.MOVIE_ANIME) && tvd.subgenre != ProgSubgenre.MOVIE_ANIME ) {
\r
3465 // ジャンル=映画でサブジャンルが複数ありアニメが優先されてないものはアニメを優先する
\r
3466 tvd.subgenre = ProgSubgenre.MOVIE_ANIME;
\r
3475 * {@link ProgDetailList} の情報を整形する
\r
3477 private void fixDetail() {
\r
3478 for ( TVProgram tvp : tvprograms ) {
\r
3479 for ( ProgList pl : tvp.getCenters() ) {
\r
3480 if ( ! pl.enabled ) {
\r
3483 for ( ProgDateList pcl : pl.pdate ) {
\r
3484 for ( ProgDetailList tvd : pcl.pdetail ) {
\r
3485 if ( tvd.start == null || tvd.start.length() == 0 ) {
\r
3489 fixDetailSub(tvp, pl, tvd);
\r
3496 private void fixDetailSub(TVProgram tvp, ProgList pl, ProgDetailList tvd) {
\r
3497 tvd.type = tvp.getType();
\r
3498 tvd.subtype = tvp.getSubtype();
\r
3499 tvd.center = pl.Center;
\r
3501 tvd.recmin = CommonUtils.getRecMinVal(tvd.startDateTime, tvd.endDateTime);
\r
3503 tvd.extension_mark = markchar.getExtensionMark(tvd);
\r
3504 tvd.prefix_mark = markchar.getOptionMark(tvd);
\r
3505 tvd.newlast_mark = markchar.getNewLastMark(tvd);
\r
3506 tvd.postfix_mark = markchar.getPostfixMark(tvd);
\r
3508 tvd.dontoverlapdown = (tvd.center.startsWith("NHK") || tvd.center.startsWith("NHK"));
\r
3512 /*******************************************************************************
\r
3514 ******************************************************************************/
\r
3517 * <P>過去ログから検索キーワードにマッチする情報を取得する
\r
3518 * <P>全部検索がヒットした結果がかえるのだから {@link ProgDetailList} ではなく {@link MarkedProgramList} を使うべきなのだが…
\r
3520 private boolean searchPassedProgram(final SearchKey sKey, final String target) {
\r
3522 Matcher ma = Pattern.compile("^(\\d\\d\\d\\d/\\d\\d/\\d\\d)-(\\d\\d\\d\\d/\\d\\d/\\d\\d)$").matcher(target);
\r
3523 if ( ! ma.find() ) {
\r
3527 final GregorianCalendar s = CommonUtils.getCalendar(ma.group(1));
\r
3528 final GregorianCalendar e = CommonUtils.getCalendar(ma.group(2));
\r
3529 final long dDays = (e.getTimeInMillis() - s.getTimeInMillis())/86400000 + 1;
\r
3531 final ArrayList<ProgDetailList> srchpdl = tvprograms.getSearched().getResultBuffer(sKey.getLabel()) ;
\r
3535 // 検索実行(時間がかかるので状況表示する)
\r
3536 new SwingBackgroundWorker(false) {
\r
3539 protected Object doWorks() throws Exception {
\r
3541 TatCount tc = new TatCount();
\r
3544 int resultCnt = 0;
\r
3545 for (int cnt=1; cnt<=dDays; cnt++) {
\r
3547 String passdt = CommonUtils.getDate(e);
\r
3548 stwin.appendMessage(String.format("[過去ログ検索] 検索中:(%d/%d) %s", cnt, dDays, passdt));
\r
3550 PassedProgram tvp = new PassedProgram();
\r
3551 if ( tvp.loadAllCenters(passdt) ) {
\r
3552 for ( ProgList pl : tvp.getCenters() ) {
\r
3553 if ( ! pl.enabled ) {
\r
3557 for ( ProgDateList pcl : pl.pdate ) {
\r
3558 for ( ProgDetailList tvd : pcl.pdetail ) {
\r
3559 if ( tvd.start == null || tvd.start.length() == 0 ) {
\r
3563 if ( SearchProgram.isMatchKeyword(sKey, pl.Center, tvd) ) {
\r
3564 tvd.dynKey = sKey;
\r
3565 tvd.dynMatched = SearchProgram.getMatchedString();
\r
3566 fixDetailSub(tvp, pl, tvd);
\r
3568 if ( ++resultCnt >= env.getSearchResultMax() ) {
\r
3569 mwin.appendMessage(String.format("[過去ログ検索] 検索件数の上限に到達しました。所要時間: %.2f秒",tc.end()));
\r
3578 e.add(Calendar.DATE,-1);
\r
3581 mwin.appendMessage(String.format("[過去ログ検索] 検索完了。所要時間: %.2f秒",tc.end()));
\r
3586 protected void doFinally() {
\r
3587 StWinSetVisible(false);
\r
3591 StWinSetLocationCenter(this);
\r
3592 StWinSetVisible(true);
\r
3598 /*******************************************************************************
\r
3600 ******************************************************************************/
\r
3603 * 番組表のスナップショットをファイルに保存したり印刷したりする
\r
3605 private boolean getSnapshot(int currentpage, int numberofpages) {
\r
3609 if ( mainWindow.isTabSelected(MWinTab.LISTED) ) {
\r
3611 fname = String.format("snapshot.%s",env.getSnapshotFmt().getExtension());
\r
3612 CommonSwingUtils.saveComponentAsJPEG(listed.getCurrentView(), listed.getTableHeader(), null, listed.getTableBody(), fname, env.getSnapshotFmt(), Viewer.this);
\r
3614 else if ( mainWindow.isTabSelected(MWinTab.PAPER) ){
\r
3616 if ( env.getDrawcacheEnable() || ! env.isPagerEnabled() ) {
\r
3617 fname = String.format("snapshot.%s",env.getSnapshotFmt().getExtension());
\r
3620 if ( env.getAllPageSnapshot() ) {
\r
3621 for ( int i=0; i<numberofpages; i++ ) {
\r
3622 if ( i != currentpage ) {
\r
3623 // カレントページは最後にスナップる(再描画を1回で済ませるため)
\r
3624 toolBar.setSelectedPagerIndex(i);
\r
3625 fname = String.format("snapshot%02d.%s",i+1,env.getSnapshotFmt().getExtension());
\r
3626 CommonSwingUtils.saveComponentAsJPEG(paper.getCurrentView(), paper.getCenterPane(), paper.getTimebarPane(), paper.getCurrentPane(), fname, env.getSnapshotFmt(), Viewer.this);
\r
3630 fname = String.format("snapshot%02d.%s",currentpage+1,env.getSnapshotFmt().getExtension());
\r
3631 toolBar.setSelectedPagerIndex(currentpage);
\r
3633 CommonSwingUtils.saveComponentAsJPEG(paper.getCurrentView(), paper.getCenterPane(), paper.getTimebarPane(), paper.getCurrentPane(), fname, env.getSnapshotFmt(), Viewer.this);
\r
3640 Desktop desktop = Desktop.getDesktop();
\r
3641 if (env.getPrintSnapshot()) {
\r
3643 desktop.print(new File(fname));
\r
3647 String emsg = CommonUtils.openFile(fname);
\r
3648 if (emsg != null) {
\r
3649 mwin.appendError(emsg);
\r
3656 } catch (IOException e) {
\r
3657 e.printStackTrace();
\r
3664 /*******************************************************************************
\r
3665 * ここからおおむね初期化処理にかかわるメソッド群
\r
3666 ******************************************************************************/
\r
3671 private boolean setEnv(final boolean reload_prog) {
\r
3677 // CommonUtilsの設定変更
\r
3678 CommonUtils.setAdjLateNight(env.getAdjLateNight());
\r
3679 CommonUtils.setExpandTo8(env.getExpandTo8());
\r
3680 CommonUtils.setUseRundll32(env.getUseRundll32());
\r
3681 CommonUtils.setDisplayPassedReserve(env.getDisplayPassedReserve());
\r
3682 CommonUtils.setDebug(env.getDebug());
\r
3684 SwingBackgroundWorker.setDebug(env.getDebug());
\r
3687 toolBar.setDebug(env.getDebug());
\r
3688 autores.setDebug(env.getDebug());
\r
3689 rdialog.setDebug(env.getDebug());
\r
3691 // PassedProgramListの設定変更
\r
3692 tvprograms.getPassed().setPassedDir(env.getPassedDir());
\r
3695 for ( HDDRecorder rec : recorders ) {
\r
3697 setSettingRecPluginExt(rec, env);
\r
3701 setSettingProgPluginCommon(env);
\r
3704 setSettingProgPluginAll(env);
\r
3707 toolBar.updateReloadReservedExtension();
\r
3708 toolBar.updateReloadProgramExtension();
\r
3710 // ページャーコンボボックスの書き換え
\r
3711 toolBar.setPagerItems();
\r
3714 listed.setMarkColumnVisible(env.getSplitMarkAndTitle());
\r
3715 listed.setDetailColumnVisible(env.getShowDetailOnList());
\r
3716 listed.setPickupColumnVisible(env.getShowRsvPickup());
\r
3717 listed.setDupColumnVisible(env.getShowRsvDup());
\r
3718 listed.setRowHeaderVisible(env.getRowHeaderVisible());
\r
3719 reserved.setRowHeaderVisible(env.getRowHeaderVisible());
\r
3722 listed.setMatchedKeywordColor(env.getMatchedKeywordColor());
\r
3723 listed.setRsvdLineColor((env.getRsvdLineEnhance())?(env.getRsvdLineColor()):(null));
\r
3724 listed.setPickedLineColor((env.getRsvdLineEnhance())?(env.getPickedLineColor()):(null));
\r
3725 listed.setCurrentLineColor((env.getCurrentLineEnhance())?(env.getCurrentLineColor()):(null));
\r
3728 setTrayIconVisible(env.getShowSysTray());
\r
3729 setXButtonAction(env.getShowSysTray() && env.getHideToTray());
\r
3731 // 新聞形式のツールチップの表示時間を変更する
\r
3732 setTooltipDelay();
\r
3735 if ( reload_prog ) {
\r
3736 loadTVProgram(false, LoadFor.ALL); // 部品呼び出し
\r
3740 mpList.setHistoryOnlyUpdateOnce(env.getHistoryOnlyUpdateOnce());
\r
3741 mpList.setShowOnlyNonrepeated(env.getShowOnlyNonrepeated());
\r
3743 doRedrawTVProgram(); // か き な お し
\r
3749 private void getTrayIcon() {
\r
3750 if ( trayicon != null ) {
\r
3755 Image image = ImageIO.read(new File(ICONFILE_SYSTRAY));
\r
3756 trayicon = new TrayIcon(image,"Tainavi");
\r
3758 final Viewer thisClass = this;
\r
3761 PopupMenu popup = new PopupMenu();
\r
3763 MenuItem item = new MenuItem("開く");
\r
3764 item.addActionListener(new ActionListener() {
\r
3766 public void actionPerformed(ActionEvent e) {
\r
3767 thisClass.setVisible(true);
\r
3768 thisClass.setState(Frame.NORMAL);
\r
3774 MenuItem item = new MenuItem("終了する");
\r
3775 item.addActionListener(new ActionListener() {
\r
3777 public void actionPerformed(ActionEvent e) {
\r
3784 trayicon.setPopupMenu(popup);
\r
3787 trayicon.addMouseListener(new MouseAdapter() {
\r
3789 public void mouseClicked(MouseEvent e) {
\r
3790 if (e.getButton() == MouseEvent.BUTTON1) {
\r
3791 thisClass.setVisible(true);
\r
3792 thisClass.setState(Frame.NORMAL);
\r
3797 } catch (IOException e) {
\r
3798 StdAppendError("アイコンファイルが読み込めませんでした: "+ICONFILE_SYSTRAY);
\r
3799 e.printStackTrace();
\r
3802 private void setTrayIconVisible(boolean b) {
\r
3804 if ( ! SystemTray.isSupported() || trayicon == null ) {
\r
3811 SystemTray.getSystemTray().remove(trayicon);
\r
3812 SystemTray.getSystemTray().add(trayicon);
\r
3816 SystemTray.getSystemTray().remove(trayicon);
\r
3818 } catch (AWTException e) {
\r
3819 e.printStackTrace();
\r
3822 private void HideToTray() {
\r
3823 if ( SystemTray.isSupported() && trayicon != null && (env.getShowSysTray() && env.getHideToTray()) ) {
\r
3824 this.setVisible(false);
\r
3827 private void setXButtonAction(boolean b) {
\r
3829 this.setDefaultCloseOperation(JFrame.ICONIFIED);
\r
3832 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
\r
3837 private void procArgs(String[] args) {
\r
3839 for (String arg : args) {
\r
3842 if (arg.compareTo("-L") == 0) {
\r
3844 //logging = false;
\r
3846 else if (arg.compareTo("-L") == 0) {
\r
3850 else if (arg.compareTo("-w") == 0) {
\r
3852 runRecWakeup = true;
\r
3854 else if (arg.compareTo("-nowebaccess") == 0) {
\r
3855 // -nowebaccess : 起動時のWeb番組表へのアクセス無効
\r
3856 enableWebAccess = false;
\r
3858 else if (arg.compareTo("-proxy") == 0) {
\r
3859 // -proxy : Web番組表へのアクセスにProxy経由を強制する
\r
3862 else if (arg.compareTo("-loadrec") == 0) {
\r
3863 // -loadrec : 起動時にレコーダにアクセスする
\r
3864 runRecLoad = true;
\r
3866 else if (arg.compareTo("-onlyLoadProgram") == 0) {
\r
3867 // -onlyLoadProgram : 番組表の取得だけ行う
\r
3868 onlyLoadProgram = true;
\r
3872 String[] dat = arg.split(":");
\r
3873 if (dat.length == 1 ) {
\r
3876 } if (dat.length >= 2 ) {
\r
3886 // メインの環境設定ファイルを読みだす
\r
3887 private void loadEnvfile() {
\r
3888 StdAppendMessage("【環境設定】環境設定ファイルを読み込みます.");
\r
3892 // 引き続きその他の環境設定ファイルも読みだす
\r
3893 private void procEnvs() {
\r
3895 StdAppendMessage("【環境設定】環境設定ファイル類を読み込みます.");
\r
3901 recInfoList.load();
\r
3904 if (pxaddr != null) {
\r
3905 env.setUseProxy(true);
\r
3906 env.setProxyAddr(pxaddr);
\r
3907 env.setProxyPort(pxport);
\r
3910 // Cookieの処理を入れようとしたけど無理だった
\r
3913 CookieManager manager = new CookieManager();
\r
3914 manager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
\r
3915 CookieHandler.setDefault(manager);
\r
3922 // 深夜の帯予約の補正(一日前にずらす)
\r
3923 // 可能なら番組表を8日分取得する
\r
3924 // 【WIN】ファイルオープンにrundll32を使用する
\r
3925 CommonUtils.setAdjLateNight(env.getAdjLateNight());
\r
3926 CommonUtils.setExpandTo8(env.getExpandTo8());
\r
3927 CommonUtils.setUseRundll32(env.getUseRundll32());
\r
3928 CommonUtils.setDisplayPassedReserve(env.getDisplayPassedReserve());
\r
3929 CommonUtils.setDebug(env.getDebug());
\r
3931 SwingBackgroundWorker.setDebug(env.getDebug());
\r
3937 bounds.setLoaded(bounds.load());
\r
3955 // スポーツ延長警告のデフォルト設定のコードはもういらないので削除(3.15.4β)
\r
3957 // 簡易描画はもういらないので削除
\r
3964 private void chkDualBoot() {
\r
3965 if ( ! env.getOnlyOneInstance() ) {
\r
3969 if ( ! CommonUtils.getLock() ) {
\r
3975 Runtime.getRuntime().addShutdownHook(new Thread() {
\r
3976 public void run() {
\r
3977 // 鯛ナビ終了時にロックを解除する
\r
3978 CommonUtils.getUnlock();
\r
3984 private void chkVerUp() {
\r
3985 if ( ! enableWebAccess || onlyLoadProgram ) {
\r
3986 stwin.appendError("【オンラインアップデート】オンラインアップデートは無効です");
\r
3990 VWUpdate vu = new VWUpdate(stwin);
\r
3991 if ( ! vu.isExpired(env.getUpdateMethod()) ) {
\r
3992 // メッセージはVWUpdate内で出力されます
\r
3995 if ( doVerUp(vu) ) {
\r
4000 private boolean doVerUp(VWUpdate vu) {
\r
4001 UpdateResult res = vu.checkUpdate(VersionInfo.getVersion());
\r
4005 // 履歴は更新しない(連続アップデートがあるかも知れないので)
\r
4006 LogViewer lv = new LogViewer(HISTORY_FILE);
\r
4007 lv.setModal(true);
\r
4008 lv.setCaretPosition(0);
\r
4009 lv.setVisible(true);
\r
4013 // 履歴は更新しない(次回に持ち越し)
\r
4017 vu.updateHistory();
\r
4021 // 履歴は更新しない(次回再挑戦)
\r
4028 * レコーダプラグインをすべて読み込みます。
\r
4030 private boolean loadRecPlugins() {
\r
4032 stwin.appendMessage("【レコーダプラグイン】プラグインを読み込みます.");
\r
4034 boolean isMailPluginEnabled = false;
\r
4036 Class.forName("javax.mail.Session");
\r
4037 isMailPluginEnabled = true;
\r
4039 catch ( Exception e ) {
\r
4040 System.err.println("【レコーダプラグイン】メール系プラグイン用の外部ライブラリがみつかりません: "+e.toString());
\r
4043 boolean isCalendarPluginEnabled = false;
\r
4045 Class.forName("com.google.gdata.client.calendar.CalendarService");
\r
4046 isCalendarPluginEnabled = true;
\r
4048 catch ( Exception e ) {
\r
4049 System.err.println("【レコーダプラグイン】カレンダー系プラグイン用の外部ライブラリがみつかりません: "+e.toString());
\r
4053 ArrayList<String> recIda = new ArrayList<String>();
\r
4054 for ( File f : new File(CommonUtils.joinPath(new String[]{"bin","tainavi","pluginrec"})).listFiles() ) {
\r
4055 Matcher ma = Pattern.compile("^(PlugIn_Rec[^$]+)[^$]*\\.class$").matcher(f.getName());
\r
4056 if ( ma.find() ) {
\r
4057 if ( ! isMailPluginEnabled && f.getName().toLowerCase().contains("mail") ) {
\r
4058 System.out.println("【レコーダプラグイン】メール系プラグインは無効です: "+f.getName());
\r
4061 if ( ! isCalendarPluginEnabled && f.getName().toLowerCase().contains("calendar") ) {
\r
4062 System.out.println("【レコーダプラグイン】カレンダー系プラグインは無効です: "+f.getName());
\r
4066 recIda.add(ma.group(1));
\r
4069 String[] recIdd = recIda.toArray(new String[0]);
\r
4070 Arrays.sort(recIdd);
\r
4073 StringBuilder sb = new StringBuilder();
\r
4074 for ( String recId : recIdd ) {
\r
4075 sb.append("tainavi.pluginrec.");
\r
4079 if ( ! CommonUtils.write2file(CommonUtils.joinPath(new String[] {"bin","META-INF","services","tainavi.HDDRecorder"}), sb.toString()) ) {
\r
4080 stwin.appendError("【レコーダプラグイン】プラグインの読み込みに失敗しました: ");
\r
4084 // ここで例外が起きてもトラップできない、スレッドが落ちる
\r
4085 ServiceLoader<HDDRecorder> r = ServiceLoader.load(HDDRecorder.class);
\r
4087 recPlugins.clear();
\r
4088 for ( HDDRecorder recorder : r ) {
\r
4089 if (env.getDebug()) {
\r
4090 StdAppendMessage("+追加します: "+recorder.getRecorderId());
\r
4092 recPlugins.add(recorder.clone());
\r
4093 StdAppendMessage("+追加しました: "+recorder.getRecorderId());
\r
4100 * レコーダ設定をもとにレコーダプラグインから実レコーダのインスタンスを生成します。
\r
4102 private void initRecPluginAll() {
\r
4104 recorders.clear();
\r
4105 for ( RecorderInfo ri : recInfoList ) {
\r
4106 ArrayList<HDDRecorder> rl = recPlugins.findPlugin(ri.getRecorderId());
\r
4107 if ( rl.size() == 0 ) {
\r
4108 stwin.appendError("【レコーダプラグイン】プラグインがみつかりません: "+ri.getRecorderId()+"("+ri.getRecorderIPAddr()+":"+ri.getRecorderPortNo()+")");
\r
4111 stwin.appendMessage("【レコーダプラグイン】プラグインを初期化します: "+ri.getRecorderId()+"("+ri.getRecorderIPAddr()+":"+ri.getRecorderPortNo()+")");
\r
4112 for ( HDDRecorder rPlugin : rl ) {
\r
4113 initRecPlugin(rPlugin, ri);
\r
4118 protected HDDRecorder initRecPlugin(HDDRecorder rPlugin, RecorderInfo ri) {
\r
4119 HDDRecorder rec = rPlugin.clone();
\r
4120 recorders.add(rec);
\r
4122 rec.getChCode().load(true); // true : ログ出力あり
\r
4123 setSettingRecPluginBase(rec, ri);
\r
4124 setSettingRecPluginExt(rec,env);
\r
4125 rec.setProgressArea(stwin);
\r
4128 protected void setSettingRecPluginBase(HDDRecorder to, RecorderInfo from) {
\r
4129 to.setIPAddr(from.getRecorderIPAddr());
\r
4130 to.setPortNo(from.getRecorderPortNo());
\r
4131 to.setUser(from.getRecorderUser());
\r
4132 to.setPasswd(from.getRecorderPasswd());
\r
4133 to.setMacAddr(from.getRecorderMacAddr());
\r
4134 to.setBroadcast(from.getRecorderBroadcast());
\r
4135 to.setUseCalendar(from.getUseCalendar());
\r
4136 to.setUseChChange(from.getUseChChange());
\r
4137 to.setRecordedCheckScope(from.getRecordedCheckScope());
\r
4138 to.setTunerNum(from.getTunerNum());
\r
4139 to.setColor(from.getRecorderColor());
\r
4141 protected void setSettingRecPluginExt(HDDRecorder recorder, Env nEnv) {
\r
4142 recorder.setUserAgent(nEnv.getUserAgent());
\r
4143 recorder.setDebug(nEnv.getDebug());
\r
4144 recorder.setAdjNotRep(nEnv.getAdjoiningNotRepetition());
\r
4145 recorder.setRecordedSaveScope(nEnv.getRecordedSaveScope());
\r
4149 protected void doRecWakeup() {
\r
4150 for ( HDDRecorder rec : recorders ) {
\r
4151 if ( ! rec.getMacAddr().equals("") && ! rec.getBroadcast().equals("") ) {
\r
4160 private boolean isOLPExpired(int expire) {
\r
4161 String fname = "env"+File.separator+"olp.history";
\r
4162 if ( ! new File(fname).exists() || ! new File(fname).canWrite() ) {
\r
4163 stwin.appendError("【警告】実行履歴ファイルがないから実行させないよ!");
\r
4167 String dat = CommonUtils.read4file(fname, true);
\r
4168 if ( dat == null ) {
\r
4169 stwin.appendError("【警告】実行履歴を取得できなかったから実行させないよ!");
\r
4173 GregorianCalendar ca = null;
\r
4174 dat = EncryptPassword.dec(b64.dec(dat));
\r
4175 if ( dat != null ) {
\r
4176 ca = CommonUtils.getCalendar(dat);
\r
4178 if ( ca == null ) {
\r
4179 stwin.appendError("【警告】実行履歴の内容が不正だったから実行させないよ! "+dat);
\r
4183 if ( CommonUtils.getCompareDateTime(ca, CommonUtils.getCalendar(-expire*3600)) >= 0 ) {
\r
4184 ca.add(Calendar.HOUR,expire);
\r
4185 stwin.appendError("【警告】"+expire+"時間以内の再実行は許さないよ!"+CommonUtils.getDateTime(ca)+"まで待って!");
\r
4189 if ( ! CommonUtils.write2file(fname, b64.enc(EncryptPassword.enc(CommonUtils.getDateTime(0)))) ) {
\r
4190 stwin.appendError("【警告】実行履歴を保存できなかったから実行させないよ!");
\r
4199 * Web番組表プラグインをすべて読み込みます。
\r
4201 private boolean loadProgPlugins() {
\r
4203 final String FUNCID = "[Web番組表プラグイン組込] ";
\r
4204 final String ERRID = "[ERROR]"+FUNCID;
\r
4207 stwin.appendMessage(FUNCID+"プラグインを読み込みます.");
\r
4210 setSettingProgPluginCommon(env);
\r
4216 // TVProgramListのインスタンスは別途初期化が必要
\r
4217 progPlugins.clear();
\r
4218 tvprograms.clear();
\r
4224 ArrayList<String> prgIda = new ArrayList<String>();
\r
4225 for ( File f : new File(CommonUtils.joinPath("bin","tainavi","plugintv")).listFiles() ) {
\r
4226 Matcher ma = Pattern.compile("^(PlugIn_(TV|CS|RAD)P[^$]+)\\.class$").matcher(f.getName());
\r
4228 prgIda.add(ma.group(1));
\r
4231 String[] prgIdd = prgIda.toArray(new String[0]);
\r
4232 Arrays.sort(prgIdd);
\r
4235 StringBuilder sb = new StringBuilder();
\r
4236 for ( String prgId : prgIdd ) {
\r
4237 sb.append("tainavi.plugintv.");
\r
4241 if ( ! CommonUtils.write2file(CommonUtils.joinPath("bin","META-INF","services","tainavi.TVProgram"), sb.toString()) ) {
\r
4242 stwin.appendError(ERRID+"プラグインの読み込みに失敗しました: ");
\r
4246 ServiceLoader<TVProgram> p = ServiceLoader.load(TVProgram.class);
\r
4248 // 実際必要ないのだが、プラグインのインスタンスはclone()して使う
\r
4249 for ( TVProgram pg : p ) {
\r
4250 TVProgram prog = pg.clone();
\r
4252 stwin.appendMessage("+追加しました: "+prog.getTVProgramId());
\r
4254 // CH設定タブではプラグイン側のインスタンスを使うので情報を追加してやる必要があるのであった
\r
4255 setSettingProgPlugin(prog, env);
\r
4257 progPlugins.add(prog);
\r
4266 * 設定にあわせてWeb番組表プラグインを絞り込みます。
\r
4268 private void setSelectedProgPlugin() {
\r
4271 Syobocal syobo = tvprograms.getSyobo();
\r
4272 PassedProgram passed = tvprograms.getPassed();
\r
4273 PickedProgram pickup = tvprograms.getPickup();
\r
4274 SearchResult searched = tvprograms.getSearched();
\r
4276 tvprograms.clear();
\r
4279 TVProgram tvp = progPlugins.getTvProgPlugin(env.getTVProgramSite());
\r
4280 if ( tvp == null ) {
\r
4281 // デフォルトもなければ先頭にあるもの
\r
4282 tvp = progPlugins.getTvProgPlugin(null);
\r
4284 if ( tvp == null ) {
\r
4286 StdAppendError("【Web番組表選択】地上波&BS番組表が選択されていません: "+env.getTVProgramSite());
\r
4289 StdAppendMessage("【Web番組表選択】地上波&BS番組表が選択されました: "+tvp.getTVProgramId());
\r
4290 tvprograms.add(tvp.clone());
\r
4294 TVProgram tvp = progPlugins.getCsProgPlugin(env.getCSProgramSite());
\r
4295 if ( tvp == null ) {
\r
4296 tvp = progPlugins.getCsProgPlugin(null);
\r
4298 if ( tvp == null ) {
\r
4299 StdAppendError("【Web番組表選択】CS番組表[プライマリ]が選択されていません: "+env.getCSProgramSite());
\r
4302 StdAppendMessage("【Web番組表選択】CS番組表[プライマリ]が選択されました: "+tvp.getTVProgramId());
\r
4303 tvprograms.add(tvp.clone());
\r
4307 TVProgram tvp = progPlugins.getCs2ProgPlugin(env.getCS2ProgramSite());
\r
4308 if ( tvp == null ) {
\r
4309 tvp = progPlugins.getCs2ProgPlugin(null);
\r
4311 if ( tvp == null ) {
\r
4312 StdAppendError("【Web番組表選択】CS番組表[プライマリ]が選択されていません: "+env.getCS2ProgramSite());
\r
4315 StdAppendMessage("【Web番組表選択】CS番組表[プライマリ]が選択されました: "+tvp.getTVProgramId());
\r
4316 tvprograms.add(tvp.clone());
\r
4320 if ( progPlugins.getRadioProgPlugins().size() > 0 )
\r
4322 TVProgram tvp = progPlugins.getCsProgPlugin(env.getRadioProgramSite());
\r
4323 if ( tvp == null ) {
\r
4324 tvp = progPlugins.getCsProgPlugin(null);
\r
4326 if ( tvp == null ) {
\r
4327 StdAppendError("【Web番組表選択】ラジオ番組表が選択されていません: "+env.getRadioProgramSite());
\r
4330 StdAppendMessage("【Web番組表選択】ラジオ番組表が選択されました: "+tvp.getTVProgramId());
\r
4331 tvprograms.add(tvp.clone());
\r
4337 if ( syobo == null ) {
\r
4338 syobo = new Syobocal();
\r
4340 tvprograms.add(syobo);
\r
4343 if ( passed == null ) {
\r
4344 passed = new PassedProgram();
\r
4346 tvprograms.add(passed);
\r
4349 if ( pickup == null ) {
\r
4350 pickup = new PickedProgram();
\r
4351 pickup.loadProgram(null, false);
\r
4353 tvprograms.add(pickup);
\r
4356 if ( searched == null ) {
\r
4357 searched = new SearchResult();
\r
4359 tvprograms.add(searched);
\r
4364 * Web番組表設定をもとにレコーダプラグインのインスタンスを生成します。
\r
4366 private void initProgPluginAll() {
\r
4368 final String FUNCID = "[Web番組表プラグイン初期化] ";
\r
4369 final LinkedHashMap<ArrayList<TVProgram>,String> map = new LinkedHashMap<ArrayList<TVProgram>, String>();
\r
4370 map.put(tvprograms.getTvProgPlugins(), "地上波&BS番組表");
\r
4371 map.put(tvprograms.getCsProgPlugins(), "CS番組表[プライマリ]");
\r
4372 map.put(tvprograms.getCs2ProgPlugins(), "CS番組表[セカンダリ]");
\r
4373 //map.put(progPlugins.getRadioProgPlugins(), "ラジオ番組表");
\r
4375 new SwingBackgroundWorker(true) {
\r
4378 protected Object doWorks() throws Exception {
\r
4380 for ( ArrayList<TVProgram> tvpa : map.keySet() ) {
\r
4381 stwin.appendMessage(FUNCID+map.get(tvpa)+"のベース情報(放送局リストなど)を取得します.");
\r
4382 for ( TVProgram p : tvpa ) {
\r
4383 stwin.appendMessage(FUNCID+"プラグインを初期化します: "+p.getTVProgramId());
\r
4386 // 個別設定(2) …(1)と(2)の順番が逆だったので前に移動してきました(3.17.3β)
\r
4387 setSettingProgPlugin(p,env); // 他からも呼び出される部分だけ分離
\r
4390 p.setOptString(null); // フリーオプション初期化
\r
4391 p.loadAreaCode(); // 放送エリア情報取得
\r
4392 p.loadCenter(p.getSelectedCode(),false); // 放送局情報取得
\r
4393 p.setSortedCRlist(); // 有効放送局だけよりわける
\r
4395 catch (Exception e) {
\r
4396 stwin.appendError(FUNCID+"ベース情報の取得に失敗しました.");
\r
4397 e.printStackTrace();
\r
4403 //setSettingProgPluginAll(env);
\r
4405 if ( env.getUseSyobocal() ) {
\r
4406 TVProgram syobo = tvprograms.getSyobo();
\r
4407 if ( syobo != null ) {
\r
4408 stwin.appendMessage(FUNCID+"しょぼかるを初期化します.");
\r
4409 setSettingProgPlugin(syobo,env); // 他からも呼び出される部分だけ分離
\r
4410 syobo.setUserAgent("tainavi");
\r
4411 syobo.setOptString(null); // フリーオプション初期化
\r
4412 syobo.loadCenter(syobo.getSelectedCode(), false);
\r
4420 protected void doFinally() {
\r
4424 protected void setSettingProgPluginAll(Env nEnv) {
\r
4426 setSettingProgPlugin(tvprograms.getTvProgPlugin(null),nEnv);
\r
4427 setSettingProgPlugin(tvprograms.getCsProgPlugin(null),nEnv);
\r
4428 setSettingProgPlugin(tvprograms.getCs2ProgPlugin(null),nEnv);
\r
4429 //setSettingProgPlugin(tvprograms.getRadioProgPlugin(null),nEnv);
\r
4430 setSettingProgPlugin(tvprograms.getSyobo(),nEnv);
\r
4433 tvprograms.getSyobo().setUserAgent("tainavi");
\r
4435 tvprograms.getSearched().setResultBufferMax(nEnv.getSearchResultBufferMax());
\r
4437 protected void setSettingProgPlugin(TVProgram p, Env nEnv) {
\r
4438 if ( p == null ) {
\r
4441 p.setUserAgent(nEnv.getUserAgent());
\r
4442 p.setProgDir(nEnv.getProgDir());
\r
4443 p.setCacheExpired((enableWebAccess)?(nEnv.getCacheTimeLimit()):(0));
\r
4444 p.setContinueTomorrow(nEnv.getContinueTomorrow());
\r
4445 p.setExpandTo8(nEnv.getExpandTo8());
\r
4446 //p.setUseDetailCache(nEnv.getUseDetailCache());
\r
4447 p.setUseDetailCache(false);
\r
4448 p.setSplitEpno(nEnv.getSplitEpno());
\r
4452 * staticで持っている共通設定の更新
\r
4454 protected void setSettingProgPluginCommon(Env nEnv) {
\r
4456 if ( nEnv.getUseProxy() && (nEnv.getProxyAddr().length() > 0 && nEnv.getProxyPort().length() > 0) ) {
\r
4457 stwin.appendMessage("+Web番組表へのアクセスにProxyが設定されています: "+nEnv.getProxyAddr()+":"+nEnv.getProxyPort());
\r
4458 TVProgramUtils.setProxy(nEnv.getProxyAddr(),nEnv.getProxyPort());
\r
4461 TVProgramUtils.setProxy(null,null);
\r
4464 TVProgramUtils.setProgressArea(stwin);
\r
4465 TVProgramUtils.setChConv(chconv);
\r
4469 private void initMpList() {
\r
4470 //mpList = new MarkedProgramList(); // 検索結果リスト
\r
4471 mpList.setHistoryOnlyUpdateOnce(env.getHistoryOnlyUpdateOnce());
\r
4472 mpList.setShowOnlyNonrepeated(env.getShowOnlyNonrepeated());
\r
4476 private void initLookAndFeelAndFont() {
\r
4480 vwlaf = new VWLookAndFeel();
\r
4482 String lafname = vwlaf.update(env.getLookAndFeel());
\r
4483 if ( lafname != null && ! lafname.equals(env.getLookAndFeel())) {
\r
4484 env.setLookAndFeel(lafname);
\r
4487 if ( CommonUtils.isMac() ) {
\r
4488 UIManager.getDefaults().put("Table.gridColor", new Color(128,128,128));
\r
4489 //UIManager.getDefaults().put("Table.selectionBackground", new Color(182,207,229));
\r
4490 //UIManager.getDefaults().put("Table.selectionForeground", new Color(0,0,0));
\r
4495 vwfont = new VWFont();
\r
4497 String fname = vwfont.update(env.getFontName(),env.getFontSize());
\r
4498 if ( fname != null && ! fname.equals(env.getFontName())) {
\r
4499 env.setFontName(fname);
\r
4503 catch ( Exception e ) {
\r
4504 // 落ちられると困るからトラップしておこうぜ
\r
4505 e.printStackTrace();
\r
4509 // L&FやFontを変えたらコンポーネントに通知が必要
\r
4510 protected void updateComponentTreeUI() {
\r
4512 SwingUtilities.updateComponentTreeUI(this);
\r
4513 SwingUtilities.updateComponentTreeUI(stwin);
\r
4514 SwingUtilities.updateComponentTreeUI(mwin);
\r
4515 SwingUtilities.updateComponentTreeUI(pcwin);
\r
4516 SwingUtilities.updateComponentTreeUI(rdialog);
\r
4517 SwingUtilities.updateComponentTreeUI(ccwin);
\r
4519 catch ( Exception e ) {
\r
4520 // 落ちられると困るからトラップしておこうぜ
\r
4521 e.printStackTrace();
\r
4525 // ツールチップの表示遅延時間を設定する
\r
4526 private void setTooltipDelay() {
\r
4527 ToolTipManager tp = ToolTipManager.sharedInstance();
\r
4528 tp.setInitialDelay(env.getTooltipInitialDelay()*100);
\r
4529 tp.setDismissDelay(env.getTooltipDismissDelay()*100);
\r
4534 * @return true:前回終了時の設定がある場合
\r
4536 private boolean buildMainWindow() {
\r
4541 mainWindow = new VWMainWindow();
\r
4544 toolBar = new VWToolBar();
\r
4545 listed = new VWListedView();
\r
4546 paper = new VWPaperView();
\r
4547 reserved = new VWReserveListView();
\r
4548 recorded = new VWRecordedListView();
\r
4549 autores = new VWAutoReserveListView();
\r
4550 setting = new VWSettingView();
\r
4551 recsetting = new VWRecorderSettingView();
\r
4552 chsetting = new VWChannelSettingView();
\r
4553 chdatsetting = new VWChannelDatSettingView();
\r
4554 chsortsetting = new VWChannelSortView();
\r
4555 chconvsetting = new VWChannelConvertView();
\r
4561 toolBar.setDebug(env.getDebug());
\r
4562 autores.setDebug(env.getDebug());
\r
4563 rdialog.setDebug(env.getDebug());
\r
4566 toolBar.setPagerItems();
\r
4572 mainWindow.addToolBar(toolBar);
\r
4573 mainWindow.addStatusArea(mwin);
\r
4576 mainWindow.addTab(listed, MWinTab.LISTED);
\r
4577 mainWindow.addTab(paper, MWinTab.PAPER);
\r
4578 mainWindow.addTab(reserved, MWinTab.RSVED);
\r
4579 mainWindow.addTab(recorded, MWinTab.RECED);
\r
4580 mainWindow.addTab(autores, MWinTab.AUTORES);
\r
4581 mainWindow.addTab(setting, MWinTab.SETTING);
\r
4582 mainWindow.addTab(recsetting, MWinTab.RECSET);
\r
4583 mainWindow.addTab(chsetting, MWinTab.CHSET);
\r
4584 mainWindow.addTab(chsortsetting, MWinTab.CHSORT);
\r
4585 mainWindow.addTab(chconvsetting, MWinTab.CHCONV);
\r
4586 mainWindow.addTab(chdatsetting, MWinTab.CHDAT);
\r
4590 setStatusVisible(bounds.getShowStatus());
\r
4593 paper.clearPanel();
\r
4594 paper.buildMainViewByDate();
\r
4599 private void ShowInitTab() {
\r
4602 mainWindow.setSelectedTab(null);
\r
4604 if ( recInfoList.size() <= 0 ) {
\r
4606 mainWindow.setSelectedTab(MWinTab.RECSET);
\r
4610 MWinTab tab = MWinTab.getAt(bounds.getSelectedTab());
\r
4611 mainWindow.setSelectedTab(tab);
\r
4616 private void setInitBounds() {
\r
4617 // ウィンドウのサイズと表示位置を設定する
\r
4618 Rectangle window = bounds.getWinRectangle();
\r
4619 if (bounds.isLoaded()) {
\r
4620 // 設定ファイルを読み込んであったらそれを設定する
\r
4621 System.out.println(DBGID+"set bounds "+window);
\r
4622 this.setBounds(window.x, window.y, window.width, window.height);
\r
4625 // 設定ファイルがなければ自動設定する
\r
4626 Rectangle screen = this.getGraphicsConfiguration().getBounds();
\r
4628 int w = window.width;
\r
4629 if (window.width > screen.width) {
\r
4634 x = (screen.width - window.width)/2;
\r
4637 int h = window.height;
\r
4638 if (window.height > screen.height) {
\r
4640 h = screen.height;
\r
4643 y = (screen.height - window.height)/2;
\r
4645 this.setBounds(x, y, w, h);
\r
4651 * {@link VWMainWindow#setStatusVisible(boolean)}の置き換え
\r
4653 private void setStatusVisible(boolean b) {
\r
4656 listed.setDetailVisible(true);
\r
4657 paper.setDetailVisible(true);
\r
4658 MWinSetVisible(true);
\r
4661 listed.setDetailVisible(false);
\r
4662 paper.setDetailVisible(false);
\r
4663 MWinSetVisible(false);
\r
4667 // フルスクリーンモードをトグル切り替え
\r
4668 private Dimension f_dim;
\r
4669 private Point f_pnt;
\r
4670 private int divloc_l = 0;
\r
4671 private int divloc_p = 0;
\r
4673 private void setFullScreen(boolean b) {
\r
4675 if ( b == true ) {
\r
4678 this.setUndecorated(true);
\r
4679 this.setVisible(true);
\r
4682 Toolkit tk = getToolkit();
\r
4683 Insets in = tk.getScreenInsets(getGraphicsConfiguration());
\r
4684 Dimension d = tk.getScreenSize();
\r
4685 f_dim = this.getSize();
\r
4686 f_pnt = this.getLocation();
\r
4687 this.setBounds(in.left, in.top, d.width-(in.left+in.right), d.height-(in.top+in.bottom));
\r
4689 divloc_l = bounds.getTreeWidth();
\r
4690 divloc_p = bounds.getTreeWidthPaper();
\r
4693 paper.setCollapseTree();
\r
4694 listed.setCollapseTree();
\r
4697 if ( f_pnt != null && f_dim != null ) { // 起動直後などは値がないですしね
\r
4701 this.setUndecorated(false);
\r
4702 this.setVisible(true);
\r
4705 this.setBounds(f_pnt.x, f_pnt.y, f_dim.width, f_dim.height);
\r
4707 bounds.setTreeWidth(divloc_l);
\r
4708 bounds.setTreeWidthPaper(divloc_p);
\r
4711 paper.setExpandTree();
\r
4712 listed.setExpandTree();
\r
4718 private void setTitleBar() {
\r
4719 MemoryMXBean mbean = ManagementFactory.getMemoryMXBean();
\r
4720 MemoryUsage heapUsage = mbean.getHeapMemoryUsage();
\r
4724 "%s - %s - Memory Usage Max:%dM Committed:%dM Used:%dM - FrameBuffer Status:%s",
\r
4725 VersionInfo.getVersion(),
\r
4726 CommonUtils.getDateTime(0),
\r
4727 heapUsage.getMax()/(1024*1024),
\r
4728 heapUsage.getCommitted()/(1024*1024),
\r
4729 heapUsage.getUsed()/(1024*1024),
\r
4730 (paper!=null)?(paper.getFrameBufferStatus()):("N/A")
\r
4736 private void ExitOnClose() {
\r
4738 if ( ! this.toolBar.isFullScreen()) {
\r
4739 Rectangle r = this.getBounds();
\r
4740 bounds.setWinRectangle(r);
\r
4743 Rectangle r = new Rectangle();
\r
4744 r.x = this.f_pnt.x;
\r
4745 r.y = this.f_pnt.y;
\r
4746 r.width = this.f_dim.width;
\r
4747 r.height = this.f_dim.height;
\r
4748 bounds.setWinRectangle(r);
\r
4750 listed.copyColumnWidth();
\r
4751 reserved.copyColumnWidth();
\r
4753 bounds.setStatusRows(mwin.getRows());
\r
4756 bounds.setSelectedTab(mainWindow.getSelectedTab().getIndex());
\r
4757 bounds.setShowSettingTabs(mainWindow.getShowSettingTabs());
\r
4758 bounds.setSelectedRecorderId(toolBar.getSelectedRecorder());
\r
4759 bounds.setShowStatus(toolBar.isStatusShown());
\r
4765 listed.saveTreeExpansion();
\r
4766 paper.saveTreeExpansion();
\r
4770 /*******************************************************************************
\r
4772 ******************************************************************************/
\r
4775 private static boolean initialized = false;
\r
4776 private static Viewer myClass = null;
\r
4781 * @throws NoSuchAlgorithmException
\r
4782 * @version 今まで初期化を行ってからウィンドウを作成していたが<BR>
\r
4783 * 途中で例外が起こるとダンマリの上にゾンビになってたりとヒドかったので<BR>
\r
4784 * 先にウィンドウを作成してから初期化を行うように変えました
\r
4785 * @throws InterruptedException
\r
4786 * @throws InvocationTargetException
\r
4788 public static void main(final String[] args) throws NoSuchAlgorithmException, InvocationTargetException, InterruptedException {
\r
4790 if ( myClass != null ) {
\r
4791 // 既に起動していたらフォアグラウンドにする
\r
4792 SwingUtilities.invokeAndWait(new Runnable() {
\r
4794 public void run() {
\r
4796 myClass.setVisible(true);
\r
4797 myClass.setState(Frame.NORMAL);
\r
4803 SwingUtilities.invokeLater(new Runnable() {
\r
4804 public void run() {
\r
4806 final Viewer thisClass = myClass = new Viewer(args);
\r
4808 thisClass.addComponentListener(new ComponentAdapter() {
\r
4810 public void componentShown(ComponentEvent e) {
\r
4813 thisClass.removeComponentListener(this);
\r
4816 thisClass.initialize(args);
\r
4821 thisClass.setVisible(true);
\r
4828 /*******************************************************************************
\r
4830 ******************************************************************************/
\r
4835 public Viewer(final String[] args) {
\r
4840 bounds.loadText();
\r
4843 // 初期化が終わるまでは閉じられないよ → どうせステータスウィンドウにブロックされて操作できない
\r
4844 //setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
\r
4845 //setResizable(false);
\r
4847 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
\r
4852 Image image = ImageIO.read(new File(ICONFILE_TAINAVI));
\r
4853 setIconImage(image);
\r
4855 catch (IOException e) {
\r
4856 StdAppendError("[ERROR] アイコンが設定できない: "+e.toString());
\r
4859 JLabel jLabel_splash_img = new JLabel(new ImageIcon("splash.gif"));
\r
4860 jLabel_splash_img.setPreferredSize(new Dimension(400,300));
\r
4861 //getContentPane().setLayout(new BorderLayout());
\r
4862 getContentPane().add(jLabel_splash_img, BorderLayout.CENTER);
\r
4865 setLocationRelativeTo(null); // 画面の真ん中に
\r
4867 // SwingLocker共有設定
\r
4868 SwingLocker.setOwner(this);
\r
4870 // とりあえずルックアンドフィールはリセットしておかないとだめっぽいよ
\r
4871 initLookAndFeelAndFont();
\r
4872 updateComponentTreeUI();
\r
4875 // 初期化をバックグラウンドで行う
\r
4876 private void initialize(final String[] args) {
\r
4880 // 初期化処理はバックグラウンドで行う
\r
4881 new SwingBackgroundWorker(false) {
\r
4884 protected Object doWorks() throws Exception {
\r
4886 TatCount tc = new TatCount();
\r
4889 _initialize(args);
\r
4891 // 終わったら閉じられるようにするよ
\r
4892 //setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
\r
4893 //setResizable(true);
\r
4896 stwin.appendMessage(String.format("【タイニー番組ナビゲータが起動しました】 所要時間: %.2f秒",tc.end()));
\r
4901 protected void doFinally() {
\r
4902 if ( ! initialized ) System.err.println("[ERROR][鯛ナビ] 【致命的エラー】 初期化処理を行っていたスレッドが異常終了しました。");
\r
4903 stwin.setClosingEnabled(false);
\r
4904 CommonUtils.milSleep(OPENING_WIAT);
\r
4905 StWinSetVisible(false);
\r
4909 StWinSetLocationUnder(this);
\r
4910 StWinSetVisible(true);
\r
4914 private void _initialize(final String[] args) {
\r
4919 // ログ出力を設定する(Windowsの場合は文字コードをMS932にする) →DOS窓を殺したので終了
\r
4920 System.setOut(new DebugPrintStream(System.out,LOG_FILE,logging));
\r
4921 System.setErr(new DebugPrintStream(System.err,LOG_FILE,logging));
\r
4924 StdAppendMessage("================================================================================");
\r
4925 StdAppendMessage("以下のメッセージは無視してください(原因調査中)");
\r
4926 StdAppendMessage("Exception occurred during event dispatching:");
\r
4927 StdAppendMessage(" java.lang.NullPointerException");
\r
4928 StdAppendMessage(" at javax.swing.plaf.basic.BasicScrollBarUI.layoutHScrollbar(Unknown Source)");
\r
4929 StdAppendMessage(" (以下略)");
\r
4930 StdAppendMessage("================================================================================");
\r
4931 stwin.appendMessage(CommonUtils.getDateTime(0));
\r
4932 stwin.appendMessage(String.format("タイニー番組ナビゲータが起動を開始しました(VersionInfo:%s on %s)",VersionInfo.getVersion(),VersionInfo.getEnvironment()));
\r
4934 // 起動時にアップデートを確認する
\r
4938 // メインの環境設定ファイルを読み込む
\r
4944 // その他の環境設定ファイルを読み込む
\r
4947 if ( onlyLoadProgram ) {
\r
4948 if ( ! isOLPExpired(4) ) {
\r
4949 CommonUtils.milSleep(3000);
\r
4953 loadProgPlugins();
\r
4955 setSelectedProgPlugin();
\r
4956 initProgPluginAll();
\r
4957 // 検索結果リストの初期化(loadTVProgram()中で使うので)
\r
4960 loadTVProgram(true,LoadFor.ALL);
\r
4961 stwin.appendMessage("番組表を取得したので終了します");
\r
4962 CommonUtils.milSleep(3000);
\r
4967 loadProgPlugins();
\r
4971 setSelectedProgPlugin();
\r
4972 initProgPluginAll();
\r
4974 initRecPluginAll();
\r
4977 if ( runRecWakeup ) {
\r
4981 // 検索結果リストの初期化(loadTVProgram()中で使うので)
\r
4985 loadTVProgram(false,LoadFor.ALL);
\r
4990 loadRdReservesAll(runRecLoad, null);
\r
4992 catch ( Exception e ) {
\r
4993 System.err.println("【致命的エラー】設定の初期化に失敗しました");
\r
4994 e.printStackTrace();
\r
4998 // 背景色設定ダイアログにフォント名の一覧を設定する
\r
4999 pcwin.setFontList(vwfont);
\r
5001 // (新聞形式の)ツールチップの表示時間を変更する
\r
5002 setTooltipDelay();
\r
5006 buildMainWindow();
\r
5008 catch ( Exception e ) {
\r
5009 System.err.println("【致命的エラー】ウィンドウの構築に失敗しました");
\r
5010 e.printStackTrace();
\r
5015 //int x = 2/0; // サブスレッドの突然死のトラップを確認するためのコード
\r
5020 setTrayIconVisible(env.getShowSysTray());
\r
5023 setXButtonAction(env.getShowSysTray() && env.getHideToTray());
\r
5026 this.addWindowListener(new WindowAdapter() {
\r
5027 // ウィンドウを最小化したときの処理
\r
5029 public void windowIconified(WindowEvent e) {
\r
5035 public void windowClosing(WindowEvent e) {
\r
5040 // 初回起動時はレコーダの登録を促す
\r
5041 if ( recorders.size() == 0 ) {
\r
5042 Container cp = getContentPane();
\r
5043 JOptionPane.showMessageDialog(cp, "レコーダが登録されていません。\n最初に登録を行ってください。\n番組表だけを使いたい場合は、\nNULLプラグインを登録してください。");
\r
5046 // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
5048 // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
5050 // [ツールバー/共通] レコーダ情報変更
\r
5051 toolBar.addHDDRecorderChangeListener(autores);
\r
5054 toolBar.addHDDRecorderSelectionListener(this); // 新聞形式
\r
5055 toolBar.addHDDRecorderSelectionListener(paper); // 新聞形式
\r
5056 toolBar.addHDDRecorderSelectionListener(autores); // 自動予約一覧
\r
5057 toolBar.addHDDRecorderSelectionListener(rdialog); // 予約ダイアログ
\r
5059 // [ツールバー/キーワード入力] キャンセル動作
\r
5060 toolBar.addKeywordCancelListener(this);
\r
5062 // [タイマー] タイトルバー更新/リスト形式の現在時刻ノード/新聞形式の現在時刻ノード
\r
5063 timer_now.addTickTimerRiseListener(this);
\r
5064 timer_now.addTickTimerRiseListener(listed);
\r
5065 timer_now.addTickTimerRiseListener(paper);
\r
5067 // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
5069 // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
5070 toolBar.setSelectedRecorder(bounds.getSelectedRecorderId());
\r
5072 // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
5073 // [Fire!] サイドツリーのデフォルトを選択することで番組情報の描画を開始する
\r
5074 // ※ここ以前だとぬぽとかOOBとか出るかもよ!
\r
5075 // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
5076 paper.selectTreeDefault();
\r
5077 listed.selectTreeDefault();
\r
5079 // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
5080 // メインウィンドウをスプラッシュからコンポーネントに入れ替える
\r
5081 // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
5082 this.setVisible(false);
\r
5083 this.setContentPane(mainWindow);
\r
5085 this.setVisible(true);
\r
5087 setTitleBar(); // タイトルバー更新
\r
5089 ShowInitTab(); // 前回開いていたタブを開く
\r
5091 // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
5093 // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
5094 timer_now.start();
\r
5096 // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
5098 // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
5099 mwin.appendMessage(String.format("タイニー番組ナビゲータが起動しました (VersionInfo:%s on %s)",VersionInfo.getVersion(),VersionInfo.getEnvironment()));
\r
5100 initialized = true;
\r