• R/O
  • HTTP
  • SSH
  • HTTPS

提交

Frequently used words (click to add to your profile)

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

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


Commit MetaInfo

修订版348f43f681ba76125bbb4ae5fcb6d75cd6985575 (tree)
时间2020-05-03 22:04:58
作者Masahiko Kimura <mkimura@u01....>
CommiterMasahiko Kimura

Log Message

Ver.1.12.13 (2020/05/03)

  1. [本体予約一覧][タイトル一覧]右クリックメニューで新聞形式と同様の番組に対するメニューを選択できるようにする
  2. [新聞形式]現在線左端の現在時刻をHH:MM形式で表示する(env.txtのtimelineLabelDispModeで変更可。0=非表示,1=MM,2=HH:MM)
  3. [新聞形式][リスト形式]右クリックメニューでしょぼいカレンダーの番組詳細を呼び出せるようにする
    (各種設定画面の「右クリックメニューの実行アイテム」に追加が必要。実行コマンドは%SYOBODETAILURL%とする)
  4. [その他]Ubuntu 19.10,20.04LTSで起動に失敗する問題の対応(Javaの最新化が必要)

更改概述

差异

--- a/TinyBannavi/src/tainavi/AbsListedView.java
+++ b/TinyBannavi/src/tainavi/AbsListedView.java
@@ -130,10 +130,8 @@ public abstract class AbsListedView extends JPanel implements TickTimerListener
130130 /**
131131 * マウス右クリックメニューを表示する
132132 */
133- protected abstract void showPopupForTraceProgram(
134- final JComponent comp,
135- final ProgDetailList tvd, final String keyword, final int threshold,
136- final int x, final int y);
133+ protected abstract void showPopupMenu(
134+ final JComponent comp, final ProgDetailList tvd, final int x, final int y);
137135
138136 /**
139137 * 予約マーク・予約枠を更新してほしい
@@ -1839,9 +1837,7 @@ public abstract class AbsListedView extends JPanel implements TickTimerListener
18391837 // 右シングルクリックでメニューの表示
18401838 t.getSelectionModel().addSelectionInterval(vrow,vrow);
18411839
1842- int threshold = getThrValByRow(row);
1843- String keyword = (threshold > 0) ? (getKeyValByRow(row)) : (tvd.title);
1844- showPopupForTraceProgram(t, tvd, keyword, threshold, p.x, p.y);
1840+ showPopupMenu(t, tvd, p.x, p.y);
18451841 }
18461842 }
18471843 else if (e.getButton() == MouseEvent.BUTTON1) {
--- a/TinyBannavi/src/tainavi/AbsPaperView.java
+++ b/TinyBannavi/src/tainavi/AbsPaperView.java
@@ -29,6 +29,7 @@ import java.beans.PropertyChangeListener;
2929 import java.io.File;
3030 import java.text.AttributedCharacterIterator;
3131 import java.text.AttributedString;
32+import java.text.SimpleDateFormat;
3233 import java.util.ArrayList;
3334 import java.util.Calendar;
3435 import java.util.GregorianCalendar;
@@ -109,11 +110,8 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
109110 /**
110111 * マウス右クリックメニューを表示する
111112 */
112- protected abstract void showPopupForTraceProgram(
113- final JComponent comp,
114- final ProgDetailList tvd, final String keyword, final int threshold,
115- final int x, final int y, final String clickedDateTime
116- );
113+ protected abstract void showPopupMenu(
114+ final JComponent comp, final ProgDetailList tvd, final int x, final int y);
117115
118116 /**
119117 * 予約マーク・予約枠を更新してほしい
@@ -331,7 +329,23 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
331329 setBackground(Color.RED);
332330 setOpaque(true);
333331
334- min = "";
332+ label = "";
333+ }
334+
335+ public void setTime(GregorianCalendar c){
336+ switch(env.getTimelineLabelDispMode()){
337+ case 0:
338+ label = ""; break;
339+ case 1:
340+ label = new SimpleDateFormat("mm").format(c.getTime());
341+ break;
342+ case 2:
343+ label = CommonUtils.getTime(c);
344+ break;
345+ case 3:
346+ label = CommonUtils.getTime529(c);
347+ break;
348+ }
335349 }
336350
337351 private static final long serialVersionUID = 1L;
@@ -339,7 +353,7 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
339353
340354 private int minpos = 0;
341355 private BufferedImage image = null;
342- private String min;
356+ private String label;
343357
344358 @Override
345359 public void repaint() {
@@ -357,33 +371,41 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
357371 image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
358372 Graphics2D g2 = (Graphics2D)image.createGraphics();
359373
360- // 書き込む文字列のサイズを算出する
361- Font f = this.getFont();
362- Font f2 = f.deriveFont(f.getStyle(), 11);
363- g2.setFont(f2);
364- FontMetrics fm = g2.getFontMetrics();
365- Rectangle2D r = fm.getStringBounds(min,g2);
366- int wt = (int)r.getWidth();
367- int ht = (int)r.getHeight();
368-
369- // 全体を赤く塗りつぶす
370- g2.setColor(Color.RED);
371- int xp[] = {-1, wt+2, wt+5, w, w, -1};
372- int yp[] = {h-ht-1, h-ht-1, h-3, h-3, h+1, h+1};
373- g2.fillPolygon(xp, yp, 6);
374-
375- // 書き込む位置を決定する
376- int x = 1;
377- int y = h-3;
378-
379- // 書き込む
380- AttributedString as = new AttributedString(min);
381- as.addAttribute(TextAttribute.FOREGROUND, Color.WHITE);
382- as.addAttribute(TextAttribute.BACKGROUND, Color.OPAQUE);
383- as.addAttribute(TextAttribute.FONT, f2);
384- AttributedCharacterIterator ac = as.getIterator();
385- g2.drawString(ac, x, y);
386-
374+ if (env.getTimelineLabelDispMode() == 0){
375+ // 全体を赤く塗りつぶす
376+ g2.setColor(Color.RED);
377+ int xp[] = {-1, w, w, -1};
378+ int yp[] = {h-3, h-3, h+1, h+1};
379+ g2.fillPolygon(xp, yp, 4);
380+ }
381+ else{
382+ // 書き込む文字列のサイズを算出する
383+ Font f = this.getFont();
384+ Font f2 = f.deriveFont(f.getStyle(), 11);
385+ g2.setFont(f2);
386+ FontMetrics fm = g2.getFontMetrics();
387+ Rectangle2D r = fm.getStringBounds(label,g2);
388+ int wt = (int)r.getWidth();
389+ int ht = (int)r.getHeight();
390+
391+ // 全体を赤く塗りつぶす
392+ g2.setColor(Color.RED);
393+ int xp[] = {-1, wt+2, wt+5, w, w, -1};
394+ int yp[] = {h-ht-1, h-ht-1, h-3, h-3, h+1, h+1};
395+ g2.fillPolygon(xp, yp, 6);
396+
397+ // 書き込む位置を決定する
398+ int x = 1;
399+ int y = h-3;
400+
401+ // 書き込む
402+ AttributedString as = new AttributedString(label);
403+ as.addAttribute(TextAttribute.FOREGROUND, Color.WHITE);
404+ as.addAttribute(TextAttribute.BACKGROUND, Color.OPAQUE);
405+ as.addAttribute(TextAttribute.FONT, f2);
406+ AttributedCharacterIterator ac = as.getIterator();
407+ g2.drawString(ac, x, y);
408+ }
387409 }
388410
389411 // 反映
@@ -407,10 +429,8 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
407429 return timeline;
408430 }
409431
410- public void setMin(String s){
411- min = s;
412- if (min.length() == 1)
413- min = "0" + min;
432+ public void setLabel(String s){
433+ label = s;
414434 repaint();
415435 }
416436 }
@@ -1433,7 +1453,7 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
14331453
14341454 // ビュー上の位置を計算してセットする
14351455 jLabel_timeline_tb.setMinpos(minpos_new, mul);
1436- jLabel_timeline_tb.setMin(String.valueOf(c.get(Calendar.MINUTE)));
1456+ jLabel_timeline_tb.setTime(c);
14371457
14381458 // ビューを移動する場合
14391459 if (vpos){
@@ -2347,7 +2367,7 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
23472367 int timeline_vpos = jLabel_timeline.setMinpos(0, minpos_new, mul);
23482368
23492369 jLabel_timeline_tb.setMinpos(minpos_new, mul);
2350- jLabel_timeline_tb.setMin(String.valueOf(c.get(Calendar.MINUTE)));
2370+ jLabel_timeline_tb.setTime(c);
23512371
23522372 // ビューポートの位置
23532373 if ( reset ) {
@@ -2696,7 +2716,7 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
26962716 if (e.getClickCount() == 1) {
26972717 // 右シングルクリックでメニューの表示
26982718 String clicked = getClickedDateTime(tvd, e.getY());
2699- showPopupForTraceProgram(b, tvd, tvd.title, TraceKey.noFazzyThreshold, p.x, p.y, clicked);
2719+ showPopupMenu(b, tvd, p.x, p.y);
27002720 }
27012721 }
27022722 else if (e.getButton() == MouseEvent.BUTTON1) {
@@ -3034,7 +3054,7 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
30343054 }
30353055 public void mouseEntered(MouseEvent e) {
30363056 bgcolor = ((JLabel)e.getSource()).getBackground();
3037- ((JLabel)e.getSource()).setBackground(new Color(180,180,255));
3057+ ((JLabel)e.getSource()).setBackground(CommonUtils.getSelBgColor(bgcolor));
30383058 }
30393059
30403060 public void mouseClicked(MouseEvent e) {
@@ -3072,7 +3092,7 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
30723092 }
30733093 public void mouseEntered(MouseEvent e) {
30743094 bgcolor = ((JTXTLabel)e.getSource()).getBackground();
3075- ((JTXTLabel)e.getSource()).setBackground(new Color(180,180,255));
3095+ ((JTXTLabel)e.getSource()).setBackground(CommonUtils.getSelBgColor(bgcolor));
30763096 }
30773097
30783098 //
--- a/TinyBannavi/src/tainavi/AbsReserveListView.java
+++ b/TinyBannavi/src/tainavi/AbsReserveListView.java
@@ -106,6 +106,11 @@ public abstract class AbsReserveListView extends JPanel implements TickTimerList
106106 protected abstract JMenuItem getJumpMenuItem(final String title, final String chnam, final String startDT);
107107 protected abstract JMenuItem getJumpToLastWeekMenuItem(final String title, final String chnam, final String startDT);
108108
109+ /*
110+ * プログラムのブラウザーメニューを呼び出す
111+ */
112+ protected abstract void addBrowseMenuToPopup( JPopupMenu pop, final ProgDetailList tvd );
113+
109114 /**
110115 * @see Viewer.VWToolBar#getSelectedRecorder()
111116 */
@@ -1079,149 +1084,168 @@ public abstract class AbsReserveListView extends JPanel implements TickTimerList
10791084 }
10801085 };
10811086
1087+ private void showPopupMenu(final int vrow, final ReservedItem ra, final int x, final int y){
1088+ final boolean fexec = ra.exec;
1089+ final String start = ra.nextstart;
1090+ final String title = ra.title;
1091+ final String chnam = ra.hide_chname;
1092+ final String recId = ra.recorder;
1093+ final String rsvId = ra.hide_rsvid;
1094+ int num =jTable_rsved.getSelectedRowCount();
1095+ final ArrayList<ReservedItem> ras = new ArrayList<ReservedItem>(num);
1096+
1097+ if (!jTable_rsved.isRowSelected(vrow)){
1098+ jTable_rsved.getSelectionModel().setSelectionInterval(vrow,vrow);
1099+ num = 1;
1100+ }
1101+
1102+ if (num > 1){
1103+ int rows[] = jTable_rsved.getSelectedRows();
1104+ for (int n=0; n<num; n++){
1105+ ras.add(rowViewTemp.get(jTable_rsved.convertRowIndexToModel(rows[n])));
1106+ }
1107+ }
1108+
1109+ // 右クリックで予約削除メニュー表示
1110+ JPopupMenu pop = new JPopupMenu();
1111+ //
1112+ {
1113+ JMenuItem menuItem = new JMenuItem(String.format("予約を編集する【%s - %s(%s)】",start,title,chnam));
1114+ menuItem.setForeground(new Color(0,127,0));
1115+ Font f = menuItem.getFont();
1116+ menuItem.setFont(f.deriveFont(f.getStyle()|Font.BOLD));
1117+
1118+ menuItem.addActionListener(new ActionListener() {
1119+ public void actionPerformed(ActionEvent e) {
1120+ editReserve(recId,rsvId,chnam,vrow);
1121+ }
1122+ });
1123+ pop.add(menuItem);
1124+ }
1125+
1126+ pop.addSeparator();
1127+
1128+ // 予約実行ON・OFF
1129+ {
1130+ pop.add(getExecOnOffMenuItem(fexec,start,title,chnam,rsvId,recId));
1131+ }
1132+
1133+ pop.addSeparator();
1134+
1135+ {
1136+ pop.add(getRemoveRsvMenuItem(start,title,chnam,rsvId,recId));
1137+ }
1138+
1139+ pop.addSeparator();
1140+
1141+ {
1142+ pop.add(getJumpMenuItem(title,chnam,start));
1143+ pop.add(getJumpToLastWeekMenuItem(title,chnam,start));
1144+ }
1145+
1146+ pop.addSeparator();
1147+
1148+ // クリップボードへコピーする
1149+ {
1150+ JMenuItem menuItem = new JMenuItem("番組名をコピー【"+title+"】");
1151+ menuItem.addActionListener(new ActionListener() {
1152+ public void actionPerformed(ActionEvent e) {
1153+ String msg = title;
1154+ Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
1155+ StringSelection s = new StringSelection(msg);
1156+ cb.setContents(s, null);
1157+ }
1158+ });
1159+
1160+ pop.add(menuItem);
1161+ }
1162+ {
1163+ JMenuItem menuItem = new JMenuItem(String.format("予約情報をコピー【%s - %s(%s)】",start,title,chnam));
1164+ menuItem.addActionListener(new ActionListener() {
1165+ public void actionPerformed(ActionEvent e) {
1166+ String msg = formatReservedItem(ra, false);
1167+ Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
1168+ StringSelection s = new StringSelection(msg);
1169+ cb.setContents(s, null);
1170+ }
1171+ });
1172+
1173+ pop.add(menuItem);
1174+ }
1175+ if (num > 1){
1176+ JMenuItem menuItem = new JMenuItem(String.format("選択中の%d個の予約情報をコピー【%s - %s(%s)】",
1177+ num,start,title,chnam));
1178+ menuItem.addActionListener(new ActionListener() {
1179+ public void actionPerformed(ActionEvent e) {
1180+ String msg = formatReservedItems(ras, false);
1181+ Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
1182+ StringSelection s = new StringSelection(msg);
1183+ cb.setContents(s, null);
1184+ }
1185+ });
1186+
1187+ pop.add(menuItem);
1188+ }
1189+
1190+ pop.addSeparator();
1191+
1192+ // CSV形式でクリップボードへコピーする
1193+ {
1194+ JMenuItem menuItem = new JMenuItem(String.format("予約情報をCSVでコピー【%s - %s(%s)】",start,title,chnam));
1195+ menuItem.addActionListener(new ActionListener() {
1196+ public void actionPerformed(ActionEvent e) {
1197+ String msg = formatReservedHeader(true) + formatReservedItem(ra, true);
1198+ Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
1199+ StringSelection s = new StringSelection(msg);
1200+ cb.setContents(s, null);
1201+ }
1202+ });
1203+
1204+ pop.add(menuItem);
1205+ }
1206+
1207+ if (num > 1){
1208+ JMenuItem menuItem = new JMenuItem(String.format("選択中の%d個の予約情報をCSVでコピー【%s - %s(%s)】",
1209+ num,start,title,chnam));
1210+ menuItem.addActionListener(new ActionListener() {
1211+ public void actionPerformed(ActionEvent e) {
1212+ String msg = formatReservedHeader(true) + formatReservedItems(ras, true);
1213+ Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
1214+ StringSelection s = new StringSelection(msg);
1215+ cb.setContents(s, null);
1216+ }
1217+ });
1218+
1219+ pop.add(menuItem);
1220+ }
1221+
1222+ ProgDetailList pdl = getProgDetailList(ra);
1223+ if (pdl != null){
1224+ pop.addSeparator();
1225+ addBrowseMenuToPopup(pop, pdl);
1226+ }
1227+
1228+ pop.show(jTable_rsved, x, y);
1229+
1230+ }
1231+
10821232 private final MouseAdapter ma_showpopup = new MouseAdapter() {
10831233 @Override
10841234 public void mouseClicked(MouseEvent e) {
10851235 //
10861236 Point p = e.getPoint();
10871237 final int vrow = jTable_rsved.rowAtPoint(p);
1088- //
10891238 final int row = jTable_rsved.convertRowIndexToModel(vrow);
1239+
10901240 ReservedItem ra = rowViewTemp.get(row);
1091- final boolean fexec = ra.exec;
1092- final String start = ra.nextstart;
1093- final String title = ra.title;
10941241 final String chnam = ra.hide_chname;
10951242 final String recId = ra.recorder;
10961243 final String rsvId = ra.hide_rsvid;
1097- int num =jTable_rsved.getSelectedRowCount();
1098- final ArrayList<ReservedItem> ras = new ArrayList<ReservedItem>(num);
10991244
11001245 //
11011246 if (e.getButton() == MouseEvent.BUTTON3) {
11021247 if (e.getClickCount() == 1) {
1103- if (!jTable_rsved.isRowSelected(vrow))
1104- jTable_rsved.getSelectionModel().setSelectionInterval(vrow,vrow);
1105-
1106- if (num > 1){
1107- int rows[] = jTable_rsved.getSelectedRows();
1108- for (int n=0; n<num; n++){
1109- ras.add(rowViewTemp.get(jTable_rsved.convertRowIndexToModel(rows[n])));
1110- }
1111- }
1112-
1113- // 右クリックで予約削除メニュー表示
1114- JPopupMenu pop = new JPopupMenu();
1115- //
1116- {
1117- JMenuItem menuItem = new JMenuItem(String.format("予約を編集する【%s - %s(%s)】",start,title,chnam));
1118- menuItem.setForeground(new Color(0,127,0));
1119- Font f = menuItem.getFont();
1120- menuItem.setFont(f.deriveFont(f.getStyle()|Font.BOLD));
1121-
1122- menuItem.addActionListener(new ActionListener() {
1123- public void actionPerformed(ActionEvent e) {
1124- editReserve(recId,rsvId,chnam,vrow);
1125- }
1126- });
1127- pop.add(menuItem);
1128- }
1129-
1130- pop.addSeparator();
1131-
1132- // 予約実行ON・OFF
1133- {
1134- pop.add(getExecOnOffMenuItem(fexec,start,title,chnam,rsvId,recId));
1135- }
1136-
1137- pop.addSeparator();
1138-
1139- {
1140- pop.add(getRemoveRsvMenuItem(start,title,chnam,rsvId,recId));
1141- }
1142-
1143- pop.addSeparator();
1144-
1145- {
1146- pop.add(getJumpMenuItem(title,chnam,start));
1147- pop.add(getJumpToLastWeekMenuItem(title,chnam,start));
1148- }
1149-
1150- pop.addSeparator();
1151-
1152- // クリップボードへコピーする
1153- {
1154- JMenuItem menuItem = new JMenuItem("番組名をコピー【"+title+"】");
1155- menuItem.addActionListener(new ActionListener() {
1156- public void actionPerformed(ActionEvent e) {
1157- String msg = title;
1158- Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
1159- StringSelection s = new StringSelection(msg);
1160- cb.setContents(s, null);
1161- }
1162- });
1163-
1164- pop.add(menuItem);
1165- }
1166- {
1167- JMenuItem menuItem = new JMenuItem(String.format("予約情報をコピー【%s - %s(%s)】",start,title,chnam));
1168- menuItem.addActionListener(new ActionListener() {
1169- public void actionPerformed(ActionEvent e) {
1170- String msg = formatReservedItem(ra, false);
1171- Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
1172- StringSelection s = new StringSelection(msg);
1173- cb.setContents(s, null);
1174- }
1175- });
1176-
1177- pop.add(menuItem);
1178- }
1179- if (num > 1){
1180- JMenuItem menuItem = new JMenuItem(String.format("選択中の%d個の予約情報をコピー【%s - %s(%s)】",
1181- num,start,title,chnam));
1182- menuItem.addActionListener(new ActionListener() {
1183- public void actionPerformed(ActionEvent e) {
1184- String msg = formatReservedItems(ras, false);
1185- Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
1186- StringSelection s = new StringSelection(msg);
1187- cb.setContents(s, null);
1188- }
1189- });
1190-
1191- pop.add(menuItem);
1192- }
1193-
1194- pop.addSeparator();
1195-
1196- // CSV形式でクリップボードへコピーする
1197- {
1198- JMenuItem menuItem = new JMenuItem(String.format("予約情報をCSVでコピー【%s - %s(%s)】",start,title,chnam));
1199- menuItem.addActionListener(new ActionListener() {
1200- public void actionPerformed(ActionEvent e) {
1201- String msg = formatReservedHeader(true) + formatReservedItem(ra, true);
1202- Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
1203- StringSelection s = new StringSelection(msg);
1204- cb.setContents(s, null);
1205- }
1206- });
1207-
1208- pop.add(menuItem);
1209- }
1210- if (num > 1){
1211- JMenuItem menuItem = new JMenuItem(String.format("選択中の%d個の予約情報をCSVでコピー【%s - %s(%s)】",
1212- num,start,title,chnam));
1213- menuItem.addActionListener(new ActionListener() {
1214- public void actionPerformed(ActionEvent e) {
1215- String msg = formatReservedHeader(true) + formatReservedItems(ras, true);
1216- Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
1217- StringSelection s = new StringSelection(msg);
1218- cb.setContents(s, null);
1219- }
1220- });
1221-
1222- pop.add(menuItem);
1223- }
1224- pop.show(jTable_rsved, e.getX(), e.getY());
1248+ showPopupMenu(vrow, ra, e.getX(), e.getY());
12251249 }
12261250 }
12271251 else if (e.getButton() == MouseEvent.BUTTON1) {
--- a/TinyBannavi/src/tainavi/AbsTitleDialog.java
+++ b/TinyBannavi/src/tainavi/AbsTitleDialog.java
@@ -153,6 +153,7 @@ abstract class AbsTitleDialog extends JDialog {
153153 // コンポーネント以外
154154 private boolean folderOnly = false;
155155 private TitleInfo info = null;
156+ private ProgDetailList prog = null;
156157 private TVProgramList tvprograms = null;
157158
158159 private boolean reg = false;
@@ -214,15 +215,14 @@ abstract class AbsTitleDialog extends JDialog {
214215 * @param t 編集対象のタイトル情報
215216 * @param tvs フォルダリスト
216217 */
217- public void open(TitleInfo t, TVProgramList tpl, String otitle) {
218+ public void open(TitleInfo t, ProgDetailList l, String otitle) {
218219 info = t;
219- tvprograms = tpl;
220+ prog = l;
220221 recorder = getSelectedRecorder();
221222 tvsFolder = recorder.getFolderList();
222223
223224 updateTitleLabel();
224- ProgDetailList pdl = updateProgramInfo(t, tpl);
225- updateTitleInfo(t, pdl, otitle);
225+ updateTitleInfo(t, prog, otitle);
226226
227227 String device_name = "[" + t.getRec_device() + "]";
228228
@@ -273,6 +273,12 @@ abstract class AbsTitleDialog extends JDialog {
273273 jComboBox_title.addItem(cand);
274274 }
275275 }
276+
277+ // 番組情報が見つかったら、タイトルと詳細をセットする
278+ if (pdl != null){
279+ jTextArea_prog.setText(pdl.prefix_mark + pdl.title + pdl.postfix_mark + "\r\n" + pdl.detail);
280+ }
281+
276282 }
277283
278284 /*
@@ -284,7 +290,7 @@ abstract class AbsTitleDialog extends JDialog {
284290
285291 String[] patterns = {
286292 "^(.*?)(#|#|♯)",
287- "^(.*?)第.*?(話|回)",
293+ "^(.*?)第.*?(話|回|羽)",
288294 "^(.*?)(\\(|()[0-90-9]+(\\)|))"};
289295
290296 for (String pat : patterns){
@@ -321,7 +327,7 @@ abstract class AbsTitleDialog extends JDialog {
321327 String[] patterns = {
322328 "(#|#|♯)( | ){0,1}([0-90-9]{1,3})",
323329 "(\\(|()( | ){0,1}([0-90-9]{1,3})(\\)|)){0,1}",
324- "(第)( | ){0,1}([0-90-9]{1,3})(話|回)"};
330+ "(第)( | ){0,1}([0-90-9]{1,3})(話|回|羽)"};
325331 String ntitle = Normalizer.normalize(title, Normalizer.Form.NFKC);
326332
327333 for (String pat : patterns){
@@ -377,7 +383,7 @@ abstract class AbsTitleDialog extends JDialog {
377383 String[] patterns = {
378384 "(#|#)([0-90-9]{1,3})",
379385 "(\\(|()([0-90-9]{1,3})(\\)|))",
380- "(第)([0-90-9]{1,3})(話|回)"
386+ "(第)([0-90-9]{1,3})(話|回|羽)"
381387 };
382388
383389 for (String pat : patterns){
@@ -449,9 +455,9 @@ abstract class AbsTitleDialog extends JDialog {
449455 */
450456 protected String searchSubtitleCombo(String title){
451457 String[] patternsCombo = {
452- "(第|#|#)([0-90-9]{1,3})(話|回)?( | )?「(.*?)」",
453- "(第|#|#)([0-90-9]{1,3})(話|回)?( | )?『(.*?)』",
454- "(第|#|#)([0-90-9]{1,3})(話|回)?( | )?【(.*?)】"};
458+ "(第|#|#)([0-90-9]{1,3})(話|回|羽)?( | )?「(.*?)」",
459+ "(第|#|#)([0-90-9]{1,3})(話|回|羽)?( | )?『(.*?)』",
460+ "(第|#|#)([0-90-9]{1,3})(話|回|羽)?( | )?【(.*?)】"};
455461
456462 for (String pat : patternsCombo){
457463 Matcher m = Pattern.compile(pat).matcher(title);
@@ -475,81 +481,6 @@ abstract class AbsTitleDialog extends JDialog {
475481 }
476482
477483 /*
478- * 番組情報を更新する
479- */
480- private ProgDetailList updateProgramInfo(TitleInfo t, TVProgramList tpl){
481- if (tvprograms == null)
482- return null;
483-
484- // 番組表の日付に変換する
485- String date = CommonUtils.getDate529(t.getStartDateTime(), true);
486- if (date == null)
487- return null;
488-
489- // 未来分の番組情報から該当番組の情報を取得する
490- TVProgramIterator pli = tvprograms.getIterator().build(null, TVProgramIterator.IterationType.ALL);
491- ProgDetailList pdl = getProgDetailForTitle(pli, t, date);
492-
493- // 見つからなかったら過去分の番組情報をロードして該当番組の情報を取得する
494- if (pdl == null){
495- PassedProgram passed = tpl.getPassed();
496-
497- if (passed.loadByCenter(date, t.getCh_name())){
498- pli = tvprograms.getIterator().build(null, TVProgramIterator.IterationType.PASSED);
499- pdl = getProgDetailForTitle(pli, t, date);
500- }
501- }
502-
503- // 番組情報が見つかったら、タイトルと詳細をセットする
504- if (pdl != null){
505- jTextArea_prog.setText(pdl.prefix_mark + pdl.title + pdl.postfix_mark + "\r\n" + pdl.detail);
506- }
507-
508- return pdl;
509- }
510-
511- /*
512- * 指定したタイトルと放送局が同じで時間が重なる番組情報を取得する
513- */
514- private ProgDetailList getProgDetailForTitle(TVProgramIterator pli, TitleInfo t, String date){
515- String start = t.getStartDateTime();
516- String end = t.getEndDateTime();
517- String ch_name = t.getCh_name();
518-
519- pli.rewind();
520-
521- // 番組情報についてループする
522- for ( ProgList pl : pli ) {
523- // チャンネルが異なる場合はスキップする
524- if (! pl.Center.equals(ch_name))
525- continue;
526-
527- // 日付についてループする
528- for (ProgDateList pdl : pl.pdate){
529- // 日付が異なる場合はスキップする
530- if (! pdl.Date.equals(date))
531- continue;
532-
533- // 日付内の番組についてループする
534- for (ProgDetailList tvd : pdl.pdetail){
535- int bse = tvd.startDateTime.compareTo(end);
536- int bes = tvd.endDateTime.compareTo(start);
537-
538- // 予約情報と時間が重なる場合はその番組情報を返す
539- if (bse * bes < 0)
540- return tvd;
541- }
542-
543- break;
544- }
545-
546- break;
547- }
548-
549- return null;
550- }
551-
552- /*
553484 * フォルダ一覧のラベルを更新する。選択中のフォルダの数を表示する
554485 */
555486 private void updateFolderLabel() {
--- a/TinyBannavi/src/tainavi/AbsTitleListView.java
+++ b/TinyBannavi/src/tainavi/AbsTitleListView.java
@@ -69,6 +69,7 @@ public abstract class AbsTitleListView extends JPanel {
6969 protected abstract Bounds getBoundsEnv();
7070 protected abstract TitleListColumnInfoList getTlItemEnv();
7171
72+ protected abstract TVProgramList getTVProgramList();
7273 protected abstract HDDRecorderList getRecorderList();
7374
7475 protected abstract StatusWindow getStWin();
@@ -130,6 +131,11 @@ public abstract class AbsTitleListView extends JPanel {
130131 protected abstract JMenuItem getStartStopPlayTitleMenuItem(final boolean start, final String title, final String chnam,
131132 final String devId, final String ttlId, final String recId);
132133
134+ /*
135+ * プログラムのブラウザーメニューを呼び出す
136+ */
137+ protected abstract void addBrowseMenuToPopup( JPopupMenu pop, final ProgDetailList tvd );
138+
133139 /*******************************************************************************
134140 * 定数
135141 ******************************************************************************/
@@ -1019,6 +1025,78 @@ public abstract class AbsTitleListView extends JPanel {
10191025 rowData.add(n,data);
10201026 }
10211027
1028+ /*
1029+ * タイトルに対する番組情報を取得する
1030+ */
1031+ protected ProgDetailList getProgDetailForTitle(TitleInfo t){
1032+ TVProgramList tpl = getTVProgramList();
1033+
1034+ if (tpl == null || t == null)
1035+ return null;
1036+
1037+ // 番組表の日付に変換する
1038+ String date = CommonUtils.getDate529(t.getStartDateTime(), true);
1039+ if (date == null)
1040+ return null;
1041+
1042+ // 未来分の番組情報から該当番組の情報を取得する
1043+ TVProgramIterator pli = tpl.getIterator().build(null, TVProgramIterator.IterationType.ALL);
1044+ ProgDetailList pdl = getProgDetailForTitle(pli, t, date);
1045+
1046+ // 見つからなかったら過去分の番組情報をロードして該当番組の情報を取得する
1047+ if (pdl == null){
1048+ PassedProgram passed = tpl.getPassed();
1049+
1050+ if (passed.loadByCenter(date, t.getCh_name())){
1051+ pli = tpl.getIterator().build(null, TVProgramIterator.IterationType.PASSED);
1052+ pdl = getProgDetailForTitle(pli, t, date);
1053+ }
1054+ }
1055+
1056+ return pdl;
1057+ }
1058+
1059+ /*
1060+ * 指定したタイトルと放送局が同じで時間が重なる番組情報を取得する
1061+ */
1062+ protected ProgDetailList getProgDetailForTitle(TVProgramIterator pli, TitleInfo t, String date){
1063+ String start = t.getStartDateTime();
1064+ String end = t.getEndDateTime();
1065+ String ch_name = t.getCh_name();
1066+
1067+ pli.rewind();
1068+
1069+ // 番組情報についてループする
1070+ for ( ProgList pl : pli ) {
1071+ // チャンネルが異なる場合はスキップする
1072+ if (! pl.Center.equals(ch_name))
1073+ continue;
1074+
1075+ // 日付についてループする
1076+ for (ProgDateList pdl : pl.pdate){
1077+ // 日付が異なる場合はスキップする
1078+ if (! pdl.Date.equals(date))
1079+ continue;
1080+
1081+ // 日付内の番組についてループする
1082+ for (ProgDetailList tvd : pdl.pdetail){
1083+ int bse = tvd.startDateTime.compareTo(end);
1084+ int bes = tvd.endDateTime.compareTo(start);
1085+
1086+ // 予約情報と時間が重なる場合はその番組情報を返す
1087+ if (bse * bes < 0)
1088+ return tvd;
1089+ }
1090+
1091+ break;
1092+ }
1093+
1094+ break;
1095+ }
1096+
1097+ return null;
1098+ }
1099+
10221100 /*******************************************************************************
10231101 * リスナー
10241102 ******************************************************************************/
@@ -1400,6 +1478,7 @@ public abstract class AbsTitleListView extends JPanel {
14001478 final String devId = rec.getDeviceID(ra.devname);
14011479 int num =jTable_title.getSelectedRowCount();
14021480 final ArrayList<TitleItem> ras = new ArrayList<TitleItem>(num);
1481+ TitleInfo ttl = rec.getTitleInfo(ttlId);
14031482
14041483 final String otitle = getNextTitleInSameFolder(vrow);
14051484
@@ -1525,6 +1604,12 @@ public abstract class AbsTitleListView extends JPanel {
15251604 pop.add(menuItem);
15261605 }
15271606
1607+ ProgDetailList pdl = getProgDetailForTitle(ttl);
1608+ if (pdl != null){
1609+ pop.addSeparator();
1610+ addBrowseMenuToPopup(pop, pdl);
1611+ }
1612+
15281613 pop.show(jTable_title, e.getX(), e.getY());
15291614 }
15301615 }
--- a/TinyBannavi/src/tainavi/CommonUtils.java
+++ b/TinyBannavi/src/tainavi/CommonUtils.java
@@ -734,6 +734,19 @@ public class CommonUtils {
734734
735735 /**
736736 * 日時を時刻形式に変換
737+ * @return hh:mm
738+ */
739+ public static String getTime529(GregorianCalendar c) {
740+ int hh = c.get(Calendar.HOUR_OF_DAY);
741+ if ( isLateNight( hh ) ) {
742+ hh += 24;
743+ }
744+
745+ return getTime(hh, c.get(Calendar.MINUTE));
746+ }
747+
748+ /**
749+ * 日時を時刻形式に変換
737750 * @see #getTimeHM(GregorianCalendar)
738751 * @return hh:mm
739752 */
--- a/TinyBannavi/src/tainavi/Env.java
+++ b/TinyBannavi/src/tainavi/Env.java
@@ -618,6 +618,11 @@ public class Env {
618618 public void setWeekEndColoring(boolean b){ weekEndColoring = b; }
619619 private boolean weekEndColoring = true;
620620
621+ // タイムラインのラベル表示モード(0:非表示, 1:分のみ, 2:時分(0-23), 3:時分(5-28))
622+ public int getTimelineLabelDispMode(){ return timelineLabelDispMode; }
623+ public void setTimelineLabelDispMode(int n){ timelineLabelDispMode = n; }
624+ private int timelineLabelDispMode = 2;
625+
621626 /*
622627 * リスト・新聞形式共通
623628 */
--- a/TinyBannavi/src/tainavi/ProgDetailList.java
+++ b/TinyBannavi/src/tainavi/ProgDetailList.java
@@ -15,35 +15,36 @@ import tainavi.TVProgram.ProgType;
1515 * 番組の個々の詳細情報です
1616 */
1717 public class ProgDetailList implements Cloneable {
18-
18+
1919 /*******************************************************************************
2020 * メンバ
2121 ******************************************************************************/
22-
22+
2323 /*
2424 * ファイルに保存されるもの
2525 */
26-
26+
2727 public String title = ""; // 分離前タイトル
2828 public String detail = ""; // 修正前タイトル
2929 protected String addedDetail = "";
30-
30+
3131 public String startDateTime = "";
3232 public String endDateTime = "";
3333 public int length = 0; // 放送時間(05:00を基準とした表示上の長さ)
34-
34+
3535 public String link = "";
36-
36+ public String linkSyobo = "";
37+
3738 // ジャンル
3839 public ProgGenre genre = ProgGenre.NOGENRE;
3940 public ProgSubgenre subgenre = ProgSubgenre.NOGENRE_ETC;
40-
41+
4142 // フラグ・オプション関連
4243 public boolean extension = false; // 延長注意
4344 public ProgFlags flag = ProgFlags.NOFLAG; // 新番組・最終回
4445 public ProgScrumble noscrumble = ProgScrumble.NONE; // 有料放送だけ別枠になってしまった!
4546 protected ArrayList<ProgOption> option = new ArrayList<ProgOption>();
46-
47+
4748 // 複数ジャンル対応
4849 public ArrayList<ProgGenre> genrelist = null;
4950 public ArrayList<ProgSubgenre> subgenrelist = null;
@@ -51,20 +52,20 @@ public class ProgDetailList implements Cloneable {
5152 /*
5253 * ファイルには保存されないもの
5354 */
54-
55+
5556 /**
5657 * <P>{@link ProgDateList#Date}が05-29時を基準とした日付を持つのに対して
5758 * <P>accurateDateは実際の日付である
5859 * <P>(startDateTimeの日付と同じ、ただし曜日文字がつく)
5960 */
60-
61+
6162 public String accurateDate = "";
6263 public String start = ""; // hh:mm
6364 public String end = ""; // hh:mm
6465 public int recmin = 0; // 番組長(実際の長さ)
65-
66+
6667 public String progid = ""; // 番組ID
67-
68+
6869 public boolean nosyobo = false; // しょぼのぼっち判定
6970 public boolean marked = false; // 検索に引っかかったマーク
7071 public boolean markedByTrace = false; // 番組追跡に引っかかったマーク
@@ -85,27 +86,27 @@ public class ProgDetailList implements Cloneable {
8586 public String splitted_title = ""; // 分離済みタイトル→これはtitleへのポインタ
8687 public String splitted_titlePop = ""; // 分離済みタイトルPOP→これはtitlePopへのポインタ
8788 public String splitted_detail = ""; // 分離済み番組詳細→detailはこれへのポインタにするよ
88-
89+
8990 public SearchKey dynKey = null; // 動的検索用
9091 public String dynMatched = null; // 動的検索用
9192
9293 // 検索高速化用のデータ
93-
94+
9495 /**
9596 * キーワード検索・番組追跡で使うよ
9697 */
9798 public String titlePop = "";
98-
99+
99100 /**
100101 * キーワード検索で使うよ
101102 */
102103 public String detailPop = "";
103-
104+
104105 /**
105106 * 番組追跡で使うよ
106107 */
107108 public static boolean tracenOnlyTitle = false;
108-
109+
109110 /*******************************************************************************
110111 * NGワード処理
111112 ******************************************************************************/
@@ -117,12 +118,12 @@ public class ProgDetailList implements Cloneable {
117118 title = splitted_title = NO_PROG_TITLE;
118119 detail = "";
119120 addedDetail = "";
120-
121+
121122 extension = false;
122123 flag = null;
123124 option = new ArrayList<ProgOption>();
124125 noscrumble = ProgScrumble.NONE;
125-
126+
126127 genre = ProgGenre.NOGENRE;
127128 subgenre = ProgSubgenre.NOGENRE_ETC;
128129 genrelist = null;
@@ -139,12 +140,14 @@ public class ProgDetailList implements Cloneable {
139140
140141 titlePop = "";
141142 detailPop = "";
143+
144+ linkSyobo = "";
142145 }
143-
146+
144147 /*******************************************************************************
145148 * 過去ログ処理高速化計画
146149 ******************************************************************************/
147-
150+
148151 public boolean isEqualsGenre(ProgGenre mGenre, ProgSubgenre mSubgenre) {
149152 if ( mGenre == null && mSubgenre == null ) {
150153 return false;
@@ -183,14 +186,14 @@ public class ProgDetailList implements Cloneable {
183186 /*
184187 * addedDetailは直接編集させない
185188 */
186-
189+
187190 public String getAddedDetail() { return addedDetail; }
188191 public void setAddedDetail(String s) { addedDetail = s; }
189192
190193 /*
191194 * optionは直接編集させない
192195 */
193-
196+
194197 public ArrayList<ProgOption> getOption() { return option; }
195198 public boolean addOption(ProgOption opt) {
196199 int i = getOptionIndex(opt);
@@ -225,7 +228,7 @@ public class ProgDetailList implements Cloneable {
225228 if (genrelist == null || genrelist.size() == 0) {
226229 return true;
227230 }
228-
231+
229232 String s = GENREMARK;
230233 for ( int n=0; n<genrelist.size(); n++ ) {
231234 s += genrelist.get(n).toString()+" - "+subgenrelist.get(n).toString()+"\n";
@@ -239,7 +242,7 @@ public class ProgDetailList implements Cloneable {
239242 return true;
240243 }
241244 private static final String GENREMARK = "\n【ジャンル】\n";
242-
245+
243246 public boolean setContentIdStr() {
244247 String pid = null;
245248 if ( ContentIdEDCB.isValid(progid) ) {
@@ -263,20 +266,20 @@ public class ProgDetailList implements Cloneable {
263266 }
264267 return false;
265268 }
266-
269+
267270 private static final String CIDMARK = "\n【ID】\nid=";
268-
271+
269272 /*******************************************************************************
270273 * 過去ログ処理高速化計画
271274 ******************************************************************************/
272275
273276 /**
274- *
277+ *
275278 */
276279 public static enum WrHeader {
277-
280+
278281 // 順番をかえなければ、どこに追加してもいい
279-
282+
280283 START ( "$ST$", true ),
281284 END ( "$ED$", true ),
282285 LENGTH ( "$LN$", true ),
@@ -288,36 +291,36 @@ public class ProgDetailList implements Cloneable {
288291 OPTION ( "$OP$", true ),
289292 LINK ( "$LK$", true ),
290293 ID ( "$ID$", true ),
291-
294+
292295 TITLE ( "$TI$", true ),
293296 DETAIL ( "$DT$", true ),
294297 ADDED ( "$AD$", true ),
295-
298+
296299 // ここから下は別の領域なので追加はNG
297-
300+
298301 BEND ( "$DE#YY$", false ), // 項目ごとのフッタ
299302 STARTMARK ( "$DE#AA$", false ), // ヘッダ
300303 ENDMARK ( "$DE#ZZ$", false ), // フッタ
301-
304+
302305 ;
303-
306+
304307 private String hdr;
305308 private boolean marker;
306-
309+
307310 private WrHeader(String hdr, boolean marker) {
308311 this.hdr = hdr;
309312 this.marker = marker;
310313 }
311-
314+
312315 // ここはtoString()をOverrideしてよい
313316 @Override
314317 public String toString() { return hdr; }
315318 }
316-
319+
317320 // 区切り文字
318321 private static final String S_CR = "\n";
319322 private static final String S_OPT = ";";
320-
323+
321324 private void addHeader(StringBuilder sb, WrHeader header) {
322325 sb.append(header.toString());
323326 }
@@ -327,24 +330,24 @@ public class ProgDetailList implements Cloneable {
327330 private void addBodyEnd(StringBuilder sb) {
328331 sb.append(WrHeader.BEND);
329332 }
330-
333+
331334 /**
332335 * @see #ProgDetailList(String)
333336 */
334337 public String toString() {
335-
338+
336339 StringBuilder sb = new StringBuilder();
337-
340+
338341 sb.append(WrHeader.STARTMARK);
339342 sb.append(S_CR);
340-
343+
341344 for ( WrHeader hdr : WrHeader.values() )
342345 {
343346 if ( ! hdr.marker )
344347 {
345348 break;
346349 }
347-
350+
348351 switch ( hdr ) {
349352 case TITLE:
350353 if ( this.title != null && this.title.length() > 0 ) {
@@ -360,7 +363,7 @@ public class ProgDetailList implements Cloneable {
360363 addBodyEnd(sb);
361364 }
362365 break;
363- case ADDED:
366+ case ADDED:
364367 if ( this.addedDetail != null && this.addedDetail.length() > 0 ) {
365368 addHeader(sb, hdr);
366369 addBody(sb, this.addedDetail);
@@ -400,7 +403,7 @@ public class ProgDetailList implements Cloneable {
400403 {
401404 addHeader(sb, hdr);
402405 addBody(sb, this.genre.toIEPG());
403-
406+
404407 if ( this.subgenre != null )
405408 {
406409 addBody(sb, this.subgenre.toIEPG());
@@ -409,7 +412,7 @@ public class ProgDetailList implements Cloneable {
409412 {
410413 addBody(sb, ProgSubgenre.NOGENRE_ETC.toIEPG());
411414 }
412-
415+
413416 addBodyEnd(sb);
414417 }
415418 break;
@@ -417,13 +420,13 @@ public class ProgDetailList implements Cloneable {
417420 if ( this.genrelist != null && this.genrelist.size() > 0 )
418421 {
419422 addHeader(sb, hdr);
420-
423+
421424 int n = -1;
422425 for ( ProgGenre g : this.genrelist )
423426 {
424427 ++n;
425428 sb.append(g.toIEPG());
426-
429+
427430 if ( this.subgenrelist != null && this.subgenrelist.size() > n )
428431 {
429432 addBody(sb, this.subgenrelist.get(n).toIEPG());
@@ -433,7 +436,7 @@ public class ProgDetailList implements Cloneable {
433436 sb.append(ProgSubgenre.NOGENRE_ETC);
434437 }
435438 }
436-
439+
437440 addBodyEnd(sb);
438441 }
439442 break;
@@ -465,13 +468,13 @@ public class ProgDetailList implements Cloneable {
465468 if ( this.option != null && this.option.size() > 0 )
466469 {
467470 addHeader(sb, hdr);
468-
471+
469472 for ( ProgOption o : this.option )
470473 {
471474 addBody(sb, o.toString());
472475 addBody(sb, S_OPT);
473476 }
474-
477+
475478 addBodyEnd(sb);
476479 }
477480 break;
@@ -485,55 +488,55 @@ public class ProgDetailList implements Cloneable {
485488 default:
486489 break;
487490 }
488- }
491+ }
489492
490493 sb.append(WrHeader.ENDMARK);
491494 sb.append(S_CR);
492-
495+
493496 return sb.toString();
494497 }
495-
498+
496499 /*******************************************************************************
497500 * コンストラクタ2種
498501 ******************************************************************************/
499-
502+
500503 /**
501504 * toString()で生成した文字列を入力にして初期化された{@link ProgDetailList}を返します
502505 * @param s 先頭の{@link WrHeader.STARTMARK}+"\n"とおしりの{@link WrHeader.ENDMARK}+"\n"は外しておいてください
503506 */
504507 public ProgDetailList(String s) {
505-
508+
506509 for ( WrHeader hdr : WrHeader.values() )
507510 {
508511 if ( ! hdr.marker )
509512 {
510513 break; // ! markerならもう終わり
511514 }
512-
515+
513516 if ( s == null || s.length() <= 0 )
514517 {
515518 break; // なんか変
516519 }
517-
520+
518521 if ( ! s.startsWith(hdr.toString()) )
519522 {
520523 continue; // 次へ
521524 }
522-
525+
523526 int newtail = s.indexOf(WrHeader.BEND.toString());
524527 if ( newtail == -1 )
525528 {
526529 break; // なんか変
527530 }
528-
531+
529532 String body = s.substring(hdr.toString().length(),newtail);
530533 s = s.substring(newtail+WrHeader.BEND.toString().length());
531-
534+
532535 if ( body == null || body.length() == 0 )
533536 {
534537 continue; // いらんわ
535538 }
536-
539+
537540 switch ( hdr ) {
538541 case TITLE:
539542 this.title = body;
@@ -548,7 +551,7 @@ public class ProgDetailList implements Cloneable {
548551 break;
549552 case START:
550553 GregorianCalendar ca = CommonUtils.getCalendar(body);
551- if ( ca != null )
554+ if ( ca != null )
552555 {
553556 this.startDateTime = CommonUtils.getDateTime(ca);
554557 this.accurateDate = CommonUtils.getDate(ca);
@@ -557,7 +560,7 @@ public class ProgDetailList implements Cloneable {
557560 break;
558561 case END:
559562 GregorianCalendar cz = CommonUtils.getCalendar(body);
560- if ( cz != null )
563+ if ( cz != null )
561564 {
562565 this.endDateTime = CommonUtils.getDateTime(cz);
563566 this.end = CommonUtils.getTime(cz);
@@ -583,7 +586,7 @@ public class ProgDetailList implements Cloneable {
583586 {
584587 this.genre = ProgGenre.NOGENRE;
585588 }
586-
589+
587590 if ( body.length() >= 2 )
588591 {
589592 this.subgenre = ProgSubgenre.getByIEPG(this.genre, body.substring(1,2));
@@ -600,9 +603,9 @@ public class ProgDetailList implements Cloneable {
600603 if ( this.genrelist == null )
601604 {
602605 this.genrelist = new ArrayList<ProgGenre>();
603- this.subgenrelist = new ArrayList<ProgSubgenre>();
606+ this.subgenrelist = new ArrayList<ProgSubgenre>();
604607 }
605-
608+
606609 ProgGenre g = ProgGenre.getByIEPG(body.substring(0,1));
607610 if ( g == null )
608611 {
@@ -613,10 +616,10 @@ public class ProgDetailList implements Cloneable {
613616 {
614617 sg = ProgSubgenre.NOGENRE_ETC;
615618 }
616-
619+
617620 this.genrelist.add(g);
618621 this.subgenrelist.add(sg);
619-
622+
620623 body = body.substring(2);
621624 }
622625 break;
--- 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.12";
8+ private static final String Version = "タイニー番組ナビゲータ for DBR-T2007 3.22.18β+1.12.13";
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
@@ -470,14 +470,12 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
470470 }
471471
472472 @Override
473- protected void showPopupForTraceProgram(
474- final JComponent comp,
475- final ProgDetailList tvd, final String keyword, final int threshold,
476- final int x, final int y) {
473+ protected void showPopupMenu(
474+ final JComponent comp, final ProgDetailList tvd, final int x, final int y) {
477475
478476 timer_now.pause(); // 停止
479477
480- Viewer.this.showPopupForTraceProgram(comp, tvd, keyword, threshold, x, y, null);
478+ Viewer.this.showPopupMenuForProgram(comp, tvd, x, y);
481479
482480 timer_now.start(); // 再開
483481 }
@@ -624,14 +622,12 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
624622 }
625623
626624 @Override
627- protected void showPopupForTraceProgram(
628- final JComponent comp,
629- final ProgDetailList tvd, final String keyword, final int threshold,
630- final int x, final int y, final String clickedDateTime) {
625+ protected void showPopupMenu(
626+ final JComponent comp, final ProgDetailList tvd, final int x, final int y) {
631627
632628 timer_now.pause(); // 停止
633629
634- Viewer.this.showPopupForTraceProgram(comp, tvd, keyword, threshold, x, y, clickedDateTime);
630+ Viewer.this.showPopupMenuForProgram(comp, tvd, x, y);
635631
636632 timer_now.start(); // 再開
637633 }
@@ -772,6 +768,14 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
772768 return Viewer.this.getJumpToLastWeekMenuItem(title, chnam, startDT);
773769 }
774770
771+ /*
772+ * プログラムのブラウザーメニューを呼び出す
773+ */
774+ @Override
775+ protected void addBrowseMenuToPopup( JPopupMenu pop, final ProgDetailList tvd ){
776+ Viewer.this.addBrowseMenuToPopup( pop, tvd);
777+ }
778+
775779 @Override
776780 protected String getSelectedRecorderOnToolbar() { return toolBar.getSelectedRecorder(); }
777781
@@ -857,6 +861,9 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
857861 protected StatusTextArea getMWin() { return mwin; }
858862
859863 @Override
864+ protected TVProgramList getTVProgramList() { return tvprograms; }
865+
866+ @Override
860867 protected HDDRecorderList getRecorderList() { return recorders; }
861868
862869 // ログ関係はないのか
@@ -1013,6 +1020,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
10131020
10141021 HDDRecorder rec = getSelectedRecorder();
10151022 TitleInfo o = rec.getTitleInfo(ttlId);
1023+ ProgDetailList prog = getProgDetailForTitle(o);
10161024
10171025 String ttlname = o.getTitle();
10181026
@@ -1022,7 +1030,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
10221030 rec.GetRdTitleDetail(o);
10231031
10241032 VWTitleDialog dlg = new VWTitleDialog(false);
1025- dlg.open(o.clone(), tvprograms, otitle);
1033+ dlg.open(o.clone(), prog, otitle);
10261034 CommonSwingUtils.setLocationCenter(Viewer.this, dlg);
10271035 dlg.setVisible(true);
10281036
@@ -1357,6 +1365,13 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
13571365 return menuItem;
13581366 }
13591367
1368+ /*
1369+ * プログラムのブラウザーメニューを呼び出す
1370+ */
1371+ @Override
1372+ protected void addBrowseMenuToPopup( JPopupMenu pop, final ProgDetailList tvd ){
1373+ Viewer.this.addBrowseMenuToPopup( pop, tvd);
1374+ }
13601375 }
13611376
13621377 /***
@@ -2296,15 +2311,57 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
22962311 /**
22972312 * 番組追跡への追加とgoogle検索
22982313 */
2299- public void showPopupForTraceProgram(
2300- final JComponent comp,
2301- final ProgDetailList tvd, final String keyword, final int threshold,
2302- final int x, final int y, final String clickedDateTime)
2314+ public void showPopupMenuForProgram(
2315+ final JComponent comp, final ProgDetailList tvd, final int x, final int y)
23032316 {
23042317 JPopupMenu pop = new JPopupMenu();
23052318
23062319 String myself = toolBar.getSelectedRecorder();
23072320
2321+ // 予約関係のメニューを追加する
2322+ addReserveMenuToPopup(pop, tvd, myself);
2323+
2324+ // ジャンプする
2325+ if (pop.getComponentCount() > 0)
2326+ pop.addSeparator();
2327+ addJumpMenuToPopup(pop, tvd);
2328+
2329+ pop.addSeparator();
2330+
2331+ // 番組追跡へ追加する
2332+ addTraceMenuToPopup(pop, tvd);
2333+
2334+ // キーワード検索へ追加する
2335+ addKeywordMenuToPopup(pop, tvd);
2336+
2337+ // ピックアップへ追加する
2338+ addPickupMenuToPopup(pop, tvd);
2339+
2340+ pop.addSeparator();
2341+
2342+ // ブラウザー呼び出しメニューを追加する
2343+ addBrowseMenuToPopup(pop, tvd);
2344+
2345+ pop.addSeparator();
2346+
2347+ // クリップボードへコピーする
2348+ addClipboardMenuToPopup(pop, tvd);
2349+
2350+ pop.addSeparator();
2351+
2352+ // 延長感染源へ追加する
2353+ addInfectionSourceMenuToPopup(pop, tvd);
2354+
2355+ // 視聴する
2356+ addChannelMenuToPopup(pop, tvd);
2357+
2358+ pop.show(comp, x, y);
2359+ }
2360+
2361+ /*
2362+ * 予約メニューを追加する
2363+ */
2364+ public void addReserveMenuToPopup( JPopupMenu pop, final ProgDetailList tvd, final String myself ){
23082365 // 類似予約検索
23092366 LikeReserveList likeRsvList;
23102367 if ( env.getDisableFazzySearch() ) {
@@ -2405,6 +2462,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
24052462 }
24062463 }
24072464 }
2465+
24082466 // 予約実行ON・OFF
24092467 if ( tvd.type != ProgType.PASSED )
24102468 {
@@ -2463,98 +2521,103 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
24632521 }
24642522 }
24652523 }
2524+ }
24662525
2467- // ジャンプする
2468- {
2469- if (pop.getComponentCount() > 0)
2470- pop.addSeparator();
2471-
2472- if ( mainWindow.isTabSelected(MWinTab.LISTED) ) {
2473- pop.add(getJumpMenuItem(tvd.title,tvd.center,tvd.accurateDate+" "+tvd.start));
2474- }
2475- if ( mainWindow.isTabSelected(MWinTab.LISTED) || mainWindow.isTabSelected(MWinTab.PAPER) ) {
2476- JMenuItem mi = getJumpToLastWeekMenuItem(tvd.title,tvd.center,tvd.startDateTime);
2477- if ( mi != null ) {
2478- pop.add(mi);
2479- }
2526+ /*
2527+ * ジャンプメニューを追加する
2528+ */
2529+ public void addJumpMenuToPopup(JPopupMenu pop, final ProgDetailList tvd){
2530+ if ( mainWindow.isTabSelected(MWinTab.LISTED) ) {
2531+ pop.add(getJumpMenuItem(tvd.title,tvd.center,tvd.accurateDate+" "+tvd.start));
2532+ }
2533+ if ( mainWindow.isTabSelected(MWinTab.LISTED) || mainWindow.isTabSelected(MWinTab.PAPER) ) {
2534+ JMenuItem mi = getJumpToLastWeekMenuItem(tvd.title,tvd.center,tvd.startDateTime);
2535+ if ( mi != null ) {
2536+ pop.add(mi);
24802537 }
24812538 }
2539+ }
24822540
2483- // 番組追跡へ追加する
2484- {
2485- pop.addSeparator();
2486-
2487- final String label = TraceProgram.getNewLabel(tvd.title, tvd.center);
2488- JMenuItem menuItem = new JMenuItem("番組追跡への追加【"+label+"】");
2489- menuItem.addActionListener(new ActionListener() {
2490- public void actionPerformed(ActionEvent e) {
2491- //
2492- VWTraceKeyDialog tD = new VWTraceKeyDialog(0,0);
2493- CommonSwingUtils.setLocationCenter(mainWindow,tD);
2541+ /*
2542+ * 追跡メニューを追加する
2543+ */
2544+ public void addTraceMenuToPopup( JPopupMenu pop, final ProgDetailList tvd ){
2545+ final String label = TraceProgram.getNewLabel(tvd.title, tvd.center);
2546+ JMenuItem menuItem = new JMenuItem("番組追跡への追加【"+label+"】");
2547+ menuItem.addActionListener(new ActionListener() {
2548+ public void actionPerformed(ActionEvent e) {
2549+ //
2550+ VWTraceKeyDialog tD = new VWTraceKeyDialog(0,0);
2551+ CommonSwingUtils.setLocationCenter(mainWindow,tD);
24942552
2495- tD.open(trKeys, tvd, env.getDefaultFazzyThreshold());
2496- tD.setVisible(true);
2553+ tD.open(trKeys, tvd, env.getDefaultFazzyThreshold());
2554+ tD.setVisible(true);
24972555
2498- if (tD.isRegistered()) {
2499- //
2500- trKeys.save();
2556+ if (tD.isRegistered()) {
2557+ //
2558+ trKeys.save();
25012559
2502- // 検索結果の再構築
2503- mpList.clear(env.getDisableFazzySearch(), env.getDisableFazzySearchReverse());
2504- mpList.build(tvprograms, trKeys.getTraceKeys(), srKeys.getSearchKeys());
2560+ // 検索結果の再構築
2561+ mpList.clear(env.getDisableFazzySearch(), env.getDisableFazzySearchReverse());
2562+ mpList.build(tvprograms, trKeys.getTraceKeys(), srKeys.getSearchKeys());
25052563
2506- // ツリーに反映する
2507- listed.redrawTreeByTrace();
2564+ // ツリーに反映する
2565+ listed.redrawTreeByTrace();
25082566
2509- // 表示を更新する
2510- paper.updateBangumiColumns();
2511- listed.reselectTree();
2567+ // 表示を更新する
2568+ paper.updateBangumiColumns();
2569+ listed.reselectTree();
25122570
2513- mwin.appendMessage("番組追跡へ追加しました【"+label+"】");
2514- }
2515- else {
2516- trKeys.remove(label);
2517- }
2571+ mwin.appendMessage("番組追跡へ追加しました【"+label+"】");
25182572 }
2519- });
2520- pop.add(menuItem);
2521- }
2573+ else {
2574+ trKeys.remove(label);
2575+ }
2576+ }
2577+ });
2578+ pop.add(menuItem);
2579+ }
25222580
2523- // キーワード検索へ追加する
2524- {
2525- final String label = tvd.title+" ("+tvd.center+")";
2526- JMenuItem menuItem = new JMenuItem("キーワード検索への追加【"+label+"】");
2527- menuItem.addActionListener(new ActionListener(){
2528- public void actionPerformed(ActionEvent e){
2581+ /*
2582+ * キーワードメニューを追加する
2583+ */
2584+ public void addKeywordMenuToPopup( JPopupMenu pop, final ProgDetailList tvd ){
2585+ final String label = tvd.title+" ("+tvd.center+")";
2586+ JMenuItem menuItem = new JMenuItem("キーワード検索への追加【"+label+"】");
2587+ menuItem.addActionListener(new ActionListener(){
2588+ public void actionPerformed(ActionEvent e){
25292589
2530- // 「キーワード検索の設定」ウィンドウを開く
2590+ // 「キーワード検索の設定」ウィンドウを開く
25312591
2532- AbsKeywordDialog kD = new VWKeywordDialog();
2533- CommonSwingUtils.setLocationCenter(mainWindow,kD);
2592+ AbsKeywordDialog kD = new VWKeywordDialog();
2593+ CommonSwingUtils.setLocationCenter(mainWindow,kD);
25342594
2535- kD.open(srKeys, srGrps, tvd);
2536- kD.setVisible(true);
2595+ kD.open(srKeys, srGrps, tvd);
2596+ kD.setVisible(true);
25372597
2538- if (kD.isRegistered()) {
2539- // 検索結果の再構築
2540- mpList.clear(env.getDisableFazzySearch(), env.getDisableFazzySearchReverse());
2541- mpList.build(tvprograms, trKeys.getTraceKeys(), srKeys.getSearchKeys());
2598+ if (kD.isRegistered()) {
2599+ // 検索結果の再構築
2600+ mpList.clear(env.getDisableFazzySearch(), env.getDisableFazzySearchReverse());
2601+ mpList.build(tvprograms, trKeys.getTraceKeys(), srKeys.getSearchKeys());
25422602
2543- // ツリーに反映する
2544- listed.redrawTreeByKeyword();
2603+ // ツリーに反映する
2604+ listed.redrawTreeByKeyword();
25452605
2546- // 表示を更新する
2547- paper.updateBangumiColumns();
2548- listed.reselectTree();
2606+ // 表示を更新する
2607+ paper.updateBangumiColumns();
2608+ listed.reselectTree();
25492609
2550- mwin.appendMessage("キーワード検索へ追加しました【"+label+"】");
2551- }
2610+ mwin.appendMessage("キーワード検索へ追加しました【"+label+"】");
25522611 }
2553- });
2554- pop.add(menuItem);
2555- }
2612+ }
2613+ });
2614+ pop.add(menuItem);
2615+ }
25562616
2557- // ピックアップへ追加する
2617+ /*
2618+ * ピックアップメニューを追加する
2619+ */
2620+ public void addPickupMenuToPopup( JPopupMenu pop, final ProgDetailList tvd ){
25582621 {
25592622 boolean isRemoveItem = false;
25602623 if ( mainWindow.isTabSelected(MWinTab.LISTED) && tvd.type == ProgType.PICKED ) {
@@ -2623,131 +2686,136 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
26232686 pop.add(menuItem);
26242687 }
26252688 }
2689+ }
2690+ /*
2691+ * ブラウザー呼び出しメニューを追加する
2692+ */
2693+ public void addBrowseMenuToPopup( JPopupMenu pop, final ProgDetailList tvd ){
2694+ for (final TextValueSet tv : env.getTvCommand()) {
2695+ JMenuItem menuItem = new JMenuItem(tv.getText());
2696+ String escepedTitle = "";
2697+ String escepedChName = "";
2698+ String escepedDetail = "";
2699+ try {
2700+ escepedTitle = URLEncoder.encode(tvd.title,"UTF-8");
2701+ escepedDetail = URLEncoder.encode(tvd.detail,"UTF-8");
2702+ escepedChName = URLEncoder.encode(tvd.center,"UTF-8");
2703+ } catch (UnsupportedEncodingException e2) {
2704+ //
2705+ }
26262706
2627- pop.addSeparator();
2628-
2629- // googleで検索する
2630- {
2631- for (final TextValueSet tv : env.getTvCommand()) {
2632- JMenuItem menuItem = new JMenuItem(tv.getText());
2633- String escepedTitle = "";
2634- String escepedChName = "";
2635- String escepedDetail = "";
2636- try {
2637- escepedTitle = URLEncoder.encode(tvd.title,"UTF-8");
2638- escepedDetail = URLEncoder.encode(tvd.detail,"UTF-8");
2639- escepedChName = URLEncoder.encode(tvd.center,"UTF-8");
2640- } catch (UnsupportedEncodingException e2) {
2641- //
2642- }
2643-
2644- String cmd = tv.getValue();
2645- if ( cmd.matches(".*%DETAILURL%.*") ) {
2646- if ( tvd.link == null || tvd.link.length() == 0 ) {
2647- // このメニューは利用できません!
2648- menuItem.setEnabled(false);
2649- menuItem.setForeground(Color.lightGray);
2650- }
2707+ String cmd = tv.getValue();
2708+ if ( cmd.matches(".*%DETAILURL%.*") ) {
2709+ if ( tvd.link == null || tvd.link.length() == 0 ) {
2710+ // このメニューは利用できません!
2711+ menuItem.setEnabled(false);
2712+ menuItem.setForeground(Color.lightGray);
26512713 }
2652- cmd = cmd.replaceAll("%ENCTITLE%", escepedTitle);
2653- cmd = cmd.replaceAll("%ENCDETAIL%", escepedDetail);
2654- cmd = cmd.replaceAll("%ENCCHNAME%", escepedChName);
2655- cmd = cmd.replaceAll("%TITLE%", tvd.title);
2656- cmd = cmd.replaceAll("%DETAIL%", tvd.detail);
2657- cmd = cmd.replaceAll("%CHNAME%", tvd.center);
2658- cmd = cmd.replaceAll("%DATE%", tvd.accurateDate);
2659- cmd = cmd.replaceAll("%START%", tvd.start);
2660- cmd = cmd.replaceAll("%END%", tvd.end);
2661- cmd = cmd.replaceAll("%DETAILURL%", tvd.link);
2662-
2663- // CHAN-TORU対応
2664- if ( cmd.matches(".*%TVKAREACODE%.*") && cmd.matches(".*%TVKPID%.*") ) {
2665- Center cr = null;
2666- for ( TVProgram tvp : progPlugins ) {
2667- if ( tvp.getTVProgramId().startsWith("Gガイド.テレビ王国") ) {
2668- for ( Center tempcr : tvp.getCRlist() ) {
2669- // CH設定が完了している必要がある
2670- if ( tvp.getSubtype() == ProgSubtype.TERRA && tvp.getSelectedCode().equals(TVProgram.allCode) && ! tempcr.getAreaCode().equals(TVProgram.bsCode) ) {
2671- // 地域が全国の地デジの場合のみ、有効局かどうかを確認する必要がある
2672- if ( tempcr.getCenter().equals(tvd.center) && tempcr.getOrder() > 0 ) {
2673- // このメニューは利用できます!
2674- cr = tempcr;
2675- break;
2676- }
2714+ }
2715+ cmd = cmd.replaceAll("%ENCTITLE%", escepedTitle);
2716+ cmd = cmd.replaceAll("%ENCDETAIL%", escepedDetail);
2717+ cmd = cmd.replaceAll("%ENCCHNAME%", escepedChName);
2718+ cmd = cmd.replaceAll("%TITLE%", tvd.title);
2719+ cmd = cmd.replaceAll("%DETAIL%", tvd.detail);
2720+ cmd = cmd.replaceAll("%CHNAME%", tvd.center);
2721+ cmd = cmd.replaceAll("%DATE%", tvd.accurateDate);
2722+ cmd = cmd.replaceAll("%START%", tvd.start);
2723+ cmd = cmd.replaceAll("%END%", tvd.end);
2724+ cmd = cmd.replaceAll("%DETAILURL%", tvd.link);
2725+ cmd = cmd.replaceAll("%SYOBODETAILURL%", tvd.linkSyobo != null ? tvd.linkSyobo : "");
2726+
2727+ // CHAN-TORU対応
2728+ if ( cmd.matches(".*%TVKAREACODE%.*") && cmd.matches(".*%TVKPID%.*") ) {
2729+ Center cr = null;
2730+ for ( TVProgram tvp : progPlugins ) {
2731+ if ( tvp.getTVProgramId().startsWith("Gガイド.テレビ王国") ) {
2732+ for ( Center tempcr : tvp.getCRlist() ) {
2733+ // CH設定が完了している必要がある
2734+ if ( tvp.getSubtype() == ProgSubtype.TERRA && tvp.getSelectedCode().equals(TVProgram.allCode) && ! tempcr.getAreaCode().equals(TVProgram.bsCode) ) {
2735+ // 地域が全国の地デジの場合のみ、有効局かどうかを確認する必要がある
2736+ if ( tempcr.getCenter().equals(tvd.center) && tempcr.getOrder() > 0 ) {
2737+ // このメニューは利用できます!
2738+ cr = tempcr;
2739+ break;
26772740 }
2678- else {
2679- if ( tempcr.getCenter().equals(tvd.center) ) {
2680- // このメニューは利用できます!
2681- cr = tempcr;
2682- break;
2683- }
2741+ }
2742+ else {
2743+ if ( tempcr.getCenter().equals(tvd.center) ) {
2744+ // このメニューは利用できます!
2745+ cr = tempcr;
2746+ break;
26842747 }
26852748 }
2749+ }
26862750
2687- if ( cr != null ) {
2688- break;
2689- }
2751+ if ( cr != null ) {
2752+ break;
26902753 }
26912754 }
2692- if ( cr != null ) {
2693- String areacode = null;
2694- String centercode = cr.getLink();
2695- String cat = cr.getLink().substring(0,1);
2696- if ( cat.equals("1") ) {
2697- areacode = cr.getAreaCode();
2755+ }
2756+ if ( cr != null ) {
2757+ String areacode = null;
2758+ String centercode = cr.getLink();
2759+ String cat = cr.getLink().substring(0,1);
2760+ if ( cat.equals("1") ) {
2761+ areacode = cr.getAreaCode();
2762+ }
2763+ else {
2764+ if ( cat.equals("4") ) {
2765+ cat = "5";
26982766 }
2699- else {
2700- if ( cat.equals("4") ) {
2701- cat = "5";
2702- }
2703- else if ( cat.equals("5") ) {
2704- cat = "4";
2705- }
2706- areacode = "10";
2767+ else if ( cat.equals("5") ) {
2768+ cat = "4";
27072769 }
2770+ areacode = "10";
2771+ }
27082772
2709- cmd = cmd.replaceAll("%TVKAREACODE%", areacode);
2710- cmd = cmd.replaceAll("%TVKCAT%", cat);
2711- cmd = cmd.replaceAll("%TVKPID%", centercode+CommonUtils.getDateTimeYMD(CommonUtils.getCalendar(tvd.startDateTime)).replaceFirst("..$", ""));
2712- System.out.println("[DEBUG] "+cmd);
2773+ cmd = cmd.replaceAll("%TVKAREACODE%", areacode);
2774+ cmd = cmd.replaceAll("%TVKCAT%", cat);
2775+ cmd = cmd.replaceAll("%TVKPID%", centercode+CommonUtils.getDateTimeYMD(CommonUtils.getCalendar(tvd.startDateTime)).replaceFirst("..$", ""));
2776+ System.out.println("[DEBUG] "+cmd);
27132777
2714- menuItem.setEnabled(true);
2715- menuItem.setForeground(Color.BLACK);
2716- }
2717- else {
2718- menuItem.setEnabled(false);
2719- menuItem.setForeground(Color.lightGray);
2720- }
2778+ menuItem.setEnabled(true);
2779+ menuItem.setForeground(Color.BLACK);
2780+ }
2781+ else {
2782+ menuItem.setEnabled(false);
2783+ menuItem.setForeground(Color.lightGray);
27212784 }
2785+ }
27222786
2723- final String run = cmd;
2787+ if (cmd.isEmpty())
2788+ continue;
27242789
2725- menuItem.addActionListener(new ActionListener() {
2726- @Override
2727- public void actionPerformed(ActionEvent e) {
2728- try {
2729- if (run.indexOf("http") == 0) {
2730- Desktop desktop = Desktop.getDesktop();
2731- desktop.browse(new URI(run));
2732- }
2733- else {
2734- CommonUtils.executeCommand(run);
2735- }
2736- } catch (IOException e1) {
2737- e1.printStackTrace();
2738- } catch (URISyntaxException e1) {
2739- e1.printStackTrace();
2790+ final String run = cmd;
2791+
2792+ menuItem.addActionListener(new ActionListener() {
2793+ @Override
2794+ public void actionPerformed(ActionEvent e) {
2795+ try {
2796+ if (run.indexOf("http") == 0) {
2797+ Desktop desktop = Desktop.getDesktop();
2798+ desktop.browse(new URI(run));
27402799 }
2800+ else {
2801+ CommonUtils.executeCommand(run);
2802+ }
2803+ } catch (IOException e1) {
2804+ e1.printStackTrace();
2805+ } catch (URISyntaxException e1) {
2806+ e1.printStackTrace();
27412807 }
2742- });
2808+ }
2809+ });
27432810
2744- pop.add(menuItem);
2745- }
2811+ pop.add(menuItem);
27462812 }
2813+ }
27472814
2748- pop.addSeparator();
2749-
2750- // クリップボードへコピーする
2815+ /*
2816+ * クリップボードへコピーメニューを追加する
2817+ */
2818+ public void addClipboardMenuToPopup(JPopupMenu pop, final ProgDetailList tvd){
27512819 {
27522820 JMenuItem menuItem = new JMenuItem("番組名をコピー【"+tvd.title+"】");
27532821 menuItem.addActionListener(new ActionListener() {
@@ -2849,10 +2917,12 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
28492917 pop.add(menuItem);
28502918 }
28512919 }
2920+ }
28522921
2853- pop.addSeparator();
2854-
2855- // 延長感染源へ追加する
2922+ /*
2923+ * 感染源メニューを追加する
2924+ */
2925+ public void addInfectionSourceMenuToPopup(JPopupMenu pop, final ProgDetailList tvd){
28562926 if (
28572927 tvd.type == ProgType.SYOBO ||
28582928 tvd.type == ProgType.PASSED ||
@@ -2888,6 +2958,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
28882958 });
28892959 pop.add(menuItem);
28902960 }
2961+
28912962 if ( tvd.type == ProgType.PASSED || (tvd.type == ProgType.PROG && tvd.subtype != ProgSubtype.RADIO) ) // ラジオは処理対象外です
28922963 {
28932964 JMenuItem menuItem = new JMenuItem("延長感染源にする【"+tvd.title+" ("+tvd.center+")】");
@@ -2917,9 +2988,12 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
29172988 });
29182989 pop.add(menuItem);
29192990 }
2991+ }
29202992
2921-
2922- // 視聴する
2993+ /*
2994+ * 視聴メニューを追加する
2995+ */
2996+ public void addChannelMenuToPopup( JPopupMenu pop, final ProgDetailList tvd){
29232997 if ( tvd.type == ProgType.PROG && tvd.subtype != ProgSubtype.RADIO) // ラジオは処理対象外です
29242998 {
29252999 boolean hassep = false;
@@ -2959,8 +3033,6 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
29593033 pop.add(menuItem);
29603034 }
29613035 }
2962-
2963- pop.show(comp, x, y);
29643036 }
29653037
29663038 // ピックアップへ追加する
@@ -4458,6 +4530,8 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
44584530 }
44594531 }
44604532
4533+ tvd.linkSyobo = svd.link;
4534+
44614535 // 「しょぼかるにのみ存在」フラグの上げ下げ(これはアニメ限定)
44624536 if ( isAnime ) {
44634537 if ( isFind ) {
@@ -5670,7 +5744,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
56705744 mainWindow.addStatusArea(mwin);
56715745
56725746 // タブ群
5673- addAllTabs();
5747+// addAllTabs();
56745748 }
56755749
56765750 // ステータスエリアを開く
@@ -6467,7 +6541,8 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
64676541 // 放送局の並び順もロード
64686542 chsort.load();
64696543
6470- loadRdReservesAll(runRecLoad, null);
6544+ _loadRdRecorderAll(runRecLoad, null);
6545+// loadRdReservesAll(runRecLoad, null);
64716546
64726547 // 録画タイトルを読み込む
64736548 // loadRdTitlesAll(false, null);
@@ -6565,6 +6640,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
65656640 // ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
65666641 this.setVisible(false);
65676642 this.setContentPane(mainWindow);
6643+ addAllTabs();
65686644 setInitBounds();
65696645 this.setVisible(true);
65706646