1 package camidion.chordhelper;
3 import java.io.UnsupportedEncodingException;
4 import java.util.HashMap;
7 import javax.sound.midi.MetaEventListener;
8 import javax.sound.midi.MetaMessage;
9 import javax.swing.JTextField;
10 import javax.swing.SwingUtilities;
12 import camidion.chordhelper.mididevice.MidiSequencerModel;
13 import camidion.chordhelper.midieditor.SequenceTrackListTableModel;
14 import camidion.chordhelper.music.Chord;
16 public class ChordTextField extends JTextField implements MetaEventListener {
17 private MidiSequencerModel sequencerModel;
18 public ChordTextField(MidiSequencerModel sequencerModel) {
21 // JTextField は、サイズ設定をしないとリサイズ時に縦に伸び過ぎてしまう。
22 // 1行しか入力できないので、縦に伸びすぎるのはスペースがもったいない。
23 // そこで、このような現象を防止するために、最大サイズを明示的に
26 // To reduce resized height, set maximum size to screen size.
29 java.awt.Toolkit.getDefaultToolkit().getScreenSize()
31 this.sequencerModel = sequencerModel;
32 sequencerModel.getSequencer().addMetaEventListener(this);
35 public void meta(MetaMessage msg) {
36 int t = msg.getType();
38 case 0x01: // Text(任意のテキスト:コメントなど)
39 case 0x05: // Lyrics(歌詞)
40 case 0x02: // Copyright(著作権表示)
41 case 0x03: // Sequence Name / Track Name(曲名またはトラック名)
43 byte[] d = msg.getData();
44 if( ! SwingUtilities.isEventDispatchThread() ) {
45 // MIDIシーケンサの EDT から呼ばれた場合、
46 // 表示処理を Swing の EDT に振り直す。
47 SwingUtilities.invokeLater(new AddTextJob(t,d));
59 public class AddTextJob implements Runnable {
62 public AddTextJob(int type, byte[] data) {
67 public void run() { addText(type, data); }
72 private long lastArrivedTime = System.nanoTime();
76 private Map<Integer,String> skippingTextMap = new HashMap<>();
78 * テキストを追加し、カーソルを末尾に移動します。
79 * @param data テキストの元データ
81 private void addText(int type, byte[] data) {
82 // 頻繁に来たかどうかだけとりあえずチェック
83 long arrivedTime = System.nanoTime();
84 boolean isSoon = (arrivedTime - lastArrivedTime < 1000000000L /* 1sec */);
85 lastArrivedTime = arrivedTime;
88 SequenceTrackListTableModel m = sequencerModel.getSequenceTrackListTableModel();
90 // 追加するデータを適切な文字コードで文字列に変換
91 String additionalText;
93 additionalText = new String(data,m.charset);
96 additionalText = new String(data,"JISAutoDetect");
98 catch( UnsupportedEncodingException e ) {
99 additionalText = new String(data);
101 additionalText = additionalText.trim();
102 String lastAdditionalText = skippingTextMap.remove(type);
103 // 歌詞とテキストで同じもの同士がすぐに来た場合は追加しない
104 if( ! (isSoon && additionalText.equals(lastAdditionalText)) ) {
105 // テキストと歌詞が同じかどうかチェックするための比較対象を記録
107 case 0x01: skippingTextMap.put(0x05,additionalText);
108 case 0x05: skippingTextMap.put(0x01,additionalText);
111 String currentText = getText();
113 currentText != null && ! currentText.isEmpty()
116 ! additionalText.isEmpty() && additionalText.length() <= 8
119 // 既存歌詞がある場合、頻繁に来たか短い歌詞だったら追加
120 currentText += " " + additionalText;
124 currentText = additionalText;
126 setText(currentText);
128 // 入力カーソル(キャレット)をテキストの末尾へ
129 setCaretPosition(getText().length());
134 private Chord currentChord = null;
139 public void appendChord(Chord chord) {
140 if( currentChord == null && chord == null )
142 if( currentChord != null && chord != null && chord.equals(currentChord) )
144 String delimiter = ""; // was "\n"
145 setText( getText() + (chord == null ? delimiter : chord + " ") );
146 currentChord = ( chord == null ? null : chord.clone() );