• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Frequently used words (click to add to your profile)

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

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


Commit MetaInfo

Revisão80845c802d5514784f279edb7ca41ce229d0354e (tree)
Hora2018-09-22 00:15:22
AutorMasahiko Kimura <mkimura@u01....>
CommiterMasahiko Kimura

Mensagem de Log

Ver.1.10 (2018/09/21):

  1. [ツールバー]検索ボックスの幅を大きくする。bounds.txtのsearchBoxAreaWidthで調整が可能
  2. [ツールバー]検索ボックスで検索した語句の履歴を記憶して、コンボボックスで選択できるようにする
  3. [録画結果一覧]リストの列幅を記憶する
  4. [録画結果一覧]番組タイトルや番組情報をクリップボードにコピーできるようにする
  5. [ログ出力]出力日時を出力するようにする

Mudança Sumário

Diff

--- a/TinyBannavi/src/tainavi/AbsListedView.java
+++ b/TinyBannavi/src/tainavi/AbsListedView.java
@@ -207,8 +207,8 @@ public abstract class AbsListedView extends JPanel implements TickTimerListener
207207 private final Component parent = getParentComponent(); // これは起動時に作成されたまま変更されないオブジェクト
208208
209209 // メソッド
210- private void StdAppendMessage(String message) { System.out.println(message); }
211- private void StdAppendError(String message) { System.err.println(message); }
210+ private void StdAppendMessage(String message) { System.out.println(CommonUtils.getNow() + message); }
211+ private void StdAppendError(String message) { System.err.println(CommonUtils.getNow() + message); }
212212 //private void StWinSetVisible(boolean b) { StWin.setVisible(b); }
213213 //private void StWinSetLocationCenter(Component frame) { CommonSwingUtils.setLocationCenter(frame, (VWStatusWindow)StWin); }
214214
--- a/TinyBannavi/src/tainavi/AbsPaperView.java
+++ b/TinyBannavi/src/tainavi/AbsPaperView.java
@@ -166,8 +166,8 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
166166 private final Component parent = getParentComponent(); // これは起動時に作成されたまま変更されないオブジェクト
167167
168168 // メソッド
169- private void StdAppendMessage(String message) { System.out.println(message); }
170- private void StdAppendError(String message) { System.err.println(message); }
169+ private void StdAppendMessage(String message) { System.out.println(CommonUtils.getNow() + message); }
170+ private void StdAppendError(String message) { System.err.println(CommonUtils.getNow() + message); }
171171 //private void StWinSetVisible(boolean b) { StWin.setVisible(b); }
172172 //private void StWinSetLocationCenter(Component frame) { CommonSwingUtils.setLocationCenter(frame, (VWStatusWindow)StWin); }
173173
--- a/TinyBannavi/src/tainavi/AbsRecordedListView.java
+++ b/TinyBannavi/src/tainavi/AbsRecordedListView.java
@@ -4,13 +4,23 @@ import java.awt.BorderLayout;
44 import java.awt.Color;
55 import java.awt.Component;
66 import java.awt.Dimension;
7+import java.awt.Point;
8+import java.awt.Toolkit;
9+import java.awt.datatransfer.Clipboard;
10+import java.awt.datatransfer.StringSelection;
11+import java.awt.event.ActionEvent;
12+import java.awt.event.ActionListener;
713 import java.awt.event.ComponentAdapter;
814 import java.awt.event.ComponentEvent;
15+import java.awt.event.MouseAdapter;
16+import java.awt.event.MouseEvent;
917 import java.util.ArrayList;
1018 import java.util.Comparator;
1119 import java.util.HashMap;
1220
21+import javax.swing.JMenuItem;
1322 import javax.swing.JPanel;
23+import javax.swing.JPopupMenu;
1424 import javax.swing.JScrollPane;
1525 import javax.swing.JTable;
1626 import javax.swing.event.ListSelectionEvent;
@@ -33,44 +43,44 @@ public abstract class AbsRecordedListView extends JPanel {
3343
3444 public static void setDebug(boolean b) {debug = b; }
3545 private static boolean debug = false;
36-
46+
3747
3848 /*******************************************************************************
3949 * 抽象メソッド
4050 ******************************************************************************/
41-
51+
4252 protected abstract Env getEnv();
4353 protected abstract Bounds getBoundsEnv();
44-
54+
4555 protected abstract HDDRecorderList getRecorderList();
46-
47- //protected abstract StatusWindow getStWin();
56+
57+ //protected abstract StatusWindow getStWin();
4858 //protected abstract StatusTextArea getMWin();
4959 //protected abstract AbsReserveDialog getReserveDialog();
50-
60+
5161 protected abstract Component getParentComponent();
52-
62+
5363 protected abstract void ringBeep();
54-
64+
5565 /**
5666 * @see Viewer.VWToolBar#getSelectedRecorder()
5767 */
5868 protected abstract String getSelectedRecorderOnToolbar();
59-
69+
6070
6171 /*******************************************************************************
6272 * 定数
6373 ******************************************************************************/
64-
74+
6575 private static final String MSGID = "[録画結果一覧] ";
6676 private static final String ERRID = "[ERROR]"+MSGID;
6777 private static final String DBGID = "[DEBUG]"+MSGID;
68-
69-
78+
79+
7080 /*******************************************************************************
7181 * 部品
7282 ******************************************************************************/
73-
83+
7484 // オブジェクト
7585 private final Env env = getEnv();
7686 private final Bounds bounds = getBoundsEnv();
@@ -78,19 +88,19 @@ public abstract class AbsRecordedListView extends JPanel {
7888
7989 //private final StatusWindow StWin = getStWin(); // これは起動時に作成されたまま変更されないオブジェクト
8090 //private final StatusTextArea MWin = getMWin(); // これは起動時に作成されたまま変更されないオブジェクト
81-
91+
8292 private final Component parent = getParentComponent(); // これは起動時に作成されたまま変更されないオブジェクト
83-
93+
8494 // メソッド
8595 //private void StdAppendMessage(String message) { System.out.println(message); }
8696 //private void StdAppendError(String message) { System.err.println(message); }
8797 //private void StWinSetVisible(boolean b) { StWin.setVisible(b); }
8898 //private void StWinSetLocationCenter(Component frame) { CommonSwingUtils.setLocationCenter(frame, (VWStatusWindow)StWin); }
89-
99+
90100 /**
91101 * カラム定義
92102 */
93-
103+
94104 public static HashMap<String,Integer> getColumnIniWidthMap() {
95105 if (rcmap.size() == 0 ) {
96106 for ( RecedColumn rc : RecedColumn.values() ) {
@@ -99,9 +109,9 @@ public abstract class AbsRecordedListView extends JPanel {
99109 }
100110 return rcmap;
101111 }
102-
112+
103113 private static final HashMap<String,Integer> rcmap = new HashMap<String, Integer>();
104-
114+
105115 public static enum RecedColumn {
106116 START ("開始", 150),
107117 END ("終了", 50),
@@ -129,19 +139,19 @@ public abstract class AbsRecordedListView extends JPanel {
129139 public int getIniWidth() {
130140 return iniWidth;
131141 }
132-
142+
133143 public int getColumn() {
134144 return ordinal();
135145 }
136146 };
137-
147+
138148
139149 /*******************************************************************************
140150 * コンポーネント
141151 ******************************************************************************/
142152
143153 private class RecordedItem extends RowItem implements Cloneable {
144-
154+
145155 String start; // YYYY/MM/DD(WD) hh:mm
146156 String end; // hh:mm
147157 Integer length;
@@ -154,11 +164,11 @@ public abstract class AbsRecordedListView extends JPanel {
154164
155165 String hide_detail;
156166 Boolean hide_succeeded;
157-
167+
158168 @Override
159169 protected void myrefresh(RowItem o) {
160170 RecordedItem c = (RecordedItem) o;
161-
171+
162172 c.addData(start);
163173 c.addData(end);
164174 c.addData(length);
@@ -169,7 +179,7 @@ public abstract class AbsRecordedListView extends JPanel {
169179 c.addData(result);
170180 c.addData(recorder);
171181 }
172-
182+
173183 public RecordedItem clone() {
174184 return (RecordedItem) super.clone();
175185 }
@@ -179,10 +189,10 @@ public abstract class AbsRecordedListView extends JPanel {
179189 private class ReservedTableModel extends DefaultTableModel {
180190
181191 private static final long serialVersionUID = 1L;
182-
192+
183193 @Override
184194 public Object getValueAt(int row, int column) {
185- RecordedItem c = rowView.get(row);
195+ RecordedItem c = rowView.get(row);
186196 if ( c.getColumnCount() > column ) {
187197 if ( column == RecedColumn.LENGTH.getColumn() ) {
188198 return String.valueOf(c.length)+"m";
@@ -191,34 +201,34 @@ public abstract class AbsRecordedListView extends JPanel {
191201 }
192202 return null;
193203 }
194-
204+
195205 @Override
196206 public int getRowCount() {
197207 return rowView.size();
198208 }
199209
200210 private boolean filtered = false;
201-
211+
202212 public boolean getFiltered() { return filtered; }
203-
213+
204214 @Deprecated
205215 public void fireTableDataChanged() {
206216 throw new NullPointerException();
207217 }
208-
218+
209219 public void fireTableDataChanged(boolean filtered) {
210220 super.fireTableDataChanged();
211221 this.filtered = filtered;
212222 }
213-
223+
214224 public ReservedTableModel(String[] colname, int i) {
215225 super(colname,i);
216226 }
217-
227+
218228 }
219-
229+
220230 //private final RecordedItem sa = new RecordedItem();
221-
231+
222232 private JScrollPane jsc_list = null;
223233 private JScrollPane jsc_detail = null;
224234 private JTextAreaWithPopup jta_detail = null;
@@ -226,27 +236,27 @@ public abstract class AbsRecordedListView extends JPanel {
226236 private JTable jTable_rowheader = null;
227237
228238 private ReservedTableModel tableModel_reced = null;
229-
239+
230240 private DefaultTableModel rowheaderModel_reced = null;
231241
232242 // 表示用のテーブル
233243 private final RowItemList<RecordedItem> rowView = new RowItemList<RecordedItem>();
234-
244+
235245 // テーブルの実体
236246 private final RowItemList<RecordedItem> rowData = new RowItemList<RecordedItem>();
237-
247+
238248 /*******************************************************************************
239249 * コンストラクタ
240250 ******************************************************************************/
241-
251+
242252 public AbsRecordedListView() {
243-
253+
244254 super();
245-
255+
246256 this.setLayout(new BorderLayout());
247257 this.add(getJScrollPane_list(), BorderLayout.CENTER);
248258 this.add(getJTextPane_detail(), BorderLayout.PAGE_END);
249-
259+
250260 // バグ対応
251261 /*
252262 if ( bounds.getRecordedColumnSize() == null ) {
@@ -265,8 +275,8 @@ public abstract class AbsRecordedListView extends JPanel {
265275 }
266276 }
267277 */
268-
269-
278+
279+
270280 //
271281 this.addComponentListener(cl_tabShown);
272282 }
@@ -274,9 +284,9 @@ public abstract class AbsRecordedListView extends JPanel {
274284 /*******************************************************************************
275285 * アクション
276286 ******************************************************************************/
277-
287+
278288 // 対外的な
279-
289+
280290 /**
281291 * 予約一覧を描画してほしいかなって
282292 * ★synchronized(rowData)★
@@ -288,11 +298,11 @@ public abstract class AbsRecordedListView extends JPanel {
288298 _redrawRecordedList();
289299 }
290300 }
291-
301+
292302 private void _redrawRecordedList() {
293303 //
294304 rowData.clear();
295-
305+
296306 // 選択されたレコーダ
297307 String myself = getSelectedRecorderOnToolbar();
298308 HDDRecorderList recs = recorders.findInstance(myself);
@@ -302,12 +312,12 @@ public abstract class AbsRecordedListView extends JPanel {
302312 if ( recorder.isBackgroundOnly() ) {
303313 continue;
304314 }
305-
315+
306316 // 並べ替えるために新しいリストを作成する
307317 for ( RecordedInfo ro : recorder.getRecorded() ) {
308-
318+
309319 RecordedItem sa = new RecordedItem();
310-
320+
311321 sa.start = ro.getDate()+" "+ro.getAhh()+":"+ro.getAmm(); // YYYY/MM/DD(WD) hh:mm
312322 sa.end = ro.getZhh()+":"+ro.getZmm();
313323 sa.length = ro.getLength();
@@ -317,16 +327,16 @@ public abstract class AbsRecordedListView extends JPanel {
317327 sa.chname = ro.getCh_name();
318328 sa.result = ro.getResult();
319329 sa.recorder = recorder.Myself();
320-
330+
321331 sa.hide_detail = ro.getDetail();
322332 sa.hide_succeeded = ro.getSucceeded();
323-
333+
324334 sa.fireChanged();
325-
335+
326336 addRow(sa);
327337 }
328338 }
329-
339+
330340 // 表示用
331341 rowView.clear();
332342 for ( RecordedItem a : rowData ) {
@@ -335,18 +345,18 @@ public abstract class AbsRecordedListView extends JPanel {
335345
336346 tableModel_reced.fireTableDataChanged(false);
337347 ((DefaultTableModel)jTable_rowheader.getModel()).fireTableDataChanged();
338-
348+
339349 jta_detail.setText(null);
340350
341351 //jta_detail.setText("レコーダから予約結果の一覧を取得して表示します。現在の対応レコーダはTvRock/EpgDataCap_Bonのみです。");
342352 }
343-
344-
353+
354+
345355 /**
346356 * 絞り込み検索の本体(現在リストアップされているものから絞り込みを行う)(親から呼ばれるよ!)
347357 */
348358 public void redrawListByKeyword(SearchKey keyword, String target) {
349-
359+
350360 // 情報を一行ずつチェックする
351361 if ( keyword != null ) {
352362
@@ -375,13 +385,13 @@ public abstract class AbsRecordedListView extends JPanel {
375385 return;
376386 }
377387 System.out.println("yyy");
378-
388+
379389 rowView.clear();
380-
390+
381391 for ( RecordedItem a : rowData ) {
382392 rowView.add(a);
383393 }
384-
394+
385395 // fire!
386396 tableModel_reced.fireTableDataChanged(false);
387397 rowheaderModel_reced.fireTableDataChanged();
@@ -417,19 +427,23 @@ public abstract class AbsRecordedListView extends JPanel {
417427 continue;
418428 }
419429 column = columnModel.getColumn(rc.ordinal());
420- //bounds.getRecordedColumnSize().put(rc.toString(), column.getPreferredWidth());
430+ if (column == null)
431+ continue;
432+
433+ int w = column.getWidth();
434+ bounds.getRecordedColumnSize().put(rc.toString(), w > 0 ? w : rc.getIniWidth()); // toString()!
421435 }
422436 }
423-
437+
424438 /**
425439 * テーブルの行番号の表示のON/OFF
426440 */
427441 public void setRowHeaderVisible(boolean b) {
428442 jsc_list.getRowHeader().setVisible(b);
429443 }
430-
444+
431445 // 内部的な
432-
446+
433447 /**
434448 * テーブル(の中の人)に追加
435449 */
@@ -448,7 +462,7 @@ public abstract class AbsRecordedListView extends JPanel {
448462 /*******************************************************************************
449463 * リスナー
450464 ******************************************************************************/
451-
465+
452466 /**
453467 * タブが開かれたら表を書き換える
454468 * ★synchronized(rowData)★
@@ -479,25 +493,262 @@ public abstract class AbsRecordedListView extends JPanel {
479493 }
480494 }
481495 };
482-
496+
497+ /**
498+ * ツールバーで選択されている「先頭の」レコーダを取得する
499+ */
500+ protected HDDRecorder getSelectedRecorder() {
501+ String myself = getSelectedRecorderOnToolbar();
502+ HDDRecorderList recs = recorders.findInstance(myself);
503+
504+ for ( HDDRecorder rec : recs ) {
505+ return rec;
506+ }
507+
508+ return null;
509+ }
510+
511+ /**
512+ * 一覧でのマウスイベント処理
513+ * 右クリック時にポップアップメニューを表示する
514+ */
515+ private final MouseAdapter ma_showpopup = new MouseAdapter() {
516+ @Override
517+ public void mouseClicked(MouseEvent e) {
518+ // 選択されたレコーダ
519+ HDDRecorder rec = getSelectedRecorder();
520+ if (rec == null)
521+ return;
522+
523+ Point p = e.getPoint();
524+ final int vrow = jTable_reced.rowAtPoint(p);
525+ final int row = jTable_reced.convertRowIndexToModel(vrow);
526+
527+ RecordedItem ra = rowView.get(row);
528+ final String title = ra.title;
529+ final String chnam = ra.chname;
530+ final String recId = ra.recorder;
531+ int num =jTable_reced.getSelectedRowCount();
532+ final ArrayList<RecordedItem> ras = new ArrayList<RecordedItem>(num);
533+
534+ //
535+ if (e.getButton() == MouseEvent.BUTTON3) {
536+ if (e.getClickCount() == 1) {
537+ if (!jTable_reced.isRowSelected(vrow))
538+ jTable_reced.getSelectionModel().setSelectionInterval(vrow,vrow);
539+
540+ if (num > 1){
541+ int rows[] = jTable_reced.getSelectedRows();
542+ for (int n=0; n<num; n++){
543+ RecordedItem ri = rowView.get(jTable_reced.convertRowIndexToModel(rows[n]));
544+ ras.add(ri);
545+ }
546+ }
547+
548+ // 右クリックでポップアップメニューを表示
549+ JPopupMenu pop = new JPopupMenu();
550+
551+ // クリップボードへコピーする
552+ {
553+ JMenuItem menuItem = new JMenuItem("番組名をコピー【"+title+"】");
554+ menuItem.addActionListener(new ActionListener() {
555+ public void actionPerformed(ActionEvent e) {
556+ String msg = title;
557+ Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
558+ StringSelection s = new StringSelection(msg);
559+ cb.setContents(s, null);
560+ }
561+ });
562+
563+ pop.add(menuItem);
564+ }
565+ {
566+ JMenuItem menuItem = new JMenuItem(String.format("タイトル情報をコピー【%s (%s)/%s】", title, chnam, recId));
567+ menuItem.addActionListener(new ActionListener() {
568+ public void actionPerformed(ActionEvent e) {
569+ String msg = formatRecordedItem(ra, false);
570+ Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
571+ StringSelection s = new StringSelection(msg);
572+ cb.setContents(s, null);
573+ }
574+ });
575+
576+ pop.add(menuItem);
577+ }
578+ if (num > 1){
579+ JMenuItem menuItem = new JMenuItem(String.format("選択中の%d個のタイトル情報をコピー【%s (%s)/%s】",
580+ num, title, chnam, recId));
581+ menuItem.addActionListener(new ActionListener() {
582+ public void actionPerformed(ActionEvent e) {
583+ String msg = formatRecordedItems(ras, false);
584+ Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
585+ StringSelection s = new StringSelection(msg);
586+ cb.setContents(s, null);
587+ }
588+ });
589+
590+ pop.add(menuItem);
591+ }
592+
593+ pop.addSeparator();
594+
595+ // CSV形式でクリップボードへコピーする
596+ {
597+ JMenuItem menuItem = new JMenuItem(String.format("タイトル情報をCSVでコピー【%s (%s)/%s】",title,chnam, recId));
598+ menuItem.addActionListener(new ActionListener() {
599+ public void actionPerformed(ActionEvent e) {
600+ String msg = formatRecordedHeader(true) + formatRecordedItem(ra, true);
601+ Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
602+ StringSelection s = new StringSelection(msg);
603+ cb.setContents(s, null);
604+ }
605+ });
606+
607+ pop.add(menuItem);
608+ }
609+ if (num > 1){
610+ JMenuItem menuItem = new JMenuItem(String.format("選択中の%d個のタイトル情報をCSVでコピー【%s (%s)/%s】",
611+ num, title, chnam, recId));
612+ menuItem.addActionListener(new ActionListener() {
613+ public void actionPerformed(ActionEvent e) {
614+ String msg = formatRecordedHeader(true) + formatRecordedItems(ras, true);
615+ Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
616+ StringSelection s = new StringSelection(msg);
617+ cb.setContents(s, null);
618+ }
619+ });
620+
621+ pop.add(menuItem);
622+ }
623+
624+ pop.show(jTable_reced, e.getX(), e.getY());
625+ }
626+ }
627+ else if (e.getButton() == MouseEvent.BUTTON1) {
628+ if (e.getClickCount() == 1) {
629+ }
630+ else if (e.getClickCount() == 2) {
631+// editTitleOfRow(vrow);
632+ }
633+ }
634+ }
635+ };
636+
637+ /*
638+ * ヘッダー情報をフォーマットする
639+ */
640+ private String formatRecordedHeader(boolean csv){
641+ StringBuilder sb = new StringBuilder();
642+
643+ for (RecedColumn col: RecedColumn.values()){
644+ String value = col.getName();
645+ boolean last = col == RecedColumn.RECORDER;
646+ if (csv){
647+ sb.append(CommonUtils.toQuoted(value));
648+ if (!last)
649+ sb.append(",");
650+ }
651+ else{
652+ sb.append(value);
653+ if (!last)
654+ sb.append("\t");
655+ }
656+ }
657+ sb.append("\n");
658+
659+ return sb.toString();
660+ }
661+ /*
662+ * 複数の録画結果情報をテキストないしCSVでフォーマットする
663+ */
664+ private String formatRecordedItems(ArrayList<RecordedItem>ras, boolean csv){
665+ StringBuilder sb = new StringBuilder();
666+
667+ for (RecordedItem ra : ras){
668+ sb.append(formatRecordedItem(ra, csv));
669+ }
670+
671+ return sb.toString();
672+ }
673+
674+ /*
675+ * 録画結果情報をテキストないしCSVでフォーマットする
676+ */
677+ private String formatRecordedItem(RecordedItem ra, boolean csv){
678+ StringBuilder sb = new StringBuilder();
679+
680+ for (RecedColumn col: RecedColumn.values()){
681+ String value = "";
682+ boolean last = col == RecedColumn.RECORDER;
683+ switch(col){
684+ case START:
685+ value = ra.start;
686+ break;
687+ case END:
688+ value = ra.end;
689+ break;
690+ case LENGTH:
691+ value = ra.length + "m";
692+ break;
693+ case DROP:
694+ value = ra.drop != null ? ra.drop.toString() : null;
695+ break;
696+ case DROPMPEG:
697+ value = ra.dropmpeg != null ? ra.dropmpeg.toString() : null;
698+ break;
699+ case TITLE:
700+ value = ra.title;
701+ break;
702+ case CHNAME:
703+ value = ra.chname;
704+ break;
705+ case RESULT:
706+ value = ra.result;
707+ break;
708+ case RECORDER:
709+ value = ra.recorder;
710+ break;
711+ }
712+
713+ if (value == null)
714+ value = "";
715+
716+ if (csv){
717+ sb.append(CommonUtils.toQuoted(value));
718+ if (!last)
719+ sb.append(",");
720+ }
721+ else{
722+ sb.append(value);
723+ if (!last)
724+ sb.append("\t");
725+ }
726+ }
727+
728+ sb.append("\n");
729+
730+ return sb.toString();
731+ }
732+
733+
483734 /*******************************************************************************
484735 * コンポーネント
485736 ******************************************************************************/
486737
487738 private JScrollPane getJScrollPane_list() {
488-
739+
489740 if ( jsc_list == null ) {
490741 jsc_list = new JScrollPane();
491-
742+
492743 jsc_list.setRowHeaderView(jTable_rowheader = new JTableRowHeader(rowView));
493744 jsc_list.setViewportView(getNETable_reced());
494-
745+
495746 Dimension d = new Dimension(jTable_rowheader.getPreferredSize().width,0);
496747 jsc_list.getRowHeader().setPreferredSize(d);
497-
748+
498749 this.setRowHeaderVisible(env.getRowHeaderVisible());
499750 }
500-
751+
501752 return jsc_list;
502753 }
503754
@@ -510,10 +761,11 @@ public abstract class AbsRecordedListView extends JPanel {
510761 }
511762 return jsc_detail;
512763 }
513-
764+
765+
514766 private JNETable getNETable_reced() {
515767 if (jTable_reced == null) {
516-
768+
517769 ArrayList<String> cola = new ArrayList<String>();
518770 for ( RecedColumn rc : RecedColumn.values() ) {
519771 if ( rc.getIniWidth() >= 0 ) {
@@ -521,21 +773,21 @@ public abstract class AbsRecordedListView extends JPanel {
521773 }
522774 }
523775 String[] colname = cola.toArray(new String[0]);
524-
776+
525777 tableModel_reced = new ReservedTableModel(colname, 0);
526- jTable_reced = new JNETableRecorded(tableModel_reced, false);
778+ jTable_reced = new JNETableRecorded(tableModel_reced, true);
527779 jTable_reced.setAutoResizeMode(JNETable.AUTO_RESIZE_OFF);
528-
780+
529781 // ヘッダのモデル
530782 rowheaderModel_reced = (DefaultTableModel) jTable_rowheader.getModel();
531-
783+
532784 // ソータを付ける
533785 TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(tableModel_reced);
534786 jTable_reced.setRowSorter(sorter);
535-
787+
536788 // 数値でソートする項目用の計算式(番組長とか)
537789 final Comparator<String> titlecomp = new Comparator<String>() {
538-
790+
539791 @Override
540792 public int compare(String o1, String o2) {
541793 String t1 = TraceProgram.replacePop(o1.replaceAll(TVProgram.titlePrefixRemoveExpr, "")).replaceFirst(TVProgram.epnoNormalizeExpr, "$1\\0$2");
@@ -543,7 +795,7 @@ public abstract class AbsRecordedListView extends JPanel {
543795 return t1.compareTo(t2);
544796 }
545797 };
546-
798+
547799 // ソーターの効かない項目用の計算式(重複マーク)
548800 final Comparator<String> noncomp = new Comparator<String>() {
549801 @Override
@@ -551,10 +803,10 @@ public abstract class AbsRecordedListView extends JPanel {
551803 return 0;
552804 }
553805 };
554-
806+
555807 sorter.setComparator(jTable_reced.getColumn(RecedColumn.TITLE.getName()).getModelIndex(),titlecomp);
556808 sorter.setComparator(jTable_reced.getColumn(RecedColumn.END.getName()).getModelIndex(),noncomp);
557-
809+
558810 // 各カラムの幅
559811 DefaultTableColumnModel columnModel = (DefaultTableColumnModel)jTable_reced.getColumnModel();
560812 TableColumn column = null;
@@ -563,23 +815,30 @@ public abstract class AbsRecordedListView extends JPanel {
563815 continue;
564816 }
565817 column = columnModel.getColumn(rc.ordinal());
566- //column.setPreferredWidth(bounds.getRecordedColumnSize().get(rc.toString()));
567- column.setPreferredWidth(rc.getIniWidth());
818+ if (column == null)
819+ continue;
820+
821+ Integer width = bounds.getRecordedColumnSize().get(rc.toString());
822+ column.setPreferredWidth(width != null ? width : rc.getIniWidth());
568823 }
569-
824+
570825 // 詳細表示
571826 jTable_reced.getSelectionModel().addListSelectionListener(lsSelectListner);
827+
828+ // 一覧表クリックで削除メニュー出現
829+ jTable_reced.addMouseListener(ma_showpopup);
830+
572831 }
573832 return jTable_reced;
574833 }
575834
576-
577-
578-
835+
836+
837+
579838 /*******************************************************************************
580839 * 表表示
581840 ******************************************************************************/
582-
841+
583842 private class JNETableRecorded extends JNETable {
584843
585844 private static final long serialVersionUID = 1L;
@@ -587,10 +846,10 @@ public abstract class AbsRecordedListView extends JPanel {
587846 private Color failedColor = new Color(255,255,0);
588847 private Color dropMpegColor = new Color(255,0,0);
589848 private Color dropColor = new Color(255,204,204);
590-
849+
591850 private int prechkrow = -1;
592851 private boolean prechksucceeded = false;
593-
852+
594853 @Override
595854 public Component prepareRenderer(TableCellRenderer tcr, int row, int column) {
596855 Component c = super.prepareRenderer(tcr, row, column);
@@ -602,10 +861,10 @@ public abstract class AbsRecordedListView extends JPanel {
602861 }
603862 else {
604863 fgColor = this.getForeground();
605-
864+
606865 int xrow = this.convertRowIndexToModel(row);
607866 RecordedItem item = rowView.get(xrow);
608-
867+
609868 if ( ! item.hide_succeeded ) {
610869 bgColor = failedColor;
611870 }
@@ -623,10 +882,10 @@ public abstract class AbsRecordedListView extends JPanel {
623882 c.setBackground(bgColor);
624883 return c;
625884 }
626-
885+
627886 // 連続して同じ行へのアクセスがあったら計算を行わず前回のままにする
628887 private boolean isRowPassed(int prow) {
629-
888+
630889 if(prechkrow == prow) {
631890 return prechksucceeded;
632891 }
@@ -641,19 +900,19 @@ public abstract class AbsRecordedListView extends JPanel {
641900 return prechksucceeded;
642901 }
643902 }
644-
903+
645904 //
646905 @Override
647906 public void tableChanged(TableModelEvent e) {
648907 reset();
649908 super.tableChanged(e);
650909 }
651-
910+
652911 private void reset() {
653912 prechkrow = -1;
654913 prechksucceeded = true;
655914 }
656-
915+
657916 /*
658917 * コンストラクタ
659918 */
--- a/TinyBannavi/src/tainavi/AbsSettingView.java
+++ b/TinyBannavi/src/tainavi/AbsSettingView.java
@@ -104,8 +104,8 @@ public abstract class AbsSettingView extends JScrollPane {
104104 private final VWColorChooserDialog ccwin = getCcWin(); // これは起動時に作成されたまま変更されないオブジェクト
105105
106106 // 雑多なメソッド
107- private void StdAppendMessage(String message) { System.out.println(message); }
108- //private void StdAppendError(String message) { System.err.println(message); }
107+ private void StdAppendMessage(String message) { System.out.println(CommonUtils.getNow() + message); }
108+ //private void StdAppendError(String message) { System.err.println(CommonUtils.getNow() + message); }
109109 private void StWinSetVisible(boolean b) { StWin.setVisible(b); }
110110 private void StWinSetLocationCenter(Component frame) { CommonSwingUtils.setLocationCenter(frame, (VWStatusWindow)StWin); }
111111
--- a/TinyBannavi/src/tainavi/AbsToolBar.java
+++ b/TinyBannavi/src/tainavi/AbsToolBar.java
@@ -8,6 +8,7 @@ import java.awt.event.ActionEvent;
88 import java.awt.event.ActionListener;
99 import java.awt.event.ItemEvent;
1010 import java.awt.event.ItemListener;
11+import java.awt.event.KeyEvent;
1112 import java.awt.event.MouseAdapter;
1213 import java.awt.event.MouseEvent;
1314 import java.awt.event.MouseListener;
@@ -21,15 +22,21 @@ import java.util.regex.Matcher;
2122 import java.util.regex.Pattern;
2223 import java.util.regex.PatternSyntaxException;
2324
25+import javax.swing.AbstractAction;
26+import javax.swing.ActionMap;
2427 import javax.swing.ImageIcon;
28+import javax.swing.InputMap;
2529 import javax.swing.JButton;
2630 import javax.swing.JComboBox;
31+import javax.swing.JComponent;
2732 import javax.swing.JMenuItem;
2833 import javax.swing.JOptionPane;
2934 import javax.swing.JPopupMenu;
3035 import javax.swing.JSlider;
36+import javax.swing.JTextField;
3137 import javax.swing.JToggleButton;
3238 import javax.swing.JToolBar;
39+import javax.swing.KeyStroke;
3340
3441 import tainavi.HDDRecorder.RecType;
3542 import tainavi.SearchKey.TargetId;
@@ -52,6 +59,8 @@ public abstract class AbsToolBar extends JToolBar implements HDDRecorderSelectab
5259 public void setDebug(boolean b) {debug = b; }
5360 private boolean debug = false;
5461
62+ private SearchWordList swlist = new SearchWordList();
63+
5564 /*******************************************************************************
5665 * 抽象メソッド
5766 ******************************************************************************/
@@ -173,10 +182,12 @@ public abstract class AbsToolBar extends JToolBar implements HDDRecorderSelectab
173182 private static final String TIPS_OPENHELP = "ブラウザでヘルプを開く(Ctrl+H)";
174183
175184 // その他
185+ private static final String ESCKEYACTION = "escape-cancel";
176186
177187 private static final String HELP_URL = "http://sourceforge.jp/projects/tainavi/wiki/FrontPage";
178188
179189 private static final int OPENING_WIAT = 500; // まあ起動時しか使わないんですけども
190+ private static final int MAX_SEARCH_WORDS = 32;
180191
181192 // ログ関連
182193
@@ -190,7 +201,8 @@ public abstract class AbsToolBar extends JToolBar implements HDDRecorderSelectab
190201
191202 // ツールバーのコンポーネント
192203
193- private JTextFieldWithPopup jTextField_keyword = null;
204+ private JComboBoxWithPopup jComboBox_keyword = null;
205+ private JTextField jTextField_keyword = null;
194206 private JButton jButton_search = null;
195207 private JButton jButton_addkeyword = null;
196208 private JWideComboBox jComboBox_select_recorder = null;
@@ -229,6 +241,8 @@ public abstract class AbsToolBar extends JToolBar implements HDDRecorderSelectab
229241
230242 private boolean statusarea_shown = bounds.getShowStatus();
231243
244+ private ArrayList<CancelListener> cancel_listeners = new ArrayList<CancelListener>();
245+
232246 /*******************************************************************************
233247 * コンストラクタ
234248 ******************************************************************************/
@@ -237,7 +251,9 @@ public abstract class AbsToolBar extends JToolBar implements HDDRecorderSelectab
237251
238252 super();
239253
240- this.add(getJTextField_keyword());
254+ swlist.load();
255+
256+ this.add(getJComboBox_keyword());
241257 this.add(getJButton_search("キーワード検索"));
242258 this.add(getJButton_addkeyword("キーワード一覧に登録"));
243259 this.addSeparator(new Dimension(4,0));
@@ -284,6 +300,12 @@ public abstract class AbsToolBar extends JToolBar implements HDDRecorderSelectab
284300 String kStr = null;
285301 String keywordStr = jTextField_keyword.getText().trim();
286302
303+ if (swlist.add(keywordStr)){
304+ swlist.save();
305+ updateKeywordComboBox();
306+ jTextField_keyword.setText(keywordStr);
307+ }
308+
287309 if ( keywordStr.matches(("^@d(?:rop)?$"))) {
288310 doKeywordSerach(null,null,null,true);
289311 return;
@@ -870,13 +892,29 @@ public abstract class AbsToolBar extends JToolBar implements HDDRecorderSelectab
870892 *
871893 */
872894 public void addKeywordCancelListener(CancelListener l) {
873- jTextField_keyword.addCancelListener(l);
895+ if ( ! cancel_listeners.contains(l) ) {
896+ cancel_listeners.add(l);
897+ }
874898 }
875899
876900 public void removeKeywordCancelChangeListener(CancelListener l) {
877- jTextField_keyword.removeCancelListener(l);
901+ cancel_listeners.remove(l);
878902 }
879903
904+ public void updateKeywordComboBox(){
905+ jComboBox_keyword.removeAllItems();
906+
907+ jComboBox_keyword.addItem("");
908+
909+ int num=0;
910+ for (SearchWordItem item : swlist.getWordList()){
911+ if (num >= MAX_SEARCH_WORDS)
912+ break;
913+
914+ jComboBox_keyword.addItem(item.getKeyword());
915+ num++;
916+ }
917+ }
880918
881919 /*******************************************************************************
882920 * イベントトリガー
@@ -1230,19 +1268,46 @@ public abstract class AbsToolBar extends JToolBar implements HDDRecorderSelectab
12301268 ******************************************************************************/
12311269
12321270 // キーワード検索ボックス
1233- private JTextFieldWithPopup getJTextField_keyword() {
1234- if (jTextField_keyword == null) {
1235- jTextField_keyword = new JTextFieldWithPopup(16);
1236- Dimension d = jTextField_keyword.getPreferredSize();
1271+ private JComboBoxWithPopup getJComboBox_keyword() {
1272+ if (jComboBox_keyword == null){
1273+ jComboBox_keyword = new JComboBoxWithPopup();
1274+ jComboBox_keyword.setEditable(true);
12371275
1238- jTextField_keyword.setMaximumSize(d); // 固定しないと環境によってサイズがかわっちゃう
1239- jTextField_keyword.setMinimumSize(d);
1276+ jComboBox_keyword.setMaximumRowCount(32);
1277+
1278+ Dimension d = jComboBox_keyword.getPreferredSize();
1279+ d.width = bounds.getSearchBoxAreaWidth();
1280+
1281+ jComboBox_keyword.setMaximumSize(d); // 固定しないと環境によってサイズがかわっちゃう
1282+ jComboBox_keyword.setMinimumSize(d);
1283+ }
1284+
1285+ if (jTextField_keyword == null) {
1286+ jTextField_keyword = ((JTextField)jComboBox_keyword.getEditor().getEditorComponent());
12401287
12411288 jTextField_keyword.setToolTipText(TIPS_KEYWORD);
12421289
12431290 jTextField_keyword.addActionListener(al_keywordEntered);
1291+
1292+ updateKeywordComboBox();
1293+
1294+ InputMap im = jTextField_keyword.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
1295+ ActionMap am = jTextField_keyword.getActionMap();
1296+ im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), ESCKEYACTION);
1297+ am.put(ESCKEYACTION, new AbstractAction(){
1298+ @Override
1299+ public void actionPerformed(ActionEvent e) {
1300+ JTextField jtf = (JTextField) e.getSource();
1301+
1302+ CancelEvent ev = new CancelEvent(jtf, CancelEvent.Cause.TOOLBAR_SEARCH);
1303+ for ( CancelListener l : cancel_listeners ) {
1304+ l.cancelRised(ev);
1305+ }
1306+ }
1307+ });
12441308 }
1245- return jTextField_keyword;
1309+
1310+ return jComboBox_keyword;
12461311 }
12471312
12481313 // 「検索ボタン」
--- a/TinyBannavi/src/tainavi/Bounds.java
+++ b/TinyBannavi/src/tainavi/Bounds.java
@@ -13,7 +13,7 @@ public class Bounds {
1313 //
1414 private static final String BOUNDS_FILE = "env"+File.separator+"bounds.xml";
1515 private static final String BOUNDS_TEXT = "env"+File.separator+"bounds.txt";
16-
16+
1717 //
1818 private Rectangle winRectangle;
1919 public Rectangle getWinRectangle() { return winRectangle; }
@@ -25,22 +25,22 @@ public class Bounds {
2525 private int bangumiColumnHeight;
2626 public int getBangumiColumnHeight() { return bangumiColumnHeight; }
2727 public void setBangumiColumnHeight(int h) { bangumiColumnHeight = h; }
28- //
28+ //
2929 private int treeWidth;
3030 public int getTreeWidth() { return treeWidth; }
3131 public void setTreeWidth(int w) { treeWidth = w; }
3232 private int treeWidthPaper;
3333 public int getTreeWidthPaper() { return treeWidthPaper; }
3434 public void setTreeWidthPaper(int w) { treeWidthPaper = w; }
35-
35+
3636 // サイドツリーの最小幅(固定)
3737 public int getMinDivLoc() { return 32; }
38-
38+
3939 //
4040 public int tooltipWidth;
4141 public int getTooltipWidth() { return tooltipWidth; }
4242 public void setTooltipWidth(int w) { tooltipWidth = w; }
43-
43+
4444 //
4545 private int timebarColumnWidth;
4646 public int getTimebarColumnWidth() { return timebarColumnWidth; }
@@ -63,12 +63,12 @@ public class Bounds {
6363 public int getStatusAreaHeight() { return statusAreaHeight; }
6464 @Deprecated
6565 public void setStatusAreaHeight(int h) { statusAreaHeight = h; }
66-
66+
6767 //
6868 private int selectedTab;
6969 public int getSelectedTab() { return selectedTab; }
7070 public void setSelectedTab(int t) { selectedTab = t; }
71-
71+
7272 //
7373 @Deprecated
7474 private boolean showSettingTabs;
@@ -76,7 +76,7 @@ public class Bounds {
7676 public boolean getShowSettingTabs() { return showSettingTabs; }
7777 @Deprecated
7878 public void setShowSettingTabs(boolean b) { showSettingTabs = b; }
79-
79+
8080 // 予約済み背景色を描画する(リスト形式)
8181 public boolean getShowReservedBackground() { return showReservedBackground; }
8282 public void setShowReservedBackground(boolean b) { showReservedBackground = b; }
@@ -91,29 +91,29 @@ public class Bounds {
9191 private boolean showStatus;
9292 public boolean getShowStatus() { return showStatus; }
9393 public void setShowStatus(boolean b) { showStatus = b; }
94-
94+
9595 // 番組詳細エリアの高さ
9696 public int getDetailRows() { return detailRows; }
9797 public void setDetailRows(int n) { detailRows = n; }
9898 private int detailRows = 4;
99-
99+
100100 // ステータスエリアの高さ
101101 public int getStatusRows() { return statusRows; }
102102 public void setStatusRows(int n) { statusRows = n; }
103103 private int statusRows = 4;
104-
104+
105105 //
106106 private boolean enableTimer;
107107 public boolean getEnableTimer() { return enableTimer; }
108108 public void setEnableTimer(boolean b) { enableTimer = b; }
109-
109+
110110 //
111111 public int getTimelinePosition() { return timelinePosition; }
112112 public void setTimelinePosition(int n) { timelinePosition = n; }
113113 private int timelinePosition = 30;
114-
114+
115115 // リスト形式のカラム幅
116-
116+
117117 @Deprecated
118118 private HashMap<Viewer.ListedColumn, Integer> listedColumnWidth;
119119 @Deprecated
@@ -135,7 +135,7 @@ public class Bounds {
135135 public void setListedColumnSize(HashMap<String, Integer> map) { listedColumnSize = map; }
136136
137137 // 本体予約一覧のカラム幅
138-
138+
139139 @Deprecated
140140 private HashMap<Viewer.RsvedColumn, Integer> rsvedColumnWidth;
141141 @Deprecated
@@ -152,6 +152,11 @@ public class Bounds {
152152 }
153153 }
154154
155+ // 録画結果一覧のカラム幅
156+ private HashMap<String, Integer> recordedColumnSize;
157+ public HashMap<String, Integer> getRecordedColumnSize() { return recordedColumnSize; }
158+ public void setRecordedColumnSize(HashMap<String, Integer> map) { recordedColumnSize = map; }
159+
155160 private HashMap<String, Integer> rsvedColumnSize;
156161 public HashMap<String, Integer> getRsvedColumnSize() { return rsvedColumnSize; }
157162 public void setRsvedColumnSize(HashMap<String, Integer> map) { rsvedColumnSize = map; }
@@ -166,7 +171,7 @@ public class Bounds {
166171 private String selectedRecorderId;
167172 public String getSelectedRecorderId() { return selectedRecorderId; }
168173 public void setSelectedRecorderId(String s) { selectedRecorderId = s; }
169-
174+
170175 //
171176 private boolean expandedSyobocalNode;
172177 private boolean expandedStandbyNode;
@@ -192,7 +197,7 @@ public class Bounds {
192197 public void setExpandedCenterListNode(boolean b) { expandedCenterListNode = b; }
193198 public boolean getExpandedExtensionNode() { return expandedExtensionNode; }
194199 public void setExpandedExtensionNode(boolean b) { expandedExtensionNode = b; }
195-
200+
196201 //
197202 private boolean expandedDateNode;
198203 private boolean expandedDgNode;
@@ -209,22 +214,27 @@ public class Bounds {
209214 public void setExpandedRadioNode(boolean b) { expandedRadioNode = b; }
210215 public boolean getExpandedCenterNode() { return expandedCenterNode; }
211216 public void setExpandedCenterNode(boolean b) { expandedCenterNode = b; }
212-
217+
213218 //
214219 private int frameBufferSize;
215220 public int getFrameBufferSize() { return frameBufferSize; }
216221 public void setFrameBufferSize(int n) { frameBufferSize = n; }
217-
222+
223+ // 検索ボックス欄の横幅
224+ private int searchBoxAreaWidth;
225+ public int getSearchBoxAreaWidth(){ return searchBoxAreaWidth; }
226+ public void setSearchBoxAreaWidth(int n){ searchBoxAreaWidth = n; }
227+
218228 //
219229 private static boolean loaded;
220230 public boolean isLoaded() { return loaded; }
221231 public void setLoaded(boolean b) { loaded = b; }
222-
223-
232+
233+
224234 /***
225- *
235+ *
226236 */
227-
237+
228238 public boolean save() {
229239 System.out.println("ウィンドウサイズ・位置情報を保存します: "+BOUNDS_TEXT);
230240 if ( ! FieldUtils.save(BOUNDS_TEXT, this) ) {
@@ -233,16 +243,16 @@ public class Bounds {
233243 }
234244 return true;
235245 }
236-
246+
237247 public boolean load() {
238-
248+
239249 File ft = new File(BOUNDS_TEXT);
240250 if ( ft.exists() ) {
241251 // 移行済み
242252 System.out.println("@Deprecated: "+BOUNDS_FILE);
243253 return true;
244254 }
245-
255+
246256 System.out.println("ウィンドウサイズ・位置情報を読み込みます: "+BOUNDS_FILE);
247257 File fx = new File(BOUNDS_FILE);
248258 if ( fx.exists() ) {
@@ -251,12 +261,12 @@ public class Bounds {
251261 b.setListedColumnWidth(b.getListedColumnWidth()); // 旧型式→新形式に変換
252262 b.setRsvedColumnWidth(b.getRsvedColumnWidth()); // 旧型式→新形式に変換
253263 FieldUtils.deepCopy(this, b);
254-
264+
255265 // テキスト形式がなければ作るよ
256266 if ( FieldUtils.save(BOUNDS_TEXT,this) ) {
257267 fx.renameTo(new File(BOUNDS_FILE+".bak"));
258268 }
259-
269+
260270 return true;
261271 }
262272 }
@@ -264,7 +274,7 @@ public class Bounds {
264274 System.err.println("ウィンドウサイズ・位置情報を読み込めなかったのでデフォルトの設定値を利用します.");
265275 return false;
266276 }
267-
277+
268278 public boolean loadText() {
269279 System.out.println("ウィンドウサイズ・位置情報を読み込みます: "+BOUNDS_TEXT);
270280 if ( FieldUtils.load(BOUNDS_TEXT, this) ) {
@@ -273,7 +283,7 @@ public class Bounds {
273283 System.err.println("ウィンドウサイズ・位置情報を読み込めなかったのでデフォルトの設定値を利用します.");
274284 return false;
275285 }
276-
286+
277287 @SuppressWarnings("unchecked")
278288 public Bounds() {
279289 //
@@ -294,9 +304,10 @@ public class Bounds {
294304 this.setEnableTimer(false);
295305 this.setFrameBufferSize(900);
296306 this.setSelectedRecorderId(null);
297-
307+ this.setSearchBoxAreaWidth(500);
308+
298309 this.setLoaded(false);
299-
310+
300311 // 旧版との互換部分
301312 listedColumnWidth = new HashMap<Viewer.ListedColumn, Integer>();
302313 /*
@@ -304,7 +315,7 @@ public class Bounds {
304315 listedColumnWidth.put(lc,lc.getIniWidth());
305316 }
306317 */
307-
318+
308319 //
309320 rsvedColumnWidth = new HashMap<Viewer.RsvedColumn, Integer>();
310321 /*
@@ -312,10 +323,11 @@ public class Bounds {
312323 rsvedColumnWidth.put(rc,rc.getIniWidth());
313324 }
314325 */
315-
326+
316327 // さむしんぐにゅー
317328 listedColumnSize = (HashMap<String, Integer>) AbsListedView.getColumnIniWidthMap().clone();
318329 rsvedColumnSize = (HashMap<String, Integer>) AbsReserveListView.getColumnIniWidthMap().clone();
319330 titleColumnSize = (HashMap<String, Integer>) AbsTitleListView.getColumnIniWidthMap().clone();
331+ recordedColumnSize = (HashMap<String, Integer>) AbsRecordedListView.getColumnIniWidthMap().clone();
320332 }
321333 }
--- a/TinyBannavi/src/tainavi/CommonUtils.java
+++ b/TinyBannavi/src/tainavi/CommonUtils.java
@@ -802,6 +802,14 @@ public class CommonUtils {
802802 return c;
803803 }
804804
805+ /*
806+ * 日時をログ形式で取得する
807+ */
808+ public static String getNow(){
809+ GregorianCalendar c = new GregorianCalendar();
810+ return new SimpleDateFormat("MM/dd HH:mm:ss.SSS ").format(c.getTime());
811+ }
812+
805813 /*******************************************************************************
806814 * Color関連
807815 ******************************************************************************/
--- /dev/null
+++ b/TinyBannavi/src/tainavi/SearchWordItem.java
@@ -0,0 +1,47 @@
1+package tainavi;
2+
3+/**
4+ * <P>ツールバーの検索キーワードを保持するクラスです。
5+ * @since 3.22.18β+1.10
6+ * @see SearchWordList
7+ */
8+public class SearchWordItem implements Cloneable {
9+ @Override
10+ public Object clone() {
11+ try {
12+ return super.clone();
13+ } catch (CloneNotSupportedException e) {
14+ throw new InternalError(e.toString());
15+ }
16+ }
17+
18+ private String keyword;
19+ private int count;
20+ private String last_used_time;
21+
22+ public SearchWordItem(){
23+ this.keyword = null;
24+ this.count = 0;
25+ this.last_used_time = null;
26+ }
27+
28+ public SearchWordItem(String s) {
29+ this.keyword = s;
30+ this.count = 1;
31+ this.last_used_time = CommonUtils.getDateTimeYMD(0);
32+ }
33+
34+ public void notifyUse(){
35+ this.count++;
36+ this.last_used_time = CommonUtils.getDateTimeYMD(0);
37+ }
38+
39+ public void setKeyword(String s){ this.keyword = s; }
40+ public String getKeyword() { return this.keyword; }
41+
42+ public void setCount(int n){ this.count = n; }
43+ public int getCount(){ return this.count; }
44+
45+ public void setLastUsedTime(String s){ this.last_used_time = s; }
46+ public String getLastUsedTime(){ return this.last_used_time; }
47+}
--- /dev/null
+++ b/TinyBannavi/src/tainavi/SearchWordList.java
@@ -0,0 +1,104 @@
1+package tainavi;
2+
3+import java.io.File;
4+import java.util.ArrayList;
5+import java.util.Comparator;
6+
7+/*
8+ * <P>ツールバーの検索キーワードのリストを保持するクラスです。
9+ * @since 3.22.18β+1.10
10+ *
11+ * @see ListedColumnInfoList
12+ */
13+
14+public class SearchWordList {
15+ /*
16+ * 定数
17+ */
18+ private final String filename = "env"+File.separator+"searchwords.xml";
19+
20+ private final String MSGID = "[検索ワード] ";
21+ private final String ERRID = "[ERROR]"+MSGID;
22+ private final int maxwords = 128;
23+
24+ /*
25+ * 部品
26+ */
27+ private ArrayList<SearchWordItem> list = new ArrayList<SearchWordItem>();
28+
29+ public int size() { return list.size(); }
30+
31+ public boolean add(String s){
32+ for (SearchWordItem item : list){
33+ if (item.getKeyword().equals(s)){
34+ item.notifyUse();
35+ sortList();
36+ return true;
37+ }
38+ }
39+
40+ SearchWordItem item = new SearchWordItem(s);
41+ list.add(item);
42+ sortList();
43+
44+ while (list.size() > maxwords){
45+ list.remove(list.size()-1);
46+ }
47+
48+ return true;
49+ }
50+
51+ /**
52+ * 検索ワードの一覧を返す
53+ */
54+ public ArrayList<SearchWordItem> getWordList() {
55+ return list;
56+ }
57+
58+ public void clear() {
59+ list.clear();
60+ }
61+
62+ public boolean load() {
63+ if ( ! new File(filename).exists() ) {
64+ System.err.println(ERRID+"設定が読み込めませんでした、検索ワードは無効です: "+filename);
65+ return false;
66+ }
67+
68+ @SuppressWarnings("unchecked")
69+ ArrayList<SearchWordItem> tlist = (ArrayList<SearchWordItem>) CommonUtils.readXML(filename);
70+ if ( tlist == null ) {
71+ System.err.println(ERRID+"設定の読み込みに失敗しました、検索ワードは無効です: "+filename);
72+ return false;
73+ }
74+
75+ System.out.println(MSGID+"設定を読み込みました: "+filename);
76+
77+ list = tlist;
78+ return true;
79+ }
80+
81+ public boolean save() {
82+ if ( ! CommonUtils.writeXML(filename, list) ) {
83+ System.err.println(ERRID+"設定の保存に失敗しました: "+filename);
84+ return false;
85+ }
86+
87+ return true;
88+ }
89+
90+ private class SearchWordComparator implements Comparator<SearchWordItem>{
91+ @Override
92+ public int compare(SearchWordItem p1, SearchWordItem p2) {
93+ int rc = p2.getCount() - p1.getCount();
94+ if (rc != 0)
95+ return (rc > 0) ? 1 : -1;
96+
97+ return p2.getLastUsedTime().compareTo(p1.getLastUsedTime());
98+ }
99+ }
100+
101+ protected void sortList(){
102+ list.sort(new SearchWordComparator());
103+ }
104+}
--- a/TinyBannavi/src/tainavi/VWStatusTextArea.java
+++ b/TinyBannavi/src/tainavi/VWStatusTextArea.java
@@ -13,22 +13,22 @@ public class VWStatusTextArea extends JPanel implements StatusTextArea {
1313 /*
1414 * 部品
1515 */
16-
16+
1717 private JScrollPane jsp = null;
1818 private JTextArea jta = null;
19-
19+
2020 /*
2121 * コンストラクタ
2222 */
23-
23+
2424 public VWStatusTextArea() {
25-
25+
2626 super();
27-
27+
2828 this.setLayout(new BorderLayout());
29-
29+
3030 this.add(getJScrollPane_statusarea());
31-
31+
3232 }
3333
3434 private JScrollPane getJScrollPane_statusarea() {
@@ -37,7 +37,7 @@ public class VWStatusTextArea extends JPanel implements StatusTextArea {
3737 }
3838 return(jsp);
3939 }
40-
40+
4141 private JTextArea getJTextArea_statusarea() {
4242 if (jta == null) {
4343 jta = new JTextAreaWithPopup(4,0);
@@ -47,7 +47,7 @@ public class VWStatusTextArea extends JPanel implements StatusTextArea {
4747 }
4848 return jta;
4949 }
50-
50+
5151 /*
5252 * StatusTextArea用のメソッド(non-Javadoc)
5353 */
@@ -58,27 +58,29 @@ public class VWStatusTextArea extends JPanel implements StatusTextArea {
5858 }
5959
6060 private void append(String message) {
61- jta.append("\n"+message);
61+ jta.append("\n"+ message);
6262 jta.setCaretPosition(jta.getText().length());
6363 }
6464
6565 @Override
6666 public void appendMessage(String message) {
67- this.append(message);
68- System.out.println(message);
67+ String msg = CommonUtils.getNow() + message;
68+ this.append(msg);
69+ System.out.println(msg);
6970 }
7071
7172 @Override
7273 public void appendError(String message) {
73- this.append(message);
74- System.err.println(message);
74+ String msg = CommonUtils.getNow() + message;
75+ this.append(msg);
76+ System.err.println(msg);
7577 }
7678
7779 @Override
7880 public int getRows() {
7981 return jta.getRows();
8082 }
81-
83+
8284 @Override
8385 public void setRows(int rows) {
8486 jta.setRows(rows);
--- a/TinyBannavi/src/tainavi/VWStatusWindow.java
+++ b/TinyBannavi/src/tainavi/VWStatusWindow.java
@@ -115,14 +115,16 @@ public class VWStatusWindow extends JDialog implements StatusWindow,Cloneable {
115115
116116 @Override
117117 public void appendMessage(String message) {
118- this.append(message);
119- System.out.println(message);
118+ String msg = CommonUtils.getNow() + message;
119+ this.append(msg);
120+ System.out.println(msg);
120121 }
121122
122123 @Override
123124 public void appendError(String message) {
124- this.append(message);
125- System.err.println(message);
125+ String msg = CommonUtils.getNow() + message;
126+ this.append(msg);
127+ System.err.println(msg);
126128 }
127129
128130 @Override
--- a/TinyBannavi/src/tainavi/VersionInfo.java
+++ b/TinyBannavi/src/tainavi/VersionInfo.java
@@ -5,7 +5,7 @@ import java.util.regex.Pattern;
55
66
77 public class VersionInfo {
8- private static final String Version = "タイニー番組ナビゲータ for DBR-T2007 3.22.18β+1.9";
8+ private static final String Version = "タイニー番組ナビゲータ for DBR-T2007 3.22.18β+1.10";
99
1010 private static final String OSname = System.getProperty("os.name");
1111 private static final String OSvers = System.getProperty("os.version");
--- a/TinyBannavi/src/tainavi/Viewer.java
+++ b/TinyBannavi/src/tainavi/Viewer.java
@@ -93,8 +93,8 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
9393 * メソッド的な
9494 */
9595
96- private void StdAppendMessage(String message) { System.out.println(message); }
97- private void StdAppendError(String message) { System.err.println(message); }
96+ private void StdAppendMessage(String message) { System.out.println(CommonUtils.getNow() + message); }
97+ private void StdAppendError(String message) { System.err.println(CommonUtils.getNow() + message); }
9898 //
9999 private void MWinSetVisible(boolean b) { mwin.setVisible(b); }
100100 //
@@ -5593,6 +5593,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
55935593 listed.copyColumnWidth();
55945594 reserved.copyColumnWidth();
55955595 titled.copyColumnWidth();
5596+ recorded.copyColumnWidth();
55965597
55975598 bounds.setStatusRows(mwin.getRows());
55985599