• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

タイニー番組ナビゲータ本体


Commit MetaInfo

Révision0838e9b02ee01ef49f9accfade7a86366d6c5580 (tree)
l'heure2019-12-27 19:11:44
AuteurMasahiko Kimura <mkimura@u01....>
CommiterMasahiko Kimura

Message de Log

Ver.1.12.8 (2019/12/27)

1.[DiMORA]BS4K/CS4Kの番組を取得できるようにする
2.[新聞形式][リスト形式][4K][8K]をキーワードとして赤字で表示する
3.[新聞形式]過去ログでも番組別表示ができるようにする
4.[新聞形式][リスト形式]詳細情報欄をマウスのドラッグでリサイズできるようにする
5.[その他]ステータス欄をマウスのドラッグでリサイズできるようにする
6.[タイトル一覧]「フォルダを選択する」メニューを追加する
7.[テレビ王国]高速キャッシュがONになっていると、「CH設定」の設定内容がすぐに反映されない問題の対応

Change Summary

Modification

--- a/TinyBannavi/src/tainavi/AbsListedView.java
+++ b/TinyBannavi/src/tainavi/AbsListedView.java
@@ -15,6 +15,8 @@ import java.awt.event.KeyEvent;
1515 import java.awt.event.MouseAdapter;
1616 import java.awt.event.MouseEvent;
1717 import java.awt.event.MouseListener;
18+import java.beans.PropertyChangeEvent;
19+import java.beans.PropertyChangeListener;
1820 import java.io.File;
1921 import java.io.IOException;
2022 import java.net.URI;
@@ -382,6 +384,7 @@ public abstract class AbsListedView extends JPanel implements TickTimerListener
382384
383385 // コンポーネント
384386
387+ private JSplitPane jSplitPane_main = null;
385388 private JDetailPanel jTextPane_detail = null;
386389 private JSplitPane jSplitPane_view = null;
387390 private JPanel jPanel_tree = null;
@@ -442,8 +445,7 @@ public abstract class AbsListedView extends JPanel implements TickTimerListener
442445
443446 // コンポーネントを追加
444447 this.setLayout(new BorderLayout());
445- this.add(getJTextPane_detail(), BorderLayout.PAGE_START);
446- this.add(getJSplitPane_view(), BorderLayout.CENTER);
448+ this.add(getJSplitPane_main(), BorderLayout.CENTER);
447449
448450 // バグ対応
449451 if ( bounds.getListedColumnSize() == null ) {
@@ -1526,6 +1528,9 @@ public abstract class AbsListedView extends JPanel implements TickTimerListener
15261528 */
15271529 public void setDetailVisible(boolean aFlag) {
15281530 jTextPane_detail.setVisible(aFlag);
1531+
1532+ if (aFlag)
1533+ jSplitPane_main.setDividerLocation(bounds.getListedDetailHeight());
15291534 }
15301535
15311536 /**
@@ -3845,7 +3850,48 @@ public abstract class AbsListedView extends JPanel implements TickTimerListener
38453850 pop.show(jTree_tree, x, y);
38463851 }
38473852
3853+ /*
3854+ * 詳細欄関係
3855+ */
3856+ /*
3857+ * 詳細欄の高さを初期化する
3858+ */
3859+ private void initDetailHeight(){
3860+ if (bounds.getDetailRows() > 0){
3861+ resetDetailHeight();
3862+ }
3863+ else{
3864+ int dh = bounds.getListedDetailHeight();
3865+ if (dh > 1)
3866+ setDetailHeight(dh);
3867+ else
3868+ resetDetailHeight();
3869+ }
3870+ }
3871+
3872+ /*
3873+ * 詳細欄の高さをセットする
3874+ */
3875+ private void setDetailHeight(int height){
3876+ if (jTextPane_detail == null)
3877+ return;
3878+
3879+ jSplitPane_main.setDividerLocation(height);
3880+ bounds.setListedDetailHeight(height);
3881+ }
3882+
3883+ /*
3884+ * 詳細欄の高さをリセットする
3885+ */
3886+ private void resetDetailHeight(){
3887+ if (jTextPane_detail == null)
3888+ return;
3889+
3890+ int rows = bounds.getDetailRows();
3891+ int height = jTextPane_detail.getHeightFromRows(rows > 0 ? rows : 4);
38483892
3893+ setDetailHeight(height);
3894+ }
38493895
38503896 /*******************************************************************************
38513897 * コンポーネント
@@ -3885,6 +3931,31 @@ public abstract class AbsListedView extends JPanel implements TickTimerListener
38853931 * 部品
38863932 */
38873933
3934+ /*
3935+ * 詳細欄とツリー+リストを分割するペインを生成する
3936+ */
3937+ private JSplitPane getJSplitPane_main() {
3938+ if ( jSplitPane_main == null ) {
3939+
3940+ jSplitPane_main = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
3941+
3942+ jSplitPane_main.setTopComponent(getJTextPane_detail());
3943+ jSplitPane_main.setBottomComponent(getJSplitPane_view());
3944+
3945+ initDetailHeight();
3946+
3947+ jSplitPane_main.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY, new PropertyChangeListener() {
3948+ @Override
3949+ public void propertyChange(PropertyChangeEvent pce) {
3950+ if (jTextPane_detail.isVisible())
3951+ bounds.setListedDetailHeight(jSplitPane_main.getDividerLocation());
3952+ }
3953+ });
3954+ }
3955+
3956+ return jSplitPane_main;
3957+ }
3958+
38883959 private JSplitPane getJSplitPane_view() {
38893960 if ( jSplitPane_view == null ) {
38903961 jSplitPane_view = new JSplitPane() {
@@ -4278,7 +4349,8 @@ public abstract class AbsListedView extends JPanel implements TickTimerListener
42784349
42794350 // 列ヘッダーの表示・非表示
42804351 setRowHeaderVisible(env.getRowHeaderVisible());
4281- jTextPane_detail.setRows(bounds.getDetailRows());
4352+
4353+ initDetailHeight();
42824354
42834355 // マーク表示分離の有無
42844356 setMarkColumnVisible(env.getSplitMarkAndTitle());
--- a/TinyBannavi/src/tainavi/AbsPaperView.java
+++ b/TinyBannavi/src/tainavi/AbsPaperView.java
@@ -24,6 +24,8 @@ import java.awt.event.MouseWheelListener;
2424 import java.awt.font.TextAttribute;
2525 import java.awt.geom.Rectangle2D;
2626 import java.awt.image.BufferedImage;
27+import java.beans.PropertyChangeEvent;
28+import java.beans.PropertyChangeListener;
2729 import java.io.File;
2830 import java.text.AttributedCharacterIterator;
2931 import java.text.AttributedString;
@@ -212,6 +214,7 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
212214
213215 // コンポーネント
214216
217+ private JSplitPane jSplitPane_main = null;
215218 private JDetailPanel jTextPane_detail = null;
216219 private JSplitPane jSplitPane_view = null;
217220 private JPanel jPanel_tree = null;
@@ -275,6 +278,7 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
275278 private float paperHeightZoom = 1.0F;
276279
277280 private boolean byCenterMode = false; // 1放送局の1週間分を表示するモード化か
281+ private String startDate = CommonUtils.getDate529(0, true); // 放送局別の場合の開始日
278282
279283 /*
280284 * ページャーのEnable/Disableを更新する
@@ -287,7 +291,7 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
287291 * Envの内容を反映する
288292 */
289293 public void reflectEnv(){
290- jTextPane_detail.setRows(bounds.getDetailRows());
294+ initDetailHeight();
291295 }
292296
293297 /**
@@ -428,8 +432,7 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
428432 super();
429433
430434 this.setLayout(new BorderLayout());
431- this.add(getJTextPane_detail(), BorderLayout.PAGE_START);
432- this.add(getJSplitPane_view(), BorderLayout.CENTER);
435+ this.add(getJSplitPane_main(), BorderLayout.CENTER);
433436
434437 // タブが開いたり閉じたりしたときの処理
435438 this.addComponentListener(cl_shownhidden);
@@ -1076,6 +1079,9 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
10761079 */
10771080 public void setDetailVisible(boolean aFlag) {
10781081 jTextPane_detail.setVisible(aFlag);
1082+
1083+ if (aFlag)
1084+ jSplitPane_main.setDividerLocation(bounds.getPaperDetailHeight());
10791085 }
10801086
10811087 /**
@@ -1736,8 +1742,32 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
17361742 clearPanel();
17371743 selectMainView(null);
17381744
1739- jPanel_space_top_view.setLayout(null);
1745+ TreePath path = jTree_tree.getSelectionPath();
1746+ if (path == null || path.getPathCount() != 3)
1747+ return;
1748+
1749+ String today = CommonUtils.getDate529(0, true);
1750+ // 開始日が当日以降であれば現在の表を作成する
1751+ if (startDate.compareTo(today) >= 0){
1752+ startDate = today;
1753+ redrawByCenterCurrent(center);
1754+ }
1755+ // 開始日が過去日であれば過去ログから表作成する
1756+ else{
1757+ redrawByCenterPassed(center);
1758+ }
1759+
1760+ // 番組枠描画バッファサイズの上限を確認する
1761+ if (framebuffersize < frameUsed.size()) {
1762+ framebuffersize = frameUsed.size();
1763+ StdAppendMessage(MSGID+"番組枠描画バッファの上限を変更: "+frameUsed.size()+"/"+framebuffersize);
1764+ }
1765+ }
17401766
1767+ /*
1768+ * 放送局別に現在の表を作成する
1769+ */
1770+ private void redrawByCenterCurrent(String center){
17411771 for (int a=0; a<tvprograms.size(); a++) {
17421772 //
17431773 TVProgram tvp = tvprograms.get(a);
@@ -1803,13 +1833,56 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
18031833 // 時間線をひく
18041834 redrawTimeline(false, false);
18051835
1806- // 番組枠描画バッファサイズの上限を確認する
1807- if (framebuffersize < frameUsed.size()) {
1808- framebuffersize = frameUsed.size();
1809- StdAppendMessage(MSGID+"番組枠描画バッファの上限を変更: "+frameUsed.size()+"/"+framebuffersize);
1810- }
18111836 }
18121837
1838+ /*
1839+ * 放送局別に過去ログから表を作成する
1840+ */
1841+ private void redrawByCenterPassed(String center){
1842+ // 過去ログの取得
1843+ PassedProgram tvp = tvprograms.getPassed();
1844+
1845+ // 開始日以降で指定日数分の番組情報を取得する
1846+ ProgList pl = tvp.loadByCenterDates(startDate, env.getDatePerPassedPage(), center);
1847+ if (pl == null)
1848+ return;
1849+
1850+ // 日付ヘッダを描画する
1851+ for (int centerid=0; centerid<pl.pdate.size(); centerid++) {
1852+ ProgDateList pcl = pl.pdate.get(centerid);
1853+
1854+ JTXTLabel b1 = new JTXTLabel();
1855+ GregorianCalendar c = CommonUtils.getCalendar(pcl.Date);
1856+ if ( c != null ) {
1857+ String date = CommonUtils.getDate(c);
1858+ b1.setValue(date);
1859+ b1.setText(date.substring(5));
1860+ b1.setOpaque(true);
1861+ if ( c.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY ) {
1862+ b1.setBackground(new Color(90,90,255));
1863+ }
1864+ else if ( c.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY ) {
1865+ b1.setBackground(new Color(255,90,90));
1866+ }
1867+ else {
1868+ b1.setBackground(new Color(180,180,180));
1869+ }
1870+ }
1871+ b1.setBorder(lborder);
1872+ b1.setHorizontalAlignment(JLabel.CENTER);
1873+ b1.setBounds(bounds.getBangumiColumnWidth()*centerid, 0, bounds.getBangumiColumnWidth(), bounds.getBangumiColumnHeight());
1874+ b1.addMouseListener(tbMouseAdapter);
1875+ jPanel_space_top_view.add(b1);
1876+ }
1877+
1878+ jPanel_space_top_view.setPreferredSize(new Dimension(bounds.getBangumiColumnWidth()*pl.pdate.size(),bounds.getBangumiColumnHeight()));
1879+ jPanel_space_top_view.updateUI();
1880+
1881+ putBangumiColumns(pl, -1, null);
1882+
1883+ jLayeredPane_space_main_view.setPreferredSize(new Dimension(pl.pdate.size()*bounds.getBangumiColumnWidth(),Math.round(24*60*bounds.getPaperHeightMultiplier()*paperHeightZoom)));
1884+ //jScrollPane_space_main.updateUI();
1885+ }
18131886
18141887 /**
18151888 * 予約待機赤枠の描画(個々の枠)
@@ -2335,6 +2408,114 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
23352408 }
23362409 }
23372410
2411+ /*
2412+ * 詳細欄関係
2413+ */
2414+ /*
2415+ * 詳細欄の高さを初期化する
2416+ */
2417+ private void initDetailHeight(){
2418+ if (bounds.getDetailRows() > 0){
2419+ resetDetailHeight();
2420+ }
2421+ else{
2422+ int dh = bounds.getPaperDetailHeight();
2423+ if (dh > 1)
2424+ setDetailHeight(dh);
2425+ else
2426+ resetDetailHeight();
2427+ }
2428+ }
2429+
2430+ /*
2431+ * 詳細欄の高さを設定する
2432+ */
2433+ private void setDetailHeight(int height){
2434+ if (jTextPane_detail == null)
2435+ return;
2436+
2437+ jSplitPane_main.setDividerLocation(height);
2438+ bounds.setPaperDetailHeight(height);
2439+ }
2440+
2441+ /*
2442+ * 詳細欄の高さをリセットする
2443+ */
2444+ private void resetDetailHeight(){
2445+ if (jTextPane_detail == null)
2446+ return;
2447+
2448+ int rows = bounds.getDetailRows();
2449+ int height = jTextPane_detail.getHeightFromRows(rows > 0 ? rows : 4);
2450+
2451+ setDetailHeight(height);
2452+ }
2453+
2454+ /*
2455+ * 放送局別で前のページに移動する
2456+ */
2457+ public void moveToPrevDatePage(){
2458+ PassedProgram passed = tvprograms.getPassed();
2459+
2460+ String date = passed.getPrevDate(startDate, env.getDatePerPassedPage());
2461+ if (date == null)
2462+ return;
2463+
2464+ startDate = date;
2465+
2466+ // 表を描画し直す
2467+ redrawByCurrentSelection();
2468+ }
2469+
2470+ /*
2471+ * 放送局別で前のページに移動可能かを返す
2472+ */
2473+ public boolean isPrevDatePageEnabled(){
2474+ PassedProgram passed = tvprograms.getPassed();
2475+
2476+ String date = passed.getPrevDate(startDate, env.getDatePerPassedPage());
2477+
2478+ return date != null;
2479+ }
2480+
2481+ /*
2482+ * 放送局別で次のページに移動する
2483+ */
2484+ public void moveToNextDatePage(){
2485+ if (!isNextDatePageEnabled())
2486+ return;
2487+
2488+ PassedProgram passed = tvprograms.getPassed();
2489+
2490+ String date = passed.getNextDate(startDate, env.getDatePerPassedPage());
2491+ if (date == null)
2492+ date = CommonUtils.getDate529(0, true);
2493+
2494+ startDate = date;
2495+
2496+ // 表を描画し直す
2497+ redrawByCurrentSelection();
2498+ }
2499+
2500+ /*
2501+ * 放送局別で次のページに移動可能かを返す
2502+ */
2503+ public boolean isNextDatePageEnabled(){
2504+ String today = CommonUtils.getDate529(0, true);
2505+
2506+ return startDate.compareTo(today) < 0;
2507+ }
2508+
2509+ /*
2510+ * 放送局別の表示モードかを返す
2511+ */
2512+ public boolean isByCenterMode(){
2513+ TreePath path = jTree_tree.getSelectionPath();
2514+ if (path == null || path.getPathCount() < 2)
2515+ return false;
2516+
2517+ return path.getPathComponent(1) == centerNode;
2518+ }
23382519
23392520 /*******************************************************************************
23402521 * ハンドラ―メソッド
@@ -2837,10 +3018,15 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
28373018 public void mouseClicked(MouseEvent e) {
28383019 if (e.getButton() == MouseEvent.BUTTON1) {
28393020 if (e.getClickCount() == 2) {
2840- if ( cur_tuner == IterationType.PASSED ) {
2841- MWin.appendMessage(MSGID+"過去ログでは一局表示に切り替えられません");
3021+ TreePath path = jTree_tree.getSelectionPath();
3022+ if (path == null || path.getPathCount() != 3)
28423023 return;
2843- }
3024+
3025+ // 過去ログノードの場合、選択されているノードを開始日とする
3026+ if (path.getPathComponent(1) == passedNode)
3027+ startDate = path.getPathComponent(2).toString();
3028+ else
3029+ startDate = CommonUtils.getDate529(0, true);
28443030
28453031 // 右ダブルクリックで局表示に切り替え
28463032 String center = ((JLabel)e.getSource()).getText();
@@ -2874,8 +3060,20 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
28743060 // 右ダブルクリックで日付表示に切り替え
28753061 String date = ((JTXTLabel)e.getSource()).getValue();
28763062 StdAppendMessage(MSGID+"日付表示に切り替え:"+date);
2877- //redrawByDate(date, -1);
2878- jLabel_tree.setView(JTreeLabel.Nodes.DATE, date);
3063+
3064+ String today = CommonUtils.getDate529(0, true);
3065+
3066+ // 過去日の場合、過去ログの日付を選択する
3067+ if (date.compareTo(today) < 0){
3068+ // 指定した日付のノードがツリーになければ作成する
3069+ addPassedNodeIfNotExist(date);
3070+
3071+ jLabel_tree.setView(JTreeLabel.Nodes.PASSED, date);
3072+ }
3073+ // 未来日の場合、日付別の日付を選択する
3074+ else
3075+ jLabel_tree.setView(JTreeLabel.Nodes.DATE, date);
3076+
28793077 reselectTree();
28803078 }
28813079 }
@@ -2891,18 +3089,34 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
28913089 private JDetailPanel getJTextPane_detail() {
28923090 if (jTextPane_detail == null) {
28933091 jTextPane_detail = new JDetailPanel();
2894- jTextPane_detail.setRows(bounds.getDetailRows());
28953092 jTextPane_detail.setBorder(detailInfoFreeBorder);
28963093 jTextPane_detail.addMouseListener(ml_detailInfoClick);
2897- //Dimension d = jTextPane_detail.getMaximumSize();
2898- //d.height = bounds.getDetailAreaHeight();
2899- //jTextPane_detail.setPreferredSize(d);
2900- //jTextPane_detail.setVerticalAlignment(JLabel.TOP);
2901- //jTextPane_detail.setHorizontalAlignment(JLabel.LEFT);
29023094 }
29033095 return jTextPane_detail;
29043096 }
29053097
3098+ private JSplitPane getJSplitPane_main() {
3099+ if ( jSplitPane_main == null ) {
3100+
3101+ jSplitPane_main = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
3102+
3103+ jSplitPane_main.setTopComponent(getJTextPane_detail());
3104+ jSplitPane_main.setBottomComponent(getJSplitPane_view());
3105+
3106+ initDetailHeight();
3107+
3108+ jSplitPane_main.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY, new PropertyChangeListener() {
3109+ @Override
3110+ public void propertyChange(PropertyChangeEvent pce) {
3111+ if (jTextPane_detail.isVisible())
3112+ bounds.setPaperDetailHeight(jSplitPane_main.getDividerLocation());
3113+ }
3114+ });
3115+ }
3116+
3117+ return jSplitPane_main;
3118+ }
3119+
29063120 private JSplitPane getJSplitPane_view() {
29073121 if ( jSplitPane_view == null ) {
29083122
--- a/TinyBannavi/src/tainavi/AbsSettingView.java
+++ b/TinyBannavi/src/tainavi/AbsSettingView.java
@@ -217,6 +217,7 @@ public abstract class AbsSettingView extends JScrollPane {
217217 private JSliderPanel jSP_tooltipDismissDelay = null;
218218 private JCheckBoxPanel jCBP_timerbarScrollEnable = null;
219219 private JSliderPanel jSP_passedLogLimit = null;
220+ private JSliderPanel jSP_datePerPage = null;
220221 private JCheckBoxPanel jCBP_effectComboToPaper = null;
221222 private JComboBoxPanel jCBX_snapshotFmt = null;
222223 private JCheckBoxPanel jCBP_printSnapshot = null;
@@ -674,6 +675,11 @@ public abstract class AbsSettingView extends JScrollPane {
674675 // RELOADリスナー不要
675676 y+=(PARTS_HEIGHT+SEP_HEIGHT);
676677
678+ CommonSwingUtils.putComponentOn(jPanel_setting, jSP_datePerPage = new JSliderPanel("過去ログのページ当たりの日数",LABEL_WIDTH,7,28,200), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
679+ jSP_datePerPage.setValue(env.getDatePerPassedPage());
680+ // RELOADリスナー不要
681+ y+=(PARTS_HEIGHT+SEP_HEIGHT);
682+
677683 CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_effectComboToPaper = new JCheckBoxPanel("レコーダコンボボックスを新聞形式でも有効に",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
678684 jCBP_effectComboToPaper.setSelected(env.getEffectComboToPaper());
679685 // RELOADリスナー不要
@@ -1158,11 +1164,11 @@ public abstract class AbsSettingView extends JScrollPane {
11581164 // RELOADリスナー不要
11591165 y+=(PARTS_HEIGHT+SEP_HEIGHT);
11601166
1161- CommonSwingUtils.putComponentOn(jPanel_setting, jSP_detailRows = new JSliderPanel("詳細情報欄の行数",LABEL_WIDTH,0,10,200), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
1167+ CommonSwingUtils.putComponentOn(jPanel_setting, jSP_detailRows = new JSliderPanel("詳細情報欄の行数(0:前回終了時の高さ)",LABEL_WIDTH,0,10,200), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
11621168 jSP_detailRows.setValue(bounds.getDetailRows());
11631169 y+=(PARTS_HEIGHT+SEP_HEIGHT);
11641170
1165- CommonSwingUtils.putComponentOn(jPanel_setting, jSP_statusRows = new JSliderPanel("ステータス欄の行数",LABEL_WIDTH,0,10,200), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
1171+ CommonSwingUtils.putComponentOn(jPanel_setting, jSP_statusRows = new JSliderPanel("ステータス欄の行数(0:前回終了時の高さ)",LABEL_WIDTH,0,10,200), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
11661172 jSP_statusRows.setValue(bounds.getStatusRows());
11671173 y+=(PARTS_HEIGHT+SEP_HEIGHT);
11681174
@@ -1364,6 +1370,7 @@ public abstract class AbsSettingView extends JScrollPane {
13641370 env.setTooltipDismissDelay(jSP_tooltipDismissDelay.getValue());
13651371 env.setTimerbarScrollEnable(jCBP_timerbarScrollEnable.isSelected());
13661372 env.setPassedLogLimit(jSP_passedLogLimit.getValue());
1373+ env.setDatePerPassedPage(jSP_datePerPage.getValue());
13671374 env.setEffectComboToPaper(jCBP_effectComboToPaper.isSelected());
13681375 env.setSnapshotFmt((SnapshotFmt) jCBX_snapshotFmt.getSelectedItem());
13691376 env.setPrintSnapshot(jCBP_printSnapshot.isSelected());
--- a/TinyBannavi/src/tainavi/AbsTitleListView.java
+++ b/TinyBannavi/src/tainavi/AbsTitleListView.java
@@ -1419,6 +1419,8 @@ public abstract class AbsTitleListView extends JPanel {
14191419 if (ttlIds != null)
14201420 pop.add(getMultiTitleDetailMenuItem(title, chnam, devId, ttlIds, recId));
14211421
1422+ appendSelectFolderMenuItem(pop, ttlId);
1423+
14221424 pop.addSeparator();
14231425 pop.add(getStartStopPlayTitleMenuItem(true, title, chnam, devId, ttlId, recId));
14241426 pop.add(getStartStopPlayTitleMenuItem(false, title, chnam, devId, ttlId, recId));
@@ -1939,4 +1941,50 @@ public abstract class AbsTitleListView extends JPanel {
19391941 }
19401942 return("");
19411943 }
1944+
1945+ /**
1946+ * フォルダー絞り込みのメニューアイテムを追加する
1947+ */
1948+ protected void appendSelectFolderMenuItem(final JPopupMenu pop, final String ttlId){
1949+ HDDRecorder rec = getSelectedRecorder();
1950+ TitleInfo ttl = rec.getTitleInfo(ttlId);
1951+
1952+ if (ttl == null)
1953+ return;
1954+
1955+ ArrayList<TextValueSet> folders = ttl.getRec_folder();
1956+ if (folders == null || folders.isEmpty())
1957+ return;
1958+
1959+ String deviceId = ttl.getRec_device();
1960+ String folderName = folders.get(0).getText();
1961+
1962+ pop.addSeparator();
1963+
1964+ int idx = jCBXPanel_folder.getSelectedIndex();
1965+ if (idx == 0){
1966+ JMenuItem menuItem = new JMenuItem("フォルダを選択する【"+folderName+"】");
1967+ menuItem.addActionListener(new ActionListener() {
1968+ public void actionPerformed(ActionEvent e) {
1969+ updateFolderList(folderName);
1970+ updateFolderButtons();
1971+ updateTitleList(false, false, false, false, false, false);
1972+ }
1973+ });
1974+
1975+ pop.add(menuItem);
1976+ }
1977+ else{
1978+ JMenuItem menuItem = new JMenuItem("フォルダの選択を解除する");
1979+ menuItem.addActionListener(new ActionListener() {
1980+ public void actionPerformed(ActionEvent e) {
1981+ jCBXPanel_folder.setSelectedIndex(0);
1982+ updateTitleList(false, false, false, false, false, false);
1983+ }
1984+ });
1985+
1986+ pop.add(menuItem);
1987+ }
1988+ }
1989+
19421990 }
--- a/TinyBannavi/src/tainavi/AbsToolBar.java
+++ b/TinyBannavi/src/tainavi/AbsToolBar.java
@@ -82,6 +82,16 @@ public abstract class AbsToolBar extends JToolBar implements HDDRecorderSelectab
8282
8383 protected abstract ToolBarIconInfoList getTbIconEnv();
8484
85+ // 前のページに移動する
86+ protected abstract void moveToPrevPage();
87+ // 前のページに移動可能かを返す
88+ protected abstract boolean isPrevPageEnabled();
89+
90+ // 次のページに移動する
91+ protected abstract void moveToNextPage();
92+ // 次のページに移動可能かを返す
93+ protected abstract boolean isNextPageEnabled();
94+
8595 // 親に依頼
8696
8797 // リスト形式
@@ -813,9 +823,9 @@ public abstract class AbsToolBar extends JToolBar implements HDDRecorderSelectab
813823 }
814824
815825 /*
816- * 前のページへ
826+ * 前の放送局ページに移動する
817827 */
818- public void moveToPrevPage(){
828+ public void moveToPrevCenterPage(){
819829 int pno = getSelectedPagerIndex();
820830 if (pno <= 0)
821831 return;
@@ -824,7 +834,10 @@ public abstract class AbsToolBar extends JToolBar implements HDDRecorderSelectab
824834 redrawByPager();
825835 }
826836
827- public boolean isPrevPageEnabled(){
837+ /*
838+ * 前の放送局ページに移動可能かを返す
839+ */
840+ public boolean isPrevCenterPageEnabled(){
828841 if (jComboBox_pager == null || jButton_prevpage == null)
829842 return false;
830843 if (!jComboBox_pager.isEnabled() || !isTabSelected(MWinTab.PAPER) || !env.isPagerEnabled())
@@ -835,9 +848,9 @@ public abstract class AbsToolBar extends JToolBar implements HDDRecorderSelectab
835848 }
836849
837850 /*
838- * 次のページへ
851+ * 次の放送局ページに移動する
839852 */
840- public void moveToNextPage(){
853+ public void moveToNextCenterPage(){
841854 int pno = getSelectedPagerIndex();
842855 int pnum = getPagerCount();
843856 if (pno >= pnum-1)
@@ -847,7 +860,10 @@ public abstract class AbsToolBar extends JToolBar implements HDDRecorderSelectab
847860 redrawByPager();
848861 }
849862
850- public boolean isNextPageEnabled(){
863+ /*
864+ * 次の放送局ページに移動可能かを返す
865+ */
866+ public boolean isNextCenterPageEnabled(){
851867 if (jComboBox_pager == null || jButton_prevpage == null)
852868 return false;
853869 if (!jComboBox_pager.isEnabled() || !isTabSelected(MWinTab.PAPER) || !env.isPagerEnabled())
--- a/TinyBannavi/src/tainavi/Bounds.java
+++ b/TinyBannavi/src/tainavi/Bounds.java
@@ -225,6 +225,21 @@ public class Bounds {
225225 public int getSearchBoxAreaWidth(){ return searchBoxAreaWidth; }
226226 public void setSearchBoxAreaWidth(int n){ searchBoxAreaWidth = n; }
227227
228+ // リスト形式の詳細欄の高さ
229+ private int listedDetailHeight;
230+ public int getListedDetailHeight(){ return listedDetailHeight; }
231+ public void setListedDetailHeight(int n){ listedDetailHeight = n; }
232+
233+ // 新聞形式の詳細欄の高さ
234+ private int paperDetailHeight;
235+ public int getPaperDetailHeight(){ return paperDetailHeight; }
236+ public void setPaperDetailHeight(int n){ paperDetailHeight = n; }
237+
238+ // ステータスウインドウの高さ
239+ private int statusWindowHeight;
240+ public int getStatusWindowHeight(){ return statusWindowHeight; }
241+ public void setStatusWindowHeight(int n){ statusWindowHeight = n; }
242+
228243 //
229244 private static boolean loaded;
230245 public boolean isLoaded() { return loaded; }
--- a/TinyBannavi/src/tainavi/CommonUtils.java
+++ b/TinyBannavi/src/tainavi/CommonUtils.java
@@ -1112,6 +1112,17 @@ public class CommonUtils {
11121112 }
11131113
11141114 /*******************************************************************************
1115+ * ウインドウ関連
1116+ ******************************************************************************/
1117+ /*
1118+ * ポイント数からピクセル数を計算する
1119+ */
1120+ public static int getPixelFromPoint(int point){
1121+ int pixelPerInch=java.awt.Toolkit.getDefaultToolkit().getScreenResolution();
1122+ return (int)((double)point/72.0*(double)pixelPerInch);
1123+ }
1124+
1125+ /*******************************************************************************
11151126 * オブジェクト操作関連
11161127 ******************************************************************************/
11171128
--- a/TinyBannavi/src/tainavi/Env.java
+++ b/TinyBannavi/src/tainavi/Env.java
@@ -365,6 +365,12 @@ public class Env {
365365 public int getCenterPerPage() { return centerPerPage; }
366366 public void setCenterPerPage(int c) { centerPerPage = c; }
367367 public boolean isPagerEnabled() { return ( ! drawcacheEnable) && (centerPerPage > 0); }
368+
369+ // 新聞形式での、過去日の放送局別表示の1ページあたりの日数
370+ public int getDatePerPassedPage(){ return datePerPassedPage; }
371+ public void setDatePerPassedPage(int n) { datePerPassedPage = n; }
372+ private int datePerPassedPage = 14;
373+
368374 /**
369375 * indexなので、0から始まる
370376 */
--- a/TinyBannavi/src/tainavi/JDetailPanel.java
+++ b/TinyBannavi/src/tainavi/JDetailPanel.java
@@ -16,38 +16,43 @@ public class JDetailPanel extends JPanel {
1616 private static final long serialVersionUID = 1L;
1717
1818 JScrollPane jscrollpane = null;
19+ private JPanel jpanel_title = null;
1920 private JTextAreaWithPopup jta = null;
2021 private JLabel jlabel_time = null;
2122 private JLabel jlabel_title = null;
22-
23+
2324 private final int titleFontSize = 20;
2425 //private int textAreaRows = 4;
25-
26+
2627 public JDetailPanel() {
27-
28+
2829 this.setLayout(new BorderLayout());
29-
30+
31+ jpanel_title = new JPanel();
32+ jpanel_title.setLayout(new BorderLayout());
33+ this.add(jpanel_title, BorderLayout.PAGE_START);
34+
3035 Font f = null;
31-
36+
3237 jlabel_time = new JLabel();
3338 f = jlabel_time.getFont();
3439 jlabel_time.setFont(f.deriveFont(f.getStyle() | Font.BOLD, titleFontSize));
35- this.add(jlabel_time,BorderLayout.LINE_START);
36-
40+ jpanel_title.add(jlabel_time,BorderLayout.LINE_START);
41+
3742 jlabel_title = new JLabel();
3843 f = jlabel_title.getFont();
3944 jlabel_title.setFont(f.deriveFont(f.getStyle() | Font.BOLD, titleFontSize));
4045 jlabel_title.setForeground(Color.BLUE);
41- this.add(jlabel_title,BorderLayout.CENTER);
46+ jpanel_title.add(jlabel_title,BorderLayout.CENTER);
4247 jlabel_title.setText(" ");
43-
48+
4449 jta = CommonSwingUtils.getJta(this,4,0);
45-
50+
4651 jscrollpane = new JScrollPane(jta,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
4752 jscrollpane.setBorder(new EmptyBorder(0,0,0,0));
48- this.add(jscrollpane,BorderLayout.PAGE_END);
53+ this.add(jscrollpane,BorderLayout.CENTER);
4954 }
50-
55+
5156 public void setLabel(String s, String e, String t) {
5257 if (s == null || s.length() == 0 || e == null || e.length() == 0) {
5358 jlabel_time.setText(" ");
@@ -73,9 +78,18 @@ public class JDetailPanel extends JPanel {
7378 public int getRows() {
7479 return jta.getRows();
7580 }
76-
81+
7782 public void setRows(int rows) {
78- jta.setRows(rows);
83+// jta.setRows(rows);
84+ }
85+
86+ /*
87+ * 行数を指定して高さを取得する
88+ */
89+ public int getHeightFromRows(int rows){
90+ int hl = jta.getFont().getSize();
91+
92+ return CommonUtils.getPixelFromPoint(hl*rows+titleFontSize);
7993 }
8094
8195 @Override
@@ -84,7 +98,7 @@ public class JDetailPanel extends JPanel {
8498 jlabel_title.addMouseListener(l);
8599 jta.addMouseListener(l);
86100 }
87-
101+
88102 @Override
89103 public void removeMouseListener(MouseListener l) {
90104 jlabel_time.removeMouseListener(l);
--- a/TinyBannavi/src/tainavi/MarkChar.java
+++ b/TinyBannavi/src/tainavi/MarkChar.java
@@ -12,7 +12,7 @@ public class MarkChar {
1212 /*******************************************************************************
1313 * 定数
1414 ******************************************************************************/
15-
15+
1616 public static enum MarkItem {
1717 EXTENTION ( "★延長注意★" ),
1818 EXTENTION_S ( "(延)" ),
@@ -36,48 +36,51 @@ public class MarkChar {
3636 MULTIVOICE ( "[多]" ),
3737 STANDIN ( "[吹]" ),
3838 DATA ( "[デ]" ),
39- SORRUND ( "[5.1]" ),
39+ SURROUND ( "[5.1]" ),
4040 PRECEDING ( "【先】" ),
41-
41+
4242 REPEATED ( "[再]" ),
43+
44+ BS4K ( "[4K]"),
45+ BS8K ( "[8K]"),
4346 ;
44-
47+
4548 private String name;
46-
49+
4750 private MarkItem(String name) {
4851 this.name = name;
4952 }
50-
53+
5154 public String getName() {
5255 return name;
5356 }
5457 }
55-
58+
5659 /*******************************************************************************
5760 * 部品
5861 ******************************************************************************/
59-
62+
6063 private Env env;
61-
64+
6265 /*******************************************************************************
6366 * コンストラクタ
6467 ******************************************************************************/
65-
68+
6669 public MarkChar(Env env) {
6770 this.env = env;
6871 }
69-
72+
7073 /*******************************************************************************
7174 * アクション
7275 ******************************************************************************/
73-
76+
7477 /**
7578 * 延長警告マークの取得
7679 */
7780 public String getExtensionMark(ProgDetailList tvd) {
7881 return ((tvd.extension) ? ((env.getShortExtMark())?(MarkItem.EXTENTION_S.getName()):(MarkItem.EXTENTION.getName())) : (""));
7982 }
80-
83+
8184 /**
8285 * 新番組と最終回だけわける
8386 */
@@ -90,19 +93,19 @@ public class MarkChar {
9093 }
9194 return "";
9295 }
93-
96+
9497 /**
9598 * 普通のマークの取得
9699 */
97100 public String getOptionMark(ProgDetailList tvd) {
98-
101+
99102 String mkNewArr = "";
100103 String mkModified = "";
101104 String mkNoscr = "";
102105 String mkSpecial = "";
103106 String mkNoSyobo = "";
104107 String mkRating = "";
105-
108+
106109 String mkFirst = "";
107110 String mkLive = "";
108111 String mkSubtitle = "";
@@ -116,11 +119,13 @@ public class MarkChar {
116119 String mkNonrepeated = "";
117120 String mkMoved = "";
118121 String mkPrec = "";
119-
122+ String mk4k = "";
123+ String mk8k = "";
124+
120125 if (tvd.noscrumble == ProgScrumble.NOSCRUMBLE && env.getOptMarks().get(ProgOption.HIDDEN_NOSCRUMBLE) == Boolean.TRUE) {
121126 mkNoscr = MarkItem.NOSCRUMBLE.getName();
122127 }
123-
128+
124129 if ( tvd.newarrival && env.getOptMarks().get(ProgOption.NEWARRIVAL) == Boolean.TRUE ) {
125130 mkNewArr = ((env.getShortExtMark())?(MarkItem.NEWARRIVAL_S.getName()):(MarkItem.NEWARRIVAL.getName()));
126131 }
@@ -147,11 +152,11 @@ public class MarkChar {
147152 // 初回放送
148153 mkFirst = MarkItem.FIRST.getName();
149154 break;
150-
155+
151156 case NOSYOBO:
152157 mkNoSyobo = MarkItem.NOSYOBO.getName();
153158 break;
154-
159+
155160 case LIVE:
156161 // 生放送
157162 mkLive = MarkItem.LIVE.getName();
@@ -182,7 +187,7 @@ public class MarkChar {
182187 break;
183188 case SURROUND:
184189 // 5.1chサラウンド
185- mkSurround = MarkItem.SORRUND.getName();
190+ mkSurround = MarkItem.SURROUND.getName();
186191 break;
187192 case MOVED:
188193 // 先週無かったか時間が違う
@@ -192,21 +197,28 @@ public class MarkChar {
192197 // 先行放送
193198 mkPrec = MarkItem.PRECEDING.getName();
194199 break;
200+ case BS4K:
201+ mk4k = MarkItem.BS4K.getName();
202+ break;
203+ case BS8K:
204+ mk8k = MarkItem.BS8K.getName();
205+ break;
195206 default:
196207 break;
197208 }
198209 }
199-
200- return(mkNewArr+mkNoSyobo+mkMoved+mkModified+mkFirst+mkNonrepeated+mkNoscr+mkSpecial+mkRating+mkPrec+mkLive+mkPv+mkSubtitle+mkBilingual+mkTextbc+mkMultivoice+mkStandin+mkData+mkSurround);
210+
211+ return(mkNewArr+mkNoSyobo+mkMoved+mkModified+mkFirst+mkNonrepeated+mkNoscr+mkSpecial+mkRating+mkPrec+mkLive+
212+ mkPv+mkSubtitle+mkBilingual+mkTextbc+mkMultivoice+mkStandin+mkData+mkSurround+mk4k+mk8k);
201213 }
202-
214+
203215 /**
204216 * タイトルの後ろにつくマークの取得
205217 */
206218 public String getPostfixMark(ProgDetailList tvd) {
207-
219+
208220 String mkRep = "";
209-
221+
210222 for ( ProgOption opt : tvd.getOption() ) {
211223 switch (opt) {
212224 case REPEAT:
@@ -216,7 +228,7 @@ public class MarkChar {
216228 break;
217229 }
218230 }
219-
231+
220232 return(mkRep);
221233 }
222234
--- a/TinyBannavi/src/tainavi/PassedProgram.java
+++ b/TinyBannavi/src/tainavi/PassedProgram.java
@@ -128,6 +128,43 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
128128 final String expr_a = "^(\\d)_(\\d+)_(.+)\\.";
129129 final String expr_z = "(xml|txt)$";
130130
131+ /*
132+ * 指定した放送局の期間分の番組情報を読み込む
133+ */
134+ public ProgList loadByCenterDates(String startDate, int max, String center){
135+ ProgList pl = new ProgList();
136+ pl.Center = center;
137+ pl.enabled = true;
138+
139+ String today = CommonUtils.getDate529(0, true);
140+ GregorianCalendar c = CommonUtils.getCalendar(startDate);
141+
142+ // 日数分ループする
143+ for (int n=0; n<max; n++){
144+ String date = CommonUtils.getDate(c);
145+ // 当日以降になったらループを抜ける
146+ if (date.compareTo(today) >= 0)
147+ break;
148+
149+ // 1日分をロードする
150+ if (loadByCenter(date, center) && pcenter.size() > 0 && pcenter.get(0).pdate.size() > 0){
151+ // 成功したら追加する
152+ pl.pdate.add(pcenter.get(0).pdate.get(0));
153+ }
154+ else{
155+ // 失敗したら空の番組情報を追加する
156+ ProgDateList pcl = new ProgDateList();
157+ pcl.Date = date;
158+ pl.pdate.add(pcl);
159+ }
160+
161+ // 日付を1日ずらす
162+ c.add(GregorianCalendar.DAY_OF_MONTH, 1);
163+ }
164+
165+ return pl;
166+ }
167+
131168 /**
132169 * 指定の日付の指定の放送局の過去ログを取得する
133170 * @param date
@@ -582,11 +619,13 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
582619 // @see #getDateList()
583620 private static String pregetdate = "1999/12/31";
584621 private static String[] dd = new String[0];
622+ private static final int maxCntDef = 720; // 放送局別過去日表示のための最大カウント
585623
586624 /**
587625 * ディレクトリ一覧を取得する(日に一回しか検索しない)
588626 */
589- public String[] getDateList(int maxCnt) {
627+ public String[] getDateList(int maxCntArg) {
628+ int maxCnt = maxCntDef > maxCntArg ? maxCntDef : maxCntArg;
590629
591630 String getdate = CommonUtils.getDate529(0,true);
592631 if ( getdate.compareTo(pregetdate) <= 0 )
@@ -662,6 +701,49 @@ public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable
662701 return dd;
663702 }
664703
704+ /*
705+ * 次の日付を取得する
706+ */
707+ public String getNextDate(String dateArg, int count){
708+ int num = dd.length;
709+
710+ for (int n=0; n<num; n++){
711+ String date = dd[num-1-n];
712+
713+ if (date.compareTo(dateArg) <= 0)
714+ continue;
715+
716+ count--;
717+ if (count <= 0)
718+ return date;
719+ }
720+
721+ return null;
722+ }
723+
724+ /*
725+ * 前の日付を取得する
726+ */
727+ public String getPrevDate(String dateArg, int count){
728+ int num = dd.length;
729+ String dateLast = null;
730+
731+ for (int n=0; n<num; n++){
732+ String date = dd[n];
733+
734+ if (date.compareTo(dateArg) >= 0)
735+ continue;
736+
737+ count--;
738+ if (count <= 0)
739+ return date;
740+
741+ dateLast = date;
742+ }
743+
744+ // 指定したカウント前の日付がなければ最古の日付を返す
745+ return dateLast;
746+ }
665747 /* ここまで */
666748
667749
--- a/TinyBannavi/src/tainavi/TVProgram.java
+++ b/TinyBannavi/src/tainavi/TVProgram.java
@@ -19,7 +19,31 @@ public interface TVProgram {
1919 /**
2020 * NOSCRUMBLEは間違って(?)ProgScrumbleを使うこととなってしまったのだ。ここにあるのはマーク表示のための一覧用なのだ。
2121 */
22- public enum ProgOption { HIDDEN_NEW, HIDDEN_LAST, HIDDEN_NOSCRUMBLE, FIRST, REPEAT, LIVE, SPECIAL, NOSYOBO, SUBTITLE, BILINGUAL, STANDIN, PV, MULTIVOICE, DATA, SURROUND, NEWARRIVAL, MODIFIED, NONREPEATED, MOVED, PRECEDING, RATING };
22+ public enum ProgOption {
23+ HIDDEN_NEW,
24+ HIDDEN_LAST,
25+ HIDDEN_NOSCRUMBLE,
26+ FIRST,
27+ REPEAT,
28+ LIVE,
29+ SPECIAL,
30+ NOSYOBO,
31+ SUBTITLE,
32+ BILINGUAL,
33+ STANDIN,
34+ PV,
35+ MULTIVOICE,
36+ DATA,
37+ SURROUND,
38+ NEWARRIVAL,
39+ MODIFIED,
40+ NONREPEATED,
41+ MOVED,
42+ PRECEDING,
43+ RATING,
44+ BS4K,
45+ BS8K
46+ };
2347
2448 public static enum ProgGenre {
2549 NEWS ("ニュース/報道", "0"),
@@ -289,6 +313,8 @@ public interface TVProgram {
289313 { ProgOption.NEWARRIVAL, "[NEW]予約待機の新着" },
290314 { ProgOption.MODIFIED, "(更)番組詳細に更新あり - 予約待機分のみ" },
291315 { ProgOption.MOVED, "(移)先週無かったか時間が違う" },
316+ { ProgOption.BS4K, "[4K]BS/CS 4K放送"},
317+ { ProgOption.BS8K, "[8K]BS 8K放送"},
292318 };
293319
294320 public static final String[] OKINIIRI = {"★★★★★","★★★★","★★★","★★","★",""};
--- a/TinyBannavi/src/tainavi/TVProgramUtils.java
+++ b/TinyBannavi/src/tainavi/TVProgramUtils.java
@@ -152,6 +152,12 @@ public class TVProgramUtils implements Cloneable {
152152 public static boolean getUseProgCache(){ return useProgCache; }
153153 private static boolean useProgCache = true;
154154
155+ /*
156+ * 高速キャッシュファイルの読み込みを無効化する
157+ */
158+ public static void invalidateProgCache(boolean b){ invalidProgCache = b; }
159+ private static boolean invalidProgCache = false;
160+
155161 /*******************************************************************************
156162 * オプション確認
157163 ******************************************************************************/
@@ -1121,6 +1127,12 @@ public class TVProgramUtils implements Cloneable {
11211127 //pdl.addOption(ProgOption.NOSCRUMBLE);
11221128 pdl.noscrumble = ProgScrumble.NOSCRUMBLE;
11231129 }
1130+ else if (mx.group(1).equals("4K")) {
1131+ pdl.addOption(ProgOption.BS4K);
1132+ }
1133+ else if (mx.group(1).equals("8K")) {
1134+ pdl.addOption(ProgOption.BS8K);
1135+ }
11241136
11251137 else if (mx.group(1).matches("^(S|N|B|映|双|解|手|天|英|日|録|HV)$")) {
11261138 // 無視するフラグ
@@ -1571,7 +1583,7 @@ public class TVProgramUtils implements Cloneable {
15711583 public boolean loadFromProgCache(String prefix){
15721584 TatCount tc = new TatCount();
15731585
1574- if (!useProgCache){
1586+ if (!useProgCache || invalidProgCache){
15751587 System.out.println("高速キャッシュファイルは使用しません");
15761588 return false;
15771589 }
@@ -1614,6 +1626,16 @@ public class TVProgramUtils implements Cloneable {
16141626
16151627 // 1放送局分を文字列から生成する
16161628 ProgList pl = new ProgList(txt.substring(index, le));
1629+
1630+ for ( Center cr : crlist ) {
1631+ if ( pl.Area.equals(cr.getAreaCode()) && pl.CenterId.equals(cr.getLink()) ) {
1632+ pl.SubArea = cr.getType();
1633+ pl.Center = cr.getCenter();
1634+ pl.BgColor = cr.getBgColor();
1635+ break;
1636+ }
1637+ }
1638+
16171639 pcl.add(pl);
16181640
16191641 if (le == -1)
--- a/TinyBannavi/src/tainavi/VWMainWindow.java
+++ b/TinyBannavi/src/tainavi/VWMainWindow.java
@@ -2,8 +2,11 @@ package tainavi;
22
33 import java.awt.BorderLayout;
44 import java.awt.Component;
5+import java.beans.PropertyChangeEvent;
6+import java.beans.PropertyChangeListener;
57
68 import javax.swing.JPanel;
9+import javax.swing.JSplitPane;
710 import javax.swing.JTabbedPane;
811
912
@@ -28,21 +31,21 @@ public class VWMainWindow extends JPanel {
2831 CHCONV ("CHコンバート設定"),
2932 CHDAT ("CHコード設定"),
3033 ;
31-
34+
3235 String name;
33-
36+
3437 private MWinTab(String name) {
3538 this.name = name;
3639 }
37-
40+
3841 public String getName() {
3942 return name;
4043 }
41-
44+
4245 public int getIndex() {
4346 return ordinal();
4447 }
45-
48+
4649 public static MWinTab getAt(int index) {
4750 for ( MWinTab tab : MWinTab.values() ) {
4851 if ( tab.ordinal() == index ) {
@@ -51,28 +54,36 @@ public class VWMainWindow extends JPanel {
5154 }
5255 return null;
5356 }
54-
57+
5558 public static int size() { return MWinTab.values().length; }
56-
59+
5760 }
5861
5962 private final String SETTING_LIST = "設定一覧";
6063
64+ private Bounds bounds = null;
65+
6166 /*
6267 * 部品
6368 */
64-
69+
70+ private JSplitPane jSplitPane = null;
6571 private JTabbedPane jTabbedPane = null;
6672 private JTabbedPane jTabbedPane_settings = null;
73+ private VWStatusTextArea statusArea = null;
74+
6775
68-
6976 /*
7077 * コンストラクタ
7178 */
72-
73- public VWMainWindow() {
79+
80+ public VWMainWindow(Viewer v) {
81+ bounds = v.getBoundsEnv();
82+
7483 this.setLayout(new BorderLayout());
75- this.add(getJTabbedPane(), BorderLayout.CENTER);
84+ this.add(getJSplitPane(), BorderLayout.CENTER);
85+
86+ jSplitPane.setTopComponent(getJTabbedPane());
7687 getJTabbedPane_settings();
7788
7889 // タブを全部準備する
@@ -83,22 +94,95 @@ public class VWMainWindow extends JPanel {
8394 addTab(null, tab);
8495 }
8596 }
86-
87-
97+
98+
8899 /*
89100 * 公開メソッド
90101 */
91-
102+
92103 // ツールバーを追加する
93104 public void addToolBar(Component comp){
94105 this.add(comp, BorderLayout.PAGE_START);
95106 }
96-
97-
98- public void addStatusArea(Component comp) {
99- this.add(comp, BorderLayout.PAGE_END);
107+
108+ /*
109+ * ステータスエリア
110+ */
111+ public void addStatusArea(VWStatusTextArea comp) {
112+ statusArea = comp;
113+ jSplitPane.setBottomComponent(comp);
114+ }
115+
116+ /*
117+ * ステータスエリアの行数を設定する
118+ */
119+ public void setStatusAreaRows(int rows){
120+ setStatusAreaHeight(statusArea.getHeightFromRows(rows));
121+ }
122+
123+ /*
124+ * ステータスエリアの高さを初期化する
125+ */
126+ public void initStatusAreaHeight(){
127+ if (bounds.getStatusRows() > 0){
128+ resetStatusAreaHeight();
129+ }
130+ else{
131+ int sh = bounds.getStatusWindowHeight();
132+ if (sh <= 1)
133+ resetStatusAreaHeight();
134+ else
135+ setStatusAreaHeight(sh);
136+ }
137+ }
138+
139+ /*
140+ * ステータス絵アリアの高さを設定する
141+ */
142+ public void setStatusAreaHeight(int sh){
143+ int h = jSplitPane.getHeight();
144+ jSplitPane.setDividerLocation(h-sh);
145+ bounds.setStatusWindowHeight(sh);
100146 }
101-
147+
148+ /*
149+ * ステータスエリアの高さをリセットする
150+ */
151+ public void resetStatusAreaHeight(){
152+ int rows = bounds.getStatusRows();
153+ int sh = statusArea.getHeightFromRows(rows > 0 ? rows : 5);
154+ bounds.setStatusWindowHeight(sh);
155+
156+ setStatusAreaHeight(sh);
157+ }
158+
159+ /*
160+ * ステータスエリアの表示・非表示を設定する
161+ */
162+ public void setStatusAreaVisible(boolean b){
163+ statusArea.setVisible(b);
164+
165+ if (b)
166+ initStatusAreaHeight();
167+ }
168+
169+ /*
170+ * ジオメトリ情報を初期化する
171+ */
172+ public void initBounds(){
173+ initStatusAreaHeight();
174+
175+ jSplitPane.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY, new PropertyChangeListener() {
176+ @Override
177+ public void propertyChange(PropertyChangeEvent pce) {
178+ if (statusArea.isVisible()){
179+ int h = jSplitPane.getHeight();
180+ bounds.setStatusWindowHeight(h-jSplitPane.getDividerLocation());
181+ }
182+ }
183+ });
184+ }
185+
102186 // タブを追加する
103187 public boolean addTab(Component comp, MWinTab tab) {
104188 if ( jTabbedPane.getTabCount() + jTabbedPane_settings.getTabCount() < tab.getIndex() ) {
@@ -132,7 +216,7 @@ public class VWMainWindow extends JPanel {
132216 }
133217 jTabbedPane.setSelectedIndex(tab.getIndex());
134218 }
135-
219+
136220 //
137221 public Component getTab(MWinTab tab) {
138222 if ( tab.getIndex() >= MWinTab.SETTING.getIndex() ) {
@@ -140,7 +224,7 @@ public class VWMainWindow extends JPanel {
140224 }
141225 return jTabbedPane.getComponent(tab.getIndex());
142226 }
143-
227+
144228 // タブが選択されているか確認する
145229 public boolean isTabSelected(MWinTab tab) {
146230 if ( tab.getIndex() >= MWinTab.SETTING.getIndex() ) {
@@ -148,7 +232,7 @@ public class VWMainWindow extends JPanel {
148232 }
149233 return (jTabbedPane.getSelectedIndex() == tab.getIndex());
150234 }
151-
235+
152236 // どのタブが選択されているのやら
153237 public MWinTab getSelectedTab() {
154238 if ( jTabbedPane.getSelectedIndex() == MWinTab.SETTING.getIndex() ) {
@@ -156,7 +240,7 @@ public class VWMainWindow extends JPanel {
156240 }
157241 return MWinTab.getAt(jTabbedPane.getSelectedIndex());
158242 }
159-
243+
160244 // 設定タブをトグル切り替え
161245 private final int firstSettingTab = MWinTab.SETTING.ordinal();
162246 private final int countSettingTab = MWinTab.size()-firstSettingTab;
@@ -165,18 +249,27 @@ public class VWMainWindow extends JPanel {
165249 public boolean toggleShowSettingTabs() {
166250 return true;
167251 }
168-
252+
169253 public boolean getShowSettingTabs() {
170254 return true;
171255 }
172256 public void setShowSettingTabs(boolean b) {
173257 }
174-
175-
258+
259+
176260 /*
177- *
261+ *
178262 */
179-
263+
264+ private JSplitPane getJSplitPane() {
265+ if (jSplitPane == null){
266+ jSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
267+ jSplitPane.setResizeWeight(1.0);
268+ }
269+
270+ return jSplitPane;
271+ }
272+
180273 private JTabbedPane getJTabbedPane() {
181274 if (jTabbedPane == null) {
182275 jTabbedPane = new JTabbedPane();
@@ -190,14 +283,14 @@ public class VWMainWindow extends JPanel {
190283 }
191284 return jTabbedPane_settings;
192285 }
193-
286+
194287 /**
195288 * @deprecated
196289 */
197290 public void appendStatusMessage(String s) {
198291 throw new UnsupportedOperationException();
199292 }
200-
293+
201294 /**
202295 * @deprecated
203296 * @see Viewer#setStatusVisible(boolean)
@@ -205,5 +298,5 @@ public class VWMainWindow extends JPanel {
205298 public void setStatusVisible(boolean b) {
206299 throw new UnsupportedOperationException();
207300 }
208-
301+
209302 }
--- a/TinyBannavi/src/tainavi/VWStatusTextArea.java
+++ b/TinyBannavi/src/tainavi/VWStatusTextArea.java
@@ -37,6 +37,14 @@ public class VWStatusTextArea extends JPanel implements StatusTextArea {
3737
3838 }
3939
40+ /*
41+ * 行数から高さを計算する
42+ */
43+ public int getHeightFromRows(int rows){
44+ int hl = jtp.getFont().getSize();
45+ return CommonUtils.getPixelFromPoint(hl*rows)+8;
46+ }
47+
4048 private JScrollPane getJScrollPane_statusarea() {
4149 if (jsp == null) {
4250 jsp = new JScrollPane(getJTextPane_statusarea(),JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
@@ -102,8 +110,7 @@ public class VWStatusTextArea extends JPanel implements StatusTextArea {
102110 if (jsp == null)
103111 return;
104112 Dimension dim = jsp.getPreferredSize();
105- double fh = (double)jtp.getFont().getSize()*1.35;
106- dim.height = (int)(fh*(float)rows);
113+ dim.height = getHeightFromRows(rows);
107114 jsp.setPreferredSize(dim);
108115 }
109116 }
--- a/TinyBannavi/src/tainavi/VersionInfo.java
+++ b/TinyBannavi/src/tainavi/VersionInfo.java
@@ -5,7 +5,7 @@ import java.util.regex.Pattern;
55
66
77 public class VersionInfo {
8- private static final String Version = "タイニー番組ナビゲータ for DBR-T2007 3.22.18β+1.12.7";
8+ private static final String Version = "タイニー番組ナビゲータ for DBR-T2007 3.22.18β+1.12.8";
99
1010 private static final String OSname = System.getProperty("os.name");
1111 private static final String OSvers = System.getProperty("os.version");
--- a/TinyBannavi/src/tainavi/Viewer.java
+++ b/TinyBannavi/src/tainavi/Viewer.java
@@ -97,7 +97,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
9797 private void StdAppendMessage(String message) { System.out.println(CommonUtils.getNow() + message); }
9898 private void StdAppendError(String message) { System.err.println(CommonUtils.getNow() + message); }
9999 //
100- private void MWinSetVisible(boolean b) { mwin.setVisible(b); }
100+ private void MWinSetVisible(boolean b) { mainWindow.setStatusAreaVisible(b); }
101101 //
102102 private void StWinClear() { stwin.clear(); }
103103 private void StWinSetVisible(boolean b) { stwin.setVisible(b); }
@@ -374,7 +374,10 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
374374
375375 private TrayIcon trayicon = null;
376376
377-
377+ /*******************************************************************************
378+ * パブリック関数
379+ ******************************************************************************/
380+ public Bounds getBoundsEnv(){ return bounds; }
378381
379382 /*******************************************************************************
380383 * タブやダイアログのインスタンス作成用クラス定義
@@ -1534,7 +1537,9 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
15341537 chdatsetting.updateChannelDatTable();
15351538
15361539 // 番組情報の再取得
1540+ TVProgramUtils.invalidateProgCache(true);
15371541 loadTVProgram(false,LoadFor.ALL, false); // 部品呼び出し
1542+ TVProgramUtils.invalidateProgCache(false);
15381543
15391544 // ツールバーに反映
15401545 toolBar.setPagerItems();
@@ -1839,6 +1844,66 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
18391844 @Override
18401845 protected void ringBeep() { Viewer.this.ringBeep(); }
18411846
1847+ /*
1848+ * 前のページに移動する
1849+ * @see tainavi.AbsToolBar#moveToPrevPage()
1850+ */
1851+ @Override
1852+ protected void moveToPrevPage(){
1853+ if (!isPrevPageEnabled())
1854+ return;
1855+
1856+ if (paper.isByCenterMode())
1857+ paper.moveToPrevDatePage();
1858+ else
1859+ moveToPrevCenterPage();
1860+ }
1861+
1862+ /*
1863+ * 前のページに移動可能かを返す
1864+ * @see tainavi.AbsToolBar#isPrevPageEnabled()
1865+ */
1866+ @Override
1867+ protected boolean isPrevPageEnabled(){
1868+ if (!mainWindow.isTabSelected(MWinTab.PAPER))
1869+ return false;
1870+
1871+ if (paper.isByCenterMode())
1872+ return paper.isPrevDatePageEnabled();
1873+ else
1874+ return isPrevCenterPageEnabled();
1875+ }
1876+
1877+ /*
1878+ * 次のページに移動する
1879+ * @see tainavi.AbsToolBar#moveToNextPage()
1880+ */
1881+ @Override
1882+ protected void moveToNextPage(){
1883+ if (!isNextPageEnabled())
1884+ return;
1885+
1886+ if (paper.isByCenterMode())
1887+ paper.moveToNextDatePage();
1888+ else
1889+ moveToNextCenterPage();
1890+ }
1891+
1892+ /*
1893+ * 次のページに移動可能かを返す
1894+ * @see tainavi.AbsToolBar#isNextPageEnabled()
1895+ */
1896+ @Override
1897+ protected boolean isNextPageEnabled(){
1898+ if (!mainWindow.isTabSelected(MWinTab.PAPER))
1899+ return false;
1900+
1901+ if (paper.isByCenterMode())
1902+ return paper.isNextDatePageEnabled();
1903+ else
1904+ return isNextCenterPageEnabled();
1905+ }
1906+
18421907 @Override
18431908 protected boolean doKeywordSerach(SearchKey search, String kStr, String sStr, boolean doFilter) {
18441909
@@ -4717,8 +4782,8 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
47174782 mpList.setHistoryOnlyUpdateOnce(env.getHistoryOnlyUpdateOnce());
47184783 mpList.setShowOnlyNonrepeated(env.getShowOnlyNonrepeated());
47194784
4720- mwin.setRows(bounds.getStatusRows());
47214785 setStatusVisible(false);
4786+ mainWindow.initStatusAreaHeight();
47224787 if (bounds.getShowStatus())
47234788 setStatusVisible(true);
47244789
@@ -5530,7 +5595,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
55305595 // コンポーネント作成
55315596 {
55325597 // メインウィンドウの作成
5533- mainWindow = new VWMainWindow();
5598+ mainWindow = new VWMainWindow(this);
55345599
55355600 // 内部クラスのインスタンス生成
55365601 toolBar = new VWToolBar();
@@ -5564,7 +5629,6 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
55645629 // ツールバーなど
55655630 mainWindow.addToolBar(toolBar);
55665631 mainWindow.addStatusArea(mwin);
5567- mwin.setRows(bounds.getStatusRows());
55685632
55695633 // タブ群
55705634 mainWindow.addTab(listed, MWinTab.LISTED);
@@ -6069,6 +6133,8 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
60696133
60706134 sca.add(new ShortCut(SCROLL_ACTION_PREV_PAPERNODE, KeyEvent.VK_F5, 0, sc_prev_papernode));
60716135 sca.add(new ShortCut(SCROLL_ACTION_NEXT_PAPERNODE, KeyEvent.VK_F6, 0, sc_next_papernode));
6136+ sca.add(new ShortCut(SCROLL_ACTION_PREV_PAPERNODE, KeyEvent.VK_UP, KeyEvent.ALT_DOWN_MASK, sc_prev_papernode));
6137+ sca.add(new ShortCut(SCROLL_ACTION_NEXT_PAPERNODE, KeyEvent.VK_DOWN, KeyEvent.ALT_DOWN_MASK, sc_next_papernode));
60726138
60736139 sca.add(new ShortCut(SCROLL_ACTION_PREV_PAGE, KeyEvent.VK_F7, 0, sc_prev_page));
60746140 sca.add(new ShortCut(SCROLL_ACTION_NEXT_PAGE, KeyEvent.VK_F8, 0, sc_next_page));
@@ -6449,6 +6515,8 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
64496515 setInitBounds();
64506516 this.setVisible(true);
64516517
6518+ mainWindow.initBounds();
6519+
64526520 setTitleBar(); // タイトルバー更新
64536521
64546522 ShowInitTab(); // 前回開いていたタブを開く
--- a/TinyBannavi/src/tainavi/plugintv/PlugIn_TVPDimora.java
+++ b/TinyBannavi/src/tainavi/plugintv/PlugIn_TVPDimora.java
@@ -74,6 +74,13 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
7474
7575 protected String getCenterInfoId() { return "ChannelTypeDB"; }
7676 protected String getChType() { return "6"; }
77+
78+ protected String getCenterInfoId4K(){ return "m_ChannelTypeUhd"; }
79+ protected String getChType4K() { return "96"; }
80+
81+ protected String getSiteUrl(){ return "https://www.dimora.jp/"; }
82+ protected String getUrl(){ return "https://www.dimora.jp/dc/pc/P4501.do"; }
83+
7784 protected String getCenterCode(String id, String code) { return id.matches("^3.*$")?(bsCode):(code); }
7885
7986 protected String getProgCacheFile(String areacode, String adate) { return String.format(getProgDir()+File.separator+"Dimora_%s_%s.html", areacode, adate.substring(6,8)); }
@@ -87,7 +94,6 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
8794 /*******************************************************************************
8895 * 番組情報を取得する
8996 ******************************************************************************/
90-
9197 @Override
9298 public boolean loadProgram(String areaCode, boolean force) {
9399 setCacheFileOnly(true);
@@ -159,6 +165,8 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
159165 }
160166
161167 // 参照する総ページ数を計算
168+ boolean has4k = hasBS4K();
169+
162170 int counterMax = 0;
163171 for ( String ac : pages.keySet() ) {
164172 if ( ac.equals(bsCode) ) {
@@ -166,6 +174,8 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
166174 }
167175 counterMax += pages.get(ac)*getDogDays();
168176 }
177+ if (has4k)
178+ counterMax += getDogDays();
169179
170180 clrCookie();
171181
@@ -193,6 +203,26 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
193203 }
194204 }
195205
206+ // 4K/8Kの放送局を含む場合別途番組情報を取得する
207+ if (has4k){
208+ cale = (GregorianCalendar) cal.clone();
209+ for ( int i=0; i<getDogDays(); i++ ) {
210+ String adate = CommonUtils.getDateYMD(cale);
211+ cale.add(Calendar.DATE, 1);
212+ String edate = CommonUtils.getDateYMD(cale);
213+ if (!_loadProgram4K(adate, edate, force, i, counter++, counterMax)){
214+ newplist = null;
215+ return false;
216+ }
217+
218+ if (isCancelRequested()){
219+ newplist = null;
220+ reportProgress(ERRID+"中止要求があったので番組表の取得にを中止します。");
221+ return false;
222+ }
223+ }
224+ }
225+
196226 // 開始・終了日時を正しい値に計算しなおす
197227 for ( ProgList pl : newplist ) {
198228 setAccurateDate(pl.pdate);
@@ -241,7 +271,7 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
241271
242272 String hh = String.valueOf(CommonUtils.getCalendar(0).get(Calendar.HOUR_OF_DAY));
243273 String tvParam = "1%2C1%2C1%2CDR%2C10%2C1%2C1%2C1%2C1%2C1%2C1";
244- String url = "http://www.dimora.jp/dc/pc/P4501.do";
274+ String url = getUrl();
245275 String pstr = String.format("c_time=%s&win_id=P4501&isLogin=1&start_time=%s0500&end_time=%s0500&ch_type=%s&args=%s0500%s%s%s",
246276 CommonUtils.getDateTimeYMD(c),
247277 adate,
@@ -317,6 +347,98 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
317347 return true;
318348 }
319349
350+ /*
351+ * BS 4K/8Kの番組情報を取得する
352+ */
353+ protected boolean _loadProgram4K(String adate, String edate, boolean force, int wdaycol, int counter, int counterMax) {
354+ //
355+ String areacode = "bs4k";
356+ String aname = "BS4K";
357+ final String progCacheFile = getProgCacheFile(areacode,adate);
358+ String dt = adate.substring(6,8);
359+ String targetCache = "["+dt+"日/"+aname+"]: ("+counter+"/"+counterMax+") "+progCacheFile;
360+ //
361+ try {
362+ //
363+ String response = null;
364+ File f = new File(progCacheFile);
365+ if (force == true || f.exists() == false || isCacheOld(progCacheFile)){
366+ GregorianCalendar c = new GregorianCalendar();
367+ c.setTime(new Date());
368+
369+ String hh = String.valueOf(CommonUtils.getCalendar(0).get(Calendar.HOUR_OF_DAY));
370+ String tvParam = "1%2C1%2C1%2CDR%2C10%2C1%2C1%2C1%2C1%2C1%2C1";
371+ String url = getUrl();
372+ String pstr = String.format("c_time=%s&win_id=P4501&isLogin=1&start_time=%s0500&end_time=%s0500&ch_type=%s&args=%s0500%s%s%s",
373+ CommonUtils.getDateTimeYMD(c),
374+ adate,
375+ edate,
376+ getChType4K(),
377+ adate,
378+ "%2C"+hh+"%2C",
379+ getChType4K(),
380+ "%2C0%2C"+tvParam);
381+
382+ // 本体
383+ //clrCookie(); -> もっと上に
384+ addCookie("tvParam", tvParam);
385+ response = webToBuffer(
386+ url,
387+ pstr,
388+ null,
389+ url,
390+ thisEncoding,
391+ false);
392+
393+ String targetOnline = "["+dt+"日/"+aname+"]: ("+counter+"/"+counterMax+") "+url+"?"+pstr+"("+areacode+")";
394+ if ( response != null ){
395+ if ( CommonUtils.write2file(progCacheFile, "<!-- "+url+"?"+pstr+" -->\n"+response) ) {
396+ reportProgress(MSGID+"番組表(オンライン)を取得しました" + targetOnline);
397+ }
398+ else{
399+ reportProgress(ERRID+"番組表(キャッシュ)の保存に失敗しました: "+targetCache);
400+ }
401+
402+ setCacheFileOnly(false);
403+ }
404+ else{
405+ reportProgress(ERRID+"番組表(オンライン)の取得に失敗しました" + targetOnline);
406+ if (f.exists() == false)
407+ return false;
408+ else
409+ reportProgress(MSGID+"番組表(キャッシュ)を代わりに使用します: "+targetCache);
410+ }
411+
412+ }
413+
414+ if (response == null){
415+ if (CommonUtils.isFileAvailable(f,10)) {
416+ // キャッシュファイルの読み込み
417+ response = CommonUtils.read4file(progCacheFile, false);
418+ if ( response == null ) {
419+ reportProgress(ERRID+"番組表(キャッシュ)の取得に失敗しました"+targetCache);
420+ return false;
421+ }
422+ reportProgress(MSGID+"番組表(キャッシュ)を取得しました"+targetCache);
423+ }
424+ else {
425+ reportProgress(ERRID+"番組表(キャッシュ)がみつかりません"+targetCache);
426+ return false;
427+ }
428+ }
429+
430+ // 番組リストの追加
431+ getPrograms(bsCode, wdaycol, response);
432+ }
433+ catch (Exception e) {
434+ reportProgress(ERRID+"番組表の取得で例外が発生しました: "+e.toString());
435+ e.printStackTrace();
436+ return false;
437+ }
438+
439+ return true;
440+ }
441+
320442 //
321443 private void getPrograms(String areacode, int wdaycol, String src) {
322444
@@ -458,6 +580,22 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
458580 }
459581 }
460582
583+ /*
584+ * BS4K/8Kの放送局が選択されているか
585+ */
586+ private boolean hasBS4K(){
587+ for (Center c : crlist){
588+ if (!c.getAreaCode().equals(bsCode))
589+ continue;
590+ if (c.getOrder() <= 0)
591+ continue;
592+
593+ if (c.getLink().startsWith("2"))
594+ return true;
595+ }
596+
597+ return false;
598+ }
461599
462600 /*******************************************************************************
463601 * 地域情報を取得する
@@ -487,7 +625,7 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
487625 }
488626
489627 // 存在していなければWeb上から
490- String uri = "http://www.dimora.jp/";
628+ String uri = getSiteUrl();
491629 String response = webToBuffer(uri, thisEncoding, true);;
492630 if ( response == null ) {
493631 System.err.println(ERRID+"地域情報の取得に失敗しました: "+uri);
@@ -589,6 +727,9 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
589727 cnt++;
590728 }
591729
730+ _loadCenter4K(newcrlist);
731+ reportProgress(MSGID+"BS4K/8K放送局情報を取得しました");
732+
592733 if ( newcrlist.size() == 0 ) {
593734 System.err.println(ERRID+"放送局情報の取得結果が0件だったため情報を更新しません");
594735 return;
@@ -601,7 +742,7 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
601742
602743 private boolean _loadCenter(ArrayList<Center> newcrlist, String code, boolean bsexist) {
603744 // 本体
604- String uri = "http://www.dimora.jp/dc/pc/P4501.do";
745+ String uri = getUrl();
605746
606747 GregorianCalendar c = CommonUtils.getCalendar(0);
607748 String cdate = CommonUtils.getDateTimeYMD(c);
@@ -623,7 +764,7 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
623764 getChType(),
624765 "%2C0%2C0%2C1%2C1%2CDR%2C10%2C1%2C1%2C1%2C1%2C1%2C1"),
625766 null,
626- "http://www.dimora.jp/dc/pc/P4501.do",
767+ getUrl(),
627768 thisEncoding,
628769 true);
629770 if ( response == null ) {
@@ -702,4 +843,81 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
702843 return true;
703844 }
704845
846+ /*
847+ * BS4K/8Kの放送局を取得する
848+ */
849+ private boolean _loadCenter4K(ArrayList<Center> newcrlist) {
850+ // 本体
851+ String uri = getUrl();
852+ String areacode = bsCode;
853+
854+ GregorianCalendar c = CommonUtils.getCalendar(0);
855+ String cdate = CommonUtils.getDateTimeYMD(c);
856+ String adate = CommonUtils.getDateYMD(c);
857+ c.add(Calendar.DAY_OF_MONTH, 1);
858+ String edate = CommonUtils.getDateYMD(c);
859+
860+ clrCookie();
861+ String response = webToBuffer(
862+ uri,
863+ String.format("c_time=%s&win_id=P4501&isLogin=1&start_time=%s0500&end_time=%s0500&ch_type=%s&args=%s0500%s%s%s",
864+ cdate,
865+ adate,
866+ edate,
867+ getChType4K(),
868+ adate,
869+ "%2C3%2C",
870+ getChType4K(),
871+ "%2C0%2C1%2C1%2C1%2CDR%2C10%2C1%2C1%2C1%2C1%2C1%2C1"),
872+ null,
873+ getUrl(),
874+ thisEncoding,
875+ true);
876+ if ( response == null ) {
877+ reportProgress(ERRID+"番組表の取得に失敗しました: "+uri);
878+ return false;
879+ }
880+
881+ //CommonUtils.write2file("TMP.htm", response);
882+
883+ String expr = String.format("<div\\s+id=\"%s\"\\s*>(.+?)</div>", getCenterInfoId4K());
884+ Matcher ma = Pattern.compile(expr).matcher(response);
885+ if ( ma.find() ) {
886+ Matcher mb = Pattern.compile("(.+?),.+?,.+?,(.+?),(.+?),.+?\\|").matcher(ma.group(1));
887+ while ( mb.find() ) {
888+ String centerName = CommonUtils.unEscape(mb.group(3));
889+// String chNo = mb.group(2);
890+ String centerId = mb.group(1);
891+
892+ // 一部の放送局がBSと同じ名前のため、4K/8Kが必ず付くようにする
893+ Matcher mc = Pattern.compile("(4K|8K|4K|8K)").matcher(centerName);
894+ if (!mc.find()){
895+ centerName += " 4K";
896+ }
897+
898+ // 重複する放送局は追加しない
899+ boolean found=false;
900+ for (Center cr2 : newcrlist){
901+ if (areacode.equals(cr2.getAreaCode()) && centerName.equals(cr2.getCenterOrig())){
902+ found = true;
903+ break;
904+ }
905+ }
906+ if (found)
907+ continue;
908+
909+ Center cr = new Center();
910+ cr.setAreaCode(areacode);
911+ cr.setCenterOrig(centerName);
912+ cr.setLink(centerId);
913+ cr.setType("");
914+ cr.setEnabled(true);
915+ if ( response.matches(String.format(".*<div\\s+id=\"%s\">.*",centerId)) ) {
916+ newcrlist.add(cr);
917+ }
918+ }
919+ }
920+
921+ return true;
922+ }
705923 }