OSDN Git Service

・あの楽器ConcurrentModificationException対策:別イテレータにしても回避できなかったのでsyncronizedをつけて排他制御するよう修正
authorAkiyoshi Kamide <kamide@yk.rim.or.jp>
Mon, 9 Dec 2013 17:04:45 +0000 (17:04 +0000)
committerAkiyoshi Kamide <kamide@yk.rim.or.jp>
Mon, 9 Dec 2013 17:04:45 +0000 (17:04 +0000)
・PianoKeyboard paint() でまれにNullPointerExceptionが出ることがあった(別スレッドからのため?)。null回避させるよう修正
・その他リファクタリング

git-svn-id: https://svn.sourceforge.jp/svnroot/midichordhelper/MIDIChordHelper@27 302f1594-2db2-43b1-aaa4-6307b5a2a2de

src/AnoGakki.java
src/ChordHelperApplet.java
src/MIDIDevice.java
src/MIDIMsgForm.java
src/Music.java
src/PianoKeyboard.java

index 0fef4d5..c43f815 100644 (file)
@@ -13,7 +13,6 @@ import java.awt.event.ActionListener;
 import java.awt.event.ComponentAdapter;\r
 import java.awt.event.ComponentEvent;\r
 import java.awt.geom.AffineTransform;\r
-import java.util.Collections;\r
 import java.util.Iterator;\r
 import java.util.LinkedList;\r
 import java.util.List;\r
@@ -258,10 +257,15 @@ class AnoGakkiPane extends JComponent {
                new ActionListener() {\r
                        @Override\r
                        public void actionPerformed(ActionEvent event) {\r
-                               Iterator<QueueEntry> i = queue.iterator();\r
-                               while( i.hasNext() )\r
-                                       if( i.next().countDown() <= 0 ) i.remove();\r
-                               if( queue.isEmpty() ) timer.stop();\r
+                               synchronized(queue) {\r
+                                       Iterator<QueueEntry> i = queue.iterator();\r
+                                       while( i.hasNext() ) {\r
+                                               if( i.next().countDown() <= 0 ) {\r
+                                                       i.remove();\r
+                                               }\r
+                                       }\r
+                               }\r
+                               if(queue.isEmpty()) timer.stop();\r
                                repaint();\r
                        }\r
                }\r
@@ -274,36 +278,29 @@ class AnoGakkiPane extends JComponent {
        }\r
        @Override\r
        public void paint(Graphics g) {\r
-               if( queue.isEmpty() )\r
-                       return;\r
+               if(queue.isEmpty()) return;\r
                Graphics2D g2 = (Graphics2D)g;\r
                g2.setStroke(stroke);\r
                g2.setColor(color);\r
-               //\r
-               // timer が queue.iterator() の返すイテレータで反復中という\r
-               // 絶妙なタイミングで、別スレッドでここへ来てしまった場合、\r
-               // そこで同じイテレータを使ってしまうと\r
-               // ConcurrentModificationException が投げられてしまう。\r
-               //\r
-               // これを避けるため、\r
-               // 描画時のイテレータは timer とは別のものを使うようにする。\r
-               //\r
-               Iterator<QueueEntry> i = Collections.unmodifiableList(queue).iterator();\r
-               while( i.hasNext() ) {\r
-                       QueueEntry entry = i.next();\r
-                       entry.shape.draw(g2, entry);\r
+               synchronized(queue) {\r
+                       Iterator<QueueEntry> i = queue.iterator();\r
+                       while( i.hasNext() ) {\r
+                               QueueEntry entry = i.next();\r
+                               entry.shape.draw(g2, entry);\r
+                       }\r
                }\r
        }\r
        private long prevStartedAt = System.nanoTime();\r
-       public void start(Component source, Point clicked_point) {\r
+       public void start(Component source, Point clickedPoint) {\r
                long startedAt = System.nanoTime();\r
                if( startedAt - prevStartedAt < (INTERVAL_MS * 1000)*50 ) {\r
                        // 頻繁すぎる場合は無視する\r
                        return;\r
                }\r
-               queue.add(new QueueEntry(\r
-                       SwingUtilities.convertPoint(source, clicked_point, this)\r
-               ));\r
+               clickedPoint = SwingUtilities.convertPoint(source, clickedPoint, this);\r
+               synchronized (queue) {\r
+                       queue.add(new QueueEntry(clickedPoint));\r
+               }\r
                timer.start();\r
                prevStartedAt = startedAt;\r
        }\r
index 7e3eb61..aa771a5 100644 (file)
@@ -268,7 +268,7 @@ public class ChordHelperApplet extends JApplet {
         */\r
        public static class VersionInfo {\r
                public static final String      NAME = "MIDI Chord Helper";\r
-               public static final String      VERSION = "Ver.20131209.1";\r
+               public static final String      VERSION = "Ver.20131210.1";\r
                public static final String      COPYRIGHT = "Copyright (C) 2004-2013";\r
                public static final String      AUTHER = "@きよし - Akiyoshi Kamide";\r
                public static final String      URL = "http://www.yk.rim.or.jp/~kamide/music/chordhelper/";\r
index b493031..60697dd 100644 (file)
@@ -405,63 +405,63 @@ abstract class AbstractMidiStatus extends Vector<AbstractMidiChannelStatus>
 abstract class AbstractMidiChannelStatus implements MidiChannel {\r
        protected int channel;\r
        protected int program = 0;\r
-       protected int pitch_bend = MIDISpec.PITCH_BEND_NONE;\r
-       protected int controller_values[] = new int[0x80];\r
-       protected boolean is_rhythm_part = false;\r
+       protected int pitchBend = MIDISpec.PITCH_BEND_NONE;\r
+       protected int controllerValues[] = new int[0x80];\r
+       protected boolean isRhythmPart = false;\r
 \r
        protected static final int DATA_NONE = 0;\r
        protected static final int DATA_FOR_RPN = 1;\r
        protected final int DATA_FOR_NRPN = 2;\r
-       protected int data_for = DATA_NONE;\r
+       protected int dataFor = DATA_NONE;\r
 \r
        public AbstractMidiChannelStatus(int channel) {\r
                this.channel = channel;\r
                resetAllValues(true);\r
        }\r
        public int getChannel() { return channel; }\r
-       public boolean isRhythmPart() { return is_rhythm_part; }\r
+       public boolean isRhythmPart() { return isRhythmPart; }\r
        public void setRhythmPart(boolean is_rhythm_part) {\r
-               this.is_rhythm_part = is_rhythm_part;\r
+               this.isRhythmPart = is_rhythm_part;\r
        }\r
        public void resetRhythmPart() {\r
-               is_rhythm_part = (channel == 9);\r
+               isRhythmPart = (channel == 9);\r
        }\r
        public void resetAllValues() { resetAllValues(false); }\r
        public void resetAllValues(boolean is_GS) {\r
-               for( int i=0; i<controller_values.length; i++ )\r
-                       controller_values[i] = 0;\r
+               for( int i=0; i<controllerValues.length; i++ )\r
+                       controllerValues[i] = 0;\r
                if( is_GS ) resetRhythmPart();\r
                resetAllControllers();\r
-               controller_values[10] = 0x40; // Set pan to center\r
+               controllerValues[10] = 0x40; // Set pan to center\r
        }\r
        public void fireRpnChanged() {}\r
        protected void changeRPNData( int data_diff ) {\r
-               int data_msb = controller_values[0x06];\r
-               int data_lsb = controller_values[0x26];\r
+               int dataMsb = controllerValues[0x06];\r
+               int dataLsb = controllerValues[0x26];\r
                if( data_diff != 0 ) {\r
                        // Data increment or decrement\r
-                       data_lsb += data_diff;\r
-                       if( data_lsb >= 100 ) {\r
-                               data_lsb = 0;\r
-                               controller_values[0x26] = ++data_msb;\r
+                       dataLsb += data_diff;\r
+                       if( dataLsb >= 100 ) {\r
+                               dataLsb = 0;\r
+                               controllerValues[0x26] = ++dataMsb;\r
                        }\r
-                       else if( data_lsb < 0 ) {\r
-                               data_lsb = 0;\r
-                               controller_values[0x26] = --data_msb;\r
+                       else if( dataLsb < 0 ) {\r
+                               dataLsb = 0;\r
+                               controllerValues[0x26] = --dataMsb;\r
                        }\r
-                       controller_values[0x06] = data_lsb;\r
+                       controllerValues[0x06] = dataLsb;\r
                }\r
                fireRpnChanged();\r
        }\r
        @Override\r
-       public void noteOff( int note_no ) {}\r
+       public void noteOff( int noteNumber ) {}\r
        @Override\r
-       public void noteOff( int note_no, int velocity ) {}\r
+       public void noteOff( int noteNumber, int velocity ) {}\r
        @Override\r
-       public void noteOn( int note_no, int velocity ) {}\r
+       public void noteOn( int noteNumber, int velocity ) {}\r
        @Override\r
        public int getController(int controller) {\r
-               return controller_values[controller];\r
+               return controllerValues[controller];\r
        }\r
        @Override\r
        public void programChange( int program ) {\r
@@ -476,11 +476,11 @@ abstract class AbstractMidiChannelStatus implements MidiChannel {
        @Override\r
        public int getProgram() { return program; }\r
        @Override\r
-       public void setPitchBend(int bend) { pitch_bend = bend; }\r
+       public void setPitchBend(int bend) { pitchBend = bend; }\r
        @Override\r
-       public int getPitchBend() { return pitch_bend; }\r
+       public int getPitchBend() { return pitchBend; }\r
        @Override\r
-       public void setPolyPressure(int note_no, int pressure) {}\r
+       public void setPolyPressure(int noteNumber, int pressure) {}\r
        @Override\r
        public int getPolyPressure(int noteNumber) { return 0x40; }\r
        @Override\r
@@ -500,16 +500,16 @@ abstract class AbstractMidiChannelStatus implements MidiChannel {
                //   http://www.midi.org/techspecs/rp15.php\r
                //\r
                // modulation\r
-               controller_values[0] = 0;\r
+               controllerValues[0] = 0;\r
                //\r
                // pedals\r
-               for(int i=64; i<=67; i++) controller_values[i] = 0;\r
+               for(int i=64; i<=67; i++) controllerValues[i] = 0;\r
                //\r
                // Set pitch bend to center\r
-               pitch_bend = 8192;\r
+               pitchBend = 8192;\r
                //\r
                // Set NRPN / RPN to null value\r
-               for(int i=98; i<=101; i++) controller_values[i] = 127;\r
+               for(int i=98; i<=101; i++) controllerValues[i] = 127;\r
        }\r
        @Override\r
        public boolean localControl(boolean on) {\r
@@ -536,7 +536,7 @@ abstract class AbstractMidiChannelStatus implements MidiChannel {
        public boolean getSolo() { return false; }\r
        @Override\r
        public void controlChange(int controller, int value) {\r
-               controller_values[controller] = value & 0x7F;\r
+               controllerValues[controller] = value & 0x7F;\r
                switch( controller ) {\r
 \r
                case 0x78: // All Sound Off\r
@@ -567,14 +567,14 @@ abstract class AbstractMidiChannelStatus implements MidiChannel {
                        // Non-Registered Parameter Number\r
                case 0x62: // NRPN (LSB)\r
                case 0x63: // NRPN (MSB)\r
-                       data_for = DATA_FOR_NRPN;\r
+                       dataFor = DATA_FOR_NRPN;\r
                        // fireRpnChanged();\r
                        break;\r
 \r
                        // Registered Parameter Number\r
                case 0x64: // RPN (LSB)\r
                case 0x65: // RPN (MSB)\r
-                       data_for = DATA_FOR_RPN;\r
+                       dataFor = DATA_FOR_RPN;\r
                        fireRpnChanged();\r
                        break;\r
                }\r
index 29d6f0c..fae0967 100644 (file)
@@ -992,7 +992,7 @@ class MidiChannelButtonSelecter extends JList<Integer>
                return (MidiChannelComboBoxModel)(super.getModel());\r
        }\r
        public void setPianoKeyboard(PianoKeyboard keyboard) {\r
-               (this.keyboard = keyboard).midi_ch_button_selecter = this;\r
+               (this.keyboard = keyboard).midiChannelButtonSelecter = this;\r
        }\r
        class MyCellRenderer extends JLabel implements ListCellRenderer<Integer> {\r
                private boolean cellHasFocus = false;\r
index 64d5a0c..fc613bb 100644 (file)
@@ -1250,11 +1250,11 @@ public class Music {
                 * あるかを表すインデックス値を返します。\r
                 * 構成音に該当しない場合は -1 を返します。\r
                 * ベース音は検索されません。\r
-                * @param noteNo MIDIノート番号\r
+                * @param noteNumber MIDIノート番号\r
                 * @return 構成音のインデックス値\r
                 */\r
-               public int indexOf(int noteNo) {\r
-                       int relative_note = noteNo - rootNoteSymbol.toNoteNumber();\r
+               public int indexOf(int noteNumber) {\r
+                       int relative_note = noteNumber - rootNoteSymbol.toNoteNumber();\r
                        if( mod12(relative_note) == 0 ) return 0;\r
                        int i=0;\r
                        for( int offset : offsets ) if( offset != ROOT ) {\r
index 1aecedd..469b164 100644 (file)
@@ -13,11 +13,11 @@ import java.awt.event.ComponentEvent;
 import java.awt.event.FocusEvent;\r
 import java.awt.event.FocusListener;\r
 import java.awt.event.InputEvent;\r
-import java.awt.event.KeyAdapter;\r
 import java.awt.event.KeyEvent;\r
-import java.awt.event.MouseAdapter;\r
+import java.awt.event.KeyListener;\r
 import java.awt.event.MouseEvent;\r
-import java.awt.event.MouseMotionAdapter;\r
+import java.awt.event.MouseListener;\r
+import java.awt.event.MouseMotionListener;\r
 import java.util.EventListener;\r
 import java.util.LinkedList;\r
 import java.util.Vector;\r
@@ -40,8 +40,8 @@ import javax.swing.event.ListDataEvent;
 import javax.swing.event.ListDataListener;\r
 \r
 interface PianoKeyboardListener extends EventListener {\r
-       void pianoKeyPressed(int note_no, InputEvent event);\r
-       void pianoKeyReleased(int note_no, InputEvent event);\r
+       void pianoKeyPressed(int noteNumber, InputEvent event);\r
+       void pianoKeyReleased(int noteNumber, InputEvent event);\r
        void octaveMoved(ChangeEvent e);\r
        void octaveResized(ChangeEvent e);\r
 }\r
@@ -83,33 +83,71 @@ public class PianoKeyboard extends JComponent {
        float widthPerOctave = Music.SEMITONES_PER_OCTAVE * 10;\r
 \r
        /** すべてのピアノキー */\r
-       PianoKey[] keys;\r
+       private PianoKey[] keys;\r
        /** 黒鍵 */\r
-       PianoKey[] blackKeys;\r
+       private PianoKey[] blackKeys;\r
        /** 白鍵 */\r
-       PianoKey[] whiteKeys;\r
-\r
+       private PianoKey[] whiteKeys;\r
+       /**\r
+        * オクターブ範囲モデル\r
+        */\r
        DefaultBoundedRangeModel octaveRangeModel;\r
+       /**\r
+        * オクターブ幅モデル\r
+        */\r
        DefaultBoundedRangeModel octaveSizeModel;\r
+       /**\r
+        * ベロシティモデル\r
+        */\r
        BoundedRangeModel velocityModel = new DefaultBoundedRangeModel(64, 0, 0, 127);\r
+       /**\r
+        * MIDIチャンネル選択コンボボックスモデル\r
+        */\r
        DefaultMidiChannelComboBoxModel\r
                midiChComboboxModel = new DefaultMidiChannelComboBoxModel();\r
 \r
-       NoteList selectedKeyNoteList = new NoteList();\r
-       Music.Key       keySignature = null;\r
-       Music.Chord     chord = null;\r
-\r
-       class NoteList extends LinkedList<Integer> { }\r
-\r
-       public ChordMatrix chord_matrix;\r
-       public ChordDisplay chordDisplay;\r
-       public AnoGakkiLayeredPane anoGakkiLayeredPane;\r
-       public MidiChannelButtonSelecter midi_ch_button_selecter;\r
+       /**\r
+        * ノートのリスト。配列の要素として使えるようクラス名を割り当てます。\r
+        */\r
+       class NoteList extends LinkedList<Integer> {\r
+               // 何もすることはない\r
+       }\r
+       /**\r
+        * 選択マーク●がついている鍵を表すノートリスト\r
+        */\r
+       private NoteList selectedKeyNoteList = new NoteList();\r
+       /**\r
+        * 調号(スケール判定用)\r
+        */\r
+       private Music.Key       keySignature = null;\r
+       /**\r
+        * 表示中のコード\r
+        */\r
+       private Music.Chord     chord = null;\r
+       /**\r
+        * コードボタンマトリクス\r
+        */\r
+       ChordMatrix chordMatrix;\r
+       /**\r
+        * コード表示部\r
+        */\r
+       ChordDisplay chordDisplay;\r
+       /**\r
+        * Innocence「あの楽器」\r
+        */\r
+       AnoGakkiLayeredPane anoGakkiLayeredPane;\r
+       /**\r
+        * MIDIチャンネルをボタンで選択\r
+        */\r
+       MidiChannelButtonSelecter midiChannelButtonSelecter;\r
 \r
        NoteList[] channelNotes = new NoteList[MIDISpec.MAX_CHANNELS];\r
        int[] pitchBendValues = new int[MIDISpec.MAX_CHANNELS];\r
-       int[] pitch_bend_sensitivities = new int[MIDISpec.MAX_CHANNELS];\r
+       int[] pitchBendSensitivities = new int[MIDISpec.MAX_CHANNELS];\r
        int[] modulations = new int[MIDISpec.MAX_CHANNELS];\r
+       /**\r
+        * この鍵盤の仮想MIDIデバイス\r
+        */\r
        VirtualMidiDevice midiDevice = new AbstractVirtualMidiDevice() {\r
                {\r
                        info = new MyInfo();\r
@@ -132,76 +170,78 @@ public class PianoKeyboard extends JComponent {
                public MidiChannelStatus(int channel) {\r
                        super(channel);\r
                        channelNotes[channel] = new NoteList();\r
-                       pitch_bend_sensitivities[channel] = 2; // Default is wholetone = 2 semitones\r
+                       pitchBendSensitivities[channel] = 2; // Default is wholetone = 2 semitones\r
                }\r
+               @Override\r
                public void fireRpnChanged() {\r
-                       if( data_for != DATA_FOR_RPN ) return;\r
+                       if( dataFor != DATA_FOR_RPN ) return;\r
 \r
                        // RPN (MSB) - Accept 0x00 only\r
-                       if( controller_values[0x65] != 0x00 ) return;\r
+                       if( controllerValues[0x65] != 0x00 ) return;\r
 \r
                        // RPN (LSB)\r
-                       switch( controller_values[0x64] ) {\r
+                       switch( controllerValues[0x64] ) {\r
                        case 0x00: // Pitch Bend Sensitivity\r
-                               if( controller_values[0x06] == 0 ) return;\r
-                               pitch_bend_sensitivities[channel] = controller_values[0x06];\r
+                               if( controllerValues[0x06] == 0 ) return;\r
+                               pitchBendSensitivities[channel] = controllerValues[0x06];\r
                                break;\r
                        }\r
                }\r
-               //\r
-               // MidiChannel interface\r
-               //\r
-               public void noteOff( int note_no, int velocity ) {\r
-                       noteOff(note_no);\r
+               @Override\r
+               public void noteOff(int noteNumber, int velocity) {\r
+                       noteOff(noteNumber);\r
                }\r
-               public void noteOff( int note_no ) {\r
-                       keyOff( channel, note_no );\r
-                       if( chord_matrix != null ) {\r
+               @Override\r
+               public void noteOff(int noteNumber) {\r
+                       keyOff( channel, noteNumber );\r
+                       if( chordMatrix != null ) {\r
                                if( ! isRhythmPart() )\r
-                                       chord_matrix.note(false, note_no);\r
+                                       chordMatrix.note(false, noteNumber);\r
                        }\r
-                       if( midi_ch_button_selecter != null ) {\r
-                               midi_ch_button_selecter.repaint();\r
+                       if( midiChannelButtonSelecter != null ) {\r
+                               midiChannelButtonSelecter.repaint();\r
                        }\r
                }\r
-               public void noteOn( int note_no, int velocity ) {\r
+               @Override\r
+               public void noteOn(int noteNumber, int velocity) {\r
                        if( velocity <= 0 ) {\r
-                               noteOff(note_no); return;\r
+                               noteOff(noteNumber); return;\r
                        }\r
-                       keyOn( channel, note_no );\r
+                       keyOn( channel, noteNumber );\r
                        if( midiChComboboxModel.getSelectedChannel() == channel ) {\r
                                if( chordDisplay != null ) {\r
-                                       if( chord_matrix != null && chord_matrix.isPlaying() )\r
+                                       if( chordMatrix != null && chordMatrix.isPlaying() )\r
                                                chordDisplay.setNote(-1);\r
                                        else\r
-                                               chordDisplay.setNote( note_no, isRhythmPart() );\r
+                                               chordDisplay.setNote(noteNumber, isRhythmPart());\r
                                }\r
                                if( anoGakkiLayeredPane != null ) {\r
-                                       PianoKey piano_key = getPianoKey(note_no);\r
+                                       PianoKey piano_key = getPianoKey(noteNumber);\r
                                        if( piano_key != null )\r
-                                               anoGakkiLayeredPane.start(\r
-                                                               PianoKeyboard.this, piano_key.indicator\r
-                                                               );\r
+                                               anoGakkiLayeredPane.start(PianoKeyboard.this, piano_key.indicator);\r
                                }\r
                        }\r
-                       if( chord_matrix != null ) {\r
+                       if( chordMatrix != null ) {\r
                                if( ! isRhythmPart() )\r
-                                       chord_matrix.note(true, note_no);\r
+                                       chordMatrix.note(true, noteNumber);\r
                        }\r
-                       if( midi_ch_button_selecter != null ) {\r
-                               midi_ch_button_selecter.repaint();\r
+                       if( midiChannelButtonSelecter != null ) {\r
+                               midiChannelButtonSelecter.repaint();\r
                        }\r
                }\r
+               @Override\r
                public void allNotesOff() {\r
                        allKeysOff( channel, -1 );\r
-                       if( chord_matrix != null )\r
-                               chord_matrix.clearIndicators();\r
+                       if( chordMatrix != null )\r
+                               chordMatrix.clearIndicators();\r
                }\r
+               @Override\r
                public void setPitchBend(int bend) {\r
                        super.setPitchBend(bend);\r
                        pitchBendValues[channel] = bend;\r
                        repaintNotes();\r
                }\r
+               @Override\r
                public void resetAllControllers() {\r
                        super.resetAllControllers();\r
                        //\r
@@ -212,6 +252,7 @@ public class PianoKeyboard extends JComponent {
                        modulations[channel] = 0;\r
                        repaintNotes();\r
                }\r
+               @Override\r
                public void controlChange(int controller, int value) {\r
                        super.controlChange(controller,value);\r
                        switch( controller ) {\r
@@ -233,7 +274,7 @@ public class PianoKeyboard extends JComponent {
        public MidiChannel getSelectedChannel() {\r
                return midiDevice.getChannels()[midiChComboboxModel.getSelectedChannel()];\r
        }\r
-       public void note(boolean isOn, int noteNumber) {\r
+       private void note(boolean isOn, int noteNumber) {\r
                MidiChannel ch = getSelectedChannel();\r
                int velocity = velocityModel.getValue();\r
                if( isOn )\r
@@ -244,35 +285,38 @@ public class PianoKeyboard extends JComponent {
        public void noteOn(int noteNumber) { note(true,noteNumber); }\r
        public void noteOff(int noteNumber) { note(false,noteNumber); }\r
 \r
-       class PianoKey extends Rectangle {\r
-               public boolean isBlack = false;\r
-               public int position = 0;\r
-               public String binded_key_char = null;\r
-               public Rectangle indicator;\r
-               public boolean out_of_bounds = false;\r
-               public PianoKey( Point p, Dimension d, Dimension indicator_size ) {\r
+       /**\r
+        * 1個のピアノ鍵盤を表す矩形\r
+        */\r
+       private class PianoKey extends Rectangle {\r
+               private boolean isBlack = false;\r
+               private int position = 0;\r
+               private String bindedKeyChar = null;\r
+               private Rectangle indicator;\r
+               private boolean outOfBounds = false;\r
+               public PianoKey(Point p, Dimension d, Dimension indicatorSize) {\r
                        super(p,d);\r
-                       Point indicator_position = new Point(\r
-                                       p.x + (d.width - indicator_size.width) / 2,\r
-                                       p.y + d.height - indicator_size.height - indicator_size.height / 2 + 2\r
-                                       );\r
-                       indicator = new Rectangle( indicator_position, indicator_size );\r
-               }\r
-               int getNote(int chromatic_offset) {\r
-                       int n = position + chromatic_offset;\r
-                       return (out_of_bounds = ( n > MIDISpec.MAX_NOTE_NO )) ? -1 : n;\r
-               }\r
-               boolean paintKey(Graphics2D g2, boolean is_pressed) {\r
-                       if( out_of_bounds ) return false;\r
-                       g2.fill3DRect( x, y, width, height, !is_pressed );\r
+                       Point indicatorPosition = new Point(\r
+                               p.x + (d.width - indicatorSize.width) / 2,\r
+                               p.y + d.height - indicatorSize.height - indicatorSize.height / 2 + 2\r
+                       );\r
+                       indicator = new Rectangle(indicatorPosition, indicatorSize);\r
+               }\r
+               int getNote(int chromaticOffset) {\r
+                       int n = position + chromaticOffset;\r
+                       return (outOfBounds = ( n > MIDISpec.MAX_NOTE_NO )) ? -1 : n;\r
+               }\r
+               boolean paintKey(Graphics2D g2, boolean isPressed) {\r
+                       if(outOfBounds) return false;\r
+                       g2.fill3DRect(x, y, width, height, !isPressed);\r
                        return true;\r
                }\r
                boolean paintKey(Graphics2D g2) {\r
                        return paintKey(g2,false);\r
                }\r
                boolean paintKeyBinding(Graphics2D g2) {\r
-                       if( binded_key_char == null ) return false;\r
-                       g2.drawString( binded_key_char, x + width/3, indicator.y - 2 );\r
+                       if( bindedKeyChar == null ) return false;\r
+                       g2.drawString( bindedKeyChar, x + width/3, indicator.y - 2 );\r
                        return true;\r
                }\r
                boolean paintIndicator(Graphics2D g2, boolean is_small, int pitch_bend_value) {\r
@@ -286,7 +330,7 @@ public class PianoKeyboard extends JComponent {
                        }\r
                        else {\r
                                int current_channel = midiChComboboxModel.getSelectedChannel();\r
-                               int sens = pitch_bend_sensitivities[current_channel];\r
+                               int sens = pitchBendSensitivities[current_channel];\r
                                if( sens == 0 ) {\r
                                        sens = 2;\r
                                }\r
@@ -308,81 +352,98 @@ public class PianoKeyboard extends JComponent {
                        return paintIndicator( g2, is_small, 0 );\r
                }\r
        }\r
-       //\r
-       // Constructors\r
-       //\r
+       private class MouseKeyListener\r
+               implements MouseListener, MouseMotionListener, KeyListener\r
+       {\r
+               private void pressed(int c, int n, InputEvent e) {\r
+                       keyOn(c,n);\r
+                       noteOn(n);\r
+                       firePianoKeyPressed(n,e);\r
+               }\r
+               private void released(int c, int n, InputEvent e) {\r
+                       keyOff(c,n);\r
+                       noteOff(n);\r
+                       firePianoKeyReleased(n,e);\r
+               }\r
+               public void mousePressed(MouseEvent e) {\r
+                       int n = getNote(e.getPoint());\r
+                       if( n < 0 ) return;\r
+                       int c = midiChComboboxModel.getSelectedChannel();\r
+                       if( channelNotes[c].contains(n) ) return;\r
+                       chord = null;\r
+                       pressed(c,n,e);\r
+                       requestFocusInWindow();\r
+                       repaint();\r
+               }\r
+               public void mouseReleased(MouseEvent e) {\r
+                       int c = midiChComboboxModel.getSelectedChannel();\r
+                       NoteList nl = channelNotes[c];\r
+                       if( ! nl.isEmpty() ) released(c, nl.poll(), e);\r
+               }\r
+               @Override\r
+               public void mouseEntered(MouseEvent e) {\r
+               }\r
+               @Override\r
+               public void mouseExited(MouseEvent e) {\r
+               }\r
+               @Override\r
+               public void mouseDragged(MouseEvent e) {\r
+                       int n = getNote(e.getPoint());\r
+                       if( n < 0 ) return;\r
+                       int c = midiChComboboxModel.getSelectedChannel();\r
+                       NoteList nl = channelNotes[c];\r
+                       if( nl.contains(n) ) return;\r
+                       if( ! nl.isEmpty() ) released(c, nl.poll(), e);\r
+                       pressed(c,n,e);\r
+               }\r
+               @Override\r
+               public void mouseMoved(MouseEvent e) {\r
+               }\r
+               @Override\r
+               public void mouseClicked(MouseEvent e) {\r
+               }\r
+               @Override\r
+               public void keyPressed(KeyEvent e) {\r
+                       int kc = e.getKeyCode();\r
+                       if( kc == KeyEvent.VK_LEFT || kc == KeyEvent.VK_KP_LEFT ) {\r
+                               octaveRangeModel.setValue( octaveRangeModel.getValue() - 1 );\r
+                               return;\r
+                       }\r
+                       else if( kc == KeyEvent.VK_RIGHT || kc == KeyEvent.VK_KP_RIGHT ) {\r
+                               octaveRangeModel.setValue( octaveRangeModel.getValue() + 1 );\r
+                               return;\r
+                       }\r
+                       int n = getNote(e); if( n < 0 ) return;\r
+                       int c = midiChComboboxModel.getSelectedChannel();\r
+                       if( channelNotes[c].contains(n) ) return;\r
+                       chord = null;\r
+                       pressed(c,n,e);\r
+               }\r
+               @Override\r
+               public void keyReleased(KeyEvent e) {\r
+                       int c = midiChComboboxModel.getSelectedChannel();\r
+                       int n = getNote(e);\r
+                       if( n < 0 || ! channelNotes[c].contains(n) ) return;\r
+                       released(c,n,e);\r
+               }\r
+               @Override\r
+               public void keyTyped(KeyEvent e) {\r
+               }\r
+       }\r
+       /**\r
+        * 新しいピアノキーボードを構築します。\r
+        */\r
        public PianoKeyboard() {\r
                setLayout(new BorderLayout());\r
                setFocusable(true);\r
-               addFocusListener( new FocusListener() {\r
+               addFocusListener(new FocusListener() {\r
                        public void focusGained(FocusEvent e) { repaint(); }\r
                        public void focusLost(FocusEvent e)   { repaint(); }\r
                });\r
-               addMouseListener( new MouseAdapter() {\r
-                       public void mousePressed(MouseEvent e) {\r
-                               int n = getNote(e.getPoint()); if( n < 0 ) return;\r
-                               int currentChannel = midiChComboboxModel.getSelectedChannel();\r
-                               if( channelNotes[currentChannel].contains(n) ) return;\r
-                               chord = null;\r
-                               keyOn( currentChannel, n );\r
-                               noteOn(n);\r
-                               firePianoKeyPressed( n, e );\r
-                               requestFocusInWindow();\r
-                               repaint();\r
-                       }\r
-                       public void mouseReleased(MouseEvent e) {\r
-                               int current_channel = midiChComboboxModel.getSelectedChannel();\r
-                               if( channelNotes[current_channel].isEmpty() ) return;\r
-                               int n = channelNotes[current_channel].poll();\r
-                               keyOff( current_channel, n );\r
-                               noteOff(n);\r
-                               firePianoKeyReleased( n, e );\r
-                       }\r
-               });\r
-               addMouseMotionListener( new MouseMotionAdapter() {\r
-                       public void mouseDragged(MouseEvent e) {\r
-                               int n = getNote(e.getPoint()); if( n < 0 ) return;\r
-                               int current_channel = midiChComboboxModel.getSelectedChannel();\r
-                               if( channelNotes[current_channel].contains(n) ) return;\r
-                               if( channelNotes[current_channel].size() > 0 ) {\r
-                                       int old_n = channelNotes[current_channel].poll();\r
-                                       keyOff( current_channel, old_n );\r
-                                       noteOff(old_n);\r
-                                       firePianoKeyReleased( old_n, e );\r
-                               }\r
-                               keyOn( current_channel, n );\r
-                               noteOn(n);\r
-                               firePianoKeyPressed( n, e );\r
-                       }\r
-               });\r
-               addKeyListener( new KeyAdapter() {\r
-                       public void keyPressed(KeyEvent e) {\r
-                               int key_code = e.getKeyCode();\r
-                               if( key_code == KeyEvent.VK_LEFT || key_code == KeyEvent.VK_KP_LEFT ) {\r
-                                       octaveRangeModel.setValue( octaveRangeModel.getValue() - 1 );\r
-                                       return;\r
-                               }\r
-                               else if( key_code == KeyEvent.VK_RIGHT || key_code == KeyEvent.VK_KP_RIGHT ) {\r
-                                       octaveRangeModel.setValue( octaveRangeModel.getValue() + 1 );\r
-                                       return;\r
-                               }\r
-                               int n = getNote(e); if( n < 0 ) return;\r
-                               int current_channel = midiChComboboxModel.getSelectedChannel();\r
-                               if( channelNotes[current_channel].contains(n) ) return;\r
-                               chord = null;\r
-                               keyOn( current_channel, n );\r
-                               noteOn(n);\r
-                               firePianoKeyPressed( n, e );\r
-                       }\r
-                       public void keyReleased(KeyEvent e) {\r
-                               int current_channel = midiChComboboxModel.getSelectedChannel();\r
-                               int n = getNote(e);\r
-                               if( n < 0 || ! channelNotes[current_channel].contains(n) ) return;\r
-                               keyOff( current_channel, n );\r
-                               noteOff(n);\r
-                               firePianoKeyReleased( n, e );\r
-                       }\r
-               });\r
+               MouseKeyListener mkl = new MouseKeyListener();\r
+               addMouseListener(mkl);\r
+               addMouseMotionListener(mkl);\r
+               addKeyListener(mkl);\r
                int octaves = getPerferredOctaves();\r
                octaveSizeModel = new DefaultBoundedRangeModel(\r
                        octaves, 0, MIN_OCTAVES, MAX_OCTAVES\r
@@ -405,7 +466,8 @@ public class PianoKeyboard extends JComponent {
                                }\r
                        });\r
                }};\r
-               addComponentListener( new ComponentAdapter() {\r
+               addComponentListener(new ComponentAdapter() {\r
+                       @Override\r
                        public void componentResized(ComponentEvent e) {\r
                                octaveSizeModel.setValue( getPerferredOctaves() );\r
                                octaveSizeChanged();\r
@@ -414,8 +476,8 @@ public class PianoKeyboard extends JComponent {
                midiChComboboxModel.addListDataListener(\r
                        new ListDataListener() {\r
                                public void contentsChanged(ListDataEvent e) {\r
-                                       int current_channel = midiChComboboxModel.getSelectedChannel();\r
-                                       for( int n : channelNotes[current_channel] )\r
+                                       int c = midiChComboboxModel.getSelectedChannel();\r
+                                       for( int n : channelNotes[c] )\r
                                                if( autoScroll(n) ) break;\r
                                        repaint();\r
                                }\r
@@ -460,9 +522,11 @@ public class PianoKeyboard extends JComponent {
                //\r
                // インジケータの表示\r
                for( NoteList nl : notesArray ) {\r
-                       for( int n : nl ) {\r
-                               if( (key=getPianoKey(n)) == null )\r
-                                       continue;\r
+                       if( nl == null ) continue;\r
+                       for( Integer ni : nl ) {\r
+                               if( ni == null ) continue;\r
+                               int n = ni;\r
+                               if( (key=getPianoKey(n)) == null ) continue;\r
                                boolean isOnScale = (keySignature == null || keySignature.isOnScale(n));\r
                                int chordIndex;\r
                                if( chord != null && (chordIndex = chord.indexOf(n)) >=0 ) {\r
@@ -471,17 +535,14 @@ public class PianoKeyboard extends JComponent {
                                else {\r
                                        g2.setColor(isDark && isOnScale ? Color.pink : DARK_PINK);\r
                                }\r
-                               key.paintIndicator(\r
-                                       g2, false,\r
-                                       pitchBendValues[midiChComboboxModel.getSelectedChannel()]\r
-                               );\r
+                               int c = midiChComboboxModel.getSelectedChannel();\r
+                               key.paintIndicator(g2, false, pitchBendValues[c]);\r
                                if( ! isOnScale ) {\r
                                        g2.setColor(Color.white);\r
                                        key.paintIndicator(g2, true);\r
                                }\r
                        }\r
                }\r
-\r
                if( isFocusOwner() ) {\r
                        // Show PC-key binding\r
                        for( PianoKey k : bindedKeys ) {\r
@@ -536,29 +597,25 @@ public class PianoKeyboard extends JComponent {
                return k==null ? -1 : k.getNote(getChromaticOffset());\r
        }\r
        private PianoKey getPianoKey(Point point) {\r
-               int i_white_key = point.x / whiteKeySize.width;\r
-               int i_octave = i_white_key / 7;\r
-               int i = (i_white_key -= i_octave * 7) * 2 + i_octave * 12;\r
-               if( i_white_key >= 3 ) i--;\r
-\r
+               int iWhiteKey = point.x / whiteKeySize.width;\r
+               int iOctave = iWhiteKey / 7;\r
+               int i = (iWhiteKey -= iOctave * 7) * 2 + iOctave * 12;\r
+               if( iWhiteKey >= 3 ) i--;\r
                if( i < 0 || i > keys.length-1 ) return null;\r
-\r
-               if( point.y > blackKeySize.height )\r
-                       return keys[i];\r
-\r
+               if( point.y > blackKeySize.height ) return keys[i];\r
                PianoKey k;\r
                if( i > 0 ) {\r
                        k = keys[i-1];\r
-                       if( k.isBlack && !(k.out_of_bounds) && k.contains(point) ) return k;\r
+                       if( k.isBlack && !(k.outOfBounds) && k.contains(point) ) return k;\r
                }\r
                if( i < keys.length-1 ) {\r
                        k = keys[i+1];\r
-                       if( k.isBlack && !(k.out_of_bounds) && k.contains(point) ) return k;\r
+                       if( k.isBlack && !(k.outOfBounds) && k.contains(point) ) return k;\r
                }\r
                return keys[i];\r
        }\r
 \r
-       PianoKey[]              bindedKeys;\r
+       private PianoKey[] bindedKeys;\r
        private int             bindedKeyPosition;\r
        private String  bindedKeyChars;\r
        private PianoKey getPianoKey(KeyEvent e) {\r
@@ -575,7 +632,7 @@ public class PianoKeyboard extends JComponent {
                bindedKeyPosition = from;\r
                for( int i = 0; i < bindedKeyChars.length(); i++ ) {\r
                        bindedKeys[i] = k = keys[ bindedKeyPosition + i ];\r
-                       k.binded_key_char = bindedKeyChars.substring( i, i+1 );\r
+                       k.bindedKeyChar = bindedKeyChars.substring( i, i+1 );\r
                }\r
                repaint();\r
        }\r
@@ -625,9 +682,9 @@ public class PianoKeyboard extends JComponent {
        int countKeyOn(int ch) {\r
                return channelNotes[ch].size();\r
        }\r
-       void allKeysOff(int ch, int n_marks) {\r
+       void allKeysOff(int ch, int numMarks) {\r
                if( ! selectedKeyNoteList.isEmpty() ) return;\r
-               switch(n_marks) {\r
+               switch(numMarks) {\r
                case -1:\r
                        selectedKeyNoteList = (NoteList)(channelNotes[ch].clone());\r
                        break;\r
@@ -687,8 +744,8 @@ public class PianoKeyboard extends JComponent {
                repaint();\r
        }\r
        private int     maxSelectable = 1;\r
-       void setMaxSelectable( int max_selectable ) {\r
-               this.maxSelectable = max_selectable;\r
+       void setMaxSelectable( int maxSelectable ) {\r
+               this.maxSelectable = maxSelectable;\r
        }\r
        int getMaxSelectable() { return maxSelectable; }\r
        int getChromaticOffset() {\r
@@ -781,6 +838,7 @@ class PianoKeyboardPanel extends JPanel {
                keyboard = new PianoKeyboard() {{\r
                        addPianoKeyboardListener(\r
                                new PianoKeyboardAdapter() {\r
+                                       @Override\r
                                        public void octaveResized(ChangeEvent e) {\r
                                                octaveSelecter.setBlockIncrement(getOctaves());\r
                                        }\r
@@ -870,7 +928,7 @@ class MidiKeyboardPanel extends JPanel {
        private static final Insets ZERO_INSETS = new Insets(0,0,0,0);\r
 \r
        public MidiKeyboardPanel( ChordMatrix chordMatrix ) {\r
-               keyboardCenterPanel.keyboard.chord_matrix = chordMatrix;\r
+               keyboardCenterPanel.keyboard.chordMatrix = chordMatrix;\r
                keyboardCenterPanel.keyboard.chordDisplay =\r
                        new ChordDisplay(\r
                                "MIDI Keyboard", chordMatrix, keyboardCenterPanel.keyboard\r