OSDN Git Service

・プレイリストを空にしても調号、拍子、テンポの表示がクリアされない問題の改善
[midichordhelper/MIDIChordHelper.git] / src / camidion / chordhelper / midieditor / TempoSelecter.java
1 package camidion.chordhelper.midieditor;
2
3 import java.awt.Component;
4 import java.awt.event.MouseAdapter;
5 import java.awt.event.MouseEvent;
6
7 import javax.swing.Box;
8 import javax.swing.BoxLayout;
9 import javax.swing.JLabel;
10 import javax.swing.JPanel;
11 import javax.swing.JSpinner;
12 import javax.swing.SpinnerNumberModel;
13
14 import camidion.chordhelper.ButtonIcon;
15 import camidion.chordhelper.music.MIDISpec;
16
17 /**
18  * テンポ選択(QPM: Quarter Per Minute)
19  */
20 public class TempoSelecter extends JPanel {
21         static final int DEFAULT_QPM = 120;
22         protected SpinnerNumberModel tempoSpinnerModel =
23                 new SpinnerNumberModel(DEFAULT_QPM, 1, 999, 1);
24         private JLabel tempoLabel = new JLabel(
25                 "=", new ButtonIcon(ButtonIcon.QUARTER_NOTE_ICON), JLabel.CENTER
26         ) {{
27                 setVerticalAlignment(JLabel.CENTER);
28         }};
29         private JLabel tempoValueLabel = new JLabel(""+DEFAULT_QPM);
30         private JSpinner tempoSpinner = new JSpinner(tempoSpinnerModel);
31         public TempoSelecter() {
32                 String tooltip = "Tempo in quatrers per minute - テンポ(1分あたりの四分音符の数)";
33                 tempoSpinner.setToolTipText(tooltip);
34                 tempoValueLabel.setToolTipText(tooltip);
35                 setLayout(new BoxLayout(this,BoxLayout.X_AXIS));
36                 add(tempoLabel);
37                 add(Box.createHorizontalStrut(5));
38                 add(tempoSpinner);
39                 add(tempoValueLabel);
40                 setEditable(true);
41                 tempoLabel.addMouseListener(new MouseAdapter() {
42                         @Override
43                         public void mousePressed(MouseEvent e) {
44                                 Component obj = e.getComponent();
45                                 if(obj == tempoLabel && isEditable()) {
46                                         //
47                                         // Adjust tempo by interval time between two clicks (tapping)
48                                         //
49                                         long currentMicrosecond = System.nanoTime()/1000;
50                                         // midi_ch_selecter.noteOn( 9, 37, 100 );
51                                         long interval_us = currentMicrosecond - prevBeatMicrosecondPosition;
52                                         prevBeatMicrosecondPosition = currentMicrosecond;
53                                         if( interval_us < 2000000L /* Shorter than 2 sec only */ ) {
54                                                 int tempo_in_bpm = (int)(240000000L / interval_us) >> 2; //  n/4拍子の場合のみを想定
55                                         int old_tempo_in_bpm = getTempoInQpm();
56                                         setTempo( ( tempo_in_bpm + old_tempo_in_bpm * 2 ) / 3 );
57                                         }
58                                 }
59                         }
60                 });
61         }
62         private long prevBeatMicrosecondPosition = 0;
63         private boolean editable;
64         /**
65          * 編集可能かどうかを返します。
66          * @return 編集可能ならtrue
67          */
68         public boolean isEditable() { return editable; }
69         /**
70          * 編集可能かどうかを設定します。
71          * @param editable 編集可能ならtrue
72          */
73         public void setEditable( boolean editable ) {
74                 this.editable = editable;
75                 tempoSpinner.setVisible( editable );
76                 tempoValueLabel.setVisible( !editable );
77                 if( !editable ) {
78                         // Copy spinner's value to label
79                         tempoValueLabel.setText(
80                                 ""+tempoSpinnerModel.getNumber().intValue()
81                         );
82                 }
83                 tempoLabel.setToolTipText(
84                         editable ?
85                         "Tap rhythmically here to adjust tempo - ここをクリックしてリズムをとるとテンポを合わせられます"
86                         : null
87                 );
88         }
89         /**
90          * テンポを返します。
91          * @return テンポ [BPM](QPM)
92          */
93         public int getTempoInQpm() {
94                 return tempoSpinnerModel.getNumber().intValue();
95         }
96         /**
97          * テンポをMIDIメタメッセージのバイト列として返します。
98          * @return MIDIメタメッセージのバイト列
99          */
100         public byte[] getTempoByteArray() {
101                 return MIDISpec.qpmTempoToByteArray(getTempoInQpm());
102         }
103         /**
104          * テンポを設定します。
105          * @param qpm BPM(QPM)の値
106          */
107         public void setTempo(int qpm) {
108                 tempoSpinnerModel.setValue(new Integer(qpm));
109                 tempoValueLabel.setText(""+qpm);
110         }
111         /**
112          * MIDIメタメッセージのバイト列からテンポを設定します。
113          * @param msgdata MIDIメタメッセージのバイト列(null を指定した場合はデフォルトに戻る)
114          */
115         public void setTempo(byte msgdata[]) {
116                 if( msgdata==null ) clear(); else setTempo(MIDISpec.byteArrayToQpmTempo(msgdata));
117         }
118         public void clear() { setTempo(DEFAULT_QPM); }
119 }