OSDN Git Service

[予約ダイアログ]自動予約編集への対応に伴うレイアウト変更(2)
[tainavi/TinyBannavi.git] / TinyBannavi / src / tainavi / AbsAutoReserveListView.java
1 package tainavi;\r
2 \r
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.ActionEvent;\r
8 import java.util.ArrayList;\r
9 import java.util.HashMap;\r
10 \r
11 import javax.swing.ImageIcon;\r
12 import javax.swing.JPanel;\r
13 import javax.swing.JScrollPane;\r
14 import javax.swing.JTable;\r
15 import javax.swing.table.DefaultTableColumnModel;\r
16 import javax.swing.table.DefaultTableModel;\r
17 import javax.swing.table.TableCellRenderer;\r
18 import javax.swing.table.TableColumn;\r
19 import javax.swing.table.TableModel;\r
20 \r
21 \r
22 /**\r
23  * 自動予約一覧タブのクラス\r
24  * @since 3.22.2β\r
25  */\r
26 public abstract class AbsAutoReserveListView extends JPanel implements HDDRecorderListener {\r
27 \r
28         private static final long serialVersionUID = 1L;\r
29         \r
30         public void setDebug(boolean b) {debug = b; }\r
31         private boolean debug = false;\r
32         \r
33 \r
34         /*******************************************************************************\r
35          * 抽象メソッド\r
36          ******************************************************************************/\r
37         \r
38         protected abstract Env getEnv();\r
39         protected abstract Bounds getBoundsEnv();\r
40 \r
41         \r
42         /*******************************************************************************\r
43          * 定数\r
44          ******************************************************************************/\r
45         \r
46         private static final String MSGID = "[自動予約一覧] ";\r
47         private static final String ERRID = "[ERROR]"+MSGID;\r
48         private static final String DBGID = "[DEBUG]"+MSGID;\r
49         \r
50         private static final String ICONFILE_EXEC                       = "icon/media-record-3.png";\r
51         \r
52         /*******************************************************************************\r
53          * 部品\r
54          ******************************************************************************/\r
55         \r
56         // オブジェクト\r
57         private final Env env = getEnv();\r
58         private final Bounds bounds = getBoundsEnv();\r
59         \r
60         private final ImageIcon execicon = new ImageIcon(ICONFILE_EXEC);\r
61         \r
62         /**\r
63          * カラム定義\r
64          */\r
65         \r
66         public static HashMap<String,Integer> getColumnIniWidthMap() {\r
67                 if (rcmap.size() == 0 ) {\r
68                         for ( AutoRsvColumn rc : AutoRsvColumn.values() ) {\r
69                                 rcmap.put(rc.toString(),rc.getIniWidth());      // toString()!\r
70                         }\r
71                 }\r
72                 return rcmap;\r
73         }\r
74         \r
75         private static final HashMap<String,Integer> rcmap = new HashMap<String, Integer>();\r
76         \r
77         public static enum AutoRsvColumn {\r
78                 EXEC            ("実行",                      50),\r
79                 TITLE           ("タイトル",                500),\r
80                 CHNAME          ("チャンネル名",  150),\r
81                 ;\r
82 \r
83                 private String name;\r
84                 private int iniWidth;\r
85 \r
86                 private AutoRsvColumn(String name, int iniWidth) {\r
87                         this.name = name;\r
88                         this.iniWidth = iniWidth;\r
89                 }\r
90 \r
91                 public String getName() {\r
92                         return name;\r
93                 }\r
94 \r
95                 public int getIniWidth() {\r
96                         return iniWidth;\r
97                 }\r
98                 \r
99                 public int getColumn() {\r
100                         return ordinal();\r
101                 }\r
102                 \r
103                 public static AutoRsvColumn getColumnValue(int column) {\r
104                         if ( column >= AutoRsvColumn.values().length ) {\r
105                                 return null;\r
106                         }\r
107                         return (AutoRsvColumn.values())[column];\r
108                 }\r
109         };\r
110         \r
111         \r
112         /*******************************************************************************\r
113          * コンポーネント\r
114          ******************************************************************************/\r
115         \r
116         // 表示用データの入れ物\r
117         private class AutoRsvItem extends RowItem implements Cloneable {\r
118                 \r
119                 AutoReserveInfo autorsv;\r
120                 \r
121                 @Override\r
122                 protected void myrefresh(RowItem o) {\r
123                         AutoRsvItem c = (AutoRsvItem) o;\r
124                         \r
125                         c.addData(c.autorsv.getExec());\r
126                         c.addData(c.autorsv.getLabel());\r
127                         c.addData(c.autorsv.getChName());\r
128                 }\r
129                 \r
130                 public AutoRsvItem clone() {\r
131                         return (AutoRsvItem) super.clone();\r
132                 }\r
133                 \r
134         }\r
135         \r
136         // ソートが必要な場合はTableModelを作る。ただし、その場合Viewのrowがわからないので行の入れ替えが行えない\r
137         private class AutoRsvTableModel extends DefaultTableModel {\r
138 \r
139                 private static final long serialVersionUID = 1L;\r
140                 \r
141                 private RowItemList<AutoRsvItem> rDat;\r
142                 \r
143                 @Override\r
144                 public Object getValueAt(int row, int column) {\r
145                         AutoRsvItem c = rDat.get(row);\r
146                         if ( c.getColumnCount() > column ) {\r
147                                 return c.get(column);\r
148                         }\r
149                         return null;\r
150                 }\r
151                 \r
152                 @Override\r
153                 public void setValueAt(Object aValue, int row, int column) {\r
154                         // ダミー\r
155                 }\r
156                 \r
157                 @Override\r
158                 public int getRowCount() {\r
159                         return (rDat!=null) ? rDat.size() : 0;  // ↓ のsuper()で呼ばれるのでnullチェックが必要\r
160                 }\r
161 \r
162                 public AutoRsvTableModel(String[] colname, int i, RowItemList<AutoRsvItem> rowdata) {\r
163                         super(colname,i);\r
164                         this.rDat = rowdata;\r
165                 }\r
166         }\r
167         \r
168         // リスト部\r
169         private JScrollPane jsc_list = null;\r
170         private JNETable jt_list = null;\r
171         private JTable jt_rowheader = null;\r
172         private DefaultTableModel tableModel_list = null;\r
173         private DefaultTableModel rowheaderModel_list = null;\r
174         \r
175         // 詳細表示部\r
176         private JScrollPane jsc_detail = null;\r
177         private JTextAreaWithPopup jta_detail = null;\r
178         \r
179         // テーブルの実体\r
180         private final RowItemList<AutoRsvItem> rowData = new RowItemList<AutoRsvItem>();\r
181         \r
182         // 表示のための一時保存用\r
183         private final RowItemList<AutoRsvItem> rowViewTemp = new RowItemList<AutoRsvItem>();\r
184         \r
185 \r
186         /*******************************************************************************\r
187          * コンストラクタ\r
188          ******************************************************************************/\r
189         \r
190         public AbsAutoReserveListView() {\r
191                 \r
192                 super();\r
193                 \r
194                 this.setLayout(new BorderLayout());\r
195                 this.add(getJScrollPane_list(), BorderLayout.CENTER);\r
196                 this.add(getJTextPane_detail(), BorderLayout.PAGE_END);\r
197                 \r
198         }\r
199         \r
200         \r
201         /*******************************************************************************\r
202          * アクション\r
203          ******************************************************************************/\r
204         \r
205         /**\r
206          * テーブルの行番号の表示のON/OFF\r
207          */\r
208         public void setRowHeaderVisible(boolean b) {\r
209                 jsc_list.getRowHeader().setVisible(b);\r
210         }\r
211         \r
212         /**\r
213          * テーブルを書き換える\r
214          */\r
215         private void redrawByRecorderSelected() {\r
216                 \r
217                 // テーブルデータを置き換える\r
218                 rowData.clear();\r
219                 rowViewTemp.clear();\r
220                 for ( HDDRecorder rec : getSelectedRecorderList() ) {\r
221                         for ( AutoReserveInfo info : rec.getAutoReserves() ) {\r
222                                 AutoRsvItem c = new AutoRsvItem();\r
223                                 c.autorsv = info;\r
224                                 c.fireChanged();\r
225                                 rowData.add(c);\r
226                                 rowViewTemp.add(c);\r
227                         }\r
228                 }\r
229                 \r
230                 // fire!\r
231                 tableModel_list.fireTableDataChanged();\r
232                 rowheaderModel_list.fireTableDataChanged();\r
233         }\r
234         \r
235         \r
236         /*******************************************************************************\r
237          * ハンドラ―メソッド\r
238          ******************************************************************************/\r
239         \r
240         /**\r
241          * ツールバーでレコーダの選択イベントが発生\r
242          */\r
243         @Override\r
244         public void valueChanged(HDDRecorderSelectionEvent e) {\r
245                 if (debug) System.out.println(DBGID+"recorder selection rised");\r
246                 \r
247                 // 選択中のレコーダ情報を保存する\r
248                 src_recsel = (HDDRecorderSelectable) e.getSource();\r
249                 \r
250                 // テーブルを書き換える\r
251                 redrawByRecorderSelected();\r
252         }\r
253         \r
254         private String getSelectedRecorderId() {\r
255                 return ( src_recsel!=null ? src_recsel.getSelectedId() : null );\r
256         }\r
257         \r
258         private HDDRecorderList getSelectedRecorderList() {\r
259                 return ( src_recsel!=null ? src_recsel.getSelectedList() : null );\r
260         }\r
261         \r
262         private HDDRecorderSelectable src_recsel;\r
263         \r
264         \r
265         /**\r
266          * レコーダ情報の変更イベントが発生\r
267          */\r
268         @Override\r
269         public void stateChanged(HDDRecorderChangeEvent e) {\r
270                 // テーブルをリフレッシュする処理\r
271                 redrawByRecorderSelected();\r
272         }\r
273         \r
274         /*******************************************************************************\r
275          * リスナー\r
276          ******************************************************************************/\r
277         \r
278         \r
279         /*******************************************************************************\r
280          * コンポーネント\r
281          ******************************************************************************/\r
282         \r
283         /**\r
284          * リストのペーン\r
285          */\r
286         private JScrollPane getJScrollPane_list() {\r
287                 \r
288                 if ( jsc_list == null ) {\r
289                         jsc_list = new JScrollPane();\r
290                         \r
291                         jsc_list.setRowHeaderView(jt_rowheader = new JTableRowHeader(rowViewTemp));\r
292                         jsc_list.setViewportView(getNETable_list());\r
293                         \r
294                         Dimension d = new Dimension(jt_rowheader.getPreferredSize().width,0);\r
295                         jsc_list.getRowHeader().setPreferredSize(d);\r
296                         \r
297                         this.setRowHeaderVisible(env.getRowHeaderVisible());\r
298                 }\r
299                 \r
300                 return jsc_list;\r
301         }\r
302         \r
303         private JNETable getNETable_list() {\r
304                 if (jt_list == null) {\r
305                         \r
306                         ArrayList<String> cola = new ArrayList<String>();\r
307                         for ( AutoRsvColumn rc : AutoRsvColumn.values() ) {\r
308                                 if ( rc.getIniWidth() >= 0 ) {\r
309                                         cola.add(rc.getName());\r
310                                 }\r
311                         }\r
312                         String[] colname = cola.toArray(new String[0]);\r
313                         \r
314                         tableModel_list = new AutoRsvTableModel(colname, 0, rowViewTemp);\r
315                         jt_list = new JNETableAutoReserve(tableModel_list, false);\r
316                         jt_list.setAutoResizeMode(JNETable.AUTO_RESIZE_OFF);\r
317                         \r
318                         // ヘッダのモデル\r
319                         rowheaderModel_list = (DefaultTableModel) jt_rowheader.getModel();\r
320                         \r
321                         /* - ソートはいらない気がする -\r
322                          \r
323                         // ソータを付ける\r
324                         TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(tableModel_list);\r
325                         jt_list.setRowSorter(sorter);\r
326                         \r
327                         // 数値でソートする項目用の計算式(番組長とか)\r
328                         final Comparator<String> titlecomp = new Comparator<String>() {\r
329                                 \r
330                                 @Override\r
331                                 public int compare(String o1, String o2) {\r
332                                         String t1 = TraceProgram.replacePop(o1.replaceAll(TVProgram.titlePrefixRemoveExpr, "")).replaceFirst(TVProgram.epnoNormalizeExpr, "$1\\0$2");\r
333                                         String t2 = TraceProgram.replacePop(o2.replaceAll(TVProgram.titlePrefixRemoveExpr, "")).replaceFirst(TVProgram.epnoNormalizeExpr, "$1\\0$2");\r
334                                         return t1.compareTo(t2);\r
335                                 }\r
336                         };\r
337                         \r
338                         // ソーターの効かない項目用の計算式(重複マーク)\r
339                         final Comparator<String> noncomp = new Comparator<String>() {\r
340                                 @Override\r
341                                 public int compare(String o1, String o2) {\r
342                                         return 0;\r
343                                 }\r
344                         };\r
345                         \r
346                         sorter.setComparator(jt_list.getColumn(AutoResColumn.TITLE.getName()).getModelIndex(),titlecomp);\r
347                         sorter.setComparator(jt_list.getColumn(AutoResColumn.END.getName()).getModelIndex(),noncomp);\r
348                         \r
349                         */\r
350                         \r
351                         // 各カラムの幅\r
352                         DefaultTableColumnModel columnModel = (DefaultTableColumnModel)jt_list.getColumnModel();\r
353                         TableColumn column = null;\r
354                         for ( AutoRsvColumn rc : AutoRsvColumn.values() ) {\r
355                                 if ( rc.getIniWidth() < 0 ) {\r
356                                         continue;\r
357                                 }\r
358                                 column = columnModel.getColumn(rc.ordinal());\r
359                                 //column.setPreferredWidth(bounds.getRecordedColumnSize().get(rc.toString()));\r
360                                 column.setPreferredWidth(rc.getIniWidth());\r
361                         }\r
362 \r
363                         // 特殊なカラムの設定\r
364                         ButtonColumn buttonColumn = new ButtonColumn(execicon);\r
365                         jt_list.getColumn(AutoRsvColumn.EXEC.getName()).setCellRenderer(buttonColumn);\r
366                         jt_list.getColumn(AutoRsvColumn.EXEC.getName()).setCellEditor(buttonColumn);\r
367                         jt_list.getColumn(AutoRsvColumn.EXEC.getName()).setResizable(false);\r
368                         \r
369                         // 詳細表示\r
370                         //jt_list.getSelectionModel().addListSelectionListener(lsSelectListner);\r
371                 }\r
372                 return jt_list;\r
373         }\r
374         \r
375         /**\r
376          * 詳細表示のペーン\r
377          */\r
378         private JScrollPane getJTextPane_detail() {\r
379                 if ( jsc_detail == null ) {\r
380                         jsc_detail = new JScrollPane(jta_detail = new JTextAreaWithPopup(),JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);\r
381                         jta_detail.setRows(8);\r
382                         jta_detail.setEditable(false);\r
383                         jta_detail.setBackground(Color.LIGHT_GRAY);\r
384                 }\r
385                 return jsc_detail;\r
386         }\r
387 \r
388         /*******************************************************************************\r
389          * 表表示\r
390          ******************************************************************************/\r
391         \r
392         private class JNETableAutoReserve extends JNETable {\r
393 \r
394                 private static final long serialVersionUID = 1L;\r
395                 \r
396                 public void setDisabledColor(Color c) { disabledColor = c; }\r
397                 private Color disabledColor = new Color(180,180,180);\r
398                 \r
399                 private int prechkrow = -1;\r
400                 private boolean prechkdisabled = false;\r
401                 \r
402                 @Override\r
403                 public Component prepareRenderer(TableCellRenderer tcr, int row, int column) {\r
404                         Component c = super.prepareRenderer(tcr, row, column);\r
405                         Color bgColor = null;\r
406                         if(isRowSelected(row)) {\r
407                                 bgColor = this.getSelectionBackground();\r
408                         }\r
409                         else {\r
410                                 isRowPassed(row);\r
411                                 if ( prechkdisabled ) {\r
412                                         bgColor = disabledColor;\r
413                                 }\r
414                                 else {\r
415                                         bgColor = (isSepRowColor && row%2 == 1)?(evenColor):(super.getBackground());\r
416                                 }\r
417                         }\r
418                         c.setBackground(bgColor);\r
419                         return c;\r
420                 }\r
421                 \r
422                 // 連続して同じ行へのアクセスがあったら計算を行わず前回のままにする\r
423                 private boolean isRowPassed(int prow) {\r
424                         \r
425                         if(prechkrow == prow) {\r
426                                 return prechkdisabled;\r
427                         }\r
428 \r
429                         int row = this.convertRowIndexToModel(prow);\r
430                         AutoRsvItem c = rowViewTemp.get(row);\r
431 \r
432                         {\r
433                                 // 実行可能かどうか\r
434                                 prechkrow = prow;\r
435                                 prechkdisabled = ! c.autorsv.getExec();\r
436                         }\r
437                         \r
438                         return true;\r
439                 }\r
440                 \r
441                 @Override\r
442                 public boolean isCellEditable(int row, int column) {\r
443                         if ( column == AutoRsvColumn.EXEC.getColumn() ) {\r
444                                 return true;\r
445                         }\r
446                         return false;\r
447                 }\r
448                 \r
449                 // コンストラクタ\r
450                 \r
451                 public JNETableAutoReserve(boolean b) {\r
452                         super(b);\r
453                 }\r
454                 public JNETableAutoReserve(TableModel d, boolean b) {\r
455                         super(d,b);\r
456                 }\r
457                 \r
458         }\r
459 \r
460         /**\r
461          * EXECボタン\r
462          */\r
463         private class ButtonColumn extends AbstractExecButtonColumn {\r
464 \r
465                 private static final long serialVersionUID = 1L;\r
466 \r
467                 public ButtonColumn(ImageIcon icon) {\r
468                         super(icon);\r
469                 }\r
470 \r
471                 @Override\r
472                 protected void toggleAction(ActionEvent e) {\r
473                         \r
474                         fireEditingStopped();\r
475                         \r
476                         int vrow = jt_list.getSelectedRow();\r
477                         int row = jt_list.convertRowIndexToModel(vrow);\r
478                         \r
479                         AutoRsvItem c = rowViewTemp.get(row);\r
480 \r
481                         //if ( doExecOnOff( ! c.exec, c.title, c.chname, c.hide_rsvid, c.recorder) )\r
482                         {\r
483                                 c.autorsv.setExec( ! c.autorsv.getExec());\r
484                                 c.fireChanged();\r
485                         }\r
486                         \r
487                         jt_list.clearSelection();\r
488                         jt_list.setRowSelectionInterval(vrow, vrow);\r
489                 }\r
490         }\r
491 \r
492 }\r