3 import java.awt.BorderLayout;
\r
4 import java.awt.Color;
\r
5 import java.awt.Component;
\r
6 import java.awt.Dimension;
\r
7 import java.awt.event.ComponentAdapter;
\r
8 import java.awt.event.ComponentEvent;
\r
9 import java.util.ArrayList;
\r
10 import java.util.Comparator;
\r
11 import java.util.HashMap;
\r
13 import javax.swing.JPanel;
\r
14 import javax.swing.JScrollPane;
\r
15 import javax.swing.JTable;
\r
16 import javax.swing.event.ListSelectionEvent;
\r
17 import javax.swing.event.ListSelectionListener;
\r
18 import javax.swing.event.TableModelEvent;
\r
19 import javax.swing.table.DefaultTableColumnModel;
\r
20 import javax.swing.table.DefaultTableModel;
\r
21 import javax.swing.table.TableCellRenderer;
\r
22 import javax.swing.table.TableColumn;
\r
23 import javax.swing.table.TableModel;
\r
24 import javax.swing.table.TableRowSorter;
\r
30 public abstract class AbsRecordedListView extends JPanel {
\r
32 private static final long serialVersionUID = 1L;
\r
34 public static void setDebug(boolean b) {debug = b; }
\r
35 private static boolean debug = false;
\r
38 /*******************************************************************************
\r
40 ******************************************************************************/
\r
42 protected abstract Env getEnv();
\r
43 protected abstract Bounds getBoundsEnv();
\r
45 protected abstract HDDRecorderList getRecorderList();
\r
47 //protected abstract StatusWindow getStWin();
\r
48 //protected abstract StatusTextArea getMWin();
\r
49 //protected abstract AbsReserveDialog getReserveDialog();
\r
51 protected abstract Component getParentComponent();
\r
53 protected abstract void ringBeep();
\r
56 * @see Viewer.VWToolBar#getSelectedRecorder()
\r
58 protected abstract String getSelectedRecorderOnToolbar();
\r
61 /*******************************************************************************
\r
63 ******************************************************************************/
\r
65 private static final String MSGID = "[録画結果一覧] ";
\r
66 private static final String ERRID = "[ERROR]"+MSGID;
\r
67 private static final String DBGID = "[DEBUG]"+MSGID;
\r
70 /*******************************************************************************
\r
72 ******************************************************************************/
\r
75 private final Env env = getEnv();
\r
76 private final Bounds bounds = getBoundsEnv();
\r
77 private final HDDRecorderList recorders = getRecorderList();
\r
79 //private final StatusWindow StWin = getStWin(); // これは起動時に作成されたまま変更されないオブジェクト
\r
80 //private final StatusTextArea MWin = getMWin(); // これは起動時に作成されたまま変更されないオブジェクト
\r
82 private final Component parent = getParentComponent(); // これは起動時に作成されたまま変更されないオブジェクト
\r
85 //private void StdAppendMessage(String message) { System.out.println(message); }
\r
86 //private void StdAppendError(String message) { System.err.println(message); }
\r
87 //private void StWinSetVisible(boolean b) { StWin.setVisible(b); }
\r
88 //private void StWinSetLocationCenter(Component frame) { CommonSwingUtils.setLocationCenter(frame, (VWStatusWindow)StWin); }
\r
94 public static HashMap<String,Integer> getColumnIniWidthMap() {
\r
95 if (rcmap.size() == 0 ) {
\r
96 for ( RecedColumn rc : RecedColumn.values() ) {
\r
97 rcmap.put(rc.toString(),rc.getIniWidth()); // toString()!
\r
103 private static final HashMap<String,Integer> rcmap = new HashMap<String, Integer>();
\r
105 public static enum RecedColumn {
\r
110 DROPMPEG ("MPEG", 50),
\r
111 TITLE ("番組タイトル", 300),
\r
112 CHNAME ("チャンネル名", 150),
\r
113 RESULT ("録画結果", 200),
\r
114 RECORDER ("レコーダ", 200),
\r
117 private String name;
\r
118 private int iniWidth;
\r
120 private RecedColumn(String name, int iniWidth) {
\r
122 this.iniWidth = iniWidth;
\r
125 public String getName() {
\r
129 public int getIniWidth() {
\r
133 public int getColumn() {
\r
139 /*******************************************************************************
\r
141 ******************************************************************************/
\r
143 private class RecordedItem extends RowItem implements Cloneable {
\r
145 String start; // YYYY/MM/DD(WD) hh:mm
\r
146 String end; // hh:mm
\r
155 String hide_detail;
\r
156 Boolean hide_succeeded;
\r
159 protected void myrefresh(RowItem o) {
\r
160 RecordedItem c = (RecordedItem) o;
\r
166 c.addData(dropmpeg);
\r
170 c.addData(recorder);
\r
173 public RecordedItem clone() {
\r
174 return (RecordedItem) super.clone();
\r
178 // ソートが必要な場合はTableModelを作る。ただし、その場合Viewのrowがわからないので行の入れ替えが行えない
\r
179 private class ReservedTableModel extends DefaultTableModel {
\r
181 private static final long serialVersionUID = 1L;
\r
184 public Object getValueAt(int row, int column) {
\r
185 RecordedItem c = rowView.get(row);
\r
186 if ( c.getColumnCount() > column ) {
\r
187 if ( column == RecedColumn.LENGTH.getColumn() ) {
\r
188 return String.valueOf(c.length)+"m";
\r
190 return c.get(column);
\r
196 public int getRowCount() {
\r
197 return rowView.size();
\r
200 public ReservedTableModel(String[] colname, int i) {
\r
206 //private final RecordedItem sa = new RecordedItem();
\r
208 private JScrollPane jsc_list = null;
\r
209 private JScrollPane jsc_detail = null;
\r
210 private JTextAreaWithPopup jta_detail = null;
\r
211 private JNETable jTable_reced = null;
\r
212 private JTable jTable_rowheader = null;
\r
214 private DefaultTableModel tableModel_reced = null;
\r
216 private DefaultTableModel rowheaderModel_reced = null;
\r
219 private final RowItemList<RecordedItem> rowView = new RowItemList<RecordedItem>();
\r
222 private final RowItemList<RecordedItem> rowData = new RowItemList<RecordedItem>();
\r
224 /*******************************************************************************
\r
226 ******************************************************************************/
\r
228 public AbsRecordedListView() {
\r
232 this.setLayout(new BorderLayout());
\r
233 this.add(getJScrollPane_list(), BorderLayout.CENTER);
\r
234 this.add(getJTextPane_detail(), BorderLayout.PAGE_END);
\r
238 if ( bounds.getRecordedColumnSize() == null ) {
\r
239 System.err.println(ERRID+"なんらかの不具合によりテーブルのカラム幅設定が取得できませんでした。設定はリセットされました。申し訳ありません。");
\r
240 bounds.setRecordedColumnSize(rcmap);
\r
243 for ( Entry<String, Integer> en : rcmap.entrySet() ) {
\r
245 bounds.getListedColumnSize().get(en.getKey());
\r
247 catch (NullPointerException e) {
\r
248 System.err.println(ERRID+en.getKey()+", "+e.toString());
\r
249 bounds.getListedColumnSize().put(en.getKey(),en.getValue());
\r
257 this.addComponentListener(cl_tabShown);
\r
260 /*******************************************************************************
\r
262 ******************************************************************************/
\r
268 * ★synchronized(rowData)★
\r
269 * @see #cl_tabShown
\r
271 public void redrawRecordedList() {
\r
272 // ★★★ イベントにトリガーされた処理がかちあわないように synchronized() ★★★
\r
273 synchronized ( rowView ) {
\r
274 _redrawRecordedList();
\r
278 private void _redrawRecordedList() {
\r
283 String myself = getSelectedRecorderOnToolbar();
\r
284 HDDRecorderList recs = recorders.findInstance(myself);
\r
286 for ( HDDRecorder recorder : recs )
\r
288 if ( recorder.isBackgroundOnly() ) {
\r
292 // 並べ替えるために新しいリストを作成する
\r
293 for ( RecordedInfo ro : recorder.getRecorded() ) {
\r
295 RecordedItem sa = new RecordedItem();
\r
297 sa.start = ro.getDate()+" "+ro.getAhh()+":"+ro.getAmm(); // YYYY/MM/DD(WD) hh:mm
\r
298 sa.end = ro.getZhh()+":"+ro.getZmm();
\r
299 sa.length = ro.getLength();
\r
300 sa.drop = ro.getDrop();
\r
301 sa.dropmpeg = ro.getDrop_mpeg();
\r
302 sa.title = ro.getTitle();
\r
303 sa.chname = ro.getCh_name();
\r
304 sa.result = ro.getResult();
\r
305 sa.recorder = recorder.Myself();
\r
307 sa.hide_detail = ro.getDetail();
\r
308 sa.hide_succeeded = ro.getSucceeded();
\r
318 for ( RecordedItem a : rowData ) {
\r
322 tableModel_reced.fireTableDataChanged();
\r
323 ((DefaultTableModel)jTable_rowheader.getModel()).fireTableDataChanged();
\r
325 jta_detail.setText(null);
\r
327 //jta_detail.setText("レコーダから予約結果の一覧を取得して表示します。現在の対応レコーダはTvRock/EpgDataCap_Bonのみです。");
\r
332 * 絞り込み検索の本体(現在リストアップされているものから絞り込みを行う)(親から呼ばれるよ!)
\r
334 public void redrawListByKeywordFilter(SearchKey keyword, String target) {
\r
339 if ( keyword != null ) {
\r
340 for ( RecordedItem a : rowData ) {
\r
342 ProgDetailList tvd = new ProgDetailList();
\r
343 tvd.title = a.title;
\r
344 tvd.titlePop = TraceProgram.replacePop(tvd.title);
\r
347 boolean isFind = SearchProgram.isMatchKeyword(keyword, "", tvd);
\r
355 for ( RecordedItem a : rowData ) {
\r
361 tableModel_reced.fireTableDataChanged();
\r
362 rowheaderModel_reced.fireTableDataChanged();
\r
366 * カラム幅を保存する(鯛ナビ終了時に呼び出されるメソッド)
\r
368 public void copyColumnWidth() {
\r
369 DefaultTableColumnModel columnModel = (DefaultTableColumnModel)jTable_reced.getColumnModel();
\r
370 TableColumn column = null;
\r
371 for ( RecedColumn rc : RecedColumn.values() ) {
\r
372 if ( rc.getIniWidth() < 0 ) {
\r
375 column = columnModel.getColumn(rc.ordinal());
\r
376 //bounds.getRecordedColumnSize().put(rc.toString(), column.getPreferredWidth());
\r
381 * テーブルの行番号の表示のON/OFF
\r
383 public void setRowHeaderVisible(boolean b) {
\r
384 jsc_list.getRowHeader().setVisible(b);
\r
392 private void addRow(RecordedItem data) {
\r
395 for ( ; n<rowData.size(); n++ ) {
\r
396 RecordedItem c = rowData.get(n);
\r
397 if ( c.start.compareTo(data.start) < 0 ) {
\r
401 rowData.add(n,data);
\r
404 /*******************************************************************************
\r
406 ******************************************************************************/
\r
410 * ★synchronized(rowData)★
\r
411 * @see #redrawRecordedList()
\r
413 private final ComponentAdapter cl_tabShown = new ComponentAdapter() {
\r
415 public void componentShown(ComponentEvent e) {
\r
416 // ★★★ イベントにトリガーされた処理がかちあわないように synchronized() ★★★
\r
417 synchronized ( rowView ) {
\r
418 _redrawRecordedList();
\r
424 * 行を選択すると詳細が表示されるようにする
\r
426 private final ListSelectionListener lsSelectListner = new ListSelectionListener() {
\r
428 public void valueChanged(ListSelectionEvent e) {
\r
429 if(e.getValueIsAdjusting()) return;
\r
430 if (jTable_reced.getSelectedRow() >= 0) {
\r
431 int row = jTable_reced.convertRowIndexToModel(jTable_reced.getSelectedRow());
\r
432 RecordedItem c = rowView.get(row);
\r
433 jta_detail.setText(c.hide_detail);
\r
434 jta_detail.setCaretPosition(0);
\r
439 /*******************************************************************************
\r
441 ******************************************************************************/
\r
443 private JScrollPane getJScrollPane_list() {
\r
445 if ( jsc_list == null ) {
\r
446 jsc_list = new JScrollPane();
\r
448 jsc_list.setRowHeaderView(jTable_rowheader = new JTableRowHeader(rowView));
\r
449 jsc_list.setViewportView(getNETable_reced());
\r
451 Dimension d = new Dimension(jTable_rowheader.getPreferredSize().width,0);
\r
452 jsc_list.getRowHeader().setPreferredSize(d);
\r
454 this.setRowHeaderVisible(env.getRowHeaderVisible());
\r
460 private JScrollPane getJTextPane_detail() {
\r
461 if ( jsc_detail == null ) {
\r
462 jsc_detail = new JScrollPane(jta_detail = new JTextAreaWithPopup(),JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
\r
463 jta_detail.setRows(8);
\r
464 jta_detail.setEditable(false);
\r
465 jta_detail.setBackground(Color.LIGHT_GRAY);
\r
470 private JNETable getNETable_reced() {
\r
471 if (jTable_reced == null) {
\r
473 ArrayList<String> cola = new ArrayList<String>();
\r
474 for ( RecedColumn rc : RecedColumn.values() ) {
\r
475 if ( rc.getIniWidth() >= 0 ) {
\r
476 cola.add(rc.getName());
\r
479 String[] colname = cola.toArray(new String[0]);
\r
481 tableModel_reced = new ReservedTableModel(colname, 0);
\r
482 jTable_reced = new JNETableRecorded(tableModel_reced, false);
\r
483 jTable_reced.setAutoResizeMode(JNETable.AUTO_RESIZE_OFF);
\r
486 rowheaderModel_reced = (DefaultTableModel) jTable_rowheader.getModel();
\r
489 TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(tableModel_reced);
\r
490 jTable_reced.setRowSorter(sorter);
\r
492 // 数値でソートする項目用の計算式(番組長とか)
\r
493 final Comparator<String> titlecomp = new Comparator<String>() {
\r
496 public int compare(String o1, String o2) {
\r
497 String t1 = TraceProgram.replacePop(o1.replaceAll(TVProgram.titlePrefixRemoveExpr, "")).replaceFirst(TVProgram.epnoNormalizeExpr, "$1\\0$2");
\r
498 String t2 = TraceProgram.replacePop(o2.replaceAll(TVProgram.titlePrefixRemoveExpr, "")).replaceFirst(TVProgram.epnoNormalizeExpr, "$1\\0$2");
\r
499 return t1.compareTo(t2);
\r
503 // ソーターの効かない項目用の計算式(重複マーク)
\r
504 final Comparator<String> noncomp = new Comparator<String>() {
\r
506 public int compare(String o1, String o2) {
\r
511 sorter.setComparator(jTable_reced.getColumn(RecedColumn.TITLE.getName()).getModelIndex(),titlecomp);
\r
512 sorter.setComparator(jTable_reced.getColumn(RecedColumn.END.getName()).getModelIndex(),noncomp);
\r
515 DefaultTableColumnModel columnModel = (DefaultTableColumnModel)jTable_reced.getColumnModel();
\r
516 TableColumn column = null;
\r
517 for ( RecedColumn rc : RecedColumn.values() ) {
\r
518 if ( rc.getIniWidth() < 0 ) {
\r
521 column = columnModel.getColumn(rc.ordinal());
\r
522 //column.setPreferredWidth(bounds.getRecordedColumnSize().get(rc.toString()));
\r
523 column.setPreferredWidth(rc.getIniWidth());
\r
527 jTable_reced.getSelectionModel().addListSelectionListener(lsSelectListner);
\r
529 return jTable_reced;
\r
535 /*******************************************************************************
\r
537 ******************************************************************************/
\r
539 private class JNETableRecorded extends JNETable {
\r
541 private static final long serialVersionUID = 1L;
\r
543 private Color failedColor = new Color(255,255,0);
\r
544 private Color dropMpegColor = new Color(255,0,0);
\r
545 private Color dropColor = new Color(255,204,204);
\r
547 private int prechkrow = -1;
\r
548 private boolean prechksucceeded = false;
\r
551 public Component prepareRenderer(TableCellRenderer tcr, int row, int column) {
\r
552 Component c = super.prepareRenderer(tcr, row, column);
\r
553 Color fgColor = null;
\r
554 Color bgColor = null;
\r
555 if(isRowSelected(row)) {
\r
556 fgColor = this.getSelectionForeground();
\r
557 bgColor = this.getSelectionBackground();
\r
560 fgColor = this.getForeground();
\r
562 int xrow = this.convertRowIndexToModel(row);
\r
563 RecordedItem item = rowView.get(xrow);
\r
565 if ( ! item.hide_succeeded ) {
\r
566 bgColor = failedColor;
\r
568 else if ( item.dropmpeg > 0 ) {
\r
569 bgColor = dropMpegColor;
\r
571 else if ( item.drop > 0 ) {
\r
572 bgColor = dropColor;
\r
575 bgColor = (isSepRowColor && row%2 == 1)?(evenColor):(super.getBackground());
\r
578 c.setForeground(fgColor);
\r
579 c.setBackground(bgColor);
\r
583 // 連続して同じ行へのアクセスがあったら計算を行わず前回のままにする
\r
584 private boolean isRowPassed(int prow) {
\r
586 if(prechkrow == prow) {
\r
587 return prechksucceeded;
\r
590 int row = this.convertRowIndexToModel(prow);
\r
591 RecordedItem c = rowView.get(row);
\r
596 prechksucceeded = c.hide_succeeded;
\r
597 return prechksucceeded;
\r
603 public void tableChanged(TableModelEvent e) {
\r
605 super.tableChanged(e);
\r
608 private void reset() {
\r
610 prechksucceeded = true;
\r
616 public JNETableRecorded(boolean b) {
\r
619 public JNETableRecorded(TableModel d, boolean b) {
\r