タイニー番組ナビゲータ本体
修訂 | 39db50f56ff34fc20ad15f63caa4463168cb5940 (tree) |
---|---|
時間 | 2021-11-03 20:32:51 |
作者 | Masahiko Kimura <mkimura@u01....> |
Commiter | Masahiko Kimura |
Ver.1.13.3 (2021/11/3)
1. [全般]管理対象の番組記号を増やす
2. [全般]番組記号の表示/非表示をタイトルの前後で独立して設定できるようにする
3. [全般]ツリービューの隠れている部分やリストの末尾省略されているセルをツールチップで表示する
4. [新聞形式]番組のツールチップのレイアウトを改善し、表示内容を増やす(終了時刻、番組長、マーク)
@@ -5,7 +5,10 @@ import java.awt.Color; | ||
5 | 5 | import java.awt.Component; |
6 | 6 | import java.awt.Desktop; |
7 | 7 | import java.awt.Dimension; |
8 | +import java.awt.FontMetrics; | |
9 | +import java.awt.Insets; | |
8 | 10 | import java.awt.Point; |
11 | +import java.awt.Rectangle; | |
9 | 12 | import java.awt.event.ActionEvent; |
10 | 13 | import java.awt.event.ActionListener; |
11 | 14 | import java.awt.event.ComponentAdapter; |
@@ -4203,7 +4206,12 @@ public abstract class AbsListedView extends JPanel implements TickTimerListener | ||
4203 | 4206 | if (jTree_tree == null) { |
4204 | 4207 | |
4205 | 4208 | // ツリーの作成 |
4206 | - jTree_tree = new JTree(); | |
4209 | + jTree_tree = new JTree(){ | |
4210 | + @Override public String getToolTipText(MouseEvent e) { | |
4211 | + return CommonUtils.GetTreeTooltip(jScrollPane_tree, jTree_tree, e); | |
4212 | + } | |
4213 | + }; | |
4214 | + jTree_tree.setToolTipText("dummy"); | |
4207 | 4215 | jTree_tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); |
4208 | 4216 | jTree_tree.setRootVisible(env.getRootNodeVisible()); |
4209 | 4217 | jTree_tree.setCellRenderer(new VWTreeCellRenderer()); // 検索結果が存在するノードの色を変える |
@@ -4730,9 +4738,6 @@ public abstract class AbsListedView extends JPanel implements TickTimerListener | ||
4730 | 4738 | Component comp = super.prepareRenderer(tcr, row, column); |
4731 | 4739 | Color fgColor = (prechknextweek)?(nextweekFgColor):(this.getForeground()); |
4732 | 4740 | Color bgColor = (isSepRowColor && row%2 == 1)?(evenColor):(super.getBackground()); |
4733 | - int mrow = this.convertRowIndexToModel(row); | |
4734 | - int mcol = convertColumnIndexToModel(column); | |
4735 | - ListedItem item = rowData.get(mrow); | |
4736 | 4741 | |
4737 | 4742 | isRowPassed(row); |
4738 | 4743 |
@@ -4765,30 +4770,58 @@ public abstract class AbsListedView extends JPanel implements TickTimerListener | ||
4765 | 4770 | comp.setBackground(bgColor); |
4766 | 4771 | } |
4767 | 4772 | |
4773 | + return comp; | |
4774 | + } | |
4775 | + | |
4776 | + // getToolTipText()をオーバーライド | |
4777 | + @Override | |
4778 | + public String getToolTipText(MouseEvent e){ | |
4779 | + int row = rowAtPoint(e.getPoint()); | |
4780 | + int column = columnAtPoint(e.getPoint()); | |
4781 | + if (row == -1 || column == -1) | |
4782 | + return null; | |
4783 | + | |
4784 | + int mrow = this.convertRowIndexToModel(row); | |
4785 | + int mcol = convertColumnIndexToModel(column); | |
4786 | + ListedItem item = rowData.get(mrow); | |
4787 | + | |
4768 | 4788 | // ツールチップテキストを生成する |
4769 | 4789 | ListColumnInfo info = lvitems.getVisibleAt(column); |
4770 | 4790 | |
4771 | - String text = null; | |
4772 | - if (item != null && info != null && comp instanceof JComponent){ | |
4773 | - int cindex = info.getId()-1; | |
4774 | - if (cindex == ListedColumn.RSVMARK.getColumn()) | |
4775 | - text = item.marker != null ? item.marker.getTooltipText() : null; | |
4776 | - else if (cindex >= ListedColumn.RSVMARK1.getColumn() && cindex < ListedColumn.RSVMARK1.getColumn()+marker_num){ | |
4777 | - int n = cindex-ListedColumn.RSVMARK1.getColumn(); | |
4778 | - text = item.marker_array[n] != null ? item.marker_array[n].getTooltipText() : null; | |
4779 | - } | |
4780 | - else if (cindex == ListedColumn.PICKMARK.getColumn() || cindex == ListedColumn.DUPMARK.getColumn()){ | |
4781 | - Object o = getModel().getValueAt(mrow, mcol); | |
4782 | - String s = (o != null) ? o.toString() : null; | |
4783 | - text = RsvMark.getTooltipText(s); | |
4784 | - } | |
4785 | - | |
4786 | - if (text != null) | |
4787 | - ((JComponent) comp).setToolTipText(text); | |
4788 | - } | |
4789 | - | |
4790 | - return comp; | |
4791 | - } | |
4791 | + int cindex = info.getId()-1; | |
4792 | + if (cindex == ListedColumn.RSVMARK.getColumn()) | |
4793 | + return item.marker != null ? item.marker.getTooltipText() : null; | |
4794 | + else if (cindex >= ListedColumn.RSVMARK1.getColumn() && cindex < ListedColumn.RSVMARK1.getColumn()+marker_num){ | |
4795 | + int n = cindex-ListedColumn.RSVMARK1.getColumn(); | |
4796 | + return item.marker_array[n] != null ? item.marker_array[n].getTooltipText() : null; | |
4797 | + } | |
4798 | + else if (cindex == ListedColumn.PICKMARK.getColumn() || cindex == ListedColumn.DUPMARK.getColumn()){ | |
4799 | + Object o = getModel().getValueAt(mrow, mcol); | |
4800 | + String s = (o != null) ? o.toString() : null; | |
4801 | + return RsvMark.getTooltipText(s); | |
4802 | + } | |
4803 | + else if (cindex == ListedColumn.TITLE.getColumn()){ | |
4804 | + if (item.title == null) | |
4805 | + return null; | |
4806 | + | |
4807 | + String text = String.join("", item.title.split("\0", 8)); | |
4808 | + if (text == null) | |
4809 | + return null; | |
4810 | + | |
4811 | + Insets i = getInsets(); | |
4812 | + Rectangle rect = getCellRect(row, column, false); | |
4813 | + FontMetrics fm = getFontMetrics(getFont()); | |
4814 | + | |
4815 | + int width = fm.stringWidth(text); | |
4816 | + | |
4817 | + if (width > rect.width-(i.left+i.right)) | |
4818 | + return text; | |
4819 | + else | |
4820 | + return null; | |
4821 | + } | |
4822 | + else | |
4823 | + return super.getToolTipText(e); | |
4824 | + } | |
4792 | 4825 | |
4793 | 4826 | // 直接rowDataを見に行くようになったから、このisRowPassed()はもういらないんじゃ… |
4794 | 4827 |
@@ -2188,20 +2188,8 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H | ||
2188 | 2188 | b2.setVBounds(col,row,1,tvd.length); |
2189 | 2189 | |
2190 | 2190 | // ツールチップを付加する |
2191 | - if ( env.getTooltipEnable() == true && ! tvd.title.equals("") && ! tvd.start.equals("") ) { | |
2192 | - String t = ""; | |
2193 | - int tlen = bounds.getTooltipWidth(); | |
2194 | - for (int i=0; i<tvd.title.length(); i+=tlen) { | |
2195 | - t += tvd.title.substring(i, (i+tlen<tvd.title.length())?(i+tlen):(tvd.title.length()))+"<BR>"; | |
2196 | - } | |
2197 | - String d = ""; | |
2198 | - int dlen = tlen+2; | |
2199 | - for (int i=0; i<tvd.detail.length(); i+=dlen) { | |
2200 | - d += " "+tvd.detail.substring(i, (i+dlen<tvd.detail.length())?(i+dlen):(tvd.detail.length()))+"<BR>"; | |
2201 | - } | |
2202 | - String e = getExtensionMark(tvd); | |
2203 | - b2.setToolTipText(("<html>"+tvd.start+" <FONT COLOR=RED><EM>"+e+"</EM></FONT><BR> <FONT COLOR=BLUE><STRONG><U>"+t+"</U></STRONG></FONT>"+d+"</html>")); | |
2204 | - } | |
2191 | + if (Env.TheEnv.getTooltipEnable() && ! tvd.title.isEmpty() && ! tvd.start.isEmpty()) | |
2192 | + b2.setToolTipText("dummy"); | |
2205 | 2193 | } |
2206 | 2194 | |
2207 | 2195 |
@@ -2626,7 +2614,7 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H | ||
2626 | 2614 | else if (byCenter && !value.equals("")){ |
2627 | 2615 | c = CommonUtils.getCalendar(value, 3600*24); |
2628 | 2616 | if (c != null) |
2629 | - redrawByDateWithCenter(node.getLabel(), CommonUtils.getDate(c)); | |
2617 | + redrawByDateWithCenter(null, CommonUtils.getDate(c)); | |
2630 | 2618 | } |
2631 | 2619 | else |
2632 | 2620 | redrawByCurrentSelection(); |
@@ -3255,7 +3243,13 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H | ||
3255 | 3243 | if (jTree_tree == null) { |
3256 | 3244 | |
3257 | 3245 | // ツリーの作成 |
3258 | - jTree_tree = new JTree(); | |
3246 | + jTree_tree = new JTree(){ | |
3247 | + @Override public String getToolTipText(MouseEvent e) { | |
3248 | + return CommonUtils.GetTreeTooltip(jScrollPane_tree, jTree_tree, e); | |
3249 | + } | |
3250 | + }; | |
3251 | + jTree_tree.setToolTipText("dummy"); | |
3252 | + | |
3259 | 3253 | jTree_tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); |
3260 | 3254 | jTree_tree.setCellRenderer(new TreeCellRenderer()); // 検索結果が存在するノードの色を変える |
3261 | 3255 | jTree_tree.setRootVisible(env.getRootNodeVisible()); |
@@ -25,7 +25,6 @@ import java.util.HashMap; | ||
25 | 25 | import java.util.Map.Entry; |
26 | 26 | |
27 | 27 | import javax.swing.ImageIcon; |
28 | -import javax.swing.JComponent; | |
29 | 28 | import javax.swing.JLabel; |
30 | 29 | import javax.swing.JMenuItem; |
31 | 30 | import javax.swing.JPanel; |
@@ -1936,35 +1935,44 @@ public abstract class AbsReserveListView extends JPanel implements TickTimerList | ||
1936 | 1935 | c.setBackground(bgColor); |
1937 | 1936 | } |
1938 | 1937 | |
1938 | + return c; | |
1939 | + } | |
1940 | + | |
1941 | + // getToolTipText()をオーバーライド | |
1942 | + @Override | |
1943 | + public String getToolTipText(MouseEvent e){ | |
1944 | + int row = rowAtPoint(e.getPoint()); | |
1945 | + int column = columnAtPoint(e.getPoint()); | |
1946 | + if (row == -1 || column == -1) | |
1947 | + return null; | |
1948 | + | |
1939 | 1949 | // ツールチップテキストを生成する |
1940 | 1950 | if (column == RsvedColumn.DUPMARK.getColumn()){ |
1941 | - if (c instanceof JComponent) { | |
1942 | - int mr = convertRowIndexToModel(row); | |
1943 | - int mc = convertColumnIndexToModel(column); | |
1944 | - Object o = getModel().getValueAt(mr, mc); | |
1945 | - | |
1946 | - String text = null; | |
1947 | - if (o != null){ | |
1948 | - String s = o.toString(); | |
1949 | - if (s == null) | |
1950 | - ; | |
1951 | - else if (s.startsWith("□")){ | |
1952 | - text = "□:開始時間と終了時間が同じ"; | |
1953 | - } | |
1954 | - else if (s.startsWith("■")){ | |
1955 | - text = "■:時間が重なっている"; | |
1956 | - } | |
1957 | - else if (s.startsWith("★")){ | |
1958 | - text = "★:エンコーダの数を超える予約がある"; | |
1959 | - } | |
1960 | - } | |
1961 | - | |
1962 | - ((JComponent) c).setToolTipText(text); | |
1963 | - } | |
1964 | - } | |
1951 | + int mr = convertRowIndexToModel(row); | |
1952 | + int mc = convertColumnIndexToModel(column); | |
1953 | + Object o = getModel().getValueAt(mr, mc); | |
1954 | + | |
1955 | + String text = null; | |
1956 | + if (o != null){ | |
1957 | + String s = o.toString(); | |
1958 | + if (s == null) | |
1959 | + ; | |
1960 | + else if (s.startsWith("□")){ | |
1961 | + text = "□:開始時間と終了時間が同じ"; | |
1962 | + } | |
1963 | + else if (s.startsWith("■")){ | |
1964 | + text = "■:時間が重なっている"; | |
1965 | + } | |
1966 | + else if (s.startsWith("★")){ | |
1967 | + text = "★:エンコーダの数を超える予約がある"; | |
1968 | + } | |
1969 | + } | |
1965 | 1970 | |
1966 | - return c; | |
1967 | - } | |
1971 | + return text; | |
1972 | + } | |
1973 | + else | |
1974 | + return super.getToolTipText(e); | |
1975 | + } | |
1968 | 1976 | |
1969 | 1977 | // 連続して同じ行へのアクセスがあったら計算を行わず前回のままにする |
1970 | 1978 | private boolean isRowPassed(int prow) { |
@@ -1512,7 +1512,8 @@ public abstract class AbsSettingView extends JScrollPane { | ||
1512 | 1512 | env.setSyncTreeWidth(jCBP_syncTreeWidth.isSelected()); |
1513 | 1513 | env.setShortExtMark(jCBP_shortExtMark.isSelected()); |
1514 | 1514 | for (int row=0; row<jTable_showmarks.getRowCount(); row++) { |
1515 | - env.getOptMarks().put((TVProgram.ProgOption) jTable_showmarks.getValueAt(row, 2), (Boolean) jTable_showmarks.getValueAt(row, 0)); | |
1515 | + env.getOptMarks().put((TVProgram.ProgOption) jTable_showmarks.getValueAt(row, 3), (Boolean) jTable_showmarks.getValueAt(row, 0)); | |
1516 | + env.getOptPostfixMarks().put((TVProgram.ProgOption) jTable_showmarks.getValueAt(row, 3), (Boolean) jTable_showmarks.getValueAt(row, 1)); | |
1516 | 1517 | } |
1517 | 1518 | for (int row=0; row<jTable_clipboard.getRowCount(); row++) { |
1518 | 1519 | cbitems.get(row).setB((Boolean)jTable_clipboard.getValueAt(row, 0)); |
@@ -2584,32 +2585,127 @@ public abstract class AbsSettingView extends JScrollPane { | ||
2584 | 2585 | } |
2585 | 2586 | private JNETable getJTable_showmarks() { |
2586 | 2587 | if (jTable_showmarks == null) { |
2587 | - jTable_showmarks = getDispTable(null); | |
2588 | + jTable_showmarks = getDispTable_showmarks(); | |
2588 | 2589 | |
2589 | 2590 | DefaultTableModel model = (DefaultTableModel)jTable_showmarks.getModel(); |
2590 | 2591 | |
2591 | 2592 | // |
2592 | 2593 | for (Object[] obj : TVProgram.optMarks) { |
2593 | - Entry<ProgOption,Boolean> entry = null; | |
2594 | + Entry<ProgOption,Boolean> entryPrefix = null; | |
2594 | 2595 | for (Entry<ProgOption,Boolean> e : env.getOptMarks().entrySet()) { |
2595 | 2596 | if (e.getKey() == obj[0]) { |
2596 | - entry = e; | |
2597 | + entryPrefix = e; | |
2597 | 2598 | break; |
2598 | 2599 | } |
2599 | 2600 | } |
2600 | - if ( entry != null ) { | |
2601 | - Object[] data = { entry.getValue(),obj[1],obj[0] }; | |
2602 | - model.addRow(data); | |
2603 | - } | |
2604 | - else { | |
2605 | - Object[] data = { Boolean.TRUE,obj[1],obj[0] }; | |
2606 | - model.addRow(data); | |
2601 | + | |
2602 | + Entry<ProgOption,Boolean> entryPostfix = null; | |
2603 | + for (Entry<ProgOption,Boolean> e : env.getOptPostfixMarks().entrySet()) { | |
2604 | + if (e.getKey() == obj[0]) { | |
2605 | + entryPostfix = e; | |
2606 | + break; | |
2607 | + } | |
2607 | 2608 | } |
2609 | + | |
2610 | + Object label = obj.length > 1 ? obj[1] : ((ProgOption)obj[0]).getProgLabel(); | |
2611 | + Object [] data = { | |
2612 | + entryPrefix != null ? entryPrefix.getValue() : Boolean.FALSE, | |
2613 | + entryPostfix != null ? entryPostfix.getValue() : Boolean.FALSE, | |
2614 | + label, | |
2615 | + obj[0] | |
2616 | + }; | |
2617 | + | |
2618 | + model.addRow(data); | |
2608 | 2619 | } |
2609 | 2620 | } |
2610 | 2621 | return(jTable_showmarks); |
2611 | 2622 | } |
2612 | 2623 | |
2624 | + /** | |
2625 | + * 表示マーク用のテーブルを生成する | |
2626 | + * | |
2627 | + * @return 生成したJNETableオブジェクト | |
2628 | + */ | |
2629 | + private JNETable getDispTable_showmarks() { | |
2630 | + String prefix = "前"; | |
2631 | + String postfix = "後"; | |
2632 | + | |
2633 | + // ヘッダの設定 | |
2634 | + String[] colname = {prefix, postfix, "アイテム", "ID"}; | |
2635 | + int[] colwidth = {30,30,240,0}; | |
2636 | + | |
2637 | + // | |
2638 | + DefaultTableModel model = new DefaultTableModel(colname, 0); | |
2639 | + JNETable jTable = new JNETable(model, false) { | |
2640 | + private static final long serialVersionUID = 1L; | |
2641 | + | |
2642 | + @Override | |
2643 | + public boolean isCellEditable(int row, int column) { | |
2644 | + return (column == 0 || column == 1); | |
2645 | + } | |
2646 | + }; | |
2647 | + | |
2648 | + jTable.setAutoResizeMode(JNETable.AUTO_RESIZE_OFF); | |
2649 | + DefaultTableColumnModel columnModel = (DefaultTableColumnModel)jTable.getColumnModel(); | |
2650 | + TableColumn column = null; | |
2651 | + for (int i = 0 ; i < columnModel.getColumnCount() ; i++){ | |
2652 | + column = columnModel.getColumn(i); | |
2653 | + column.setPreferredWidth(colwidth[i]); | |
2654 | + } | |
2655 | + | |
2656 | + // にゃーん | |
2657 | + jTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); | |
2658 | + | |
2659 | + // エディタに手を入れる | |
2660 | + DefaultCellEditor editor = new DefaultCellEditor(new JCheckBox() { | |
2661 | + | |
2662 | + private static final long serialVersionUID = 1L; | |
2663 | + | |
2664 | + @Override | |
2665 | + public int getHorizontalAlignment() { | |
2666 | + return JCheckBox.CENTER; | |
2667 | + } | |
2668 | + }); | |
2669 | + | |
2670 | + jTable.getColumn(prefix).setCellEditor(editor); | |
2671 | + jTable.getColumn(postfix).setCellEditor(editor); | |
2672 | + | |
2673 | + // レンダラに手を入れる | |
2674 | + DefaultTableCellRenderer renderer = new DefaultTableCellRenderer() { | |
2675 | + private static final long serialVersionUID = 1L; | |
2676 | + | |
2677 | + @Override | |
2678 | + public Component getTableCellRendererComponent(JTable table, Object value, | |
2679 | + boolean isSelected, boolean hasFocus, int row, int column) { | |
2680 | + // | |
2681 | + JCheckBox cBox = new JCheckBox(); | |
2682 | + cBox.setHorizontalAlignment(JCheckBox.CENTER); | |
2683 | + // | |
2684 | + Boolean b = (Boolean)value; | |
2685 | + cBox.setSelected(b.booleanValue()); | |
2686 | + // | |
2687 | + if (isSelected) { | |
2688 | + cBox.setBackground(table.getSelectionBackground()); | |
2689 | + } | |
2690 | + else { | |
2691 | + cBox.setBackground(table.getBackground()); | |
2692 | + } | |
2693 | + | |
2694 | + // 【新】【終】は後ろには表示できない | |
2695 | + if (column == 1 && (row == 0 || row == 1)){ | |
2696 | + cBox.setEnabled(false); | |
2697 | + cBox.setSelected(false); | |
2698 | + } | |
2699 | + | |
2700 | + return cBox; | |
2701 | + } | |
2702 | + }; | |
2703 | + jTable.getColumn(prefix).setCellRenderer(renderer); | |
2704 | + jTable.getColumn(postfix).setCellRenderer(renderer); | |
2705 | + | |
2706 | + return jTable; | |
2707 | + } | |
2708 | + | |
2613 | 2709 | /* |
2614 | 2710 | * クリップボードアイテムの選択 |
2615 | 2711 | */ |
@@ -10,6 +10,8 @@ import java.util.HashMap; | ||
10 | 10 | * 【結論】ちゃんと設計しないとメンバの変更で簡単に例外が起きる。できるならシリアライズは自前で組もう! |
11 | 11 | */ |
12 | 12 | public class Bounds { |
13 | + public static Bounds TheBounds = null; | |
14 | + | |
13 | 15 | // |
14 | 16 | private static final String BOUNDS_FILE = "env"+File.separator+"bounds.xml"; |
15 | 17 | private static final String BOUNDS_TEXT = "env"+File.separator+"bounds.txt"; |
@@ -3,6 +3,9 @@ package tainavi; | ||
3 | 3 | |
4 | 4 | import java.awt.Color; |
5 | 5 | import java.awt.Desktop; |
6 | +import java.awt.Point; | |
7 | +import java.awt.Rectangle; | |
8 | +import java.awt.event.MouseEvent; | |
6 | 9 | import java.beans.XMLDecoder; |
7 | 10 | import java.beans.XMLEncoder; |
8 | 11 | import java.io.BufferedInputStream; |
@@ -33,12 +36,18 @@ import java.util.Calendar; | ||
33 | 36 | import java.util.GregorianCalendar; |
34 | 37 | import java.util.HashMap; |
35 | 38 | import java.util.Map.Entry; |
39 | +import java.util.Objects; | |
36 | 40 | import java.util.regex.Matcher; |
37 | 41 | import java.util.regex.Pattern; |
38 | 42 | import java.util.zip.ZipEntry; |
39 | 43 | import java.util.zip.ZipFile; |
40 | 44 | import java.util.zip.ZipOutputStream; |
41 | 45 | |
46 | +import javax.swing.JScrollPane; | |
47 | +import javax.swing.JTree; | |
48 | +import javax.swing.JViewport; | |
49 | +import javax.swing.tree.TreePath; | |
50 | + | |
42 | 51 | /** |
43 | 52 | * <P>頻繁に使用する雑多なメソッドをstaticで提供します。 |
44 | 53 | * <P>パッケージを小分けにしておけばよかった… |
@@ -1784,4 +1793,25 @@ public class CommonUtils { | ||
1784 | 1793 | public static void closing(HttpURLConnection ucon) { |
1785 | 1794 | if ( ucon != null ) ucon.disconnect(); |
1786 | 1795 | } |
1796 | + | |
1797 | + public static String GetTreeTooltip(JScrollPane pane, JTree tree, MouseEvent e){ | |
1798 | + Object o = null; | |
1799 | + TreePath path = tree.getPathForLocation(e.getX(), e.getY()); | |
1800 | + if (Objects.nonNull(path) && pane != null) { | |
1801 | + JViewport vp = pane.getViewport(); | |
1802 | + if (vp == null) | |
1803 | + return null; | |
1804 | + | |
1805 | + Point pt = vp.getViewPosition(); | |
1806 | + Rectangle rp = tree.getPathBounds(path); | |
1807 | + Rectangle rt = pane.getViewportBorderBounds(); | |
1808 | + rt.setLocation(pt); | |
1809 | + if (rt.contains(rp)) | |
1810 | + return null; | |
1811 | + | |
1812 | + o = path.getLastPathComponent(); | |
1813 | + } | |
1814 | + | |
1815 | + return Objects.toString(o, null); | |
1816 | + } | |
1787 | 1817 | } |
@@ -674,10 +674,17 @@ public class Env { | ||
674 | 674 | public boolean getShortExtMark() { return shortExtMark; } |
675 | 675 | public void setShortExtMark(boolean b) { shortExtMark = b; } |
676 | 676 | private boolean shortExtMark = false; |
677 | + | |
677 | 678 | // 表示マークの選択 |
678 | 679 | public HashMap<TVProgram.ProgOption,Boolean> getOptMarks() { return optMarks; } |
679 | 680 | public void setOptMarks(HashMap<TVProgram.ProgOption,Boolean> h) { optMarks = h; } |
680 | 681 | private HashMap<TVProgram.ProgOption,Boolean> optMarks = new HashMap<TVProgram.ProgOption, Boolean>(); |
682 | + | |
683 | + // 表示マークの選択(後付け) | |
684 | + public HashMap<TVProgram.ProgOption,Boolean> getOptPostfixMarks() { return optPostfixMarks; } | |
685 | + public void setOptPostfixMarks(HashMap<TVProgram.ProgOption,Boolean> h) { optPostfixMarks = h; } | |
686 | + private HashMap<TVProgram.ProgOption,Boolean> optPostfixMarks = new HashMap<TVProgram.ProgOption, Boolean>(); | |
687 | + | |
681 | 688 | // クリップボードアイテムの選択(->clipboardItem) |
682 | 689 | // 右クリックメニューの実行アイテム |
683 | 690 | public ArrayList<TextValueSet> getTvCommand() { return tvCommand; } |
@@ -2,6 +2,10 @@ package tainavi; | ||
2 | 2 | |
3 | 3 | import java.awt.Color; |
4 | 4 | import java.awt.Component; |
5 | +import java.awt.FontMetrics; | |
6 | +import java.awt.Insets; | |
7 | +import java.awt.Rectangle; | |
8 | +import java.awt.event.MouseEvent; | |
5 | 9 | |
6 | 10 | import javax.swing.JTable; |
7 | 11 | import javax.swing.ListSelectionModel; |
@@ -116,6 +120,40 @@ public class JNETable extends JTable { | ||
116 | 120 | } |
117 | 121 | } |
118 | 122 | |
123 | + | |
124 | + // getToolTipText()をオーバーライド | |
125 | + @Override | |
126 | + public String getToolTipText(MouseEvent e){ | |
127 | + int row = rowAtPoint(e.getPoint()); | |
128 | + int column = columnAtPoint(e.getPoint()); | |
129 | + if (row == -1 || column == -1) | |
130 | + return null; | |
131 | + | |
132 | + try{ | |
133 | + String text = (String)getModel().getValueAt(row, column); | |
134 | + if (text == null) | |
135 | + return null; | |
136 | + | |
137 | + String[] xs = text.split("\0", 4); | |
138 | + if (xs.length <= 0 || xs[0] == null) | |
139 | + return null; | |
140 | + | |
141 | + Insets i = getInsets(); | |
142 | + Rectangle rect = getCellRect(row, column, false); | |
143 | + FontMetrics fm = getFontMetrics(getFont()); | |
144 | + | |
145 | + int width = fm.stringWidth(xs[0]); | |
146 | + | |
147 | + if (width > rect.width-(i.left+i.right)) | |
148 | + return xs[0]; | |
149 | + else | |
150 | + return null; | |
151 | + } | |
152 | + catch(ClassCastException ex){ | |
153 | + return null; | |
154 | + } | |
155 | + } | |
156 | + | |
119 | 157 | /* |
120 | 158 | * コンストラクタ |
121 | 159 | */ |
@@ -9,6 +9,7 @@ import java.awt.Graphics; | ||
9 | 9 | import java.awt.Graphics2D; |
10 | 10 | import java.awt.Rectangle; |
11 | 11 | import java.awt.RenderingHints; |
12 | +import java.awt.event.MouseEvent; | |
12 | 13 | import java.awt.font.FontRenderContext; |
13 | 14 | import java.awt.font.GlyphMetrics; |
14 | 15 | import java.awt.font.GlyphVector; |
@@ -30,7 +31,7 @@ public class JTXTButton extends JLabel { | ||
30 | 31 | /******************************************************************************* |
31 | 32 | * 定数 |
32 | 33 | ******************************************************************************/ |
33 | - | |
34 | + | |
34 | 35 | /** |
35 | 36 | * フォントスタイル |
36 | 37 | */ |
@@ -38,23 +39,23 @@ public class JTXTButton extends JLabel { | ||
38 | 39 | BOLD ("太字"), |
39 | 40 | ITALIC ("斜体"), |
40 | 41 | UNDERLINE ("下線"); |
41 | - | |
42 | + | |
42 | 43 | private String name; |
43 | - | |
44 | + | |
44 | 45 | private FontStyle(String name) { |
45 | 46 | this.name = name; |
46 | 47 | } |
47 | - | |
48 | + | |
48 | 49 | @Override |
49 | 50 | public String toString() { |
50 | 51 | return name; |
51 | 52 | } |
52 | - | |
53 | - | |
53 | + | |
54 | + | |
54 | 55 | public String getId() { |
55 | 56 | return super.toString(); |
56 | 57 | } |
57 | - | |
58 | + | |
58 | 59 | public static FontStyle get(String id) { |
59 | 60 | for ( FontStyle fs : FontStyle.values() ) { |
60 | 61 | if ( fs.getId().equals(id) ) { |
@@ -64,62 +65,62 @@ public class JTXTButton extends JLabel { | ||
64 | 65 | return null; |
65 | 66 | } |
66 | 67 | }; |
67 | - | |
68 | + | |
68 | 69 | private static final float DRAWTAB = 2.0F; |
69 | - | |
70 | - | |
70 | + | |
71 | + | |
71 | 72 | /******************************************************************************* |
72 | 73 | * 部品 |
73 | 74 | ******************************************************************************/ |
74 | - | |
75 | + | |
75 | 76 | // 描画バッファ |
76 | 77 | private BufferedImage image = null; // ビットマップ |
77 | - | |
78 | + | |
78 | 79 | private int vrow; // 仮想座標縦位置 |
79 | 80 | private int vcolumn; // 仮想座標横位置 |
80 | 81 | private int vheight; // 仮想座標高さ |
81 | 82 | private int vwidth; // 仮想座標幅 |
82 | - | |
83 | + | |
83 | 84 | // 番組情報 |
84 | 85 | private ProgDetailList tvd = null; // 番組情報そのまま |
85 | - | |
86 | + | |
86 | 87 | // 表示設定 |
87 | 88 | private static boolean showStart = true; |
88 | 89 | private static boolean splitEpno = false; |
89 | 90 | private static boolean showDetail = true; |
90 | 91 | private static float detailTab = 2.0F; |
91 | - | |
92 | + | |
92 | 93 | private static Font defaultFont = new JLabel().getFont(); |
93 | - | |
94 | + | |
94 | 95 | private static Font titleFont = defaultFont; |
95 | 96 | private static int titleFontSize = defaultFont.getSize(); |
96 | 97 | private static Color titleFontColor = Color.BLUE; |
97 | 98 | private static int titleFontStyle = Font.BOLD; |
98 | - | |
99 | + | |
99 | 100 | private static Font detailFont = defaultFont; |
100 | 101 | private static int detailFontSize = defaultFont.getSize(); |
101 | 102 | private static Color detailFontColor = Color.DARK_GRAY; |
102 | 103 | private static int detailFontStyle = defaultFont.getStyle(); |
103 | - | |
104 | + | |
104 | 105 | private static Font startFont = defaultFont; |
105 | - | |
106 | + | |
106 | 107 | private static FontRenderContext frc = new FontRenderContext(null, RenderingHints.VALUE_TEXT_ANTIALIAS_ON, RenderingHints.VALUE_FRACTIONALMETRICS_DEFAULT); |
107 | 108 | |
108 | 109 | private static int columnWidth = 0; |
109 | 110 | private static float heightMultiplier = 0; |
110 | - | |
111 | - | |
111 | + | |
112 | + | |
112 | 113 | /******************************************************************************* |
113 | 114 | * コンストラクタ |
114 | 115 | ******************************************************************************/ |
115 | - | |
116 | + | |
116 | 117 | // ないよ |
117 | - | |
118 | - | |
118 | + | |
119 | + | |
119 | 120 | /******************************************************************************* |
120 | 121 | * メソッド |
121 | 122 | ******************************************************************************/ |
122 | - | |
123 | + | |
123 | 124 | // 内容をリセットする |
124 | 125 | // setVisible(false)するとリソースが解放されてしまうのか再描画に時間がかかるようになるので表示範囲外に出して隠してしまう |
125 | 126 | public void clean() { |
@@ -127,13 +128,13 @@ public class JTXTButton extends JLabel { | ||
127 | 128 | image = null; |
128 | 129 | setBounds(-1,-1,0,0); |
129 | 130 | } |
130 | - | |
131 | + | |
131 | 132 | // フラグを変えた後に再描画させる |
132 | 133 | public void forceRepaint() { |
133 | 134 | image = null; |
134 | 135 | super.repaint(); |
135 | 136 | } |
136 | - | |
137 | + | |
137 | 138 | // 仮想位置の変更 |
138 | 139 | //public void setVRow(int n) { vrow = n; } |
139 | 140 | public int getVRow() { return vrow; } |
@@ -141,10 +142,10 @@ public class JTXTButton extends JLabel { | ||
141 | 142 | public int getVColumn() { return vcolumn; } |
142 | 143 | //public void setVHeight(int n) { vheight = n; } |
143 | 144 | public int getVHeight() { return vheight; } |
144 | - | |
145 | + | |
145 | 146 | public static void setColumnWidth(int n) { columnWidth = n; } |
146 | 147 | public static void setHeightMultiplier(float f) { heightMultiplier = f; } |
147 | - | |
148 | + | |
148 | 149 | public void setVBounds(int x, int y, int width, int height) { |
149 | 150 | vrow = y; |
150 | 151 | vcolumn = x; |
@@ -156,7 +157,7 @@ public class JTXTButton extends JLabel { | ||
156 | 157 | vwidth*columnWidth, |
157 | 158 | (int) Math.ceil(((float)vheight)*heightMultiplier)); |
158 | 159 | } |
159 | - | |
160 | + | |
160 | 161 | public void reVBounds() { |
161 | 162 | super.setBounds( |
162 | 163 | vcolumn*columnWidth, |
@@ -164,12 +165,12 @@ public class JTXTButton extends JLabel { | ||
164 | 165 | vwidth*columnWidth, |
165 | 166 | (int) Math.ceil(((float)vheight)*heightMultiplier)); |
166 | 167 | } |
167 | - | |
168 | + | |
168 | 169 | // 番組情報のやりとり |
169 | 170 | public void setInfo(ProgDetailList tvd) { |
170 | 171 | this.tvd = tvd; |
171 | 172 | this.setText(null); // 簡易表示時代の名残 |
172 | - | |
173 | + | |
173 | 174 | this.setVerticalAlignment(JButton.TOP); |
174 | 175 | this.setHorizontalAlignment(JButton.LEFT); |
175 | 176 | //this.setBorder(new LineBorder(Color.BLACK,1)); |
@@ -178,7 +179,7 @@ public class JTXTButton extends JLabel { | ||
178 | 179 | public ProgDetailList getInfo() { |
179 | 180 | return tvd; |
180 | 181 | } |
181 | - | |
182 | + | |
182 | 183 | // 予約待機枠を表示するかどうかの確認 |
183 | 184 | public boolean isStandby() { return tvd.marked && tvd.showinstandby; } |
184 | 185 | public boolean isStandbyByTrace() { return tvd.markedByTrace; } |
@@ -196,7 +197,7 @@ public class JTXTButton extends JLabel { | ||
196 | 197 | public static void setDetailTab(float n) { |
197 | 198 | detailTab = n; |
198 | 199 | } |
199 | - | |
200 | + | |
200 | 201 | // フォントスタイル |
201 | 202 | public static void setTitleFont(String fn) { |
202 | 203 | if ( fn != null && ! fn.equals("") ) { |
@@ -234,7 +235,7 @@ public class JTXTButton extends JLabel { | ||
234 | 235 | public static void setDetailFontColor(Color c) { |
235 | 236 | detailFontColor = c; |
236 | 237 | } |
237 | - | |
238 | + | |
238 | 239 | // フォントスタイルの変更 |
239 | 240 | public static void setTitleFontStyle(ArrayList<FontStyle> fsa) { |
240 | 241 | titleFont = setFontStyle(titleFont, (float)titleFontSize, fsa); |
@@ -242,7 +243,7 @@ public class JTXTButton extends JLabel { | ||
242 | 243 | public static void setDetailFontStyle(ArrayList<FontStyle> fsa) { |
243 | 244 | detailFont = setFontStyle(detailFont, (float)detailFontSize, fsa); |
244 | 245 | } |
245 | - | |
246 | + | |
246 | 247 | private static Font setFontStyle(Font f, float size, ArrayList<FontStyle> fsa) { |
247 | 248 | Map<TextAttribute, Object> attributes = new HashMap<TextAttribute, Object>(); |
248 | 249 | attributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_REGULAR); |
@@ -264,25 +265,25 @@ public class JTXTButton extends JLabel { | ||
264 | 265 | attributes.put(TextAttribute.SIZE, size); |
265 | 266 | return f.deriveFont(attributes); |
266 | 267 | } |
267 | - | |
268 | + | |
268 | 269 | // フォントエイリアスの変更 |
269 | 270 | public static void setAAHint(Object o) { |
270 | 271 | frc = new FontRenderContext(null, o, RenderingHints.VALUE_FRACTIONALMETRICS_DEFAULT); |
271 | 272 | } |
272 | - | |
273 | - | |
273 | + | |
274 | + | |
274 | 275 | /******************************************************************************* |
275 | 276 | * メソッド |
276 | 277 | ******************************************************************************/ |
277 | - | |
278 | + | |
278 | 279 | /** |
279 | 280 | * ビットマップの描画処理 |
280 | 281 | */ |
281 | 282 | @Override |
282 | - protected void paintComponent(Graphics g) { | |
283 | - | |
283 | + protected void paintComponent(Graphics g) { | |
284 | + | |
284 | 285 | super.paintComponent(g); |
285 | - | |
286 | + | |
286 | 287 | // 初回描画時 |
287 | 288 | if (image == null) { |
288 | 289 | // |
@@ -295,12 +296,12 @@ public class JTXTButton extends JLabel { | ||
295 | 296 | |
296 | 297 | image = new BufferedImage(imgw, imgh, BufferedImage.TYPE_INT_ARGB); |
297 | 298 | Graphics2D g2 = (Graphics2D)image.createGraphics(); |
298 | - | |
299 | + | |
299 | 300 | g2.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_SPEED); |
300 | 301 | g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f)); |
301 | - | |
302 | + | |
302 | 303 | float baseline = 0.0F; |
303 | - | |
304 | + | |
304 | 305 | // 開始時刻と延長警告の描画 |
305 | 306 | if (showStart && tvd.start != null && tvd.start.length() > 0) { |
306 | 307 | FontMetrics fm = g2.getFontMetrics(startFont); |
@@ -310,31 +311,31 @@ public class JTXTButton extends JLabel { | ||
310 | 311 | float startx = Float.valueOf(DRAWTAB); |
311 | 312 | float startw = draww; |
312 | 313 | float xposstartx = 0.0F; |
313 | - | |
314 | - baseline = as; // 初期垂直位置 | |
315 | - | |
314 | + | |
315 | + baseline = as; // 初期垂直位置 | |
316 | + | |
316 | 317 | { |
317 | 318 | WrappedGlyphVector wgv = getWrappedGlyphVector(tvd.start, startw, xposstartx, startFont, as, frc); |
318 | 319 | GlyphVector gv = wgv.getGv(); |
319 | 320 | g2.setPaint(Color.BLACK); |
320 | 321 | g2.drawGlyphVector(gv, startx, baseline); |
321 | - | |
322 | + | |
322 | 323 | xposstartx = wgv.getLastX(); // 後続有り |
323 | 324 | baseline += wgv.getLastY(); |
324 | 325 | } |
325 | - | |
326 | + | |
326 | 327 | { |
327 | 328 | WrappedGlyphVector wgv = getWrappedGlyphVector(" "+tvd.extension_mark, startw, xposstartx, startFont, as, frc); |
328 | 329 | GlyphVector gv = wgv.getGv(); |
329 | 330 | g2.setPaint(Color.RED); |
330 | 331 | g2.drawGlyphVector(gv, startx, baseline); |
331 | - | |
332 | + | |
332 | 333 | baseline += wgv.getLastY(); |
333 | 334 | } |
334 | - | |
335 | + | |
335 | 336 | baseline += hi; |
336 | 337 | } |
337 | - | |
338 | + | |
338 | 339 | // タイトルの描画 |
339 | 340 | String title = ( splitEpno ) ? tvd.splitted_title : tvd.title; |
340 | 341 | if ( title.length() > 0 ) { |
@@ -351,19 +352,19 @@ public class JTXTButton extends JLabel { | ||
351 | 352 | aMark = tvd.prefix_mark + tvd.newlast_mark; |
352 | 353 | } |
353 | 354 | } |
354 | - | |
355 | + | |
355 | 356 | FontMetrics fm = g2.getFontMetrics(titleFont); |
356 | 357 | float hi = Float.valueOf(fm.getHeight()); |
357 | 358 | float as = Float.valueOf(fm.getAscent()); |
358 | - | |
359 | + | |
359 | 360 | float titlex = Float.valueOf(DRAWTAB); |
360 | 361 | float titlew = draww; |
361 | 362 | float xpos = 0.0F; |
362 | - | |
363 | + | |
363 | 364 | if ( baseline == 0.0F ) { |
364 | 365 | baseline = as; // 初期垂直位置 |
365 | 366 | } |
366 | - | |
367 | + | |
367 | 368 | if ( aMark.length() > 0 ) { |
368 | 369 | WrappedGlyphVector wgv = getWrappedGlyphVector(aMark, titlew, xpos, titleFont, as, frc); |
369 | 370 | GlyphVector gv = wgv.getGv(); |
@@ -373,20 +374,20 @@ public class JTXTButton extends JLabel { | ||
373 | 374 | xpos = wgv.getLastX(); // 後続有り |
374 | 375 | baseline += wgv.getLastY(); |
375 | 376 | } |
376 | - | |
377 | + | |
377 | 378 | { |
378 | 379 | WrappedGlyphVector wgv = getWrappedGlyphVector(title+tvd.postfix_mark, titlew, xpos, titleFont, as, frc); |
379 | 380 | GlyphVector gv = wgv.getGv(); |
380 | 381 | g2.setPaint(titleFontColor); |
381 | - | |
382 | + | |
382 | 383 | drawString(g2, wgv, titlex, baseline); |
383 | 384 | |
384 | 385 | baseline += wgv.getLastY(); |
385 | 386 | } |
386 | - | |
387 | + | |
387 | 388 | baseline += hi; |
388 | 389 | } |
389 | - | |
390 | + | |
390 | 391 | // 番組詳細の描画 |
391 | 392 | if ( showDetail ) { |
392 | 393 | String detail; |
@@ -417,35 +418,35 @@ public class JTXTButton extends JLabel { | ||
417 | 418 | float as = Float.valueOf(fm.getAscent()); |
418 | 419 | float detailx = Float.valueOf(DRAWTAB+detailTab); |
419 | 420 | float detailw = draww-detailTab; |
420 | - | |
421 | + | |
421 | 422 | if ( baseline == 0.0F ) { |
422 | 423 | baseline = as; // 初期垂直位置 |
423 | 424 | } |
424 | 425 | |
425 | 426 | WrappedGlyphVector wgv = getWrappedGlyphVector(detail, detailw, 0.0f, detailFont, as, frc); |
426 | 427 | g2.setPaint(detailFontColor); |
427 | - | |
428 | + | |
428 | 429 | drawString(g2, wgv, detailx, baseline); |
429 | 430 | } |
430 | 431 | } |
431 | - | |
432 | + | |
432 | 433 | // 反映 |
433 | 434 | g.drawImage(image, 0, 0, this); |
434 | 435 | } |
435 | - | |
436 | + | |
436 | 437 | /** |
437 | - * | |
438 | + * | |
438 | 439 | */ |
439 | 440 | private void drawString(Graphics2D g2, WrappedGlyphVector wgv, float x, float y) { |
440 | 441 | g2.drawGlyphVector(wgv.getGv(), x, y); |
441 | - | |
442 | + | |
442 | 443 | if ( wgv.getGv().getFont().getAttributes().get(TextAttribute.UNDERLINE) != null ) { |
443 | 444 | for ( Rectangle r : wgv.getLinePositions() ) { |
444 | 445 | g2.drawLine((int)x+r.x, (int)y+r.y+1, (int)x+r.x+r.width-1, (int)y+r.y+1); |
445 | 446 | } |
446 | 447 | } |
447 | 448 | } |
448 | - | |
449 | + | |
449 | 450 | /** |
450 | 451 | * 参考:てんぷらメモ/JTableのセル幅で文字列を折り返し ( http://terai.xrea.jp/Swing/TableCellRenderer.html ) |
451 | 452 | * @param str 描画する文字列 |
@@ -485,34 +486,60 @@ public class JTXTButton extends JLabel { | ||
485 | 486 | gmPos.setLocation(xpos, ypos); |
486 | 487 | gv.setGlyphPosition(i, gmPos); |
487 | 488 | xpos = xpos + advance; |
488 | - | |
489 | + | |
489 | 490 | wgv.setLastX(xpos); |
490 | 491 | wgv.setLastY(ypos); |
491 | 492 | } |
492 | 493 | return wgv; |
493 | 494 | } |
494 | - | |
495 | + | |
495 | 496 | private class WrappedGlyphVector { |
496 | - | |
497 | + | |
497 | 498 | public WrappedGlyphVector(GlyphVector gv) { |
498 | 499 | super(); |
499 | 500 | this.gv = gv; |
500 | 501 | } |
501 | - | |
502 | + | |
502 | 503 | private GlyphVector gv; |
503 | - | |
504 | + | |
504 | 505 | public GlyphVector getGv() { return gv; } |
505 | - | |
506 | + | |
506 | 507 | private float lastx; |
507 | 508 | private float lasty; |
508 | - | |
509 | + | |
509 | 510 | public void setLastX(float x) { lastx = x; } |
510 | 511 | public float getLastX() { return lastx; } |
511 | 512 | public void setLastY(float y) { lasty = y; } |
512 | 513 | public float getLastY() { return lasty; } |
513 | - | |
514 | + | |
514 | 515 | private ArrayList<Rectangle> linePositions = new ArrayList<Rectangle>(); |
515 | 516 | public ArrayList<Rectangle> getLinePositions() { return linePositions; } |
516 | 517 | public void addLinePosition(Rectangle r) { linePositions.add(r); } |
517 | 518 | } |
519 | + | |
520 | + @Override | |
521 | + public String getToolTipText(MouseEvent e){ | |
522 | + // ツールチップを付加する | |
523 | + if (! Env.TheEnv.getTooltipEnable() || tvd == null || tvd.title.isEmpty() || tvd.start.isEmpty()) | |
524 | + return null; | |
525 | + | |
526 | + int tlen = Bounds.TheBounds.getTooltipWidth()*15; | |
527 | + StringBuilder sb = new StringBuilder(""); | |
528 | + | |
529 | + sb.append("<html>"); | |
530 | + sb.append(tvd.start + "~" + tvd.end + " (" + tvd.recmin + "分)"); | |
531 | + sb.append(" <FONT COLOR=RED><EM>" + tvd.extension_mark + "</EM></FONT><BR>"); | |
532 | + | |
533 | + sb.append("<DIV width=\"" + String.valueOf(tlen+10) + "\"><STRONG><U><FONT COLOR=RED>"); | |
534 | + sb.append(tvd.prefix_mark); | |
535 | + sb.append("</FONT><FONT COLOR=BLUE>"); | |
536 | + sb.append(tvd.title + tvd.postfix_mark); | |
537 | + sb.append("</FONT></U></STRONG></DIV>"); | |
538 | + | |
539 | + sb.append("<DIV style=\"margin-left: 10px;\" width=\"" + String.valueOf(tlen) + "\">"); | |
540 | + sb.append(tvd.detail); | |
541 | + sb.append("</DIV></html>"); | |
542 | + | |
543 | + return sb.toString(); | |
544 | + } | |
518 | 545 | } |
@@ -1,5 +1,7 @@ | ||
1 | 1 | package tainavi; |
2 | 2 | |
3 | +import java.util.HashMap; | |
4 | + | |
3 | 5 | import tainavi.TVProgram.ProgFlags; |
4 | 6 | import tainavi.TVProgram.ProgOption; |
5 | 7 | import tainavi.TVProgram.ProgScrumble; |
@@ -36,13 +38,10 @@ public class MarkChar { | ||
36 | 38 | MULTIVOICE ( "[多]" ), |
37 | 39 | STANDIN ( "[吹]" ), |
38 | 40 | DATA ( "[デ]" ), |
39 | - SURROUND ( "[5.1]" ), | |
41 | + SURROUND ( "[SS]" ), | |
40 | 42 | PRECEDING ( "【先】" ), |
41 | 43 | |
42 | 44 | REPEATED ( "[再]" ), |
43 | - | |
44 | - BS4K ( "[4K]"), | |
45 | - BS8K ( "[8K]"), | |
46 | 45 | ; |
47 | 46 | |
48 | 47 | private String name; |
@@ -98,138 +97,50 @@ public class MarkChar { | ||
98 | 97 | * 普通のマークの取得 |
99 | 98 | */ |
100 | 99 | public String getOptionMark(ProgDetailList tvd) { |
101 | - | |
102 | - String mkNewArr = ""; | |
103 | - String mkModified = ""; | |
104 | - String mkNoscr = ""; | |
105 | - String mkSpecial = ""; | |
106 | - String mkNoSyobo = ""; | |
107 | - String mkRating = ""; | |
108 | - | |
109 | - String mkFirst = ""; | |
110 | - String mkLive = ""; | |
111 | - String mkSubtitle = ""; | |
112 | - String mkBilingual = ""; | |
113 | - String mkTextbc = ""; | |
114 | - String mkMultivoice = ""; | |
115 | - String mkStandin = ""; | |
116 | - String mkPv = ""; | |
117 | - String mkData = ""; | |
118 | - String mkSurround = ""; | |
119 | - String mkNonrepeated = ""; | |
120 | - String mkMoved = ""; | |
121 | - String mkPrec = ""; | |
122 | - String mk4k = ""; | |
123 | - String mk8k = ""; | |
124 | - | |
125 | - if (tvd.noscrumble == ProgScrumble.NOSCRUMBLE && env.getOptMarks().get(ProgOption.HIDDEN_NOSCRUMBLE) == Boolean.TRUE) { | |
126 | - mkNoscr = MarkItem.NOSCRUMBLE.getName(); | |
127 | - } | |
128 | - | |
129 | - if ( tvd.newarrival && env.getOptMarks().get(ProgOption.NEWARRIVAL) == Boolean.TRUE ) { | |
130 | - mkNewArr = ((env.getShortExtMark())?(MarkItem.NEWARRIVAL_S.getName()):(MarkItem.NEWARRIVAL.getName())); | |
131 | - } | |
132 | - if ( tvd.modified && env.getOptMarks().get(ProgOption.MODIFIED) == Boolean.TRUE ) { | |
133 | - mkModified = MarkItem.MODIFIED.getName(); | |
134 | - } | |
135 | - if ( tvd.nonrepeated && env.getOptMarks().get(ProgOption.NONREPEATED) == Boolean.TRUE ) { | |
136 | - mkNonrepeated = MarkItem.NONREPEATED.getName(); | |
137 | - } | |
138 | - for ( ProgOption opt : tvd.getOption() ) { | |
139 | - if ( env.getOptMarks().get(opt) != null && env.getOptMarks().get(opt) == Boolean.FALSE ) { | |
140 | - continue; | |
141 | - } | |
142 | - switch (opt) { | |
143 | - case SPECIAL: | |
144 | - // 特別番組 | |
145 | - mkSpecial = MarkItem.SPECIAL.getName(); | |
146 | - break; | |
147 | - case RATING: | |
148 | - // 視聴年齢制限 | |
149 | - mkRating = MarkItem.RATING.getName(); | |
150 | - break; | |
151 | - case FIRST: | |
152 | - // 初回放送 | |
153 | - mkFirst = MarkItem.FIRST.getName(); | |
154 | - break; | |
155 | - | |
156 | - case NOSYOBO: | |
157 | - mkNoSyobo = MarkItem.NOSYOBO.getName(); | |
158 | - break; | |
159 | - | |
160 | - case LIVE: | |
161 | - // 生放送 | |
162 | - mkLive = MarkItem.LIVE.getName(); | |
163 | - break; | |
164 | - case PV: | |
165 | - // ペイパービュー | |
166 | - mkPv = MarkItem.PV.getName(); | |
167 | - break; | |
168 | - case SUBTITLE: | |
169 | - // 字幕放送 | |
170 | - mkSubtitle = MarkItem.SUBTITLE.getName(); | |
171 | - break; | |
172 | - case BILINGUAL: | |
173 | - // 二か国語放送 | |
174 | - mkBilingual = MarkItem.BILINGUAL.getName(); | |
175 | - break; | |
176 | - case MULTIVOICE: | |
177 | - // 音声多重放送 | |
178 | - mkMultivoice = MarkItem.MULTIVOICE.getName(); | |
179 | - break; | |
180 | - case STANDIN: | |
181 | - // 吹き替え | |
182 | - mkStandin = MarkItem.STANDIN.getName(); | |
183 | - break; | |
184 | - case DATA: | |
185 | - // データ放送 | |
186 | - mkData = MarkItem.DATA.getName(); | |
187 | - break; | |
188 | - case SURROUND: | |
189 | - // 5.1chサラウンド | |
190 | - mkSurround = MarkItem.SURROUND.getName(); | |
191 | - break; | |
192 | - case MOVED: | |
193 | - // 先週無かったか時間が違う | |
194 | - mkMoved = MarkItem.MOVED.getName(); | |
195 | - break; | |
196 | - case PRECEDING: | |
197 | - // 先行放送 | |
198 | - mkPrec = MarkItem.PRECEDING.getName(); | |
199 | - break; | |
200 | - case BS4K: | |
201 | - mk4k = MarkItem.BS4K.getName(); | |
202 | - break; | |
203 | - case BS8K: | |
204 | - mk8k = MarkItem.BS8K.getName(); | |
205 | - break; | |
206 | - default: | |
207 | - break; | |
208 | - } | |
209 | - } | |
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); | |
100 | + return getOptionMark(tvd, env.getOptMarks()); | |
213 | 101 | } |
214 | 102 | |
215 | 103 | /** |
216 | 104 | * タイトルの後ろにつくマークの取得 |
217 | 105 | */ |
218 | 106 | public String getPostfixMark(ProgDetailList tvd) { |
107 | + return getOptionMark(tvd, env.getOptPostfixMarks()); | |
108 | + } | |
109 | + | |
110 | + /** | |
111 | + * 前後のマークの取得 | |
112 | + * | |
113 | + * @param tvd 番組詳細情報 | |
114 | + * @param options 表示オプション | |
115 | + * @return マーク | |
116 | + */ | |
117 | + public String getOptionMark(ProgDetailList tvd, HashMap<TVProgram.ProgOption,Boolean> options) { | |
118 | + | |
119 | + StringBuilder sb = new StringBuilder(""); | |
120 | + | |
121 | + if (tvd.noscrumble == ProgScrumble.NOSCRUMBLE && options.get(ProgOption.HIDDEN_NOSCRUMBLE) == Boolean.TRUE) { | |
122 | + sb.append(MarkItem.NOSCRUMBLE.getName()); | |
123 | + } | |
219 | 124 | |
220 | - String mkRep = ""; | |
125 | + if ( tvd.newarrival && options.get(ProgOption.NEWARRIVAL) == Boolean.TRUE ) { | |
126 | + sb.append(((env.getShortExtMark())?(MarkItem.NEWARRIVAL_S.getName()):(MarkItem.NEWARRIVAL.getName()))); | |
127 | + } | |
128 | + | |
129 | + if ( tvd.modified && options.get(ProgOption.MODIFIED) == Boolean.TRUE ) { | |
130 | + sb.append(MarkItem.MODIFIED.getName()); | |
131 | + } | |
132 | + if ( tvd.nonrepeated && options.get(ProgOption.NONREPEATED) == Boolean.TRUE ) { | |
133 | + sb.append(MarkItem.NONREPEATED.getName()); | |
134 | + } | |
221 | 135 | |
222 | 136 | for ( ProgOption opt : tvd.getOption() ) { |
223 | - switch (opt) { | |
224 | - case REPEAT: | |
225 | - mkRep = MarkItem.REPEATED.getName(); | |
226 | - break; | |
227 | - default: | |
228 | - break; | |
137 | + if ( options.get(opt) != null && options.get(opt) == Boolean.FALSE ) { | |
138 | + continue; | |
229 | 139 | } |
140 | + | |
141 | + sb.append(opt.getMark()); | |
230 | 142 | } |
231 | 143 | |
232 | - return(mkRep); | |
144 | + return sb.toString(); | |
233 | 145 | } |
234 | - | |
235 | 146 | } |
@@ -20,31 +20,76 @@ public interface TVProgram { | ||
20 | 20 | * NOSCRUMBLEは間違って(?)ProgScrumbleを使うこととなってしまったのだ。ここにあるのはマーク表示のための一覧用なのだ。 |
21 | 21 | */ |
22 | 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 | - NOOPTION | |
47 | - }; | |
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 ("[PV]", "ペイパービュー" ), | |
35 | + MULTIVOICE ("[多]", "音声多重放送" ), | |
36 | + DATA ("[デ]", "番組連動データ放送" ), | |
37 | + SURROUND ("[SS]", "サラウンドステレオ" ), | |
38 | + NEWARRIVAL ("[NEW]", "予約待機の新着" ), | |
39 | + MODIFIED ("(更)", "番組詳細に更新あり - 予約待機分のみ" ), | |
40 | + NONREPEATED ("[初]", "リピート放送の初回放送回" ), | |
41 | + MOVED ("(移)", "先週無かったか時間が違う" ), | |
42 | + PRECEDING ("【先】", "先行放送" ), | |
43 | + RATING ("[R]", "視聴制限あり" ), | |
44 | + | |
45 | + BS4K ("[4K]", "BS/CS 4K放送" ), | |
46 | + BS8K ("[8K]", "BS 8K放送"), | |
47 | + | |
48 | + NOOPTION ("", ""), | |
49 | + | |
50 | + BMODE ("[B]", "圧縮Bモードステレオ" ), | |
51 | + NEWS ("[N]", "ニュース" ), | |
52 | + PROGRESSIVE ("[P]", "プログレッシブ放送" ), | |
53 | + STEREO ("[S]", "ステレオ放送" ), | |
54 | + WIDE ("[W]", "ワイド放送" ), | |
55 | + HDTV ("[HV]", "HDTV" ), | |
56 | + MULTIVIEW ("[MV]", "マルチビューテレビ" ), | |
57 | + SDTV ("[SD]", "SDTV" ), | |
58 | + PPV ("[PPV]", "ペイパービュー" ), | |
59 | + SIGN ("[手]", "手話通訳放送" ), | |
60 | + TWOWAY ("[双]", "双方向放送" ), | |
61 | + COMMENTARY ("[解]", "音声解説" ), | |
62 | + WEATHER ("[天]", "天気予報" ), | |
63 | + TRAFFIC ("[交]", "交通情報" ), | |
64 | + MOVIE ("[映]", "劇映画" ), | |
65 | + FREE ("[無]", "無料放送" ), | |
66 | + PAY ("[料]", "有料放送"), | |
67 | + SHOPPING ("[販]", "通販" ), | |
68 | + SURROUND51 ("[5.1]", "5.1chサラウンド" ), | |
69 | + SURROUND222 ("[22.2]", "22.2chサラウンド" ), | |
70 | + HDR ("[HDR]", "ハイダイナミックレンジ" ), | |
71 | + ; | |
72 | + | |
73 | + String mark; | |
74 | + String desc; | |
75 | + | |
76 | + ProgOption(String m, String d){ | |
77 | + mark = m; | |
78 | + desc = d; | |
79 | + } | |
80 | + | |
81 | + public String getProgLabel(){ return mark + desc; } | |
82 | + public String getMark(){ return mark; } | |
83 | + | |
84 | + public static ProgOption GetProgOptionFromMark(String mark){ | |
85 | + for (ProgOption po : ProgOption.values()){ | |
86 | + if (po.getMark().equals(mark)) | |
87 | + return po; | |
88 | + } | |
89 | + | |
90 | + return null; | |
91 | + } | |
92 | + }; | |
48 | 93 | |
49 | 94 | public static enum ProgGenre { |
50 | 95 | NEWS ("ニュース/報道", "0"), |
@@ -293,29 +338,52 @@ public interface TVProgram { | ||
293 | 338 | }; |
294 | 339 | |
295 | 340 | public static final Object[][] optMarks = { |
296 | - { ProgOption.HIDDEN_NEW, "【新】新番組" }, | |
297 | - { ProgOption.HIDDEN_LAST, "【終】最終回" }, | |
298 | - { ProgOption.HIDDEN_NOSCRUMBLE, "【無料】無料放送" }, | |
299 | - { ProgOption.FIRST, "【初】初回放送" }, | |
300 | - { ProgOption.PRECEDING, "【先】先行放送" }, | |
301 | - { ProgOption.NONREPEATED, "[初]リピート放送の初回放送回" }, | |
341 | + { ProgOption.HIDDEN_NEW }, | |
342 | + { ProgOption.HIDDEN_LAST }, | |
343 | + { ProgOption.HIDDEN_NOSCRUMBLE }, | |
344 | + { ProgOption.FIRST }, | |
345 | + { ProgOption.PRECEDING }, | |
346 | + { ProgOption.NONREPEATED }, | |
302 | 347 | //{ false, ProgOption.REPEAT, "[再]再放送" }, |
303 | - { ProgOption.LIVE, "[生]生放送" }, | |
304 | - { ProgOption.SPECIAL, "[特]特番" }, | |
305 | - { ProgOption.RATING, "[R]視聴制限あり" }, | |
306 | - { ProgOption.SUBTITLE, "[字]文字多重放送" }, | |
307 | - { ProgOption.MULTIVOICE, "[多]音声多重放送" }, | |
308 | - { ProgOption.BILINGUAL, "[二]二か国語放送" }, | |
309 | - { ProgOption.STANDIN, "[吹]吹替放送" }, | |
310 | - { ProgOption.SURROUND, "[5.1]5.1chサラウンド" }, | |
311 | - { ProgOption.DATA, "[デ]データ放送" }, | |
312 | - { ProgOption.PV, "[PV]ペイパービュー" }, | |
313 | - { ProgOption.NOSYOBO, "[!]しょぼかる未定義" }, | |
314 | - { ProgOption.NEWARRIVAL, "[NEW]予約待機の新着" }, | |
315 | - { ProgOption.MODIFIED, "(更)番組詳細に更新あり - 予約待機分のみ" }, | |
316 | - { ProgOption.MOVED, "(移)先週無かったか時間が違う" }, | |
317 | - { ProgOption.BS4K, "[4K]BS/CS 4K放送"}, | |
318 | - { ProgOption.BS8K, "[8K]BS 8K放送"}, | |
348 | + { ProgOption.LIVE }, | |
349 | + { ProgOption.SPECIAL }, | |
350 | + { ProgOption.RATING }, | |
351 | + { ProgOption.SUBTITLE }, | |
352 | + { ProgOption.MULTIVOICE }, | |
353 | + { ProgOption.BILINGUAL }, | |
354 | + { ProgOption.STANDIN }, | |
355 | + { ProgOption.SURROUND }, | |
356 | + { ProgOption.DATA }, | |
357 | + { ProgOption.PV }, | |
358 | + { ProgOption.NOSYOBO }, | |
359 | + { ProgOption.NEWARRIVAL }, | |
360 | + { ProgOption.MODIFIED }, | |
361 | + { ProgOption.MOVED }, | |
362 | + { ProgOption.BS4K}, | |
363 | + { ProgOption.BS8K}, | |
364 | + | |
365 | + { ProgOption.REPEAT }, | |
366 | + { ProgOption.BMODE }, | |
367 | + { ProgOption.NEWS }, | |
368 | + { ProgOption.PROGRESSIVE }, | |
369 | + { ProgOption.STEREO }, | |
370 | + { ProgOption.WIDE }, | |
371 | + { ProgOption.HDTV }, | |
372 | + { ProgOption.MULTIVIEW }, | |
373 | + { ProgOption.SDTV }, | |
374 | + { ProgOption.PPV }, | |
375 | + { ProgOption.SIGN }, | |
376 | + { ProgOption.TWOWAY }, | |
377 | + { ProgOption.COMMENTARY } , | |
378 | + { ProgOption.WEATHER }, | |
379 | + { ProgOption.TRAFFIC }, | |
380 | + { ProgOption.MOVIE }, | |
381 | + { ProgOption.FREE }, | |
382 | + { ProgOption.PAY }, | |
383 | + { ProgOption.SHOPPING }, | |
384 | + { ProgOption.SURROUND51 }, | |
385 | + { ProgOption.SURROUND222 }, | |
386 | + { ProgOption.HDR }, | |
319 | 387 | }; |
320 | 388 | |
321 | 389 | public static final String[] OKINIIRI = {"★★★★★","★★★★","★★★","★★","★",""}; |
@@ -1047,49 +1047,48 @@ public class TVProgramUtils implements Cloneable { | ||
1047 | 1047 | /* |
1048 | 1048 | * UNIODEの番組記号のマッピング情報 |
1049 | 1049 | * |
1050 | - * 無視するオプション:S|N|B|映|双|解|手|天|英|日|録|HV | |
1051 | 1050 | */ |
1052 | 1051 | enum UnicodeCharMap{ |
1053 | - BS4K ("4K" ,0x0001F19E, ProgOption.BS4K), | |
1054 | - BS8K ("8K" ,0x0001F19F, ProgOption.BS8K), | |
1055 | - | |
1056 | - BMODE ("B" ,0x0001F131, ProgOption.NOOPTION), | |
1057 | - NEWS ("N" ,0x0001F13D, ProgOption.NOOPTION), | |
1058 | -// PROGRESSIVE ("P" ,0x0001F13F), | |
1059 | - STEREO ("S" ,0x0001F142, ProgOption.NOOPTION), | |
1060 | -// WIDE ("W" ,0x0001F146), | |
1061 | - HDTV ("HV" ,0x0001F14A, ProgOption.NOOPTION), | |
1062 | -// MULTIVIEW ("MV" ,0x0001F14B), | |
1063 | -// SDTV ("SD" ,0x0001F14C), | |
1052 | + BMODE ("B" ,0x0001F131, ProgOption.BMODE), | |
1053 | + NEWS ("N" ,0x0001F13D, ProgOption.NEWS), | |
1054 | + PROGRESSIVE ("P" ,0x0001F13F,ProgOption.PROGRESSIVE), | |
1055 | + STEREO ("S" ,0x0001F142, ProgOption.STEREO), | |
1056 | + WIDE ("W" ,0x0001F146, ProgOption.WIDE), | |
1057 | + HDTV ("HV" ,0x0001F14A, ProgOption.HDTV), | |
1058 | + MULTIVIEW ("MV" ,0x0001F14B, ProgOption.MULTIVIEW), | |
1059 | + SDTV ("SD" ,0x0001F14C, ProgOption.SDTV), | |
1064 | 1060 | SURROUND ("SS" ,0x0001F14D, ProgOption.SURROUND), |
1065 | -// PPV ("PPV" ,0x0001F14E), | |
1061 | + PPV ("PPV" ,0x0001F14E, ProgOption.PPV), | |
1066 | 1062 | |
1067 | - SIGN ("手" ,0x0001F210, ProgOption.NOOPTION), | |
1063 | + SIGN ("手" ,0x0001F210, ProgOption.SIGN), | |
1068 | 1064 | SUBTITLE ("字" ,0x0001F211, ProgOption.SUBTITLE), |
1069 | - TWOWAY ("双" ,0x0001F212, ProgOption.NOOPTION), | |
1065 | + TWOWAY ("双" ,0x0001F212, ProgOption.TWOWAY), | |
1070 | 1066 | DATA ("デ" ,0x0001F213, ProgOption.DATA), |
1071 | 1067 | BILINGUAL ("二" ,0x0001F214, ProgOption.BILINGUAL), |
1072 | - MULTIPLEX ("多" ,0x0001F215, ProgOption.MULTIVOICE), | |
1073 | - COMMENTARY ("解" ,0x0001F216, ProgOption.NOOPTION), | |
1074 | - WEATHER ("天" ,0x0001F217, ProgOption.NOOPTION), | |
1075 | -// TRAFFIC ("交" ,0x0001F218), | |
1076 | - MOVIE ("映" ,0x0001F219, ProgOption.NOOPTION), | |
1077 | - FREE ("無" ,0x0001F21A, ProgOption.NOOPTION), | |
1078 | - PAY ("料" ,0x0001F21B, ProgOption.PV), | |
1079 | -// FORMER ("前" ,0x0001F21C), | |
1080 | -// LATTER ("後" ,0x0001F21D), | |
1081 | - REAIR ("再" ,0x0001F21E, ProgOption.REPEAT), | |
1068 | + MULTIVOICE ("多" ,0x0001F215, ProgOption.MULTIVOICE), | |
1069 | + COMMENTARY ("解" ,0x0001F216, ProgOption.COMMENTARY), | |
1070 | + WEATHER ("天" ,0x0001F217, ProgOption.WEATHER), | |
1071 | + TRAFFIC ("交" ,0x0001F218, ProgOption.TRAFFIC), | |
1072 | + MOVIE ("映" ,0x0001F219, ProgOption.MOVIE), | |
1073 | + FREE ("無" ,0x0001F21A, ProgOption.FREE), | |
1074 | + PAY ("料" ,0x0001F21B, ProgOption.PAY), | |
1075 | + FORMER ("前" ,0x0001F21C, ProgOption.NOOPTION), | |
1076 | + LATTER ("後" ,0x0001F21D, ProgOption.NOOPTION), | |
1077 | + REPEAT ("再" ,0x0001F21E, ProgOption.REPEAT), | |
1082 | 1078 | NEW ("新" ,0x0001F21F, ProgOption.NOOPTION), |
1083 | 1079 | FIRST ("初" ,0x0001F220, ProgOption.FIRST), |
1084 | 1080 | END ("終" ,0x0001F221, ProgOption.NOOPTION), |
1085 | 1081 | LIVE ("生" ,0x0001F222, ProgOption.LIVE), |
1086 | -// SHOPPING ("販" ,0x0001F223), | |
1087 | -// VOICE ("声" ,0x0001F224), | |
1088 | - DUBBED ("吹" ,0x0001F225, ProgOption.STANDIN), | |
1082 | + SHOPPING ("販" ,0x0001F223, ProgOption.SHOPPING), | |
1083 | + VOICE ("声" ,0x0001F224, ProgOption.NOOPTION), | |
1084 | + STANDIN ("吹" ,0x0001F225, ProgOption.STANDIN), | |
1089 | 1085 | |
1090 | - SURROUND51 ("5.1" ,0x0001F1A0, ProgOption.NOOPTION), | |
1091 | - SURROUND222 ("22.2" ,0x0001F1A2, ProgOption.NOOPTION), | |
1092 | - HDR ("HDR" ,0x0001F1A7, ProgOption.NOOPTION), | |
1086 | + // テレビ王国の独自コード | |
1087 | + BS4K ("4K" ,0x0001F19E, ProgOption.BS4K), | |
1088 | + BS8K ("8K" ,0x0001F19F, ProgOption.BS8K), | |
1089 | + SURROUND51 ("5.1" ,0x0001F1A0, ProgOption.SURROUND51), | |
1090 | + SURROUND222 ("22.2" ,0x0001F1A2, ProgOption.SURROUND222), | |
1091 | + HDR ("HDR" ,0x0001F1A7, ProgOption.HDR), | |
1093 | 1092 | ; |
1094 | 1093 | |
1095 | 1094 | String label; // ラベル |
@@ -1109,12 +1108,9 @@ public class TVProgramUtils implements Cloneable { | ||
1109 | 1108 | progOption = po; |
1110 | 1109 | } |
1111 | 1110 | |
1112 | - /** | |
1113 | - * ラベルを取得する | |
1114 | - * | |
1115 | - * @return ラベル | |
1116 | - */ | |
1117 | 1111 | public String getLabel(){ return label; } |
1112 | + public String getCode(){ return cp2s(codePoint); } | |
1113 | + public ProgOption getProgOption(){ return progOption; } | |
1118 | 1114 | |
1119 | 1115 | /** |
1120 | 1116 | * 指定した文字列で検索する |
@@ -1145,10 +1141,44 @@ public class TVProgramUtils implements Cloneable { | ||
1145 | 1141 | * |
1146 | 1142 | * @param pdl 番組情報 |
1147 | 1143 | */ |
1144 | + private static String codeList = null; | |
1148 | 1145 | public static void ExtractAllSymbols(ProgDetailList pdl){ |
1146 | + if (codeList == null){ | |
1147 | + StringBuilder sb = new StringBuilder(""); | |
1148 | + for (UnicodeCharMap chm : UnicodeCharMap.values()){ | |
1149 | + sb.append(chm.getCode()); | |
1150 | + } | |
1151 | + | |
1152 | + codeList = sb.toString(); | |
1153 | + } | |
1154 | + | |
1155 | + Matcher md = Pattern.compile("[" + codeList + "]").matcher(pdl.title); | |
1156 | + boolean found = false; | |
1157 | + while (md.find()){ | |
1158 | + UnicodeCharMap chm = getMapFromCode(md.group()); | |
1159 | + if (chm != null && chm.getProgOption() != ProgOption.NOOPTION) | |
1160 | + pdl.addOption(chm.getProgOption()); | |
1161 | + found = true; | |
1162 | + } | |
1163 | + | |
1164 | + if (found) | |
1165 | + pdl.title = md.replaceAll(""); | |
1166 | + } | |
1167 | + | |
1168 | + /** | |
1169 | + * 文字コードからマップ情報を取得する | |
1170 | + * | |
1171 | + * @param code 文字コード | |
1172 | + * @return マップ情報 | |
1173 | + */ | |
1174 | + public static UnicodeCharMap getMapFromCode(String code){ | |
1149 | 1175 | for (UnicodeCharMap chm : UnicodeCharMap.values()){ |
1150 | - chm.extractSymbol(pdl); | |
1176 | + if (code.equals(chm.getCode())){ | |
1177 | + return chm; | |
1178 | + } | |
1151 | 1179 | } |
1180 | + | |
1181 | + return null; | |
1152 | 1182 | } |
1153 | 1183 | } |
1154 | 1184 |
@@ -1184,6 +1214,7 @@ public class TVProgramUtils implements Cloneable { | ||
1184 | 1214 | * タイトルからフラグを抽出する |
1185 | 1215 | */ |
1186 | 1216 | protected void doSplitFlags(ProgDetailList pdl, HashMap<String, String> nf) { |
1217 | + // テレビ王国のUNICODE記号を抽出する | |
1187 | 1218 | ExtractAllUnicodeSymbols(pdl); |
1188 | 1219 | |
1189 | 1220 | Matcher md = Pattern.compile("(#1|第1話)\\b").matcher(pdl.title); |
@@ -1233,78 +1264,60 @@ public class TVProgramUtils implements Cloneable { | ||
1233 | 1264 | |
1234 | 1265 | HashMap<String, String> xf = new HashMap<String, String>(); |
1235 | 1266 | |
1236 | - String flagExpr = "[\\[[((【](.{1,3})[\\]]))】]"; | |
1267 | + String flagExpr = "[\\[[((【]([^\\]]))】]{1,4})[\\]]))】]"; | |
1237 | 1268 | Matcher mx = Pattern.compile(flagExpr).matcher(pdl.title); |
1238 | 1269 | while (mx.find()) { |
1239 | - if (mx.group(1).equals("新") || mx.group(1).equals("新番組")) { | |
1270 | + String mark = mx.group(1); | |
1271 | + ProgOption po = ProgOption.GetProgOptionFromMark("[" + mark + "]"); | |
1272 | + | |
1273 | + if (mark.equals("新") || mark.equals("新番組")) { | |
1240 | 1274 | pdl.flag = ProgFlags.NEW; |
1241 | 1275 | } |
1242 | - else if (mx.group(1).equals("終") || mx.group(1).equals("完") || mx.group(1).equals("最終回")) { | |
1276 | + else if (mark.equals("終") || mark.equals("完") || mark.equals("最終回")) { | |
1243 | 1277 | pdl.flag = ProgFlags.LAST; |
1244 | 1278 | } |
1245 | - else if (mx.group(1).equals("再")) { | |
1279 | + else if (mark.equals("再")) { | |
1246 | 1280 | pdl.addOption(ProgOption.REPEAT); |
1247 | 1281 | } |
1248 | - else if (mx.group(1).equals("初")) { | |
1282 | + else if (mark.equals("初")) { | |
1249 | 1283 | pdl.addOption(ProgOption.FIRST); |
1250 | 1284 | } |
1251 | - else if (mx.group(1).equals("生")) { | |
1252 | - pdl.addOption(ProgOption.LIVE); | |
1285 | + else if (mark.equals("無") || mark.equals("無料")) { | |
1286 | + //pdl.addOption(ProgOption.NOSCRUMBLE); | |
1287 | + pdl.noscrumble = ProgScrumble.NOSCRUMBLE; | |
1253 | 1288 | } |
1254 | - | |
1255 | - else if (mx.group(1).equals("二/吹")) { | |
1289 | + else if (mark.equals("二/吹")) { | |
1256 | 1290 | pdl.addOption(ProgOption.BILINGUAL); |
1257 | 1291 | pdl.addOption(ProgOption.STANDIN); |
1258 | 1292 | } |
1259 | - else if (mx.group(1).equals("字") || mx.group(1).equals("字幕") || mx.group(1).equals("字幕版")) { | |
1293 | + else if (mark.equals("字幕") || mark.equals("字幕版")) { | |
1260 | 1294 | pdl.addOption(ProgOption.SUBTITLE); |
1261 | 1295 | } |
1262 | - else if (mx.group(1).equals("二")) { | |
1263 | - pdl.addOption(ProgOption.BILINGUAL); | |
1264 | - } | |
1265 | - else if (mx.group(1).equals("多")) { | |
1266 | - pdl.addOption(ProgOption.MULTIVOICE); | |
1267 | - } | |
1268 | - else if (mx.group(1).equals("SS") || mx.group(1).equals("5.1")) { | |
1269 | - pdl.addOption(ProgOption.SURROUND); | |
1270 | - } | |
1271 | - else if (mx.group(1).equals("吹") || mx.group(1).equals("吹替") || mx.group(1).equals("吹替版")) { | |
1296 | + else if (mark.equals("吹替") || mark.equals("吹替版")) { | |
1272 | 1297 | pdl.addOption(ProgOption.STANDIN); // (ないよ) |
1273 | 1298 | } |
1274 | - else if (mx.group(1).equals("デ")) { | |
1275 | - pdl.addOption(ProgOption.DATA); | |
1276 | - } | |
1277 | - else if (mx.group(1).equals("無") || mx.group(1).equals("無料")) { | |
1278 | - //pdl.addOption(ProgOption.NOSCRUMBLE); | |
1279 | - pdl.noscrumble = ProgScrumble.NOSCRUMBLE; | |
1280 | - } | |
1281 | - else if (mx.group(1).equals("4K")) { | |
1282 | - pdl.addOption(ProgOption.BS4K); | |
1283 | - } | |
1284 | - else if (mx.group(1).equals("8K")) { | |
1285 | - pdl.addOption(ProgOption.BS8K); | |
1286 | - } | |
1287 | - | |
1288 | - else if (mx.group(1).matches("^(S|N|B|映|双|解|手|天|英|日|録|HV)$")) { | |
1299 | + else if (po != null && po != ProgOption.NOOPTION) | |
1300 | + pdl.addOption(po); | |
1301 | + else if (mark.matches("^(S|N|B|映|双|解|手|天|英|日|録|HV)$")) { | |
1289 | 1302 | // 無視するフラグ |
1290 | - if ( mx.group(1).equals("日") && ( ! pdl.title.matches(String.format("^(%s)*[((]日[))].*", flagExpr)) && ! pdl.title.matches(".*[\\[[]日[\\]]].*")) ) { | |
1303 | + if ( mark.equals("日") && ( ! pdl.title.matches(String.format("^(%s)*[((]日[))].*", flagExpr)) && ! pdl.title.matches(".*[\\[[]日[\\]]].*")) ) { | |
1291 | 1304 | // 削除しないフラグ(特殊) |
1292 | 1305 | continue; |
1293 | 1306 | } |
1294 | 1307 | } |
1295 | - else if (mx.group(1).matches("^(韓|仮|[前後][編篇半]|[月火水木金土]|[0-90-9]+)$")) { | |
1308 | + else if (mark.matches("^(韓|仮|[前後][編篇半]|[月火水木金土]|[0-90-9]+)$")) { | |
1296 | 1309 | // 削除しないフラグ |
1297 | 1310 | continue; |
1298 | 1311 | } |
1299 | 1312 | |
1300 | 1313 | else { |
1301 | 1314 | // 未知のフラグ |
1302 | - nf.put(mx.group(1),null); | |
1315 | + nf.put(mark, null); | |
1303 | 1316 | continue; |
1304 | 1317 | } |
1305 | 1318 | |
1306 | 1319 | // 削除するフラグ |
1307 | - xf.put(mx.group(1), null); | |
1320 | + xf.put(mark, null); | |
1308 | 1321 | } |
1309 | 1322 | { |
1310 | 1323 | // 認識されたフラグだけ削除する. |
@@ -5,7 +5,7 @@ import java.util.regex.Pattern; | ||
5 | 5 | |
6 | 6 | |
7 | 7 | public class VersionInfo { |
8 | - private static final String Version = "タイニー番組ナビゲータ for DBR-T2007 3.22.18β+1.13.2"; | |
8 | + private static final String Version = "タイニー番組ナビゲータ for DBR-T2007 3.22.18β+1.13.3"; | |
9 | 9 | |
10 | 10 | private static final String OSname = System.getProperty("os.name"); |
11 | 11 | private static final String OSvers = System.getProperty("os.version"); |
@@ -114,7 +114,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H | ||
114 | 114 | |
115 | 115 | // 設定値をいれるところ |
116 | 116 | private final Env env = Env.TheEnv = new Env(); // 主要な設定 |
117 | - private final Bounds bounds = new Bounds(); // ウィンドウサイズとか動的に変化するもの | |
117 | + private final Bounds bounds = Bounds.TheBounds = new Bounds(); // ウィンドウサイズとか動的に変化するもの | |
118 | 118 | private final ClipboardInfoList cbitems = new ClipboardInfoList(); // クリップボード対応機能でどの項目をコピーするかとかの設定 |
119 | 119 | private final ListedColumnInfoList lvitems = new ListedColumnInfoList(); // リスト形式ビューの表示項目 |
120 | 120 | private final ReserveListColumnInfoList rlitems = new ReserveListColumnInfoList(); |
@@ -2746,13 +2746,20 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H | ||
2746 | 2746 | for (final TextValueSet tv : env.getTvCommand()) { |
2747 | 2747 | JMenuItem menuItem = new JMenuItem(tv.getText()); |
2748 | 2748 | |
2749 | + String body = ""; | |
2750 | + Matcher ma = Pattern.compile("^(.*)[ ]").matcher(tvd.title); | |
2751 | + if (ma.find()) | |
2752 | + body = ma.group(1); | |
2753 | + | |
2749 | 2754 | String escepedTitle = ""; |
2750 | 2755 | String escepedChName = ""; |
2751 | 2756 | String escepedDetail = ""; |
2757 | + String escepedBody = ""; | |
2752 | 2758 | try { |
2753 | 2759 | escepedTitle = URLEncoder.encode(tvd.title,"UTF-8"); |
2754 | 2760 | escepedDetail = URLEncoder.encode(tvd.detail,"UTF-8"); |
2755 | 2761 | escepedChName = URLEncoder.encode(tvd.center,"UTF-8"); |
2762 | + escepedBody = URLEncoder.encode(body,"UTF-8"); | |
2756 | 2763 | } catch (UnsupportedEncodingException e2) { |
2757 | 2764 | // |
2758 | 2765 | } |
@@ -2776,6 +2783,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H | ||
2776 | 2783 | cmd = cmd.replaceAll("%END%", tvd.end); |
2777 | 2784 | cmd = cmd.replaceAll("%DETAILURL%", tvd.link); |
2778 | 2785 | cmd = cmd.replaceAll("%SYOBODETAILURL%", tvd.linkSyobo != null ? tvd.linkSyobo : ""); |
2786 | + cmd = cmd.replaceAll("%ENCBODY%", escepedBody); | |
2779 | 2787 | |
2780 | 2788 | // CHAN-TORU対応 |
2781 | 2789 | if ( cmd.matches(".*%TVKAREACODE%.*") && cmd.matches(".*%TVKPID%.*") ) { |
@@ -4942,6 +4950,8 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H | ||
4942 | 4950 | if ( reload_prog ) { |
4943 | 4951 | loadTVProgram(false, LoadFor.ALL, false); // 部品呼び出し |
4944 | 4952 | } |
4953 | + else | |
4954 | + loadTVProgramPostProcess(false); | |
4945 | 4955 | |
4946 | 4956 | // Web番組表の再構築 |
4947 | 4957 | mpList.setHistoryOnlyUpdateOnce(env.getHistoryOnlyUpdateOnce()); |