OSDN Git Service

リファクタリング(2013/11/10未明版)
authorAkiyoshi Kamide <kamide@yk.rim.or.jp>
Sun, 10 Nov 2013 02:50:23 +0000 (02:50 +0000)
committerAkiyoshi Kamide <kamide@yk.rim.or.jp>
Sun, 10 Nov 2013 02:50:23 +0000 (02:50 +0000)
git-svn-id: https://svn.sourceforge.jp/svnroot/midichordhelper/MIDIChordHelper@6 302f1594-2db2-43b1-aaa4-6307b5a2a2de

src/Base64Dialog.java
src/ChordHelperApplet.java
src/MIDIDevice.java
src/MIDIEditor.java
src/MIDIMsgForm.java
src/MIDISequencer.java
src/MidiChordHelper.java
src/NewSequenceDialog.java

index f4236ea..24379a4 100644 (file)
@@ -48,6 +48,10 @@ public class Base64Dialog extends JDialog implements ActionListener {
                        }\r
                }\r
        }\r
+       /**\r
+        * Base64テキスト入力ダイアログを構築します。\r
+        * @param midiEditor 親画面となるMIDIエディタ\r
+        */\r
        public Base64Dialog(MidiEditor midiEditor) {\r
                this.midiEditor = midiEditor;\r
                setTitle("Base64-encoded MIDI sequence - " + ChordHelperApplet.VersionInfo.NAME);\r
@@ -92,7 +96,7 @@ public class Base64Dialog extends JDialog implements ActionListener {
                                base64TextArea.requestFocusInWindow();\r
                                last_index = midiEditor.seqListModel.getRowCount() - 1;\r
                        }\r
-                       midiEditor.seq_selection_model.setSelectionInterval( last_index, last_index );\r
+                       midiEditor.seqSelectionModel.setSelectionInterval( last_index, last_index );\r
                        setVisible(false);\r
                }\r
                else if( obj == clearButton ) {\r
index ec1371e..122b6c4 100644 (file)
@@ -79,7 +79,7 @@ public class ChordHelperApplet extends JApplet implements MetaEventListener {
         * @return 追加先のインデックス値(0から始まる)。追加できなかったときは -1\r
         */\r
        public int addRandomSongToPlaylist(int measureLength) {\r
-               editorDialog.new_seq_dialog.setRandomChordProgression(measureLength);\r
+               editorDialog.newSequenceDialog.setRandomChordProgression(measureLength);\r
                return editorDialog.addSequence();\r
        }\r
        /**\r
@@ -154,7 +154,7 @@ public class ChordHelperApplet extends JApplet implements MetaEventListener {
         * @return MIDIファイル名(設定されていないときは空文字列)\r
         */\r
        public String getMidiFilename() {\r
-               MidiSequenceModel seq_model = deviceManager.timeRangeModel.getSequenceModel();\r
+               MidiSequenceTableModel seq_model = deviceManager.timeRangeModel.getSequenceTableModel();\r
                if( seq_model == null ) return null;\r
                String fn = seq_model.getFilename();\r
                return fn == null ? "" : fn ;\r
@@ -218,9 +218,9 @@ public class ChordHelperApplet extends JApplet implements MetaEventListener {
         * @param isVisible 表示するときtrue\r
         */\r
        public void setChordDiagramVisible(boolean isVisible) {\r
-               keyboard_split_pane.resetToPreferredSizes();\r
+               keyboardSplitPane.resetToPreferredSizes();\r
                if( ! isVisible )\r
-                       keyboard_split_pane.setDividerLocation((double)1.0);\r
+                       keyboardSplitPane.setDividerLocation((double)1.0);\r
        }\r
        /**\r
         * コードダイヤグラムをギターモードに変更します。\r
@@ -234,14 +234,14 @@ public class ChordHelperApplet extends JApplet implements MetaEventListener {
         * @param isDark ダークモードのときtrue、明るい表示のときfalse(デフォルト)\r
         */\r
        public void setDarkMode(boolean isDark) {\r
-               dark_mode_toggle_button.setSelected(isDark);\r
+               darkModeToggleButton.setSelected(isDark);\r
        }\r
        /**\r
         * バージョン情報\r
         */\r
        public static class VersionInfo {\r
                public static final String      NAME = "MIDI Chord Helper";\r
-               public static final String      VERSION = "Ver.20131031.1";\r
+               public static final String      VERSION = "Ver.20131110.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
@@ -253,7 +253,7 @@ public class ChordHelperApplet extends JApplet implements MetaEventListener {
        public String getAppletInfo() {\r
                return VersionInfo.getInfo();\r
        }\r
-       class AboutMessagePane extends JEditorPane {\r
+       private class AboutMessagePane extends JEditorPane implements ActionListener {\r
                URI uri = null;\r
                public AboutMessagePane() { this(true); }\r
                public AboutMessagePane(boolean link_enabled) {\r
@@ -301,11 +301,11 @@ public class ChordHelperApplet extends JApplet implements MetaEventListener {
                                }\r
                        });\r
                }\r
-               // バージョン情報を表示\r
-               public void showMessage() {\r
-                       JOptionPane.showMessageDialog( null, this, "Version info",\r
-                               JOptionPane.INFORMATION_MESSAGE,\r
-                               imageIcon\r
+               @Override\r
+               public void actionPerformed(ActionEvent e) {\r
+                       JOptionPane.showMessageDialog(\r
+                               null, this, "Version info",\r
+                               JOptionPane.INFORMATION_MESSAGE, imageIcon\r
                        );\r
                }\r
        }\r
@@ -322,45 +322,45 @@ public class ChordHelperApplet extends JApplet implements MetaEventListener {
        // アプリケーションのアイコンイメージ\r
        public ImageIcon imageIcon;\r
        // ボタンの余白を詰めたいときは setMargin() の引数にこれを指定する\r
-       Insets  zero_insets = new Insets(0,0,0,0);\r
+       public static final Insets      ZERO_INSETS = new Insets(0,0,0,0);\r
        //\r
-       JPanel\r
-       keyboard_sequencer_panel,\r
-       chord_guide,\r
-       sequencer_panel,\r
-       sequencer_upper_panel,\r
-       sequencer_lower_panel,\r
-       midi_io_panel;\r
-       Color\r
-       root_pane_default_bgcolor,\r
-       lyric_display_default_bgcolor;\r
-       Border\r
-       lyric_display_default_border,\r
-       dark_mode_toggle_border;\r
-       AboutMessagePane        aboutMessagePane = new AboutMessagePane();\r
-       //\r
-       JSplitPane              main_split_pane, keyboard_split_pane;\r
-       ChordTextField  lyric_display;\r
-       MidiKeyboardPanel       keyboardPanel;\r
-       ChordMatrix             chordMatrix;\r
-       ChordButtonLabel        enterButtonLabel;\r
-       InversionAndOmissionLabel       inversionOmissionButton;\r
-       JToggleButton                   dark_mode_toggle_button;\r
-       MidiDeviceManager       deviceManager;\r
-       MidiDeviceDialog        midiConnectionDialog;\r
-       MidiEditor              editorDialog;\r
-       ChordDiagram            chordDiagram;\r
-       //\r
-       // Tempo, Time signature, Key signature\r
-       //\r
-       TempoSelecter           tempo_selecter = new TempoSelecter();\r
-       TimeSignatureSelecter   timesig_selecter = new TimeSignatureSelecter();\r
-       KeySignatureLabel       keysig_label = new KeySignatureLabel();\r
-       JLabel          song_title_label = new JLabel();\r
+       private JPanel keyboardSequencerPanel;\r
+       private JPanel chordGuide;\r
+       private Color rootPaneDefaultBgcolor;\r
+       private Color lyricDisplayDefaultBgcolor;\r
+       private Border lyricDisplayDefaultBorder;\r
+       private JSplitPane mainSplitPane;\r
+       private JSplitPane keyboardSplitPane;\r
+       private ChordButtonLabel enterButtonLabel;\r
+       private ChordTextField  lyricDisplay;\r
+       private MidiKeyboardPanel keyboardPanel;\r
+       ChordMatrix chordMatrix;\r
+       private InversionAndOmissionLabel inversionOmissionButton;\r
+       private JToggleButton darkModeToggleButton;\r
+       MidiDeviceModelList     deviceManager;\r
+       MidiDeviceDialog midiConnectionDialog;\r
+       MidiEditor editorDialog;\r
+       ChordDiagram chordDiagram;\r
+       TempoSelecter tempoSelecter = new TempoSelecter() {\r
+               { setEditable(false); }\r
+       };\r
+       TimeSignatureSelecter timesigSelecter = new TimeSignatureSelecter() {\r
+               { setEditable(false); }\r
+       };\r
+       KeySignatureLabel keysigLabel = new KeySignatureLabel() {\r
+               {\r
+                       addMouseListener(new MouseAdapter() {\r
+                               public void mousePressed(MouseEvent e) {\r
+                                       chordMatrix.setKeySignature(keysigLabel.getKey());\r
+                               }\r
+                       });\r
+               }\r
+       };\r
+       JLabel songTitleLabel = new JLabel();\r
        //\r
        // あの楽器\r
        AnoGakkiLayeredPane anoGakkiLayeredPane;\r
-       JToggleButton ano_gakki_toggle_button;\r
+       JToggleButton anoGakkiToggleButton;\r
 \r
        public void init() {\r
                String imageIconPath = "images/midichordhelper.png";\r
@@ -372,37 +372,18 @@ public class ChordHelperApplet extends JApplet implements MetaEventListener {
                else {\r
                        imageIcon = new ImageIcon(imageIconUrl);\r
                }\r
-               root_pane_default_bgcolor = getContentPane().getBackground();\r
-               //\r
-               // About\r
-               JButton aboutButton = new JButton("Version info");\r
-               aboutButton.setToolTipText( VersionInfo.NAME + " " + VersionInfo.VERSION );\r
-               aboutButton.addActionListener( new ActionListener() {\r
-                       public void actionPerformed(ActionEvent e) {\r
-                               aboutMessagePane.showMessage();\r
-                       }\r
-               });\r
-               //\r
-               // Chord matrix\r
-               //\r
-               chordMatrix = new ChordMatrix();\r
-               chordMatrix.addChordMatrixListener(new ChordMatrixListener(){\r
-                       public void keySignatureChanged() {\r
-                               Music.Key capo_key = chordMatrix.getKeySignatureCapo();\r
-                               keyboardPanel.keySelecter.setKey(capo_key);\r
-                               keyboardPanel.keyboardCenterPanel.keyboard.setKeySignature(capo_key);\r
-                       }\r
-                       public void chordChanged() { chordOn(); }\r
-               });\r
-               enterButtonLabel = new ChordButtonLabel("Enter",chordMatrix);\r
-               enterButtonLabel.addMouseListener(new MouseAdapter() {\r
-                       public void mousePressed(MouseEvent e) {\r
-                               if( (e.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK) != 0 ) // RightClicked\r
-                                       chordMatrix.setSelectedChord( (Music.Chord)null );\r
-                               else\r
-                                       chordMatrix.setSelectedChord( lyric_display.getText() );\r
-                       }\r
-               });\r
+               Image iconImage = (imageIcon == null) ? null : imageIcon.getImage();\r
+               rootPaneDefaultBgcolor = getContentPane().getBackground();\r
+               chordMatrix = new ChordMatrix() {{\r
+                       addChordMatrixListener(new ChordMatrixListener(){\r
+                               public void keySignatureChanged() {\r
+                                       Music.Key capoKey = getKeySignatureCapo();\r
+                                       keyboardPanel.keySelecter.setKey(capoKey);\r
+                                       keyboardPanel.keyboardCenterPanel.keyboard.setKeySignature(capoKey);\r
+                               }\r
+                               public void chordChanged() { chordOn(); }\r
+                       });\r
+               }};\r
                chordMatrix.capoSelecter.checkbox.addItemListener(\r
                        new ItemListener() {\r
                                public void itemStateChanged(ItemEvent e) {\r
@@ -421,114 +402,50 @@ public class ChordHelperApplet extends JApplet implements MetaEventListener {
                                }\r
                        }\r
                );\r
-               // Piano keyboard\r
-               //\r
-               keyboardPanel = new MidiKeyboardPanel(chordMatrix);\r
-               keyboardPanel.keyboardCenterPanel.keyboard.addPianoKeyboardListener(\r
-                       new PianoKeyboardAdapter() {\r
-                               public void pianoKeyPressed(int n, InputEvent e) {\r
-                                       chordDiagram.clear();\r
+               keyboardPanel = new MidiKeyboardPanel(chordMatrix) {{\r
+                       keyboardCenterPanel.keyboard.addPianoKeyboardListener(\r
+                               new PianoKeyboardAdapter() {\r
+                                       public void pianoKeyPressed(int n, InputEvent e) {\r
+                                               chordDiagram.clear();\r
+                                       }\r
                                }\r
-                       }\r
-               );\r
-               keyboardPanel.keySelecter.keysigCombobox.addActionListener(\r
-                       new ActionListener() {\r
-                               public void actionPerformed(ActionEvent e) {\r
-                                       Music.Key key = keyboardPanel.keySelecter.getKey();\r
-                                       key.transpose( - chordMatrix.capoSelecter.getCapo() );\r
-                                       chordMatrix.setKeySignature(key);\r
+                       );\r
+                       keySelecter.keysigCombobox.addActionListener(\r
+                               new ActionListener() {\r
+                                       public void actionPerformed(ActionEvent e) {\r
+                                               Music.Key key = keySelecter.getKey();\r
+                                               key.transpose( - chordMatrix.capoSelecter.getCapo() );\r
+                                               chordMatrix.setKeySignature(key);\r
+                                       }\r
+                               }\r
+                       );\r
+                       keyboardCenterPanel.keyboard.setPreferredSize(new Dimension(571, 80));\r
+               }};\r
+               deviceManager = new MidiDeviceModelList(\r
+                       new Vector<VirtualMidiDevice>() {\r
+                               {\r
+                                       add(keyboardPanel.keyboardCenterPanel.keyboard.midiDevice);\r
                                }\r
                        }\r
                );\r
-               keyboardPanel.keyboardCenterPanel.keyboard.setPreferredSize(\r
-                       new Dimension( 571, 80 )\r
-               );\r
-               // MIDI connection and MIDI editor\r
-               //\r
-               Vector<VirtualMidiDevice> vmdList = new Vector<VirtualMidiDevice>();\r
-               vmdList.add(keyboardPanel.keyboardCenterPanel.keyboard.midiDevice);\r
-               deviceManager = new MidiDeviceManager(vmdList);\r
                editorDialog = new MidiEditor(deviceManager);\r
-               Image iconImage = imageIcon == null ? null : imageIcon.getImage();\r
                editorDialog.setIconImage(iconImage);\r
-               JButton editButton = new JButton(\r
-                       "Edit/Playlist/Speed", new ButtonIcon(ButtonIcon.EDIT_ICON)\r
-               );\r
-               editButton.setMargin(zero_insets);\r
-               editButton.addActionListener(\r
-                       new ActionListener() {\r
-                               public void actionPerformed(ActionEvent e) {\r
-                                       editorDialog.setVisible(true);\r
-                               }\r
-                       }\r
-               );\r
-               new DropTarget(\r
-                       this, DnDConstants.ACTION_COPY_OR_MOVE, editorDialog, true\r
-               );\r
+               new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, editorDialog, true);\r
                deviceManager.setMidiEditor(editorDialog);\r
                keyboardPanel.eventDialog = editorDialog.eventDialog;\r
-               //\r
                midiConnectionDialog = new MidiDeviceDialog(deviceManager);\r
                midiConnectionDialog.setIconImage(iconImage);\r
-               JButton midiConnectionButton = new JButton(\r
-                       "MIDI device connection",\r
-                       new ButtonIcon( ButtonIcon.MIDI_CONNECTOR_ICON )\r
-               );\r
-               midiConnectionButton.addActionListener(new ActionListener() {\r
-                       public void actionPerformed( ActionEvent event ) {\r
-                               midiConnectionDialog.setVisible(true);\r
-                       }\r
-               });\r
-               //\r
-               // Displays\r
-               //\r
-               lyric_display = new ChordTextField();\r
-               lyric_display.addActionListener( new ActionListener() {\r
-                       public void actionPerformed(ActionEvent event) {\r
-                               chordMatrix.setSelectedChord(\r
-                                       event.getActionCommand().trim().split("[ \t\r\n]")[0]\r
-                               );\r
-                       }\r
-               });\r
-               lyric_display_default_border = lyric_display.getBorder();\r
-               lyric_display_default_bgcolor = lyric_display.getBackground();\r
-               //\r
-               // Dark mode\r
-               //\r
-               dark_mode_toggle_button = new JToggleButton(\r
-                               new ButtonIcon(ButtonIcon.DARK_MODE_ICON)\r
-                               );\r
-               dark_mode_toggle_button.setMargin(zero_insets);\r
-               dark_mode_toggle_button.addItemListener(new ItemListener() {\r
-                       public void itemStateChanged(ItemEvent e) {\r
-                               innerSetDarkMode(dark_mode_toggle_button.isSelected());\r
-                       }\r
-               });\r
-               dark_mode_toggle_button.setToolTipText("Light / Dark - 明かりを点灯/消灯");\r
-               dark_mode_toggle_border = dark_mode_toggle_button.getBorder();\r
-               dark_mode_toggle_button.setBorder( null );\r
-               //\r
-               // Inversion/Omission(転回・省略音)\r
-               //\r
-               inversionOmissionButton = new InversionAndOmissionLabel();\r
-               //\r
-               // あの楽器 切り替えボタン\r
-               //\r
-               ano_gakki_toggle_button = new JToggleButton(\r
-                       new ButtonIcon(ButtonIcon.ANO_GAKKI_ICON)\r
-               );\r
-               ano_gakki_toggle_button.setOpaque(false);\r
-               ano_gakki_toggle_button.setMargin(zero_insets);\r
-               ano_gakki_toggle_button.setBorder( null );\r
-               ano_gakki_toggle_button.setToolTipText("あの楽器");\r
-               ano_gakki_toggle_button.addItemListener(\r
-                       new ItemListener() {\r
-                               public void itemStateChanged(ItemEvent e) {\r
-                                       keyboardPanel.keyboardCenterPanel.keyboard.anoGakkiLayeredPane\r
-                                       = ano_gakki_toggle_button.isSelected() ? anoGakkiLayeredPane : null ;\r
+               lyricDisplay = new ChordTextField() {{\r
+                       addActionListener(new ActionListener() {\r
+                               public void actionPerformed(ActionEvent event) {\r
+                                       chordMatrix.setSelectedChord(\r
+                                               event.getActionCommand().trim().split("[ \t\r\n]")[0]\r
+                                       );\r
                                }\r
-                       }\r
-               );\r
+                       });\r
+               }};\r
+               lyricDisplayDefaultBorder = lyricDisplay.getBorder();\r
+               lyricDisplayDefaultBgcolor = lyricDisplay.getBackground();\r
                //\r
                // Chord diagram\r
                //\r
@@ -536,40 +453,32 @@ public class ChordHelperApplet extends JApplet implements MetaEventListener {
                //\r
                // MIDI parts\r
                //\r
-               tempo_selecter.setEditable(false);\r
-               timesig_selecter.setEditable(false);\r
-               keysig_label.addMouseListener(new MouseAdapter() {\r
-                       public void mousePressed(MouseEvent e) {\r
-                               chordMatrix.setKeySignature( keysig_label.getKey() );\r
-                       }\r
-               });\r
                deviceManager.getSequencer().addMetaEventListener(this);\r
                deviceManager.timeRangeModel.addChangeListener(\r
                        new ChangeListener() {\r
                                public void stateChanged(ChangeEvent e) {\r
-                                       MidiSequenceModel seq_model = deviceManager.timeRangeModel.getSequenceModel();\r
-                                       SequenceListModel seq_list_model = editorDialog.seqListModel;\r
-                                       int i = seq_list_model.getLoadedIndex();\r
-                                       song_title_label.setText(\r
+                                       MidiSequenceTableModel sequenceTableModel = deviceManager.timeRangeModel.getSequenceTableModel();\r
+                                       int i = editorDialog.seqListModel.getLoadedIndex();\r
+                                       songTitleLabel.setText(\r
                                                "<html>"+(\r
                                                        i < 0 ? "[No MIDI file loaded]" :\r
                                                        "MIDI file " + i + ": " + (\r
-                                                       seq_model == null ||\r
-                                                       seq_model.toString() == null ||\r
-                                                       seq_model.toString().isEmpty() ?\r
+                                                       sequenceTableModel == null ||\r
+                                                       sequenceTableModel.toString() == null ||\r
+                                                       sequenceTableModel.toString().isEmpty() ?\r
                                                                "[Untitled]" :\r
-                                                               "<font color=maroon>"+seq_model+"</font>"\r
+                                                               "<font color=maroon>"+sequenceTableModel+"</font>"\r
                                                        )\r
                                                )+"</html>"\r
                                        );\r
                                        chordMatrix.setPlaying(deviceManager.timeRangeModel.timer.isRunning());\r
-                                       long current_tick_position = deviceManager.getSequencer().getTickPosition();\r
-                                       SequenceIndex seq_index = null;\r
-                                       if( seq_model != null ) {\r
-                                               seq_index = seq_model.getSequenceIndex();\r
-                                               seq_index.tickToMeasure( current_tick_position );\r
+                                       long currentTickPosition = deviceManager.getSequencer().getTickPosition();\r
+                                       SequenceTickIndex tickIndex = null;\r
+                                       if( sequenceTableModel != null ) {\r
+                                               tickIndex = sequenceTableModel.getSequenceTickIndex();\r
+                                               tickIndex.tickToMeasure(currentTickPosition);\r
                                                chordMatrix.setBeat(\r
-                                                       (byte)(seq_index.last_beat), seq_index.timesig_upper\r
+                                                       (byte)(tickIndex.lastBeat), tickIndex.timesigUpper\r
                                                );\r
                                                if(\r
                                                        deviceManager.timeRangeModel.getValueIsAdjusting()\r
@@ -579,148 +488,168 @@ public class ChordHelperApplet extends JApplet implements MetaEventListener {
                                                                ! deviceManager.getSequencer().isRecording()\r
                                                        )\r
                                                ) {\r
-                                                       MetaMessage msg = seq_index.lastTimeSignatureAt( current_tick_position );\r
-                                                       if( msg == null ) timesig_selecter.clear(); else meta(msg);\r
-                                                       msg = seq_index.lastTempoAt( current_tick_position );\r
-                                                       if( msg == null ) tempo_selecter.clear(); else meta(msg);\r
-                                                       msg = seq_index.lastKeySignatureAt( current_tick_position );\r
-                                                       if( msg == null ) keysig_label.clear(); else meta(msg);\r
+                                                       MetaMessage msg = tickIndex.lastMetaMessageAt(\r
+                                                               SequenceTickIndex.TIME_SIGNATURE, currentTickPosition\r
+                                                       );\r
+                                                       if( msg == null )\r
+                                                               timesigSelecter.clear();\r
+                                                       else\r
+                                                               meta(msg);\r
+                                                       msg = tickIndex.lastMetaMessageAt(\r
+                                                               SequenceTickIndex.TEMPO, currentTickPosition\r
+                                                       );\r
+                                                       if( msg == null )\r
+                                                               tempoSelecter.clear();\r
+                                                       else\r
+                                                               meta(msg);\r
+                                                       msg = tickIndex.lastMetaMessageAt(\r
+                                                               SequenceTickIndex.KEY_SIGNATURE, currentTickPosition\r
+                                                       );\r
+                                                       if( msg == null )\r
+                                                               keysigLabel.clear();\r
+                                                       else\r
+                                                               meta(msg);\r
                                                }\r
                                        }\r
                                }\r
                        }\r
                );\r
                deviceManager.timeRangeModel.fireStateChanged();\r
-               //\r
-               // Construct tree of panels\r
-               //\r
-               chord_guide = new JPanel();\r
-               chord_guide.setLayout(new BoxLayout( chord_guide, BoxLayout.X_AXIS ));\r
-               chord_guide.add( Box.createHorizontalStrut(2) );\r
-               chord_guide.add( chordMatrix.chordGuide );\r
-               chord_guide.add( Box.createHorizontalStrut(2) );\r
-               chord_guide.add( lyric_display );\r
-               chord_guide.add( Box.createHorizontalStrut(2) );\r
-               chord_guide.add( enterButtonLabel );\r
-               chord_guide.add( Box.createHorizontalStrut(5) );\r
-               chord_guide.add( chordMatrix.chordDisplay );\r
-               chord_guide.add( Box.createHorizontalStrut(5) );\r
-               chord_guide.add( dark_mode_toggle_button );\r
-               chord_guide.add( Box.createHorizontalStrut(5) );\r
-               chord_guide.add( ano_gakki_toggle_button );\r
-               chord_guide.add( Box.createHorizontalStrut(5) );\r
-               chord_guide.add( inversionOmissionButton );\r
-               chord_guide.add( Box.createHorizontalStrut(5) );\r
-               chord_guide.add( chordMatrix.capoSelecter );\r
-               chord_guide.add( Box.createHorizontalStrut(2) );\r
-               //\r
-               sequencer_upper_panel = new JPanel();\r
-               sequencer_upper_panel.setLayout(\r
-                       new BoxLayout( sequencer_upper_panel, BoxLayout.X_AXIS )\r
-               );\r
-               sequencer_upper_panel.add( Box.createHorizontalStrut(12) );\r
-               sequencer_upper_panel.add( keysig_label );\r
-               sequencer_upper_panel.add( Box.createHorizontalStrut(12) );\r
-               sequencer_upper_panel.add( timesig_selecter );\r
-               sequencer_upper_panel.add( Box.createHorizontalStrut(12) );\r
-               sequencer_upper_panel.add( tempo_selecter );\r
-               sequencer_upper_panel.add( Box.createHorizontalStrut(12) );\r
-               sequencer_upper_panel.add(\r
-                       new MeasureIndicator(deviceManager.timeRangeModel)\r
-               );\r
-               sequencer_upper_panel.add( Box.createHorizontalStrut(12) );\r
-               sequencer_upper_panel.add( song_title_label );\r
-               sequencer_upper_panel.add( Box.createHorizontalStrut(12) );\r
-               sequencer_upper_panel.add( editButton );\r
-               //\r
-               JButton top_button, bottom_button, backward_button, forward_button;\r
-               JToggleButton repeat_button;\r
-               sequencer_lower_panel = new JPanel();\r
-               sequencer_lower_panel.setLayout(\r
-                       new BoxLayout( sequencer_lower_panel, BoxLayout.X_AXIS )\r
-               );\r
-               sequencer_lower_panel.add( Box.createHorizontalStrut(10) );\r
-               sequencer_lower_panel.add(\r
-                       new JSlider(deviceManager.timeRangeModel)\r
-               );\r
-               sequencer_lower_panel.add(\r
-                       new TimeIndicator(deviceManager.timeRangeModel)\r
-               );\r
-               sequencer_lower_panel.add( Box.createHorizontalStrut(5) );\r
-               sequencer_lower_panel.add(\r
-                       top_button = new JButton(editorDialog.move_to_top_action)\r
-               );\r
-               sequencer_lower_panel.add(\r
-                       backward_button = new JButton(\r
-                               deviceManager.timeRangeModel.move_backward_action\r
-                       )\r
-               );\r
-               sequencer_lower_panel.add(\r
-                       new JToggleButton(deviceManager.timeRangeModel.startStopAction)\r
-               );\r
-               sequencer_lower_panel.add(\r
-                       forward_button = new JButton(\r
-                               deviceManager.timeRangeModel.move_forward_action\r
-                       )\r
-               );\r
-               sequencer_lower_panel.add(\r
-                       bottom_button = new JButton(\r
-                               editorDialog.move_to_bottom_action\r
-                       )\r
-               );\r
-               sequencer_lower_panel.add(\r
-                       repeat_button = new JToggleButton(\r
-                               deviceManager.timeRangeModel.toggle_repeat_action\r
-                       )\r
-               );\r
-               sequencer_lower_panel.add( Box.createHorizontalStrut(10) );\r
-               top_button.setMargin(zero_insets);\r
-               bottom_button.setMargin(zero_insets);\r
-               backward_button.setMargin(zero_insets);\r
-               forward_button.setMargin(zero_insets);\r
-               repeat_button.setMargin(zero_insets);\r
-               //\r
-               midi_io_panel = new JPanel();\r
-               midi_io_panel.add( midiConnectionButton );\r
-               midi_io_panel.add( aboutButton );\r
-               //\r
-               sequencer_panel = new JPanel();\r
-               sequencer_panel.setLayout(\r
-                       new BoxLayout( sequencer_panel, BoxLayout.Y_AXIS )\r
-               );\r
-               sequencer_panel.add( sequencer_upper_panel );\r
-               sequencer_panel.add( sequencer_lower_panel );\r
-               sequencer_panel.add( midi_io_panel );\r
-               //\r
-               keyboard_split_pane = new JSplitPane(\r
-                       JSplitPane.HORIZONTAL_SPLIT, keyboardPanel, chordDiagram\r
-               );\r
-               keyboard_split_pane.setOneTouchExpandable(true);\r
-               keyboard_split_pane.setResizeWeight(1.0);\r
-               keyboard_split_pane.setAlignmentX((float)0.5);\r
-               //\r
-               keyboard_sequencer_panel = new JPanel();\r
-               keyboard_sequencer_panel.setLayout(\r
-                       new BoxLayout( keyboard_sequencer_panel, BoxLayout.Y_AXIS )\r
-               );\r
-               keyboard_sequencer_panel.add(chord_guide);\r
-               keyboard_sequencer_panel.add(Box.createVerticalStrut(5));\r
-               keyboard_sequencer_panel.add(keyboard_split_pane);\r
-               keyboard_sequencer_panel.add(Box.createVerticalStrut(5));\r
-               keyboard_sequencer_panel.add(sequencer_panel);\r
-               //\r
-               main_split_pane = new JSplitPane(\r
-                       JSplitPane.VERTICAL_SPLIT,\r
-                       chordMatrix, keyboard_sequencer_panel\r
-               );\r
-               main_split_pane.setResizeWeight(0.5);\r
-               main_split_pane.setAlignmentX((float)0.5);\r
-               main_split_pane.setDividerSize(5);\r
-               //\r
-               anoGakkiLayeredPane = new AnoGakkiLayeredPane();\r
-               anoGakkiLayeredPane.add(main_split_pane);\r
+               chordGuide = new JPanel() {\r
+                       {\r
+                               setLayout(new BoxLayout(this, BoxLayout.X_AXIS));\r
+                               add( Box.createHorizontalStrut(2) );\r
+                               add( chordMatrix.chordGuide );\r
+                               add( Box.createHorizontalStrut(2) );\r
+                               add( lyricDisplay );\r
+                               add( Box.createHorizontalStrut(2) );\r
+                               add( enterButtonLabel = new ChordButtonLabel("Enter",chordMatrix) {{\r
+                                       addMouseListener(new MouseAdapter() {\r
+                                               public void mousePressed(MouseEvent e) {\r
+                                                       if( (e.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK) != 0 ) // RightClicked\r
+                                                               chordMatrix.setSelectedChord( (Music.Chord)null );\r
+                                                       else\r
+                                                               chordMatrix.setSelectedChord( lyricDisplay.getText() );\r
+                                               }\r
+                                       });\r
+                               }});\r
+                               add( Box.createHorizontalStrut(5) );\r
+                               add( chordMatrix.chordDisplay );\r
+                               add( Box.createHorizontalStrut(5) );\r
+                               add( darkModeToggleButton = new JToggleButton(new ButtonIcon(ButtonIcon.DARK_MODE_ICON)) {{\r
+                                       setMargin(ZERO_INSETS);\r
+                                       addItemListener(new ItemListener() {\r
+                                               public void itemStateChanged(ItemEvent e) {\r
+                                                       innerSetDarkMode(darkModeToggleButton.isSelected());\r
+                                               }\r
+                                       });\r
+                                       setToolTipText("Light / Dark - 明かりを点灯/消灯");\r
+                                       setBorder(null);\r
+                               }});\r
+                               add( Box.createHorizontalStrut(5) );\r
+                               add( anoGakkiToggleButton = new JToggleButton(\r
+                                       new ButtonIcon(ButtonIcon.ANO_GAKKI_ICON)\r
+                               ) {{\r
+                                       setOpaque(false);\r
+                                       setMargin(ZERO_INSETS);\r
+                                       setBorder( null );\r
+                                       setToolTipText("あの楽器");\r
+                                       addItemListener(\r
+                                               new ItemListener() {\r
+                                                       public void itemStateChanged(ItemEvent e) {\r
+                                                               keyboardPanel.keyboardCenterPanel.keyboard.anoGakkiLayeredPane\r
+                                                               = anoGakkiToggleButton.isSelected() ? anoGakkiLayeredPane : null ;\r
+                                                       }\r
+                                               }\r
+                                       );\r
+                               }} );\r
+                               add( Box.createHorizontalStrut(5) );\r
+                               add( inversionOmissionButton = new InversionAndOmissionLabel() );\r
+                               add( Box.createHorizontalStrut(5) );\r
+                               add( chordMatrix.capoSelecter );\r
+                               add( Box.createHorizontalStrut(2) );\r
+                       }\r
+               };\r
+               keyboardSequencerPanel = new JPanel() {{\r
+                       setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));\r
+                       add(chordGuide);\r
+                       add(Box.createVerticalStrut(5));\r
+                       add(keyboardSplitPane = new JSplitPane(\r
+                               JSplitPane.HORIZONTAL_SPLIT, keyboardPanel, chordDiagram\r
+                       ) {{\r
+                               setOneTouchExpandable(true);\r
+                               setResizeWeight(1.0);\r
+                               setAlignmentX((float)0.5);\r
+                       }});\r
+                       add(Box.createVerticalStrut(5));\r
+                       add(new JPanel() {{\r
+                               setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));\r
+                               add(new JPanel() {{\r
+                                       setLayout(new BoxLayout(this, BoxLayout.X_AXIS));\r
+                                       add( Box.createHorizontalStrut(12) );\r
+                                       add( keysigLabel );\r
+                                       add( Box.createHorizontalStrut(12) );\r
+                                       add( timesigSelecter );\r
+                                       add( Box.createHorizontalStrut(12) );\r
+                                       add( tempoSelecter );\r
+                                       add( Box.createHorizontalStrut(12) );\r
+                                       add( new MeasureIndicator(deviceManager.timeRangeModel) );\r
+                                       add( Box.createHorizontalStrut(12) );\r
+                                       add( songTitleLabel );\r
+                                       add( Box.createHorizontalStrut(12) );\r
+                                       add( new JButton("Edit/Playlist/Speed", new ButtonIcon(ButtonIcon.EDIT_ICON)) {{\r
+                                               setMargin(ZERO_INSETS);\r
+                                               addActionListener(editorDialog);\r
+                                       }});\r
+                               }});\r
+                               add(new JPanel() {{\r
+                                       setLayout(new BoxLayout(this, BoxLayout.X_AXIS));\r
+                                       add( Box.createHorizontalStrut(10) );\r
+                                       add( new JSlider(deviceManager.timeRangeModel));\r
+                                       add( new TimeIndicator(deviceManager.timeRangeModel) );\r
+                                       add( Box.createHorizontalStrut(5) );\r
+                                       add( new JButton(editorDialog.move_to_top_action) {{\r
+                                               setMargin(ZERO_INSETS);\r
+                                       }});\r
+                                       add(new JButton(deviceManager.timeRangeModel.moveBackwardAction) {{\r
+                                               setMargin(ZERO_INSETS);\r
+                                       }});\r
+                                       add(new JToggleButton(deviceManager.timeRangeModel.startStopAction));\r
+                                       add(new JButton(deviceManager.timeRangeModel.moveForwardAction) {{\r
+                                               setMargin(ZERO_INSETS);\r
+                                       }});\r
+                                       add(new JButton(editorDialog.move_to_bottom_action) {{\r
+                                               setMargin(ZERO_INSETS);\r
+                                       }});\r
+                                       add(new JToggleButton(deviceManager.timeRangeModel.toggleRepeatAction) {{\r
+                                               setMargin(ZERO_INSETS);\r
+                                       }});\r
+                                       add( Box.createHorizontalStrut(10) );\r
+                               }});\r
+                               add(new JPanel() {{\r
+                                       add(new JButton(\r
+                                               "MIDI device connection",\r
+                                               new ButtonIcon( ButtonIcon.MIDI_CONNECTOR_ICON )\r
+                                       ) {{\r
+                                               addActionListener(midiConnectionDialog);\r
+                                       }});\r
+                                       add(new JButton("Version info") {{\r
+                                               setToolTipText(VersionInfo.NAME + " " + VersionInfo.VERSION);\r
+                                               addActionListener(new AboutMessagePane());\r
+                                       }});\r
+                               }});\r
+                       }});\r
+               }};\r
+               mainSplitPane = new JSplitPane(\r
+                       JSplitPane.VERTICAL_SPLIT, chordMatrix, keyboardSequencerPanel\r
+               ) {{\r
+                       setResizeWeight(0.5);\r
+                       setAlignmentX((float)0.5);\r
+                       setDividerSize(5);\r
+               }};\r
+               anoGakkiLayeredPane = new AnoGakkiLayeredPane() {{ add(mainSplitPane); }};\r
                setContentPane(anoGakkiLayeredPane);\r
-               setPreferredSize( new Dimension(750,470) );\r
+               setPreferredSize(new Dimension(750,470));\r
        }\r
        /////////////////////////////////////////\r
        //\r
@@ -759,59 +688,53 @@ public class ChordHelperApplet extends JApplet implements MetaEventListener {
                case 0x05: // Lyrics(歌詞)\r
                case 0x06: // Marker\r
                case 0x03: // Sequence Name / Track Name(曲名またはトラック名)\r
-                       lyric_display.addLyric(msg.getData());\r
+                       lyricDisplay.addLyric(msg.getData());\r
                        break;\r
 \r
                case 0x51: // Tempo (3 bytes) - テンポ\r
-                       tempo_selecter.setTempo(msg.getData());\r
+                       tempoSelecter.setTempo(msg.getData());\r
                        break;\r
                case 0x58: // Time signature (4 bytes) - 拍子\r
-                       timesig_selecter.setValue(msg.getData());\r
+                       timesigSelecter.setValue(msg.getData());\r
                        break;\r
                case 0x59: // Key signature (2 bytes) : 調号\r
-                       keysig_label.setKeySignature( new Music.Key(msg.getData()) );\r
+                       keysigLabel.setKeySignature( new Music.Key(msg.getData()) );\r
                        chordMatrix.setKeySignature( new Music.Key(msg.getData()) );\r
                        break;\r
 \r
                }\r
        }\r
-       //\r
-       ///////////////////////////////////////////////////////////////\r
-       //\r
-       // Methods\r
-       //\r
-       ///////////////////////////////////////////////////////////////\r
        private void innerSetDarkMode(boolean is_dark) {\r
                Color col = is_dark ? Color.black : null;\r
                // Color fgcol = is_dark ? Color.pink : null;\r
                getContentPane().setBackground(\r
-                               is_dark ? Color.black : root_pane_default_bgcolor\r
-                               );\r
-               main_split_pane.setBackground( col );\r
-               keyboard_split_pane.setBackground( col );\r
+                       is_dark ? Color.black : rootPaneDefaultBgcolor\r
+               );\r
+               mainSplitPane.setBackground( col );\r
+               keyboardSplitPane.setBackground( col );\r
                enterButtonLabel.setDarkMode( is_dark );\r
-               chord_guide.setBackground( col );\r
-               lyric_display.setBorder( is_dark ? null : lyric_display_default_border );\r
-               lyric_display.setBackground( is_dark ?\r
-                               chordMatrix.darkModeColorset.backgrounds[2] : lyric_display_default_bgcolor\r
-                               );\r
-               lyric_display.setForeground( is_dark ? Color.white : null );\r
+               chordGuide.setBackground( col );\r
+               lyricDisplay.setBorder( is_dark ? null : lyricDisplayDefaultBorder );\r
+               lyricDisplay.setBackground( is_dark ?\r
+                       chordMatrix.darkModeColorset.backgrounds[2] : lyricDisplayDefaultBgcolor\r
+               );\r
+               lyricDisplay.setForeground( is_dark ? Color.white : null );\r
                inversionOmissionButton.setBackground( col );\r
-               ano_gakki_toggle_button.setBackground( col );\r
-               keyboard_sequencer_panel.setBackground( col );\r
+               anoGakkiToggleButton.setBackground( col );\r
+               keyboardSequencerPanel.setBackground( col );\r
                chordDiagram.setBackground( col );\r
                chordDiagram.titleLabel.setDarkMode( is_dark );\r
                chordMatrix.setDarkMode( is_dark );\r
                keyboardPanel.setDarkMode( is_dark );\r
        }\r
-       /////////////////////////////////////////////////////////////////\r
-       //\r
-       // 発音(和音)\r
-       //\r
-       // 注:この関数を直接呼ぶとアルペジオが効かないので、\r
-       // chord_matrix.setSelectedChord() を使うことを推奨\r
-       //\r
-       int[] chordOnNotes = null;\r
+\r
+       private int[] chordOnNotes = null;\r
+       /**\r
+        * 和音を発音します。\r
+        * <p>この関数を直接呼ぶとアルペジオが効かないので、\r
+        * chord_matrix.setSelectedChord() を使うことを推奨\r
+        * </p>\r
+        */\r
        public void chordOn() {\r
                Music.Chord playChord = chordMatrix.getSelectedChord();\r
                if(\r
@@ -828,8 +751,8 @@ public class ChordHelperApplet extends JApplet implements MetaEventListener {
                }\r
                if( playChord == null ) {\r
                        // もう鳴らさないので、歌詞表示に通知して終了\r
-                       if( lyric_display != null )\r
-                               lyric_display.currentChord = null;\r
+                       if( lyricDisplay != null )\r
+                               lyricDisplay.currentChord = null;\r
                        return;\r
                }\r
                // あの楽器っぽい表示\r
@@ -911,7 +834,7 @@ public class ChordHelperApplet extends JApplet implements MetaEventListener {
                        );\r
                chordDiagram.setChord(diagramChord);\r
                if( chordDiagram.recordTextButton.isSelected() )\r
-                       lyric_display.appendChord(diagramChord);\r
+                       lyricDisplay.appendChord(diagramChord);\r
        }\r
 }\r
 \r
@@ -1029,10 +952,11 @@ class ChordDisplay extends JLabel {
        }\r
 }\r
 \r
-// Inversion and Omission menu button\r
-//\r
+/**\r
+ * 転回・省略音メニューボタン\r
+ */\r
 class InversionAndOmissionLabel extends JLabel\r
-implements MouseListener, PopupMenuListener\r
+       implements MouseListener, PopupMenuListener\r
 {\r
        JPopupMenu popup_menu;\r
        ButtonGroup omission_group = new ButtonGroup();\r
index a1caed4..bb9c55b 100644 (file)
@@ -1211,28 +1211,27 @@ class MidiDeviceTree extends JTree
 }\r
 \r
 /**\r
- * MIDIã\83\87ã\83\90ã\82¤ã\82¹ã\83\9eã\83\8dã\83¼ã\82¸ã\83£ (Model)\r
+ * MIDIã\83\87ã\83\90ã\82¤ã\82¹ã\83¢ã\83\87ã\83«ã\83ªã\82¹ã\83\88\r
  */\r
-class MidiDeviceManager extends Vector<MidiConnecterListModel> {\r
+class MidiDeviceModelList extends Vector<MidiConnecterListModel> {\r
        private Sequencer sequencer = null;\r
        SpeedSliderModel speedSliderModel = null;\r
        SequencerTimeRangeModel timeRangeModel = null;\r
        MidiEditor editorDialog = null;\r
-       MidiConnecterListModel firstMidiOutModel = null;\r
-       public MidiDeviceManager( Vector<VirtualMidiDevice> vmds ) {\r
+       private MidiConnecterListModel firstMidiOutModel = null;\r
+       /**\r
+        * MIDIデバイスモデルリストを生成します。\r
+        * @param vmdList 仮想MIDIデバイスのリスト\r
+        */\r
+       public MidiDeviceModelList(List<VirtualMidiDevice> vmdList) {\r
                MidiDevice.Info[] devInfos = MidiSystem.getMidiDeviceInfo();\r
-               MidiConnecterListModel\r
-               guiModels[] = new MidiConnecterListModel[vmds.size()],\r
-               sequencerModel = null,\r
-               firstMidiInModel = null;\r
-               for( int i=0; i<vmds.size(); i++ )\r
-                       guiModels[i] = addMidiDevice(vmds.get(i));\r
-\r
+               MidiConnecterListModel guiModels[] = new MidiConnecterListModel[vmdList.size()];\r
+               MidiConnecterListModel sequencerModel = null;\r
+               MidiConnecterListModel firstMidiInModel = null;\r
+               for( int i=0; i<vmdList.size(); i++ )\r
+                       guiModels[i] = addMidiDevice(vmdList.get(i));\r
                try {\r
                        sequencer = MidiSystem.getSequencer(false);\r
-                       sequencerModel = addMidiDevice(sequencer);\r
-                       speedSliderModel = new SpeedSliderModel(sequencer);\r
-                       timeRangeModel = new SequencerTimeRangeModel(this);\r
                } catch( MidiUnavailableException e ) {\r
                        System.out.println(\r
                                ChordHelperApplet.VersionInfo.NAME +\r
@@ -1240,6 +1239,9 @@ class MidiDeviceManager extends Vector<MidiConnecterListModel> {
                        );\r
                        e.printStackTrace();\r
                }\r
+               sequencerModel = addMidiDevice(sequencer);\r
+               speedSliderModel = new SpeedSliderModel(sequencer);\r
+               timeRangeModel = new SequencerTimeRangeModel(this);\r
                for( MidiDevice.Info info : devInfos ) {\r
                        MidiDevice device;\r
                        try {\r
@@ -1247,7 +1249,7 @@ class MidiDeviceManager extends Vector<MidiConnecterListModel> {
                        } catch( MidiUnavailableException e ) {\r
                                e.printStackTrace(); continue;\r
                        }\r
-                       if( device instanceof Sequencer )  continue;\r
+                       if( device instanceof Sequencer ) continue;\r
                        if( device instanceof Synthesizer ) {\r
                                try {\r
                                        addMidiDevice(MidiSystem.getSynthesizer());\r
@@ -1300,15 +1302,27 @@ class MidiDeviceManager extends Vector<MidiConnecterListModel> {
                        sequencerModel.connectToReceiverOf(firstMidiOutModel);\r
                }\r
        }\r
-       private MidiConnecterListModel addMidiDevice( MidiDevice device ) {\r
+       /**\r
+        * 指定のMIDIデバイスからMIDIデバイスモデルを生成して追加します。\r
+        * @param device MIDIデバイス\r
+        * @return 生成されたMIDIデバイスモデル\r
+        */\r
+       private MidiConnecterListModel addMidiDevice(MidiDevice device) {\r
                MidiConnecterListModel m = new MidiConnecterListModel(device,this);\r
                addElement(m);\r
                return m;\r
        }\r
-       public void setMidiEditor( MidiEditor editorDialog ) {\r
+       /**\r
+        * MIDIエディタを設定します。\r
+        * <p>MIDIエディタが持つ仮想MIDIデバイスからMIDIデバイスモデルを生成し、\r
+        * このデバイスモデルリストに追加します。\r
+        * </p>\r
+        * @param editorDialog MIDIエディタ\r
+        */\r
+       public void setMidiEditor(MidiEditor editorDialog) {\r
                editorDialog.deviceManager = this;\r
                MidiConnecterListModel mclm = addMidiDevice(\r
-                       (this.editorDialog = editorDialog).midiDevice\r
+                       (this.editorDialog = editorDialog).virtualMidiDevice\r
                );\r
                try {\r
                        mclm.openDevice();\r
@@ -1317,20 +1331,24 @@ class MidiDeviceManager extends Vector<MidiConnecterListModel> {
                }\r
                mclm.connectToReceiverOf(firstMidiOutModel);\r
        }\r
+       /**\r
+        * MIDIシーケンサを返します。\r
+        * @return MIDIシーケンサ\r
+        */\r
        public Sequencer getSequencer() { return sequencer; }\r
+       /**\r
+        * 録音可能かどうか調べます。\r
+        * @return 録音可能ならtrue\r
+        */\r
        public boolean isRecordable() {\r
                return editorDialog != null && editorDialog.isRecordable();\r
        }\r
-       public void resetMicrosecondPosition() {\r
-               for( MidiConnecterListModel model : this )\r
-                       model.resetMicrosecondPosition();\r
-       }\r
 }\r
 \r
 /**\r
  * MIDIデバイスダイアログ (View)\r
  */\r
-class MidiDeviceDialog extends JDialog {\r
+class MidiDeviceDialog extends JDialog implements ActionListener {\r
        MidiDeviceTree deviceTree;\r
        JEditorPane deviceInfoPane = new JEditorPane("text/html","<html></html>") {\r
                {\r
@@ -1398,6 +1416,10 @@ class MidiDeviceDialog extends JDialog {
                        }\r
                });\r
        }\r
+       @Override\r
+       public void actionPerformed(ActionEvent event) {\r
+               setVisible(true);\r
+       }\r
 }\r
 \r
 /**\r
index aa77d0c..74252f1 100644 (file)
@@ -33,6 +33,9 @@ import java.net.URL;
 import java.security.AccessControlException;\r
 import java.util.ArrayList;\r
 import java.util.EventObject;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
 import java.util.Vector;\r
 \r
 import javax.sound.midi.InvalidMidiDataException;\r
@@ -83,39 +86,37 @@ import javax.swing.table.TableModel;
  *     Copyright (C) 2006-2013 Akiyoshi Kamide\r
  *     http://www.yk.rim.or.jp/~kamide/music/chordhelper/\r
  */\r
-class MidiEditor extends JDialog implements DropTargetListener, ListSelectionListener {\r
-       Insets  zero_insets = new Insets(0,0,0,0);\r
+class MidiEditor extends JDialog\r
+       implements DropTargetListener, ListSelectionListener, ActionListener\r
+{\r
+       public static final Insets      ZERO_INSETS = new Insets(0,0,0,0);\r
 \r
-       MidiDeviceManager deviceManager;\r
+       MidiDeviceModelList deviceManager;\r
 \r
-       SequenceListModel seqListModel;\r
-       JFileChooser    file_chooser = null;\r
-       Base64Dialog    base64_dialog = null;\r
-       NewSequenceDialog       new_seq_dialog;\r
+       SequenceListTableModel seqListModel;\r
+       private JFileChooser fileChooser = null;\r
+       private Base64Dialog base64Dialog = new Base64Dialog(this);\r
+       NewSequenceDialog       newSequenceDialog;\r
        MidiEventDialog eventDialog = new MidiEventDialog();\r
 \r
        MidiEvent copied_events[] = null;\r
        int copied_events_PPQ = 0;\r
 \r
-       ListSelectionModel\r
-       seq_selection_model,\r
-       track_selection_model,\r
-       event_selection_model;\r
+       ListSelectionModel seqSelectionModel;\r
+       ListSelectionModel track_selection_model;\r
+       ListSelectionModel event_selection_model;\r
 \r
-       JTable\r
-       sequence_table_view,\r
-       track_table_view,\r
-       event_table_view;\r
+       JTable sequence_table_view;\r
+       JTable track_table_view;\r
+       JTable event_table_view;\r
 \r
-       JScrollPane\r
-       scrollable_sequence_table,\r
-       scrollable_track_table_view,\r
-       scrollable_event_table_view;\r
+       JScrollPane scrollable_sequence_table;\r
+       JScrollPane scrollable_track_table_view;\r
+       JScrollPane scrollable_event_table_view;\r
 \r
-       JLabel\r
-       total_time_label,\r
-       tracks_label,\r
-       midi_events_label;\r
+       JLabel totalTimeLabel;\r
+       JLabel tracks_label;\r
+       JLabel midi_events_label;\r
 \r
        JButton\r
        add_new_sequence_button, delete_sequence_button,\r
@@ -130,13 +131,14 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
 \r
        JCheckBox pair_note_checkbox;\r
 \r
-       JButton forward_button, backward_button;\r
+       JButton forward_button;\r
+       JButton backward_button;\r
        JToggleButton play_pause_button;\r
 \r
-       JSplitPane\r
-       sequence_split_pane, track_split_pane;\r
+       JSplitPane sequence_split_pane;\r
+       JSplitPane track_split_pane;\r
 \r
-       VirtualMidiDevice midiDevice = new AbstractVirtualMidiDevice() {\r
+       VirtualMidiDevice virtualMidiDevice = new AbstractVirtualMidiDevice() {\r
                {\r
                        info = new MyInfo();\r
                        setMaxReceivers(0);\r
@@ -157,8 +159,8 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
 \r
        class MidiEventCellEditor extends AbstractCellEditor implements TableCellEditor {\r
                MidiEvent[] midi_events_to_be_removed; // 削除対象にする変更前イベント(null可)\r
-               MidiTrackModel midi_track_model; // 対象トラック\r
-               MidiSequenceModel seq_model;   // 対象シーケンス\r
+               MidiTrackTableModel midi_track_model; // 対象トラック\r
+               MidiSequenceTableModel seq_model;   // 対象シーケンス\r
                MidiEvent sel_midi_evt = null; // 選択されたイベント\r
                int sel_index = -1; // 選択されたイベントの場所\r
                long current_tick = 0; // 選択されたイベントのtick位置\r
@@ -178,17 +180,15 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                };\r
 \r
                private void setSelectedEvent() {\r
-                       seq_model = seqListModel.getSequenceModel(seq_selection_model);\r
+                       seq_model = seqListModel.getSequenceModel(seqSelectionModel);\r
                        eventDialog.midiMessageForm.durationForm.setPPQ(\r
-                                       seq_model.getSequence().getResolution()\r
-                                       );\r
-                       tick_position_model.setSequenceIndex(\r
-                                       seq_model.getSequenceIndex()\r
-                                       );\r
+                               seq_model.getSequence().getResolution()\r
+                       );\r
+                       tick_position_model.setSequenceIndex(seq_model.getSequenceTickIndex());\r
                        sel_index = -1;\r
                        current_tick = 0;\r
                        sel_midi_evt = null;\r
-                       midi_track_model = (MidiTrackModel)event_table_view.getModel();\r
+                       midi_track_model = (MidiTrackTableModel)event_table_view.getModel();\r
                        if( ! event_selection_model.isSelectionEmpty() ) {\r
                                sel_index = event_selection_model.getMinSelectionIndex();\r
                                sel_midi_evt = midi_track_model.getMidiEvent(sel_index);\r
@@ -210,9 +210,7 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                Action jump_event_action = new AbstractAction() {\r
                        { putValue(NAME,"Jump"); }\r
                        public void actionPerformed(ActionEvent e) {\r
-                               scrollToEventAt(\r
-                                               tick_position_model.getTickPosition()\r
-                                               );\r
+                               scrollToEventAt(tick_position_model.getTickPosition());\r
                                eventDialog.setVisible(false);\r
                        }\r
                };\r
@@ -231,11 +229,11 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                        { putValue(NAME,"Paste"); }\r
                        public void actionPerformed(ActionEvent e) {\r
                                long tick = tick_position_model.getTickPosition();\r
-                               ((MidiTrackModel)event_table_view.getModel()).addMidiEvents(\r
+                               ((MidiTrackTableModel)event_table_view.getModel()).addMidiEvents(\r
                                                copied_events, tick, copied_events_PPQ\r
                                                );\r
                                scrollToEventAt( tick );\r
-                               seqListModel.fireSequenceChanged(seq_selection_model);\r
+                               seqListModel.fireSequenceChanged(seqSelectionModel);\r
                                eventDialog.setVisible(false);\r
                        }\r
                };\r
@@ -300,9 +298,7 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                public MidiEventCellEditor() {\r
                        edit_event_button.setHorizontalAlignment(JButton.LEFT);\r
                        eventDialog.cancel_button.setAction(cancel_action);\r
-                       eventDialog.midiMessageForm.setOutputMidiChannels(\r
-                                       midiDevice.getChannels()\r
-                                       );\r
+                       eventDialog.midiMessageForm.setOutputMidiChannels(virtualMidiDevice.getChannels());\r
                        eventDialog.tick_position_form.setModel(tick_position_model);\r
                        edit_event_button.addActionListener(\r
                                new ActionListener() {\r
@@ -344,8 +340,8 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                        pair_note_on_off_model.addItemListener(new ItemListener() {\r
                                public void itemStateChanged(ItemEvent e) {\r
                                        eventDialog.midiMessageForm.durationForm.setEnabled(\r
-                                                       pair_note_on_off_model.isSelected()\r
-                                                       );\r
+                                               pair_note_on_off_model.isSelected()\r
+                                       );\r
                                }\r
                        });\r
                        pair_note_on_off_model.setSelected(true);\r
@@ -360,9 +356,9 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                        return "";\r
                }\r
                public Component getTableCellEditorComponent(\r
-                               JTable table, Object value, boolean isSelected,\r
-                               int row, int column\r
-                               ) {\r
+                       JTable table, Object value, boolean isSelected,\r
+                       int row, int column\r
+               ) {\r
                        edit_event_button.setText((String)value);\r
                        return edit_event_button;\r
                }\r
@@ -371,8 +367,8 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
        public Action move_to_top_action = new AbstractAction() {\r
                {\r
                        putValue( SHORT_DESCRIPTION,\r
-                                       "Move to top or previous song - 曲の先頭または前の曲へ戻る"\r
-                                       );\r
+                               "Move to top or previous song - 曲の先頭または前の曲へ戻る"\r
+                       );\r
                        putValue( LARGE_ICON_KEY, new ButtonIcon(ButtonIcon.TOP_ICON) );\r
                }\r
                public void actionPerformed( ActionEvent event ) {\r
@@ -393,79 +389,75 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
        //\r
        // Constructor\r
        //\r
-       public MidiEditor(MidiDeviceManager deviceManager) {\r
+       public MidiEditor(MidiDeviceModelList deviceManager) {\r
                this.deviceManager = deviceManager;\r
                setTitle("MIDI Editor/Playlist - MIDI Chord Helper");\r
                setBounds( 150, 200, 850, 500 );\r
                setLayout(new FlowLayout());\r
                Icon delete_icon = new ButtonIcon(ButtonIcon.X_ICON);\r
-               new DropTarget(\r
-                       this, DnDConstants.ACTION_COPY_OR_MOVE, this, true\r
-               );\r
-               total_time_label = new JLabel();\r
+               new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, this, true);\r
+               totalTimeLabel = new JLabel();\r
                //\r
                // Buttons (Sequence)\r
                //\r
                add_new_sequence_button = new JButton("New");\r
                add_new_sequence_button.setToolTipText("Generate new song - 新しい曲を生成");\r
-               add_new_sequence_button.setMargin(zero_insets);\r
+               add_new_sequence_button.setMargin(ZERO_INSETS);\r
                add_new_sequence_button.addActionListener(\r
                        new ActionListener() {\r
                                public void actionPerformed(ActionEvent e) {\r
-                                       new_seq_dialog.setVisible(true);\r
+                                       newSequenceDialog.setVisible(true);\r
                                }\r
                        }\r
                );\r
                add_midi_file_button = new JButton("Open");\r
-               add_midi_file_button.setMargin(zero_insets);\r
+               add_midi_file_button.setMargin(ZERO_INSETS);\r
                add_midi_file_button.addActionListener(\r
                        new ActionListener() {\r
                                public void actionPerformed(ActionEvent e) {\r
                                        if(\r
-                                                       file_chooser == null ||\r
-                                                       file_chooser.showOpenDialog(MidiEditor.this) != JFileChooser.APPROVE_OPTION\r
-                                                       ) return;\r
-                                       addSequenceFromMidiFile(file_chooser.getSelectedFile());\r
+                                               fileChooser == null ||\r
+                                               fileChooser.showOpenDialog(MidiEditor.this) != JFileChooser.APPROVE_OPTION\r
+                                       ) return;\r
+                                       addSequenceFromMidiFile(fileChooser.getSelectedFile());\r
                                }\r
                        }\r
                );\r
                //\r
-               play_pause_button = new JToggleButton(\r
-                               deviceManager.timeRangeModel.startStopAction\r
-                               );\r
+               play_pause_button = new JToggleButton(deviceManager.timeRangeModel.startStopAction);\r
                backward_button = new JButton(move_to_top_action);\r
-               backward_button.setMargin(zero_insets);\r
+               backward_button.setMargin(ZERO_INSETS);\r
                forward_button = new JButton(move_to_bottom_action);\r
-               forward_button.setMargin(zero_insets);\r
+               forward_button.setMargin(ZERO_INSETS);\r
                //\r
                jump_sequence_button = new JButton("Jump");\r
                jump_sequence_button.setToolTipText("Move to selected song - 選択した曲へ進む");\r
-               jump_sequence_button.setMargin(zero_insets);\r
+               jump_sequence_button.setMargin(ZERO_INSETS);\r
                jump_sequence_button.addActionListener(\r
                        new ActionListener() {\r
                                public void actionPerformed(ActionEvent e) {\r
-                                       load( seq_selection_model.getMinSelectionIndex() );\r
+                                       load( seqSelectionModel.getMinSelectionIndex() );\r
                                }\r
                        }\r
                );\r
                save_midi_file_button = new JButton("Save");\r
-               save_midi_file_button.setMargin(zero_insets);\r
+               save_midi_file_button.setMargin(ZERO_INSETS);\r
                save_midi_file_button.addActionListener(\r
                        new ActionListener() {\r
                                public void actionPerformed(ActionEvent e) {\r
-                                       if( file_chooser == null ) return;\r
+                                       if( fileChooser == null ) return;\r
                                        File midi_file;\r
-                                       MidiSequenceModel seq_model =\r
-                                                       seqListModel.getSequenceModel(seq_selection_model);\r
+                                       MidiSequenceTableModel seq_model =\r
+                                                       seqListModel.getSequenceModel(seqSelectionModel);\r
                                        String filename = seq_model.getFilename();\r
                                        if( filename != null && ! filename.isEmpty() ) {\r
                                                midi_file = new File(filename);\r
-                                               file_chooser.setSelectedFile(midi_file);\r
+                                               fileChooser.setSelectedFile(midi_file);\r
                                        }\r
-                                       if( file_chooser.showSaveDialog(MidiEditor.this) != JFileChooser.APPROVE_OPTION ) {\r
+                                       if( fileChooser.showSaveDialog(MidiEditor.this) != JFileChooser.APPROVE_OPTION ) {\r
                                                return;\r
                                        }\r
-                                       midi_file = file_chooser.getSelectedFile();\r
+                                       midi_file = fileChooser.getSelectedFile();\r
                                        if( midi_file.exists() && ! confirm(\r
                                                        "Overwrite " + midi_file.getName() + " ?\n"\r
                                                                        + midi_file.getName() + " を上書きしてよろしいですか?"\r
@@ -494,20 +486,20 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                        }\r
                );\r
                delete_sequence_button = new JButton("Delete", delete_icon);\r
-               delete_sequence_button.setMargin(zero_insets);\r
+               delete_sequence_button.setMargin(ZERO_INSETS);\r
                delete_sequence_button.addActionListener(\r
                        new ActionListener() {\r
                                public void actionPerformed(ActionEvent e) {\r
                                        if(\r
-                                                       file_chooser != null &&\r
-                                                       seqListModel.getSequenceModel(seq_selection_model).isModified() &&\r
-                                                       ! confirm(\r
-                                                                       "Selected MIDI sequence not saved - delete it ?\n" +\r
-                                                                                       "選択したMIDIシーケンスは保存されていませんが、削除しますか?"\r
-                                                                       )\r
-                                                       ) return;\r
-                                       seqListModel.removeSequence(seq_selection_model);\r
-                                       total_time_label.setText( seqListModel.getTotalLength() );\r
+                                               fileChooser != null &&\r
+                                               seqListModel.getSequenceModel(seqSelectionModel).isModified() &&\r
+                                               ! confirm(\r
+                                                       "Selected MIDI sequence not saved - delete it ?\n" +\r
+                                                       "選択したMIDIシーケンスは保存されていませんが、削除しますか?"\r
+                                               )\r
+                                       ) return;\r
+                                       seqListModel.removeSequence(seqSelectionModel);\r
+                                       totalTimeLabel.setText( seqListModel.getTotalLength() );\r
                                }\r
                        }\r
                );\r
@@ -516,24 +508,24 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                //\r
                tracks_label = new JLabel("Tracks");\r
                add_track_button = new JButton("New");\r
-               add_track_button.setMargin(zero_insets);\r
+               add_track_button.setMargin(ZERO_INSETS);\r
                add_track_button.addActionListener(\r
                                new ActionListener() {\r
                                        public void actionPerformed(ActionEvent e) {\r
-                                               seqListModel.getSequenceModel(seq_selection_model).createTrack();\r
-                                               int n_tracks = seqListModel.getSequenceModel(seq_selection_model).getRowCount();\r
+                                               seqListModel.getSequenceModel(seqSelectionModel).createTrack();\r
+                                               int n_tracks = seqListModel.getSequenceModel(seqSelectionModel).getRowCount();\r
                                                if( n_tracks > 0 ) {\r
                                                        // Select a created track\r
                                                        track_selection_model.setSelectionInterval(\r
                                                                        n_tracks - 1, n_tracks - 1\r
                                                                        );\r
                                                }\r
-                                               seqListModel.fireSequenceChanged(seq_selection_model);\r
+                                               seqListModel.fireSequenceChanged(seqSelectionModel);\r
                                        }\r
                                }\r
                                );\r
                remove_track_button = new JButton("Delete", delete_icon);\r
-               remove_track_button.setMargin(zero_insets);\r
+               remove_track_button.setMargin(ZERO_INSETS);\r
                remove_track_button.addActionListener(\r
                                new ActionListener() {\r
                                        public void actionPerformed(ActionEvent e) {\r
@@ -541,9 +533,9 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                                                                "Do you want to delete selected track ?\n選択したトラックを削除しますか?"\r
                                                                )) return;\r
                                                seqListModel.getSequenceModel(\r
-                                                               seq_selection_model\r
+                                                               seqSelectionModel\r
                                                                ).deleteTracks( track_selection_model );\r
-                                               seqListModel.fireSequenceChanged(seq_selection_model);\r
+                                               seqListModel.fireSequenceChanged(seqSelectionModel);\r
                                        }\r
                                }\r
                                );\r
@@ -555,52 +547,52 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                //\r
                event_cell_editor = new MidiEventCellEditor();\r
                add_event_button = new JButton(event_cell_editor.query_add_event_action);\r
-               add_event_button.setMargin(zero_insets);\r
+               add_event_button.setMargin(ZERO_INSETS);\r
                jump_event_button = new JButton(event_cell_editor.query_jump_event_action);\r
-               jump_event_button.setMargin(zero_insets);\r
+               jump_event_button.setMargin(ZERO_INSETS);\r
                paste_event_button = new JButton(event_cell_editor.query_paste_event_action);\r
-               paste_event_button.setMargin(zero_insets);\r
+               paste_event_button.setMargin(ZERO_INSETS);\r
                remove_event_button = new JButton("Delete", delete_icon);\r
-               remove_event_button.setMargin(zero_insets);\r
+               remove_event_button.setMargin(ZERO_INSETS);\r
                remove_event_button.addActionListener(\r
                        new ActionListener() {\r
                                public void actionPerformed(ActionEvent e) {\r
                                        if( ! confirm(\r
                                                        "Do you want to delete selected event ?\n選択したMIDIイベントを削除しますか?"\r
                                                        )) return;\r
-                                       ((MidiTrackModel)event_table_view.getModel()).removeMidiEvents( event_selection_model );\r
-                                       seqListModel.fireSequenceChanged(seq_selection_model);\r
+                                       ((MidiTrackTableModel)event_table_view.getModel()).removeMidiEvents( event_selection_model );\r
+                                       seqListModel.fireSequenceChanged(seqSelectionModel);\r
                                }\r
                        }\r
                );\r
                cut_event_button = new JButton("Cut");\r
-               cut_event_button.setMargin(zero_insets);\r
+               cut_event_button.setMargin(ZERO_INSETS);\r
                cut_event_button.addActionListener(\r
                        new ActionListener() {\r
                                public void actionPerformed(ActionEvent e) {\r
                                        if( ! confirm(\r
                                                        "Do you want to cut selected event ?\n選択したMIDIイベントを切り取りますか?"\r
                                                        )) return;\r
-                                       MidiTrackModel track_model = (MidiTrackModel)event_table_view.getModel();\r
+                                       MidiTrackTableModel track_model = (MidiTrackTableModel)event_table_view.getModel();\r
                                        copied_events = track_model.getMidiEvents( event_selection_model );\r
                                        copied_events_PPQ = seqListModel.getSequenceModel(\r
-                                                       seq_selection_model\r
+                                                       seqSelectionModel\r
                                                        ).getSequence().getResolution();\r
                                        track_model.removeMidiEvents( copied_events );\r
-                                       seqListModel.fireSequenceChanged(seq_selection_model);\r
+                                       seqListModel.fireSequenceChanged(seqSelectionModel);\r
                                }\r
                        }\r
                );\r
                copy_event_button = new JButton("Copy");\r
-               copy_event_button.setMargin(zero_insets);\r
+               copy_event_button.setMargin(ZERO_INSETS);\r
                copy_event_button.addActionListener(\r
                        new ActionListener() {\r
                                public void actionPerformed(ActionEvent e) {\r
-                                       copied_events = ((MidiTrackModel)event_table_view.getModel()).getMidiEvents(\r
+                                       copied_events = ((MidiTrackTableModel)event_table_view.getModel()).getMidiEvents(\r
                                                        event_selection_model\r
                                                        );\r
                                        copied_events_PPQ = seqListModel.getSequenceModel(\r
-                                                       seq_selection_model\r
+                                                       seqSelectionModel\r
                                                        ).getSequence().getResolution();\r
                                        updateButtonStatus();\r
                                }\r
@@ -611,21 +603,21 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                //\r
                // Tables\r
                //\r
-               MidiSequenceModel empty_track_table_model = new MidiSequenceModel(\r
-                       seqListModel = new SequenceListModel(deviceManager)\r
+               MidiSequenceTableModel empty_track_table_model = new MidiSequenceTableModel(\r
+                       seqListModel = new SequenceListTableModel(deviceManager)\r
                );\r
                sequence_table_view = new JTable( seqListModel );\r
                track_table_view = new JTable( empty_track_table_model );\r
-               event_table_view = new JTable( new MidiTrackModel() );\r
+               event_table_view = new JTable( new MidiTrackTableModel() );\r
                //\r
                seqListModel.sizeColumnWidthToFit( sequence_table_view );\r
                //\r
                TableColumnModel track_column_model = track_table_view.getColumnModel();\r
                empty_track_table_model.sizeColumnWidthToFit(track_column_model);\r
                //\r
-               seq_selection_model = sequence_table_view.getSelectionModel();\r
-               seq_selection_model.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );\r
-               seq_selection_model.addListSelectionListener(\r
+               seqSelectionModel = sequence_table_view.getSelectionModel();\r
+               seqSelectionModel.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );\r
+               seqSelectionModel.addListSelectionListener(\r
                        new ListSelectionListener() {\r
                                public void valueChanged(ListSelectionEvent e) {\r
                                        if( e.getValueIsAdjusting() ) return;\r
@@ -652,29 +644,28 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                scrollable_event_table_view\r
                = new JScrollPane(event_table_view);\r
 \r
-               base64_dialog = new Base64Dialog(this);\r
-               if( base64_dialog.isBase64Available() ) {\r
+               if( base64Dialog.isBase64Available() ) {\r
                        base64_encode_button = new JButton( "Base64 Encode" );\r
-                       base64_encode_button.setMargin(zero_insets);\r
+                       base64_encode_button.setMargin(ZERO_INSETS);\r
                        base64_encode_button.addActionListener(\r
                                new ActionListener() {\r
                                        public void actionPerformed(ActionEvent e) {\r
-                                               MidiSequenceModel seq_model =\r
-                                                               seqListModel.getSequenceModel(seq_selection_model);\r
-                                               base64_dialog.setMIDIData(\r
-                                                               seq_model.getMIDIdata(), seq_model.getFilename()\r
-                                                               );\r
-                                               base64_dialog.setVisible(true);\r
+                                               MidiSequenceTableModel seq_model =\r
+                                                               seqListModel.getSequenceModel(seqSelectionModel);\r
+                                               base64Dialog.setMIDIData(\r
+                                                       seq_model.getMIDIdata(), seq_model.getFilename()\r
+                                               );\r
+                                               base64Dialog.setVisible(true);\r
                                        }\r
                                }\r
                        );\r
                }\r
-               new_seq_dialog = new NewSequenceDialog(this);\r
-               new_seq_dialog.setChannels( midiDevice.getChannels() );\r
+               newSequenceDialog = new NewSequenceDialog(this);\r
+               newSequenceDialog.setChannels(virtualMidiDevice.getChannels());\r
 \r
                JPanel button_panel = new JPanel();\r
                button_panel.setLayout( new BoxLayout( button_panel, BoxLayout.LINE_AXIS ) );\r
-               button_panel.add( total_time_label );\r
+               button_panel.add( totalTimeLabel );\r
                button_panel.add( Box.createRigidArea(new Dimension(10, 0)) );\r
                button_panel.add( add_new_sequence_button );\r
                button_panel.add( Box.createRigidArea(new Dimension(5, 0)) );\r
@@ -708,25 +699,25 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                playlist_panel.add( Box.createRigidArea(new Dimension(0, 10)) );\r
 \r
                sequenceSelectionChanged();\r
-               total_time_label.setText( seqListModel.getTotalLength() );\r
+               totalTimeLabel.setText( seqListModel.getTotalLength() );\r
 \r
                try {\r
-                       file_chooser = new JFileChooser();\r
+                       fileChooser = new JFileChooser();\r
                        FileNameExtensionFilter filter = new FileNameExtensionFilter(\r
-                                       "MIDI sequence (*.mid)", "mid"\r
-                                       );\r
-                       file_chooser.setFileFilter(filter);\r
+                               "MIDI sequence (*.mid)", "mid"\r
+                       );\r
+                       fileChooser.setFileFilter(filter);\r
                }\r
                catch( ExceptionInInitializerError e ) {\r
-                       file_chooser = null;\r
+                       fileChooser = null;\r
                }\r
                catch( NoClassDefFoundError e ) {\r
-                       file_chooser = null;\r
+                       fileChooser = null;\r
                }\r
                catch( AccessControlException e ) {\r
-                       file_chooser = null;\r
+                       fileChooser = null;\r
                }\r
-               if( file_chooser == null ) {\r
+               if( fileChooser == null ) {\r
                        // Applet cannot access local files\r
                        add_midi_file_button.setVisible(false);\r
                        save_midi_file_button.setVisible(false);\r
@@ -775,7 +766,7 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                cp.add(Box.createVerticalStrut(2));\r
                cp.add(sequence_split_pane);\r
                //\r
-               seq_selection_model.setSelectionInterval(0,0);\r
+               seqSelectionModel.setSelectionInterval(0,0);\r
                updateButtonStatus();\r
        }\r
        public void dragEnter(DropTargetDragEvent event) {\r
@@ -810,20 +801,20 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                Object src = e.getSource();\r
                if( src == track_selection_model ) {\r
                        if(\r
-                               seqListModel.getSequenceModel(seq_selection_model) == null\r
+                               seqListModel.getSequenceModel(seqSelectionModel) == null\r
                                ||\r
                                track_selection_model.isSelectionEmpty()\r
                        ) {\r
                                midi_events_label.setText("MIDI Events (No track selected)");\r
-                               event_table_view.setModel(new MidiTrackModel());\r
+                               event_table_view.setModel(new MidiTrackTableModel());\r
                        }\r
                        else {\r
                                int sel_index = track_selection_model.getMinSelectionIndex();\r
-                               MidiTrackModel track_model\r
-                               = seqListModel.getSequenceModel(seq_selection_model).getTrackModel(sel_index);\r
+                               MidiTrackTableModel track_model\r
+                               = seqListModel.getSequenceModel(seqSelectionModel).getTrackModel(sel_index);\r
                                if( track_model == null ) {\r
                                        midi_events_label.setText("MIDI Events (No track selected)");\r
-                                       event_table_view.setModel(new MidiTrackModel());\r
+                                       event_table_view.setModel(new MidiTrackTableModel());\r
                                }\r
                                else {\r
                                        midi_events_label.setText(\r
@@ -832,7 +823,7 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                                        event_table_view.setModel(track_model);\r
                                        TableColumnModel tcm = event_table_view.getColumnModel();\r
                                        track_model.sizeColumnWidthToFit(tcm);\r
-                                       tcm.getColumn( MidiTrackModel.COLUMN_MESSAGE ).setCellEditor(event_cell_editor);\r
+                                       tcm.getColumn( MidiTrackTableModel.COLUMN_MESSAGE ).setCellEditor(event_cell_editor);\r
                                }\r
                        }\r
                        updateButtonStatus();\r
@@ -840,8 +831,8 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                }\r
                else if( src == event_selection_model ) {\r
                        if( ! event_selection_model.isSelectionEmpty() ) {\r
-                               MidiTrackModel track_model\r
-                               = (MidiTrackModel)event_table_view.getModel();\r
+                               MidiTrackTableModel track_model\r
+                               = (MidiTrackTableModel)event_table_view.getModel();\r
                                int min_index = event_selection_model.getMinSelectionIndex();\r
                                if( track_model.hasTrack() ) {\r
                                        MidiEvent midi_event = track_model.getMidiEvent(min_index);\r
@@ -851,7 +842,7 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                                                int cmd = sm.getCommand();\r
                                                if( cmd == 0x80 || cmd == 0x90 || cmd == 0xA0 ) {\r
                                                        // ノート番号を持つ場合、音を鳴らす。\r
-                                                       MidiChannel out_midi_channels[] = midiDevice.getChannels();\r
+                                                       MidiChannel out_midi_channels[] = virtualMidiDevice.getChannels();\r
                                                        int ch = sm.getChannel();\r
                                                        int note = sm.getData1();\r
                                                        int vel = sm.getData2();\r
@@ -903,13 +894,20 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                        JOptionPane.WARNING_MESSAGE\r
                ) == JOptionPane.YES_OPTION ;\r
        }\r
-       public void setVisible(boolean is_to_visible) {\r
-               if( is_to_visible && isVisible() ) toFront();\r
-               else super.setVisible(is_to_visible);\r
+       @Override\r
+       public void setVisible(boolean isToVisible) {\r
+               if( isToVisible && isVisible() )\r
+                       toFront();\r
+               else\r
+                       super.setVisible(isToVisible);\r
+       }\r
+       @Override\r
+       public void actionPerformed(ActionEvent e) {\r
+               setVisible(true);\r
        }\r
        public void sequenceSelectionChanged() {\r
-               MidiSequenceModel seq_model\r
-               = seqListModel.getSequenceModel(seq_selection_model);\r
+               MidiSequenceTableModel seq_model\r
+               = seqListModel.getSequenceModel(seqSelectionModel);\r
                jump_sequence_button.setEnabled( seq_model != null );\r
                save_midi_file_button.setEnabled( seq_model != null );\r
                add_track_button.setEnabled( seq_model != null );\r
@@ -917,12 +915,12 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                        base64_encode_button.setEnabled( seq_model != null );\r
 \r
                if( seq_model != null ) {\r
-                       int sel_index = seq_selection_model.getMinSelectionIndex();\r
+                       int sel_index = seqSelectionModel.getMinSelectionIndex();\r
                        delete_sequence_button.setEnabled(true);\r
                        track_table_view.setModel(seq_model);\r
                        TableColumnModel tcm = track_table_view.getColumnModel();\r
                        seq_model.sizeColumnWidthToFit(tcm);\r
-                       tcm.getColumn(MidiSequenceModel.COLUMN_RECORD_CHANNEL).setCellEditor(\r
+                       tcm.getColumn(MidiSequenceTableModel.COLUMN_RECORD_CHANNEL).setCellEditor(\r
                                        seq_model.new RecordChannelCellEditor()\r
                                        );\r
                        track_selection_model.setSelectionInterval(0,0);\r
@@ -933,7 +931,7 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                }\r
                else {\r
                        delete_sequence_button.setEnabled(false);\r
-                       track_table_view.setModel(new MidiSequenceModel(seqListModel));\r
+                       track_table_view.setModel(new MidiSequenceTableModel(seqListModel));\r
                        tracks_label.setText("Tracks (No MIDI file selected)");\r
                }\r
                updateButtonStatus();\r
@@ -942,18 +940,18 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                boolean is_track_selected = (\r
                                ! track_selection_model.isSelectionEmpty()\r
                                &&\r
-                               seqListModel.getSequenceModel(seq_selection_model) != null\r
+                               seqListModel.getSequenceModel(seqSelectionModel) != null\r
                                &&\r
-                               seqListModel.getSequenceModel(seq_selection_model).getRowCount() > 0\r
+                               seqListModel.getSequenceModel(seqSelectionModel).getRowCount() > 0\r
                                );\r
                //\r
                // Track list\r
                remove_track_button.setEnabled( is_track_selected );\r
                //\r
                TableModel tm = event_table_view.getModel();\r
-               if( ! (tm instanceof MidiTrackModel) ) return;\r
+               if( ! (tm instanceof MidiTrackTableModel) ) return;\r
                //\r
-               MidiTrackModel track_model = (MidiTrackModel)tm;\r
+               MidiTrackTableModel track_model = (MidiTrackTableModel)tm;\r
                jump_sequence_button.setEnabled(\r
                                track_model != null && track_model.getRowCount() > 0\r
                                );\r
@@ -979,28 +977,28 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                                );\r
        }\r
        public String getMIDIdataBase64() {\r
-               base64_dialog.setMIDIData(\r
-                               deviceManager.timeRangeModel.getSequenceModel().getMIDIdata()\r
-                               );\r
-               return base64_dialog.getBase64Data();\r
+               base64Dialog.setMIDIData(\r
+                       deviceManager.timeRangeModel.getSequenceTableModel().getMIDIdata()\r
+               );\r
+               return base64Dialog.getBase64Data();\r
        }\r
        public int addSequence() {\r
-               return addSequence(new_seq_dialog.getMidiSequence());\r
+               return addSequence(newSequenceDialog.getMidiSequence());\r
        }\r
        public int addSequence(Sequence seq) {\r
-               int last_index = seqListModel.addSequence(seq);\r
-               total_time_label.setText( seqListModel.getTotalLength() );\r
+               int lastIndex = seqListModel.addSequence(seq);\r
+               totalTimeLabel.setText( seqListModel.getTotalLength() );\r
                if( ! deviceManager.getSequencer().isRunning() ) {\r
-                       loadAndPlay(last_index);\r
+                       loadAndPlay(lastIndex);\r
                }\r
-               return last_index;\r
+               return lastIndex;\r
        }\r
        public int addSequenceFromBase64Text(String base64_encoded_text, String filename) {\r
-               base64_dialog.setBase64Data( base64_encoded_text );\r
-               return addSequenceFromMidiData( base64_dialog.getMIDIData(), filename );\r
+               base64Dialog.setBase64Data( base64_encoded_text );\r
+               return addSequenceFromMidiData( base64Dialog.getMIDIData(), filename );\r
        }\r
        public int addSequenceFromBase64Text() {\r
-               return addSequenceFromMidiData( base64_dialog.getMIDIData(), null );\r
+               return addSequenceFromMidiData( base64Dialog.getMIDIData(), null );\r
        }\r
        public int addSequenceFromMidiData(byte[] data, String filename) {\r
                int last_index;\r
@@ -1010,7 +1008,7 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                        showWarning("MIDI data invalid");\r
                        return -1;\r
                }\r
-               total_time_label.setText( seqListModel.getTotalLength() );\r
+               totalTimeLabel.setText( seqListModel.getTotalLength() );\r
                return last_index;\r
        }\r
        public int addSequenceFromMidiFile(File midi_file) {\r
@@ -1028,7 +1026,7 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                        e.printStackTrace();\r
                        return -1;\r
                }\r
-               total_time_label.setText( seqListModel.getTotalLength() );\r
+               totalTimeLabel.setText( seqListModel.getTotalLength() );\r
                return last_index;\r
        }\r
        public int addSequenceFromURL(String midi_file_url) {\r
@@ -1043,7 +1041,7 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                        e.printStackTrace();\r
                        return -1;\r
                }\r
-               total_time_label.setText( seqListModel.getTotalLength() );\r
+               totalTimeLabel.setText( seqListModel.getTotalLength() );\r
                return last_index;\r
        }\r
        public void load(int index) {\r
@@ -1060,7 +1058,7 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                deviceManager.timeRangeModel.start();\r
        }\r
        public void loadAndPlay() {\r
-               loadAndPlay( seq_selection_model.getMinSelectionIndex() );\r
+               loadAndPlay( seqSelectionModel.getMinSelectionIndex() );\r
        }\r
        public void loadAndPlay( java.util.List<File> fileList ) {\r
                int lastIndex = -1;\r
@@ -1080,12 +1078,12 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
                return seqListModel.isModified();\r
        }\r
        public boolean isRecordable() {\r
-               MidiSequenceModel seq_model =\r
-                               seqListModel.getSequenceModel(seq_selection_model);\r
+               MidiSequenceTableModel seq_model =\r
+                               seqListModel.getSequenceModel(seqSelectionModel);\r
                return seq_model == null ? false : seq_model.isRecordable();\r
        }\r
        public void scrollToEventAt( long tick ) {\r
-               MidiTrackModel track_model = (MidiTrackModel)event_table_view.getModel();\r
+               MidiTrackTableModel track_model = (MidiTrackTableModel)event_table_view.getModel();\r
                scrollToEventAt( track_model.tickToIndex(tick) );\r
        }\r
        public void scrollToEventAt( int index ) {\r
@@ -1096,12 +1094,10 @@ class MidiEditor extends JDialog implements DropTargetListener, ListSelectionLis
        }\r
 }\r
 \r
-/////////////////////////////////////////////////////////////\r
-//\r
-// プレイリスト\r
-//\r
-class SequenceListModel extends AbstractTableModel\r
-{\r
+/**\r
+ * プレイリスト(MIDIシーケンスリスト)のテーブルモデル\r
+ */\r
+class SequenceListTableModel extends AbstractTableModel implements ChangeListener {\r
        public static final int COLUMN_SEQ_NUMBER       = 0;\r
        public static final int COLUMN_MODIFIED = 1;\r
        public static final int COLUMN_DIVISION_TYPE    = 2;\r
@@ -1111,7 +1107,7 @@ class SequenceListModel extends AbstractTableModel
        public static final int COLUMN_SEQ_LENGTH       = 6;\r
        public static final int COLUMN_FILENAME = 7;\r
        public static final int COLUMN_SEQ_NAME = 8;\r
-       static String column_titles[] = {\r
+       private static final String COLUMN_TITLES[] = {\r
                "No.",\r
                "Modified",\r
                "DivType",\r
@@ -1122,36 +1118,30 @@ class SequenceListModel extends AbstractTableModel
                "Filename",\r
                "Sequence name",\r
        };\r
-       static int column_width_ratios[] = {\r
+       private static final int COLUMN_WIDTH_RATIOS[] = {\r
                2, 6, 6, 6, 6, 6, 6, 16, 40,\r
        };\r
-\r
-       private ArrayList<MidiSequenceModel>\r
-       sequences = new ArrayList<MidiSequenceModel>();\r
-\r
-       MidiDeviceManager device_manager;\r
-       int second_position = 0;\r
-\r
-       public SequenceListModel( MidiDeviceManager device_manager ) {\r
-               (this.device_manager = device_manager).timeRangeModel.addChangeListener(\r
-                               new ChangeListener() {\r
-                                       public void stateChanged(ChangeEvent e) {\r
-                                               int sec_pos = SequenceListModel.this.device_manager.timeRangeModel.getValue() / 1000;\r
-                                               if( second_position == sec_pos ) return;\r
-                                               second_position = sec_pos;\r
-                                               fireTableCellUpdated( getLoadedIndex(), COLUMN_SEQ_POSITION );\r
-                                       }\r
-                               }\r
-                               );\r
-       }\r
-\r
-       // TableModel\r
-       //\r
-       public int getRowCount() { return sequences.size(); }\r
-       public int getColumnCount() { return column_titles.length; }\r
-       public String getColumnName(int column) {\r
-               return column_titles[column];\r
+       private List<MidiSequenceTableModel> sequenceList = new ArrayList<>();\r
+       MidiDeviceModelList deviceManager;\r
+       /**\r
+        * 新しいプレイリストのテーブルモデルを構築します。\r
+        * @param deviceManager MIDIデバイスマネージャ\r
+        */\r
+       public SequenceListTableModel(MidiDeviceModelList deviceManager) {\r
+               (this.deviceManager = deviceManager).timeRangeModel.addChangeListener(this);\r
+       }\r
+       private int secondPosition = 0;\r
+       @Override\r
+       public void stateChanged(ChangeEvent e) {\r
+               int sec = deviceManager.timeRangeModel.getValue() / 1000;\r
+               if( secondPosition == sec )\r
+                       return;\r
+               secondPosition = sec;\r
+               fireTableCellUpdated(getLoadedIndex(), COLUMN_SEQ_POSITION);\r
        }\r
+       public int getRowCount() { return sequenceList.size(); }\r
+       public int getColumnCount() { return COLUMN_TITLES.length; }\r
+       public String getColumnName(int column) { return COLUMN_TITLES[column]; }\r
        public Class<?> getColumnClass(int column) {\r
                switch(column) {\r
                case COLUMN_MODIFIED: return Boolean.class;\r
@@ -1164,9 +1154,9 @@ class SequenceListModel extends AbstractTableModel
        public Object getValueAt(int row, int column) {\r
                switch(column) {\r
                case COLUMN_SEQ_NUMBER: return row;\r
-               case COLUMN_MODIFIED: return sequences.get(row).isModified();\r
+               case COLUMN_MODIFIED: return sequenceList.get(row).isModified();\r
                case COLUMN_DIVISION_TYPE: {\r
-                       float div_type = sequences.get(row).getSequence().getDivisionType();\r
+                       float div_type = sequenceList.get(row).getSequence().getDivisionType();\r
                        if( div_type == Sequence.PPQ ) return "PPQ";\r
                        else if( div_type == Sequence.SMPTE_24 ) return "SMPTE_24";\r
                        else if( div_type == Sequence.SMPTE_25 ) return "SMPTE_25";\r
@@ -1174,26 +1164,26 @@ class SequenceListModel extends AbstractTableModel
                        else if( div_type == Sequence.SMPTE_30DROP ) return "SMPTE_30DROP";\r
                        else return "[Unknown]";\r
                }\r
-               case COLUMN_RESOLUTION: return sequences.get(row).getSequence().getResolution();\r
-               case COLUMN_TRACKS: return sequences.get(row).getSequence().getTracks().length;\r
+               case COLUMN_RESOLUTION: return sequenceList.get(row).getSequence().getResolution();\r
+               case COLUMN_TRACKS: return sequenceList.get(row).getSequence().getTracks().length;\r
                case COLUMN_SEQ_POSITION: {\r
-                       Sequence loaded_seq = device_manager.getSequencer().getSequence();\r
-                       if( loaded_seq != null && loaded_seq == sequences.get(row).getSequence() )\r
-                               return String.format( "%02d:%02d", second_position/60, second_position%60 );\r
+                       Sequence loaded_seq = deviceManager.getSequencer().getSequence();\r
+                       if( loaded_seq != null && loaded_seq == sequenceList.get(row).getSequence() )\r
+                               return String.format("%02d:%02d", secondPosition/60, secondPosition%60);\r
                        else\r
                                return "";\r
                }\r
                case COLUMN_SEQ_LENGTH: {\r
-                       long usec = sequences.get(row).getSequence().getMicrosecondLength();\r
+                       long usec = sequenceList.get(row).getSequence().getMicrosecondLength();\r
                        int sec = (int)( (usec < 0 ? usec += 0x100000000L : usec) / 1000L / 1000L );\r
                        return String.format( "%02d:%02d", sec/60, sec%60 );\r
                }\r
                case COLUMN_FILENAME: {\r
-                       String filename = sequences.get(row).getFilename();\r
+                       String filename = sequenceList.get(row).getFilename();\r
                        return filename == null ? "" : filename;\r
                }\r
                case COLUMN_SEQ_NAME: {\r
-                       String seq_name = sequences.get(row).toString();\r
+                       String seq_name = sequenceList.get(row).toString();\r
                        return seq_name == null ? "" : seq_name;\r
                }\r
                default: return "";\r
@@ -1207,12 +1197,12 @@ class SequenceListModel extends AbstractTableModel
                case COLUMN_FILENAME:\r
                        // ファイル名の変更\r
                        String filename = (String)val;\r
-                       sequences.get(row).setFilename(filename);\r
+                       sequenceList.get(row).setFilename(filename);\r
                        fireTableCellUpdated(row, COLUMN_FILENAME);\r
                        break;\r
                case COLUMN_SEQ_NAME:\r
                        // シーケンス名の設定または変更\r
-                       if( sequences.get(row).setName((String)val) )\r
+                       if( sequenceList.get(row).setName((String)val) )\r
                                fireTableCellUpdated(row, COLUMN_MODIFIED);\r
                        break;\r
                }\r
@@ -1223,17 +1213,17 @@ class SequenceListModel extends AbstractTableModel
                TableColumnModel column_model = table_view.getColumnModel();\r
                int total_width = column_model.getTotalColumnWidth();\r
                int i, total_width_ratio;\r
-               for( i=0, total_width_ratio = 0; i<column_width_ratios.length; i++ ) {\r
-                       total_width_ratio += column_width_ratios[i];\r
+               for( i=0, total_width_ratio = 0; i<COLUMN_WIDTH_RATIOS.length; i++ ) {\r
+                       total_width_ratio += COLUMN_WIDTH_RATIOS[i];\r
                }\r
-               for( i=0; i<column_width_ratios.length; i++ ) {\r
+               for( i=0; i<COLUMN_WIDTH_RATIOS.length; i++ ) {\r
                        column_model.getColumn(i).setPreferredWidth(\r
-                                       total_width * column_width_ratios[i] / total_width_ratio\r
+                                       total_width * COLUMN_WIDTH_RATIOS[i] / total_width_ratio\r
                                        );\r
                }\r
        }\r
        public boolean isModified() {\r
-               for( MidiSequenceModel seq_model : sequences ) {\r
+               for( MidiSequenceTableModel seq_model : sequenceList ) {\r
                        if( seq_model.isModified() ) return true;\r
                }\r
                return false;\r
@@ -1243,16 +1233,16 @@ class SequenceListModel extends AbstractTableModel
                int max_index = sel_model.getMaxSelectionIndex();\r
                for( int i = min_index; i <= max_index; i++ ) {\r
                        if( sel_model.isSelectedIndex(i) ) {\r
-                               sequences.get(i).setModified(is_modified);\r
+                               sequenceList.get(i).setModified(is_modified);\r
                                fireTableCellUpdated(i, COLUMN_MODIFIED);\r
                        }\r
                }\r
        }\r
-       public MidiSequenceModel getSequenceModel(ListSelectionModel sel_model) {\r
+       public MidiSequenceTableModel getSequenceModel(ListSelectionModel sel_model) {\r
                if( sel_model.isSelectionEmpty() ) return null;\r
                int sel_index = sel_model.getMinSelectionIndex();\r
-               if( sel_index >= sequences.size() ) return null;\r
-               return sequences.get(sel_index);\r
+               if( sel_index >= sequenceList.size() ) return null;\r
+               return sequenceList.get(sel_index);\r
        }\r
        public void fireSequenceChanged( ListSelectionModel sel_model ) {\r
                if( sel_model.isSelectionEmpty() ) return;\r
@@ -1261,19 +1251,19 @@ class SequenceListModel extends AbstractTableModel
                                sel_model.getMaxSelectionIndex()\r
                                );\r
        }\r
-       public void fireSequenceChanged( MidiSequenceModel seq_model ) {\r
-               for( int index=0; index<sequences.size(); index++ )\r
-                       if( sequences.get(index) == seq_model )\r
+       public void fireSequenceChanged( MidiSequenceTableModel seq_model ) {\r
+               for( int index=0; index<sequenceList.size(); index++ )\r
+                       if( sequenceList.get(index) == seq_model )\r
                                fireSequenceChanged(index,index);\r
        }\r
        public void fireSequenceChanged( int min_index, int max_index ) {\r
                for( int index = min_index; index <= max_index; index++ ) {\r
-                       MidiSequenceModel seq_model = sequences.get(index);\r
+                       MidiSequenceTableModel seq_model = sequenceList.get(index);\r
                        seq_model.setModified(true);\r
-                       if( device_manager.getSequencer().getSequence() == seq_model.getSequence() ) {\r
+                       if( deviceManager.getSequencer().getSequence() == seq_model.getSequence() ) {\r
                                // シーケンサーに対して、同じシーケンスを再度セットする。\r
                                // (これをやらないと更新が反映されないため)\r
-                               device_manager.timeRangeModel.setSequenceModel(seq_model);\r
+                               deviceManager.timeRangeModel.setSequenceModel(seq_model);\r
                        }\r
                }\r
                fireTableRowsUpdated( min_index, max_index );\r
@@ -1282,41 +1272,33 @@ class SequenceListModel extends AbstractTableModel
                Sequence seq = (new Music.ChordProgression()).toMidiSequence();\r
                return seq == null ? -1 : addSequence(seq,null);\r
        }\r
-       public int addSequence( Sequence seq ) {\r
-               return addSequence( seq, "" );\r
-       }\r
-       public int addSequence( Sequence seq, String filename ) {\r
-               MidiSequenceModel seq_model = new MidiSequenceModel(this);\r
-               seq_model.setSequence(seq);\r
-               seq_model.setFilename(filename);\r
-               sequences.add(seq_model);\r
-               int last_index = sequences.size() - 1;\r
-               fireTableRowsInserted( last_index, last_index );\r
-               return last_index;\r
-       }\r
-       public int addSequence( byte[] midiData, String filename )\r
-                       throws InvalidMidiDataException\r
-                       {\r
-               return ( midiData == null ) ?\r
-                               addSequence() :\r
-                                       addSequence( new ByteArrayInputStream(midiData), filename ) ;\r
-                       }\r
-       public int addSequence( File midi_file )\r
-                       throws InvalidMidiDataException, FileNotFoundException\r
-                       {\r
-               FileInputStream fis = new FileInputStream(midi_file);\r
-               int retval = addSequence( fis, midi_file.getName() );\r
+       public int addSequence(Sequence seq) {\r
+               return addSequence(seq, "");\r
+       }\r
+       public int addSequence(Sequence seq, String filename) {\r
+               MidiSequenceTableModel seqModel = new MidiSequenceTableModel(this);\r
+               seqModel.setSequence(seq);\r
+               seqModel.setFilename(filename);\r
+               sequenceList.add(seqModel);\r
+               int lastIndex = sequenceList.size() - 1;\r
+               fireTableRowsInserted(lastIndex, lastIndex);\r
+               return lastIndex;\r
+       }\r
+       public int addSequence(byte[] midiData, String filename) throws InvalidMidiDataException {\r
+               return (midiData == null) ? addSequence() : addSequence(new ByteArrayInputStream(midiData), filename);\r
+       }\r
+       public int addSequence(File midiFile) throws InvalidMidiDataException, FileNotFoundException {\r
+               FileInputStream fis = new FileInputStream(midiFile);\r
+               int retval = addSequence(fis, midiFile.getName());\r
                try {\r
                        fis.close();\r
                } catch( IOException ex ) {\r
                        ex.printStackTrace();\r
                }\r
                return retval;\r
-                       }\r
-       public int addSequence( InputStream in, String filename )\r
-                       throws InvalidMidiDataException\r
-                       {\r
-               if( in == null ) return addSequence();\r
+       }\r
+       public int addSequence(InputStream in, String filename) throws InvalidMidiDataException {\r
+               if(in == null) return addSequence();\r
                Sequence seq;\r
                try {\r
                        seq = MidiSystem.getSequence(in);\r
@@ -1330,11 +1312,9 @@ class SequenceListModel extends AbstractTableModel
                        return -1;\r
                }\r
                return addSequence( seq, filename );\r
-                       }\r
-       public int addSequence( String midi_file_url )\r
-                       throws InvalidMidiDataException, AccessControlException\r
-                       {\r
-               URL url = toURL( midi_file_url );\r
+       }\r
+       public int addSequence(String midiFileUrl) throws InvalidMidiDataException, AccessControlException {\r
+               URL url = toURL(midiFileUrl);\r
                if( url == null ) {\r
                        return -1;\r
                }\r
@@ -1352,42 +1332,42 @@ class SequenceListModel extends AbstractTableModel
                } catch( AccessControlException e ) {\r
                        throw e;\r
                }\r
-               return addSequence( seq, url.getFile().replaceFirst("^.*/","") );\r
-                       }\r
+               return addSequence(seq, url.getFile().replaceFirst("^.*/",""));\r
+       }\r
        public void removeSequence( ListSelectionModel sel_model ) {\r
                if( sel_model.isSelectionEmpty() ) return;\r
                int sel_index = sel_model.getMinSelectionIndex();\r
-               if( sequences.get(sel_index) == device_manager.timeRangeModel.getSequenceModel() )\r
-                       device_manager.timeRangeModel.setSequenceModel(null);\r
-               sequences.remove(sel_index);\r
+               if( sequenceList.get(sel_index) == deviceManager.timeRangeModel.getSequenceTableModel() )\r
+                       deviceManager.timeRangeModel.setSequenceModel(null);\r
+               sequenceList.remove(sel_index);\r
                fireTableRowsDeleted( sel_index, sel_index );\r
        }\r
        public void loadToSequencer( int index ) {\r
                int loaded_index = getLoadedIndex();\r
                if( loaded_index == index ) return;\r
-               MidiSequenceModel seq_model = sequences.get(index);\r
-               device_manager.timeRangeModel.setSequenceModel(seq_model);\r
+               MidiSequenceTableModel seq_model = sequenceList.get(index);\r
+               deviceManager.timeRangeModel.setSequenceModel(seq_model);\r
                seq_model.fireTableDataChanged();\r
                fireTableCellUpdated( loaded_index, COLUMN_SEQ_POSITION );\r
                fireTableCellUpdated( index, COLUMN_SEQ_POSITION );\r
        }\r
        public int getLoadedIndex() {\r
-               MidiSequenceModel seq_model = device_manager.timeRangeModel.getSequenceModel();\r
-               for( int i=0; i<sequences.size(); i++ )\r
-                       if( sequences.get(i) == seq_model ) return i;\r
+               MidiSequenceTableModel seq_model = deviceManager.timeRangeModel.getSequenceTableModel();\r
+               for( int i=0; i<sequenceList.size(); i++ )\r
+                       if( sequenceList.get(i) == seq_model ) return i;\r
                return -1;\r
        }\r
        public boolean loadNext( int offset ) {\r
                int loaded_index = getLoadedIndex();\r
                int index = (loaded_index < 0 ? 0 : loaded_index + offset);\r
-               if( index < 0 || index >= sequences.size() ) return false;\r
+               if( index < 0 || index >= sequenceList.size() ) return false;\r
                loadToSequencer( index );\r
                return true;\r
        }\r
        public int getTotalSeconds() {\r
                int total_sec = 0;\r
                long usec;\r
-               for( MidiSequenceModel seq_model : sequences ) {\r
+               for( MidiSequenceTableModel seq_model : sequenceList ) {\r
                        usec = seq_model.getSequence().getMicrosecondLength();\r
                        total_sec += (int)( (usec < 0 ? usec += 0x100000000L : usec) / 1000L / 1000L );\r
                }\r
@@ -1397,17 +1377,19 @@ class SequenceListModel extends AbstractTableModel
                int sec = getTotalSeconds();\r
                return String.format( "MIDI file playlist - Total length = %02d:%02d", sec/60, sec%60 );\r
        }\r
-       //\r
-       // 文字列を URL オブジェクトに変換\r
-       //\r
-       public URL toURL( String url_string ) {\r
-               if( url_string == null || url_string.isEmpty() ) {\r
+       /**\r
+        * 文字列をURLオブジェクトに変換\r
+        * @param urlString URL文字列\r
+        * @return URLオブジェクト\r
+        */\r
+       private URL toURL(String urlString) {\r
+               if( urlString == null || urlString.isEmpty() ) {\r
                        return null;\r
                }\r
                URI uri = null;\r
                URL url = null;\r
                try {\r
-                       uri = new URI(url_string);\r
+                       uri = new URI(urlString);\r
                        url = uri.toURL();\r
                } catch( URISyntaxException e ) {\r
                        e.printStackTrace();\r
@@ -1418,12 +1400,10 @@ class SequenceListModel extends AbstractTableModel
        }\r
 }\r
 \r
-//////////////////////////////////////////////////////////\r
-//\r
-// Track List (MIDI Sequence) Model\r
-//\r
-//////////////////////////////////////////////////////////\r
-class MidiSequenceModel extends AbstractTableModel\r
+/**\r
+ * MIDIシーケンス(トラックリスト)を表すテーブルモデル\r
+ */\r
+class MidiSequenceTableModel extends AbstractTableModel\r
 {\r
        public static final int COLUMN_TRACK_NUMBER     = 0;\r
        public static final int COLUMN_EVENTS           = 1;\r
@@ -1432,48 +1412,60 @@ class MidiSequenceModel extends AbstractTableModel
        public static final int COLUMN_RECORD_CHANNEL   = 4;\r
        public static final int COLUMN_CHANNEL  = 5;\r
        public static final int COLUMN_TRACK_NAME       = 6;\r
-       public static final String column_titles[] = {\r
+       public static final String columnTitles[] = {\r
                "No.", "Events", "Mute", "Solo", "RecCh", "Ch", "Track name"\r
        };\r
-       public static final int column_width_ratios[] = {\r
+       public static final int columnWidthRatios[] = {\r
                30, 60, 40, 40, 60, 40, 200\r
        };\r
-       private SequenceListModel seq_list_model;\r
-       private Sequence seq;\r
-       private SequenceIndex seq_index;\r
+       private SequenceListTableModel sequenceListTableModel;\r
+       private Sequence sequence;\r
+       private SequenceTickIndex seqIndex;\r
        private String filename = "";\r
-       private boolean is_modified = false;\r
-       private ArrayList<MidiTrackModel> track_models\r
-       = new ArrayList<MidiTrackModel>();\r
+       private List<MidiTrackTableModel> trackModelList = new ArrayList<>();\r
 \r
+       /**\r
+        * 記録するMIDIチャンネル\r
+        */\r
        class RecordChannelCellEditor extends DefaultCellEditor {\r
                public RecordChannelCellEditor() {\r
-                       super(new JComboBox<String>() {\r
-                               {\r
-                                       addItem("OFF");\r
-                                       for( int i=1; i <= MIDISpec.MAX_CHANNELS; i++ )\r
-                                               addItem( String.format( "%d", i ) );\r
-                                       addItem("ALL");\r
+                       super(\r
+                               new JComboBox<String>() {\r
+                                       {\r
+                                               addItem("OFF");\r
+                                               for( int i=1; i <= MIDISpec.MAX_CHANNELS; i++ )\r
+                                                       addItem( String.format("%d", i) );\r
+                                               addItem("ALL");\r
+                                       }\r
                                }\r
-                       });\r
+                       );\r
                }\r
        }\r
 \r
-       public MidiSequenceModel( SequenceListModel slm ) {\r
-               seq_list_model = slm;\r
-       }\r
-       //\r
-       // TableModel interface\r
-       //\r
+       /**\r
+        * 新しい {@link MidiSequenceTableModel} を構築します。\r
+        * @param sequenceListTableModel プレイリスト\r
+        */\r
+       public MidiSequenceTableModel(SequenceListTableModel sequenceListTableModel) {\r
+               this.sequenceListTableModel = sequenceListTableModel;\r
+       }\r
+       @Override\r
        public int getRowCount() {\r
-               return seq == null ? 0 : seq.getTracks().length;\r
-       }\r
-       public int getColumnCount() {\r
-               return column_titles.length;\r
-       }\r
-       public String getColumnName(int column) {\r
-               return column_titles[column];\r
-       }\r
+               return sequence == null ? 0 : sequence.getTracks().length;\r
+       }\r
+       @Override\r
+       public int getColumnCount() { return columnTitles.length; }\r
+       /**\r
+        * 列名を返します。\r
+        * @return 列名\r
+        */\r
+       @Override\r
+       public String getColumnName(int column) { return columnTitles[column]; }\r
+       /**\r
+        * 指定された列の型を返します。\r
+        * @return 指定された列の型\r
+        */\r
+       @Override\r
        public Class<?> getColumnClass(int column) {\r
                switch(column) {\r
                case COLUMN_TRACK_NUMBER:\r
@@ -1481,45 +1473,49 @@ class MidiSequenceModel extends AbstractTableModel
                        return Integer.class;\r
                case COLUMN_MUTE:\r
                case COLUMN_SOLO:\r
-                       return\r
-                                       (seq == getSequencer().getSequence()) ?\r
-                                                       Boolean.class : String.class;\r
+                       return (sequence == getSequencer().getSequence()) ? Boolean.class : String.class;\r
                case COLUMN_RECORD_CHANNEL:\r
                case COLUMN_CHANNEL:\r
                case COLUMN_TRACK_NAME:\r
                        return String.class;\r
-               default: return super.getColumnClass(column);\r
+               default:\r
+                       return super.getColumnClass(column);\r
                }\r
        }\r
+       @Override\r
        public Object getValueAt(int row, int column) {\r
                switch(column) {\r
                case COLUMN_TRACK_NUMBER: return row;\r
                case COLUMN_EVENTS:\r
-                       return seq.getTracks()[row].size();\r
+                       return sequence.getTracks()[row].size();\r
                case COLUMN_MUTE:\r
-                       return (seq == getSequencer().getSequence()) ?\r
+                       return (sequence == getSequencer().getSequence()) ?\r
                                        getSequencer().getTrackMute(row) : "";\r
                case COLUMN_SOLO:\r
-                       return (seq == getSequencer().getSequence()) ?\r
+                       return (sequence == getSequencer().getSequence()) ?\r
                                        getSequencer().getTrackSolo(row) : "";\r
                case COLUMN_RECORD_CHANNEL:\r
-                       return (seq == getSequencer().getSequence()) ?\r
-                                       track_models.get(row).getRecordingChannel() : "";\r
+                       return (sequence == getSequencer().getSequence()) ?\r
+                                       trackModelList.get(row).getRecordingChannel() : "";\r
                case COLUMN_CHANNEL: {\r
-                       int ch = track_models.get(row).getChannel();\r
+                       int ch = trackModelList.get(row).getChannel();\r
                        return ch < 0 ? "" : ch + 1 ;\r
                }\r
                case COLUMN_TRACK_NAME:\r
-                       return track_models.get(row).toString();\r
+                       return trackModelList.get(row).toString();\r
                default: return "";\r
                }\r
        }\r
+       /**\r
+        * セルが編集可能かどうかを返します。\r
+        */\r
+       @Override\r
        public boolean isCellEditable( int row, int column ) {\r
                switch(column) {\r
                case COLUMN_MUTE:\r
                case COLUMN_SOLO:\r
                case COLUMN_RECORD_CHANNEL:\r
-                       return seq == getSequencer().getSequence();\r
+                       return sequence == getSequencer().getSequence();\r
                case COLUMN_CHANNEL:\r
                case COLUMN_TRACK_NAME:\r
                        return true;\r
@@ -1527,6 +1523,10 @@ class MidiSequenceModel extends AbstractTableModel
                        return false;\r
                }\r
        }\r
+       /**\r
+        * 列の値を設定します。\r
+        */\r
+       @Override\r
        public void setValueAt(Object val, int row, int column) {\r
                switch(column) {\r
                case COLUMN_MUTE:\r
@@ -1536,7 +1536,7 @@ class MidiSequenceModel extends AbstractTableModel
                        getSequencer().setTrackSolo( row, ((Boolean)val).booleanValue() );\r
                        break;\r
                case COLUMN_RECORD_CHANNEL:\r
-                       track_models.get(row).setRecordingChannel((String)val);\r
+                       trackModelList.get(row).setRecordingChannel((String)val);\r
                        break;\r
                case COLUMN_CHANNEL: {\r
                        Integer ch;\r
@@ -1549,7 +1549,7 @@ class MidiSequenceModel extends AbstractTableModel
                        }\r
                        if( --ch <= 0 || ch > MIDISpec.MAX_CHANNELS )\r
                                break;\r
-                       MidiTrackModel track_model = track_models.get(row);\r
+                       MidiTrackTableModel track_model = trackModelList.get(row);\r
                        int old_ch = track_model.getChannel();\r
                        if( ch == old_ch ) break;\r
                        track_model.setChannel(ch);\r
@@ -1558,74 +1558,98 @@ class MidiSequenceModel extends AbstractTableModel
                        break;\r
                }\r
                case COLUMN_TRACK_NAME:\r
-                       track_models.get(row).setString((String)val);\r
+                       trackModelList.get(row).setString((String)val);\r
                        break;\r
                }\r
                fireTableCellUpdated(row,column);\r
        }\r
-       // Methods (Table view)\r
-       //\r
-       public void sizeColumnWidthToFit( TableColumnModel column_model ) {\r
-               int total_width = column_model.getTotalColumnWidth();\r
-               int i, total_width_ratio = 0;\r
-               for( i=0; i<column_width_ratios.length; i++ ) {\r
-                       total_width_ratio += column_width_ratios[i];\r
-               }\r
-               for( i=0; i<column_width_ratios.length; i++ ) {\r
-                       column_model.getColumn(i).setPreferredWidth(\r
-                                       total_width * column_width_ratios[i] / total_width_ratio\r
-                                       );\r
+       /**\r
+        * 列に合わせて幅を調整します。\r
+        * @param columnModel テーブル列モデル\r
+        */\r
+       public void sizeColumnWidthToFit(TableColumnModel columnModel) {\r
+               int totalWidth = columnModel.getTotalColumnWidth();\r
+               int totalWidthRatio = 0;\r
+               for( int i=0; i<columnWidthRatios.length; i++ ) {\r
+                       totalWidthRatio += columnWidthRatios[i];\r
+               }\r
+               for( int i=0; i<columnWidthRatios.length; i++ ) {\r
+                       columnModel.getColumn(i).setPreferredWidth(\r
+                               totalWidth * columnWidthRatios[i] / totalWidthRatio\r
+                       );\r
                }\r
        }\r
-       // Methods (sequence)\r
-       //\r
-       public Sequence getSequence() { return this.seq; }\r
-       public void setSequence( Sequence seq ) {\r
-               //\r
+       /**\r
+        * MIDIシーケンスを返します。\r
+        * @return MIDIシーケンス\r
+        */\r
+       public Sequence getSequence() { return sequence; }\r
+       /**\r
+        * MIDIシーケンスを設定します。\r
+        * @param sequence MIDIシーケンス\r
+        */\r
+       public void setSequence(Sequence sequence) {\r
                getSequencer().recordDisable(null); // The "null" means all tracks\r
-               //\r
-               this.seq = seq;\r
-               int old_size = track_models.size();\r
-               if( old_size > 0 ) {\r
-                       track_models.clear();\r
-                       fireTableRowsDeleted(0, old_size-1);\r
+               this.sequence = sequence;\r
+               int oldSize = trackModelList.size();\r
+               if( oldSize > 0 ) {\r
+                       trackModelList.clear();\r
+                       fireTableRowsDeleted(0, oldSize-1);\r
                }\r
-               if( seq == null ) {\r
-                       seq_index = null;\r
+               if( sequence == null ) {\r
+                       seqIndex = null;\r
                }\r
                else {\r
-                       seq_index = new SequenceIndex( seq );\r
-                       Track tklist[] = seq.getTracks();\r
+                       seqIndex = new SequenceTickIndex(sequence);\r
+                       Track tklist[] = sequence.getTracks();\r
                        for( Track tk : tklist )\r
-                               track_models.add( new MidiTrackModel( tk, this ) );\r
+                               trackModelList.add( new MidiTrackTableModel( tk, this ) );\r
                        fireTableRowsInserted(0, tklist.length-1);\r
                }\r
        }\r
-       public SequenceIndex getSequenceIndex() {\r
-               return this.seq_index;\r
-       }\r
-       public void setModified(boolean is_modified) {\r
-               this.is_modified = is_modified;\r
-       }\r
-       public boolean isModified() { return is_modified; }\r
-       public void setFilename(String filename) {\r
-               this.filename = filename;\r
-       }\r
+       /**\r
+        * シーケンスtickインデックスを返します。\r
+        * @return シーケンスtickインデックス\r
+        */\r
+       public SequenceTickIndex getSequenceTickIndex() { return this.seqIndex; }\r
+       private boolean isModified = false;\r
+       /**\r
+        * 変更されたかどうかを設定します。\r
+        * @param isModified 変更されたときtrue\r
+        */\r
+       public void setModified(boolean isModified) {\r
+               this.isModified = isModified;\r
+       }\r
+       /**\r
+        * 変更されたかどうかを返します。\r
+        * @return 変更済みのときtrue\r
+        */\r
+       public boolean isModified() { return isModified; }\r
+       /**\r
+        * ファイル名を設定します。\r
+        * @param filename ファイル名\r
+        */\r
+       public void setFilename(String filename) { this.filename = filename; }\r
+       /**\r
+        * ファイル名を返します。\r
+        * @return ファイル名\r
+        */\r
        public String getFilename() { return filename; }\r
+       @Override\r
        public String toString() {\r
-               return MIDISpec.getNameOf(seq);\r
+               return MIDISpec.getNameOf(sequence);\r
        }\r
        public boolean setName( String name ) {\r
                if( name.equals(toString()) )\r
                        return false;\r
-               if( ! MIDISpec.setNameOf(seq,name) )\r
+               if( ! MIDISpec.setNameOf(sequence,name) )\r
                        return false;\r
                setModified(true);\r
                fireTableDataChanged();\r
                return true;\r
        }\r
        public byte[] getMIDIdata() {\r
-               if( seq == null || seq.getTracks().length == 0 ) {\r
+               if( sequence == null || sequence.getTracks().length == 0 ) {\r
                        return null;\r
                }\r
                /*\r
@@ -1635,7 +1659,7 @@ class MidiSequenceModel extends AbstractTableModel
                 */\r
                ByteArrayOutputStream out = new ByteArrayOutputStream();\r
                try {\r
-                       MidiSystem.write(seq, 1, out);\r
+                       MidiSystem.write(sequence, 1, out);\r
                        return out.toByteArray();\r
                } catch ( IOException e ) {\r
                        e.printStackTrace();\r
@@ -1643,7 +1667,7 @@ class MidiSequenceModel extends AbstractTableModel
                }\r
        }\r
        public void fireTimeSignatureChanged() {\r
-               seq_index = new SequenceIndex( seq );\r
+               seqIndex = new SequenceTickIndex( sequence );\r
        }\r
        public void fireTrackChanged( Track tk ) {\r
                int row = getTrackRow(tk);\r
@@ -1652,28 +1676,28 @@ class MidiSequenceModel extends AbstractTableModel
                fireSequenceChanged();\r
        }\r
        public void fireSequenceChanged() {\r
-               seq_list_model.fireSequenceChanged(this);\r
+               sequenceListTableModel.fireSequenceChanged(this);\r
        }\r
-       public MidiTrackModel getTrackModel( int index ) {\r
-               Track tracks[] = seq.getTracks();\r
+       public MidiTrackTableModel getTrackModel( int index ) {\r
+               Track tracks[] = sequence.getTracks();\r
                if( tracks.length == 0 ) return null;\r
                Track tk = tracks[index];\r
-               for( MidiTrackModel model : track_models )\r
+               for( MidiTrackTableModel model : trackModelList )\r
                        if( model.getTrack() == tk )\r
                                return model;\r
                return null;\r
        }\r
-       public int getTrackRow( Track tk ) {\r
-               Track tracks[] = seq.getTracks();\r
+       public int getTrackRow(Track tk) {\r
+               Track tracks[] = sequence.getTracks();\r
                for( int i=0; i<tracks.length; i++ )\r
                        if( tracks[i] == tk )\r
                                return i;\r
                return -1;\r
        }\r
        public void createTrack() {\r
-               Track tk = seq.createTrack();\r
-               track_models.add( new MidiTrackModel( tk, this ) );\r
-               int last_row = seq.getTracks().length - 1;\r
+               Track tk = sequence.createTrack();\r
+               trackModelList.add( new MidiTrackTableModel( tk, this ) );\r
+               int last_row = sequence.getTracks().length - 1;\r
                fireTableRowsInserted( last_row, last_row );\r
        }\r
        public void deleteTracks( ListSelectionModel selection_model ) {\r
@@ -1681,42 +1705,43 @@ class MidiSequenceModel extends AbstractTableModel
                        return;\r
                int min_sel_index = selection_model.getMinSelectionIndex();\r
                int max_sel_index = selection_model.getMaxSelectionIndex();\r
-               Track tklist[] = seq.getTracks();\r
+               Track tklist[] = sequence.getTracks();\r
                for( int i = max_sel_index; i >= min_sel_index; i-- ) {\r
                        if( ! selection_model.isSelectedIndex(i) )\r
                                continue;\r
-                       seq.deleteTrack( tklist[i] );\r
-                       track_models.remove(i);\r
+                       sequence.deleteTrack( tklist[i] );\r
+                       trackModelList.remove(i);\r
                }\r
                fireTableRowsDeleted( min_sel_index, max_sel_index );\r
        }\r
-       //\r
-       // Methods (sequencer)\r
-       //\r
+       /**\r
+        * MIDIシーケンサを返します。\r
+        * @return MIDIシーケンサ\r
+        */\r
        public Sequencer getSequencer() {\r
-               return seq_list_model.device_manager.getSequencer();\r
+               return sequenceListTableModel.deviceManager.getSequencer();\r
        }\r
+       /**\r
+        * 録音可能かどうかを返します。\r
+        * @return 録音可能であればtrue\r
+        */\r
        public boolean isRecordable() {\r
-               if( seq != getSequencer().getSequence() ) return false;\r
-               int num_row = getRowCount();\r
-               String s;\r
-               for( int row=0; row<num_row; row++ ) {\r
-                       s = (String)getValueAt(\r
-                                       row, COLUMN_RECORD_CHANNEL\r
-                                       );\r
-                       if( s.equals("OFF") ) continue;\r
+               if( sequence != getSequencer().getSequence() )\r
+                       return false;\r
+               int rowCount = getRowCount();\r
+               for( int row=0; row < rowCount; row++ ) {\r
+                       if("OFF".equals(getValueAt(row, COLUMN_RECORD_CHANNEL)))\r
+                               continue;\r
                        return true;\r
                }\r
                return false;\r
        }\r
 }\r
 \r
-////////////////////////////////////////////////////////\r
-//\r
-// Event List (Track) Model\r
-//\r
-////////////////////////////////////////////////////////\r
-class MidiTrackModel extends AbstractTableModel\r
+/**\r
+ * MIDIトラック(MIDIイベントリスト)テーブルモデル\r
+ */\r
+class MidiTrackTableModel extends AbstractTableModel\r
 {\r
        public static final int COLUMN_EVENT_NUMBER     = 0;\r
        public static final int COLUMN_TICK_POSITION    = 1;\r
@@ -1724,36 +1749,25 @@ class MidiTrackModel extends AbstractTableModel
        public static final int COLUMN_BEAT_POSITION            = 3;\r
        public static final int COLUMN_EXTRA_TICK_POSITION      = 4;\r
        public static final int COLUMN_MESSAGE  = 5;\r
-       public static final String column_titles[] = {\r
+       public static final String COLUMN_TITLES[] = {\r
                "No.", "TickPos.", "Measure", "Beat", "ExTick", "MIDI Message",\r
        };\r
        public static final int column_width_ratios[] = {\r
                30, 40, 20,20,20, 280,\r
        };\r
        private Track track;\r
-       private MidiSequenceModel parent_model;\r
-       //\r
-       // Constructor\r
-       //\r
-       public MidiTrackModel() { } // To create empty model\r
-       public MidiTrackModel( MidiSequenceModel parent_model ) {\r
-               this.parent_model = parent_model;\r
-       }\r
-       public MidiTrackModel( Track tk, MidiSequenceModel parent_model ) {\r
-               this.track = tk;\r
-               this.parent_model = parent_model;\r
-       }\r
-       // TableModel interface\r
-       //\r
-       public int getRowCount() {\r
-               return track == null ? 0 : track.size();\r
-       }\r
-       public int getColumnCount() {\r
-               return column_titles.length;\r
-       }\r
-       public String getColumnName(int column) {\r
-               return column_titles[column];\r
-       }\r
+       private MidiSequenceTableModel parent;\r
+       public MidiTrackTableModel() { } // To create empty model\r
+       public MidiTrackTableModel(MidiSequenceTableModel parent) {\r
+               this.parent = parent;\r
+       }\r
+       public MidiTrackTableModel(Track track, MidiSequenceTableModel parent) {\r
+               this.track = track;\r
+               this.parent = parent;\r
+       }\r
+       public int getRowCount() { return track == null ? 0 : track.size(); }\r
+       public int getColumnCount() { return COLUMN_TITLES.length; }\r
+       public String getColumnName(int column) { return COLUMN_TITLES[column]; }\r
        public Class<?> getColumnClass(int column) {\r
                switch(column) {\r
                case COLUMN_EVENT_NUMBER:\r
@@ -1779,26 +1793,19 @@ class MidiTrackModel extends AbstractTableModel
                        return track.get(row).getTick();\r
 \r
                case COLUMN_MEASURE_POSITION:\r
-                       return parent_model.getSequenceIndex().tickToMeasure(\r
-                                       track.get(row).getTick()\r
-                                       ) + 1;\r
+                       return parent.getSequenceTickIndex().tickToMeasure(track.get(row).getTick()) + 1;\r
 \r
                case COLUMN_BEAT_POSITION:\r
-                       parent_model.getSequenceIndex().tickToMeasure(\r
-                                       track.get(row).getTick()\r
-                                       );\r
-                       return parent_model.getSequenceIndex().last_beat + 1;\r
+                       parent.getSequenceTickIndex().tickToMeasure(track.get(row).getTick());\r
+                       return parent.getSequenceTickIndex().lastBeat + 1;\r
 \r
                case COLUMN_EXTRA_TICK_POSITION:\r
-                       parent_model.getSequenceIndex().tickToMeasure(\r
-                                       track.get(row).getTick()\r
-                                       );\r
-                       return parent_model.getSequenceIndex().last_extra_tick;\r
+                       parent.getSequenceTickIndex().tickToMeasure(track.get(row).getTick());\r
+                       return parent.getSequenceTickIndex().lastExtraTick;\r
 \r
                case COLUMN_MESSAGE:\r
-                       return msgToString(\r
-                                       track.get(row).getMessage()\r
-                                       );\r
+                       return msgToString(track.get(row).getMessage());\r
+\r
                default: return "";\r
                }\r
        }\r
@@ -1822,25 +1829,25 @@ class MidiTrackModel extends AbstractTableModel
                        tick = (Long)value;\r
                        break;\r
                case COLUMN_MEASURE_POSITION:\r
-                       tick = parent_model.getSequenceIndex().measureToTick(\r
-                                       (Integer)value - 1,\r
-                                       (Integer)getValueAt( row, COLUMN_BEAT_POSITION ) - 1,\r
-                                       (Integer)getValueAt( row, COLUMN_EXTRA_TICK_POSITION )\r
-                                       );\r
+                       tick = parent.getSequenceTickIndex().measureToTick(\r
+                               (Integer)value - 1,\r
+                               (Integer)getValueAt( row, COLUMN_BEAT_POSITION ) - 1,\r
+                               (Integer)getValueAt( row, COLUMN_EXTRA_TICK_POSITION )\r
+                       );\r
                        break;\r
                case COLUMN_BEAT_POSITION:\r
-                       tick = parent_model.getSequenceIndex().measureToTick(\r
-                                       (Integer)getValueAt( row, COLUMN_MEASURE_POSITION ) - 1,\r
-                                       (Integer)value - 1,\r
-                                       (Integer)getValueAt( row, COLUMN_EXTRA_TICK_POSITION )\r
-                                       );\r
+                       tick = parent.getSequenceTickIndex().measureToTick(\r
+                               (Integer)getValueAt( row, COLUMN_MEASURE_POSITION ) - 1,\r
+                               (Integer)value - 1,\r
+                               (Integer)getValueAt( row, COLUMN_EXTRA_TICK_POSITION )\r
+                       );\r
                        break;\r
                case COLUMN_EXTRA_TICK_POSITION:\r
-                       tick = parent_model.getSequenceIndex().measureToTick(\r
-                                       (Integer)getValueAt( row, COLUMN_MEASURE_POSITION ) - 1,\r
-                                       (Integer)getValueAt( row, COLUMN_BEAT_POSITION ) - 1,\r
-                                       (Integer)value\r
-                                       );\r
+                       tick = parent.getSequenceTickIndex().measureToTick(\r
+                               (Integer)getValueAt( row, COLUMN_MEASURE_POSITION ) - 1,\r
+                               (Integer)getValueAt( row, COLUMN_BEAT_POSITION ) - 1,\r
+                               (Integer)value\r
+                       );\r
                        break;\r
                case COLUMN_MESSAGE:\r
                        return;\r
@@ -1848,9 +1855,6 @@ class MidiTrackModel extends AbstractTableModel
                }\r
                changeEventTick(row,tick);\r
        }\r
-\r
-       // Methods (Table view)\r
-       //\r
        public void sizeColumnWidthToFit( TableColumnModel column_model ) {\r
                int total_width = column_model.getTotalColumnWidth();\r
                int i, total_width_ratio = 0;\r
@@ -1859,43 +1863,45 @@ class MidiTrackModel extends AbstractTableModel
                }\r
                for( i=0; i<column_width_ratios.length; i++ ) {\r
                        column_model.getColumn(i).setPreferredWidth(\r
-                                       total_width * column_width_ratios[i] / total_width_ratio\r
-                                       );\r
+                               total_width * column_width_ratios[i] / total_width_ratio\r
+                       );\r
                }\r
        }\r
-       // Methods\r
-       //\r
-       private boolean isRhythmPart(int ch) {\r
-               return (ch == 9);\r
-       }\r
-       // トラックオブジェクトの取得\r
+       /**\r
+        * MIDIトラックを返します。\r
+        * @return MIDIトラック\r
+        */\r
        public Track getTrack() { return track; }\r
-       //\r
-       // 文字列としてトラック名を返す\r
-       public String toString() {\r
-               return MIDISpec.getNameOf(track);\r
-       }\r
-       // トラック名をセットする\r
-       public boolean setString( String name ) {\r
-               if(\r
-                               name.equals(toString())\r
-                               ||\r
-                               ! MIDISpec.setNameOf( track, name )\r
-                               )\r
+       /**\r
+        * 文字列としてトラック名を返します。\r
+        */\r
+       @Override\r
+       public String toString() { return MIDISpec.getNameOf(track); }\r
+       /**\r
+        * トラック名を設定します。\r
+        * @param name トラック名\r
+        * @return 設定が行われたらtrue\r
+        */\r
+       public boolean setString(String name) {\r
+               if(name.equals(toString()) || ! MIDISpec.setNameOf(track, name))\r
                        return false;\r
-               parent_model.setModified(true);\r
-               parent_model.fireSequenceChanged();\r
+               parent.setModified(true);\r
+               parent.fireSequenceChanged();\r
                fireTableDataChanged();\r
                return true;\r
        }\r
-       //\r
-       // 録音中の MIDI チャンネル\r
        private String rec_ch = "OFF";\r
-       public String getRecordingChannel() {\r
-               return rec_ch;\r
-       }\r
+       /**\r
+        * 録音中のMIDIチャンネルを返します。\r
+        * @return 録音中のMIDIチャンネル\r
+        */\r
+       public String getRecordingChannel() { return rec_ch; }\r
+       /**\r
+        * 録音中のMIDIチャンネルを設定します。\r
+        * @param ch_str 録音中のMIDIチャンネル\r
+        */\r
        public void setRecordingChannel(String ch_str) {\r
-               Sequencer sequencer = parent_model.getSequencer();\r
+               Sequencer sequencer = parent.getSequencer();\r
                if( ch_str.equals("OFF") ) {\r
                        sequencer.recordDisable( track );\r
                }\r
@@ -1940,36 +1946,36 @@ class MidiTrackModel extends AbstractTableModel
        public void setChannel(int ch) {\r
                // すべてのチャンネルメッセージに対して\r
                // 同一のMIDIチャンネルをセットする\r
-               MidiMessage msg;\r
-               ShortMessage smsg;\r
-               int index, track_size = track.size();\r
-               for( index=0; index < track_size; index++ ) {\r
-                       msg = track.get(index).getMessage();\r
-                       if(\r
-                                       ! (msg instanceof ShortMessage)\r
-                                       ||\r
-                                       ! MIDISpec.isChannelMessage(smsg = (ShortMessage)msg)\r
-                                       ||\r
-                                       smsg.getChannel() == ch\r
-                                       )\r
+               int track_size = track.size();\r
+               for( int index=0; index < track_size; index++ ) {\r
+                       MidiMessage msg = track.get(index).getMessage();\r
+                       if( ! (msg instanceof ShortMessage) )\r
+                               continue;\r
+                       ShortMessage smsg = (ShortMessage)msg;\r
+                       if( ! MIDISpec.isChannelMessage(smsg) )\r
+                               continue;\r
+                       if( smsg.getChannel() == ch )\r
                                continue;\r
                        try {\r
                                smsg.setMessage(\r
-                                               smsg.getCommand(), ch,\r
-                                               smsg.getData1(), smsg.getData2()\r
-                                               );\r
+                                       smsg.getCommand(), ch,\r
+                                       smsg.getData1(), smsg.getData2()\r
+                               );\r
                        }\r
                        catch( InvalidMidiDataException e ) {\r
                                e.printStackTrace();\r
                        }\r
-                       parent_model.setModified(true);\r
+                       parent.setModified(true);\r
                }\r
-               parent_model.fireTrackChanged( track );\r
-               parent_model.fireSequenceChanged();\r
+               parent.fireTrackChanged( track );\r
+               parent.fireSequenceChanged();\r
                fireTableDataChanged();\r
        }\r
-       //\r
-       // MIDI イベントの tick 位置変更\r
+       /**\r
+        * MIDIイベントのtick位置を変更します。\r
+        * @param row 行インデックス\r
+        * @param new_tick 新しいtick位置\r
+        */\r
        public void changeEventTick(int row, long new_tick) {\r
                MidiEvent old_midi_event = track.get(row);\r
                if( old_midi_event.getTick() == new_tick ) {\r
@@ -1980,16 +1986,20 @@ class MidiTrackModel extends AbstractTableModel
                track.remove(old_midi_event);\r
                track.add(new_midi_event);\r
                fireTableDataChanged();\r
-               //\r
                if( MIDISpec.isEOT(msg) ) {\r
                        // EOTの場所が変わると曲の長さが変わるので、親モデルへ通知する。\r
-                       parent_model.fireSequenceChanged();\r
+                       parent.fireSequenceChanged();\r
                }\r
        }\r
-       //\r
-       // MIDI tick から位置を取得(バイナリーサーチ)\r
+       /**\r
+        * MIDI tick を行インデックスに変換します。\r
+        * 検索はバイナリーサーチで行われます。\r
+        * @param tick MIDI tick\r
+        * @return 行インデックス\r
+        */\r
        public int tickToIndex( long tick ) {\r
-               if( track == null ) return 0;\r
+               if( track == null )\r
+                       return 0;\r
                int min_index = 0;\r
                int max_index = track.size() - 1;\r
                long current_tick;\r
@@ -2009,10 +2019,15 @@ class MidiTrackModel extends AbstractTableModel
                }\r
                return (min_index + max_index) / 2;\r
        }\r
-       // NoteOn/NoteOff ペアの一方のインデックスから、\r
-       // その相手を返す\r
+       /**\r
+        * NoteOn/NoteOff ペアの一方の行インデックスから、\r
+        * もう一方(ペアの相手)の行インデックスを返します。\r
+        * @param index 行インデックス\r
+        * @return ペアを構成する相手の行インデックス(ない場合は -1)\r
+        */\r
        public int getIndexOfPartnerFor( int index ) {\r
-               if( track == null || index >= track.size() ) return -1;\r
+               if( track == null || index >= track.size() )\r
+                       return -1;\r
                MidiMessage msg = track.get(index).getMessage();\r
                if( ! (msg instanceof ShortMessage) ) return -1;\r
                ShortMessage sm = (ShortMessage)msg;\r
@@ -2070,15 +2085,20 @@ class MidiTrackModel extends AbstractTableModel
                // Not found\r
                return -1;\r
        }\r
-       //\r
+       /**\r
+        * 指定のMIDIメッセージが拍子記号かどうか調べます。\r
+        * @param msg MIDIメッセージ\r
+        * @return 拍子記号のときtrue\r
+        */\r
        public boolean isTimeSignature( MidiMessage msg ) {\r
-               // 拍子記号のとき True を返す\r
-               return\r
-                               (msg instanceof MetaMessage)\r
-                               &&\r
-                               ((MetaMessage)msg).getType() == 0x58;\r
-       }\r
-       public boolean isNote( int index ) { // Note On または Note Off のとき True を返す\r
+               return (msg instanceof MetaMessage) && ((MetaMessage)msg).getType() == 0x58;\r
+       }\r
+       /**\r
+        * ノートメッセージかどうか調べます。\r
+        * @param index 行インデックス\r
+        * @return Note On または Note Off のとき true\r
+        */\r
+       public boolean isNote(int index) {\r
                MidiEvent midi_evt = getMidiEvent(index);\r
                MidiMessage msg = midi_evt.getMessage();\r
                if( ! (msg instanceof ShortMessage) ) return false;\r
@@ -2086,43 +2106,56 @@ class MidiTrackModel extends AbstractTableModel
                return cmd == ShortMessage.NOTE_ON || cmd == ShortMessage.NOTE_OFF ;\r
        }\r
        public boolean hasTrack() { return track != null; }\r
-       //\r
-       // イベントの取得\r
-       //\r
-       public MidiEvent getMidiEvent( int index ) {\r
-               return track.get(index);\r
-       }\r
-       public MidiEvent[] getMidiEvents( ListSelectionModel sel_model ) {\r
+       /**\r
+        * 指定の行インデックスのMIDIイベントを返します。\r
+        * @param index 行インデックス\r
+        * @return MIDIイベント\r
+        */\r
+       public MidiEvent getMidiEvent(int index) { return track.get(index); }\r
+       /**\r
+        * 選択されているMIDIイベントを返します。\r
+        * @param selectionModel 選択状態モデル\r
+        * @return 選択されているMIDIイベント\r
+        */\r
+       public MidiEvent[] getMidiEvents(ListSelectionModel selectionModel) {\r
                Vector<MidiEvent> events = new Vector<MidiEvent>();\r
-               if( ! sel_model.isSelectionEmpty() ) {\r
-                       int min_sel_index = sel_model.getMinSelectionIndex();\r
-                       int max_sel_index = sel_model.getMaxSelectionIndex();\r
-                       for( int i = min_sel_index; i <= max_sel_index; i++ )\r
-                               if( sel_model.isSelectedIndex(i) )\r
+               if( ! selectionModel.isSelectionEmpty() ) {\r
+                       int i = selectionModel.getMinSelectionIndex();\r
+                       int max_sel_index = selectionModel.getMaxSelectionIndex();\r
+                       for( ; i <= max_sel_index; i++ )\r
+                               if( selectionModel.isSelectedIndex(i) )\r
                                        events.add(track.get(i));\r
                }\r
                return events.toArray(new MidiEvent[1]);\r
        }\r
-       //\r
-       // イベントの追加\r
-       //\r
+       /**\r
+        * MIDIイベントを追加します。\r
+        * @param midi_event 追加するMIDIイベント\r
+        * @return 追加できたらtrue\r
+        */\r
        public boolean addMidiEvent( MidiEvent midi_event ) {\r
                if( !(track.add(midi_event)) )\r
                        return false;\r
                if( isTimeSignature(midi_event.getMessage()) )\r
-                       parent_model.fireTimeSignatureChanged();\r
-               parent_model.fireTrackChanged( track );\r
+                       parent.fireTimeSignatureChanged();\r
+               parent.fireTrackChanged( track );\r
                int last_index = track.size() - 1;\r
                fireTableRowsInserted( last_index-1, last_index-1 );\r
                return true;\r
        }\r
+       /**\r
+        * MIDIイベントを追加します。\r
+        * @param midi_events 追加するMIDIイベント\r
+        * @param destination_tick 追加先tick\r
+        * @param midi_events_ppq PPQ値(タイミング解像度)\r
+        * @return 追加できたらtrue\r
+        */\r
        public boolean addMidiEvents(\r
-                       MidiEvent midi_events[],\r
-                       long destination_tick,\r
-                       int midi_events_ppq\r
-                       ) {\r
-               int dest_ppq = parent_model.getSequence().getResolution();\r
-               boolean done = false, has_time_signature = false;\r
+               MidiEvent midi_events[], long destination_tick, int midi_events_ppq\r
+       ) {\r
+               int dest_ppq = parent.getSequence().getResolution();\r
+               boolean done = false;\r
+               boolean has_time_signature = false;\r
                long event_tick = 0;\r
                long first_event_tick = -1;\r
                MidiEvent new_midi_event;\r
@@ -2132,34 +2165,35 @@ class MidiTrackModel extends AbstractTableModel
                        msg = midi_event.getMessage();\r
                        if( first_event_tick < 0 ) {\r
                                first_event_tick = event_tick;\r
-                               new_midi_event = new MidiEvent(\r
-                                               msg, destination_tick\r
-                                               );\r
+                               new_midi_event = new MidiEvent(msg, destination_tick);\r
                        }\r
                        else {\r
                                new_midi_event = new MidiEvent(\r
-                                               msg,\r
-                                               destination_tick + (event_tick - first_event_tick) * dest_ppq / midi_events_ppq\r
-                                               );\r
+                                       msg,\r
+                                       destination_tick + (event_tick - first_event_tick) * dest_ppq / midi_events_ppq\r
+                               );\r
                        }\r
-                       if( ! track.add(new_midi_event) ) continue;\r
+                       if( ! track.add(new_midi_event) )\r
+                               continue;\r
                        done = true;\r
-                       if( isTimeSignature(msg) ) has_time_signature = true;\r
+                       if( isTimeSignature(msg) )\r
+                               has_time_signature = true;\r
                }\r
                if( done ) {\r
                        if( has_time_signature )\r
-                               parent_model.fireTimeSignatureChanged();\r
-                       parent_model.fireTrackChanged( track );\r
+                               parent.fireTimeSignatureChanged();\r
+                       parent.fireTrackChanged( track );\r
                        int last_index = track.size() - 1;\r
                        int old_last_index = last_index - midi_events.length;\r
                        fireTableRowsInserted( old_last_index, last_index );\r
                }\r
                return done;\r
        }\r
-       //\r
-       // イベントの削除\r
-       //\r
-       public void removeMidiEvents( MidiEvent midi_events[] ) {\r
+       /**\r
+        * MIDIイベントを除去します。\r
+        * @param midi_events 除去するMIDIイベント\r
+        */\r
+       public void removeMidiEvents(MidiEvent midi_events[]) {\r
                boolean had_time_signature = false;\r
                for( MidiEvent midi_event : midi_events ) {\r
                        if( isTimeSignature(midi_event.getMessage()) )\r
@@ -2167,19 +2201,26 @@ class MidiTrackModel extends AbstractTableModel
                        track.remove(midi_event);\r
                }\r
                if( had_time_signature )\r
-                       parent_model.fireTimeSignatureChanged();\r
-               parent_model.fireTrackChanged( track );\r
+                       parent.fireTimeSignatureChanged();\r
+               parent.fireTrackChanged( track );\r
                int last_index = track.size() - 1;\r
                int old_last_index = last_index + midi_events.length;\r
                if( last_index < 0 ) last_index = 0;\r
                fireTableRowsDeleted( old_last_index, last_index );\r
        }\r
-       public void removeMidiEvents( ListSelectionModel sel_model ) {\r
-               removeMidiEvents( getMidiEvents(sel_model) );\r
-       }\r
-       //\r
-       // イベントの表示\r
-       //\r
+       /**\r
+        * 引数の選択内容が示すMIDIイベントを除去します。\r
+        * @param sel_model 選択内容\r
+        */\r
+       public void removeMidiEvents(ListSelectionModel sel_model) {\r
+               removeMidiEvents(getMidiEvents(sel_model));\r
+       }\r
+       private boolean isRhythmPart(int ch) { return (ch == 9); }\r
+       /**\r
+        * MIDIメッセージの内容を文字列で返します。\r
+        * @param msg MIDIメッセージ\r
+        * @return MIDIメッセージの内容を表す文字列\r
+        */\r
        public String msgToString(MidiMessage msg) {\r
                String str = "";\r
                if( msg instanceof ShortMessage ) {\r
@@ -2221,9 +2262,7 @@ class MidiTrackModel extends AbstractTableModel
                                        break;\r
                                case ShortMessage.PITCH_BEND:\r
                                {\r
-                                       int val = (\r
-                                                       (data1 & 0x7F) | ( (data2 & 0x7F) << 7 )\r
-                                                       );\r
+                                       int val = ((data1 & 0x7F) | ((data2 & 0x7F) << 7));\r
                                        str += ch_prefix + status_prefix + ( (val-8192) * 100 / 8191) + "% (" + val + ")";\r
                                }\r
                                break;\r
@@ -2292,9 +2331,9 @@ class MidiTrackModel extends AbstractTableModel
                        case 0x00: // Sequence Number (for MIDI Format 2)\r
                                if( msgdata.length == 2 ) {\r
                                        str += String.format(\r
-                                                       ": %04X",\r
-                                                       ((msgdata[0] & 0xFF) << 8) | (msgdata[1] & 0xFF)\r
-                                                       );\r
+                                               ": %04X",\r
+                                               ((msgdata[0] & 0xFF) << 8) | (msgdata[1] & 0xFF)\r
+                                       );\r
                                        break;\r
                                }\r
                                str += ": Size not 2 byte : data=(";\r
@@ -2319,11 +2358,11 @@ class MidiTrackModel extends AbstractTableModel
                        case 0x54: // SMPTE Offset\r
                                if( msgdata.length == 5 ) {\r
                                        str += ": "\r
-                                                       + (msgdata[0] & 0xFF) + ":"\r
-                                                       + (msgdata[1] & 0xFF) + ":"\r
-                                                       + (msgdata[2] & 0xFF) + "."\r
-                                                       + (msgdata[3] & 0xFF) + "."\r
-                                                       + (msgdata[4] & 0xFF);\r
+                                               + (msgdata[0] & 0xFF) + ":"\r
+                                               + (msgdata[1] & 0xFF) + ":"\r
+                                               + (msgdata[2] & 0xFF) + "."\r
+                                               + (msgdata[3] & 0xFF) + "."\r
+                                               + (msgdata[4] & 0xFF);\r
                                        break;\r
                                }\r
                                str += ": Size not 5 byte : data=(";\r
@@ -2382,8 +2421,7 @@ class MidiTrackModel extends AbstractTableModel
                        int manufacturer_id = (int)(msgdata[0] & 0xFF );\r
                        int device_id = (int)(msgdata[1] & 0xFF);\r
                        int model_id = (int)(msgdata[2] & 0xFF);\r
-                       String manufacturer_name\r
-                       = MIDISpec.getSysExManufacturerName(manufacturer_id);\r
+                       String manufacturer_name = MIDISpec.getSysExManufacturerName(manufacturer_id);\r
                        if( manufacturer_name == null ) {\r
                                manufacturer_name = String.format( "[Manufacturer code %02X]", msgdata[0] );\r
                        }\r
@@ -2622,45 +2660,58 @@ class MidiTrackModel extends AbstractTableModel
        }\r
 }\r
 \r
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// MIDI シーケンスデータのインデックス\r
-//\r
-// 拍子、テンポ、調だけを抜き出したトラックを保持するためのインデックス。\r
-//\r
-// 指定の MIDI tick の位置におけるテンポ、調、拍子を取得したり、\r
-// 拍子情報から MIDI tick と小節位置との間の変換を行うために使います。\r
-//\r
-class SequenceIndex {\r
-\r
-       private Track timesig_positions;\r
-       private Track tempo_positions;\r
-       private Track keysig_positions;\r
-       private Sequence tmp_seq;\r
-\r
-       public int       ticks_per_whole_note;\r
-\r
-       public SequenceIndex( Sequence source_seq ) {\r
+/**\r
+ *  MIDI シーケンスデータのtickインデックス\r
+ * <p>拍子、テンポ、調だけを抜き出したトラックを保持するためのインデックスです。\r
+ * 指定の MIDI tick の位置におけるテンポ、調、拍子を取得したり、\r
+ * 拍子情報から MIDI tick と小節位置との間の変換を行うために使います。\r
+ * </p>\r
+ */\r
+class SequenceTickIndex {\r
+       /**\r
+        * メタメッセージの種類:テンポ\r
+        */\r
+       public static final int TEMPO = 0;\r
+       /**\r
+        * メタメッセージの種類:拍子\r
+        */\r
+       public static final int TIME_SIGNATURE = 1;\r
+       /**\r
+        * メタメッセージの種類:調号\r
+        */\r
+       public static final int KEY_SIGNATURE = 2;\r
+       /**\r
+        * メタメッセージタイプ → メタメッセージの種類 変換マップ\r
+        */\r
+       private static final Map<Integer,Integer> INDEX_META_TO_TRACK =\r
+               new HashMap<Integer,Integer>() {\r
+                       {\r
+                               put(0x51, TEMPO);\r
+                               put(0x58, TIME_SIGNATURE);\r
+                               put(0x59, KEY_SIGNATURE);\r
+                       }\r
+               };\r
+       /**\r
+        * 新しいMIDIシーケンスデータのインデックスを構築します。\r
+        * @param sourceSequence 元のMIDIシーケンス\r
+        */\r
+       public SequenceTickIndex(Sequence sourceSequence) {\r
                try {\r
-                       int ppq = source_seq.getResolution();\r
-                       ticks_per_whole_note = ppq * 4;\r
-                       tmp_seq = new Sequence(Sequence.PPQ, ppq, 3);\r
-                       Track[] tmp_tracks = tmp_seq.getTracks();\r
-                       timesig_positions = tmp_tracks[0];\r
-                       tempo_positions = tmp_tracks[1];\r
-                       keysig_positions = tmp_tracks[2];\r
-                       Track[] tracks = source_seq.getTracks();\r
-                       for( Track tk : tracks ) {\r
+                       int ppq = sourceSequence.getResolution();\r
+                       wholeNoteTickLength = ppq * 4;\r
+                       tmpSequence = new Sequence(Sequence.PPQ, ppq, 3);\r
+                       tracks = tmpSequence.getTracks();\r
+                       Track[] sourceTracks = sourceSequence.getTracks();\r
+                       for( Track tk : sourceTracks ) {\r
                                for( int i_evt = 0 ; i_evt < tk.size(); i_evt++ ) {\r
                                        MidiEvent evt = tk.get(i_evt);\r
                                        MidiMessage msg = evt.getMessage();\r
-                                       if( ! (msg instanceof MetaMessage) ) continue;\r
-                                       switch( ((MetaMessage)msg).getType() ) {\r
-                                       case 0x51: tempo_positions.add(evt); break;\r
-                                       case 0x58: timesig_positions.add(evt); break;\r
-                                       case 0x59: keysig_positions.add(evt); break;\r
-                                       default: break;\r
-                                       }\r
+                                       if( ! (msg instanceof MetaMessage) )\r
+                                               continue;\r
+                                       MetaMessage metaMsg = (MetaMessage)msg;\r
+                                       int metaType = metaMsg.getType();\r
+                                       Integer metaIndex = INDEX_META_TO_TRACK.get(metaType);\r
+                                       if( metaIndex != null ) tracks[metaIndex].add(evt);\r
                                }\r
                        }\r
                }\r
@@ -2668,106 +2719,119 @@ class SequenceIndex {
                        e.printStackTrace();\r
                }\r
        }\r
-\r
-       private MetaMessage lastMessageAt( Track tk, long tick_position ) {\r
-               if( tk == null ) return null;\r
-               MidiEvent evt;\r
-               MetaMessage msg;\r
-               for( int i_evt = tk.size() - 1 ; i_evt >= 0; i_evt-- ) {\r
-                       evt = tk.get(i_evt);\r
-                       if( evt.getTick() > tick_position ) continue;\r
-                       msg = (MetaMessage)( evt.getMessage() );\r
-                       if( msg.getType() != 0x2F /* EOT */ ) return msg;\r
+       private Sequence tmpSequence;\r
+       /**\r
+        * このtickインデックスのタイミング解像度を返します。\r
+        * @return このtickインデックスのタイミング解像度\r
+        */\r
+       public int getResolution() {\r
+               return tmpSequence.getResolution();\r
+       }\r
+       private Track[] tracks;\r
+       /**\r
+        * 指定されたtick位置以前の最後のメタメッセージを返します。\r
+        * @param trackIndex メタメッセージの種類()\r
+        * @param tickPosition\r
+        * @return\r
+        */\r
+       public MetaMessage lastMetaMessageAt(int trackIndex, long tickPosition) {\r
+               Track track = tracks[trackIndex];\r
+               for(int eventIndex = track.size()-1 ; eventIndex >= 0; eventIndex--) {\r
+                       MidiEvent event = track.get(eventIndex);\r
+                       if( event.getTick() > tickPosition )\r
+                               continue;\r
+                       MetaMessage metaMessage = (MetaMessage)(event.getMessage());\r
+                       if( metaMessage.getType() == 0x2F /* skip EOT (last event) */ )\r
+                               continue;\r
+                       return metaMessage;\r
                }\r
                return null;\r
        }\r
-       public MetaMessage lastTimeSignatureAt( long tick_position ) {\r
-               return lastMessageAt( timesig_positions, tick_position );\r
-       }\r
-       public MetaMessage lastKeySignatureAt( long tick_position ) {\r
-               return lastMessageAt( keysig_positions, tick_position );\r
-       }\r
-       public MetaMessage lastTempoAt( long tick_position ) {\r
-               return lastMessageAt( tempo_positions, tick_position );\r
-       }\r
-       public int getResolution() { return tmp_seq.getResolution(); }\r
 \r
-       // MIDI tick を小節位置に変換\r
-       public int last_measure;\r
-       public int last_beat;\r
-       public int last_extra_tick;\r
-       public int ticks_per_beat;\r
-       public byte timesig_upper;\r
-       public byte timesig_lower_index;\r
-       int tickToMeasure(long tick_position) {\r
-               byte extra_beats = 0;\r
-               MidiEvent evt = null;\r
-               MidiMessage msg = null;\r
+       private int wholeNoteTickLength;\r
+       public int lastBeat;\r
+       public int lastExtraTick;\r
+       public byte timesigUpper;\r
+       public byte timesigLowerIndex;\r
+       /**\r
+        * tick位置を小節位置に変換します。\r
+        * @param tickPosition tick位置\r
+        * @return 小節位置\r
+        */\r
+       int tickToMeasure(long tickPosition) {\r
+               byte extraBeats = 0;\r
+               MidiEvent event = null;\r
+               MidiMessage message = null;\r
                byte[] data = null;\r
-               long current_tick = 0L;\r
-               long next_timesig_tick = 0L;\r
-               long prev_tick = 0L;\r
+               long currentTick = 0L;\r
+               long nextTimesigTick = 0L;\r
+               long prevTick = 0L;\r
                long duration = 0L;\r
-               last_measure = 0;\r
-               int measures, beats;\r
-               int i_evt = 0;\r
-               timesig_upper = 4;\r
-               timesig_lower_index = 2; // =log2(4)\r
-                               if( timesig_positions != null ) {\r
-                                       do {\r
-                                               // Check current time-signature event\r
-                                               if( i_evt < timesig_positions.size() ) {\r
-                                                       msg = (evt = timesig_positions.get(i_evt)).getMessage();\r
-                                                       current_tick = next_timesig_tick = evt.getTick();\r
-                                                       if(\r
-                                                                       current_tick > tick_position || (\r
-                                                                                       msg.getStatus() == 0xFF && ((MetaMessage)msg).getType() == 0x2F /* EOT */\r
-                                                                                       )\r
-                                                                       ) {\r
-                                                               current_tick = tick_position;\r
-                                                       }\r
-                                               }\r
-                                               else { // No event\r
-                                                       current_tick = next_timesig_tick = tick_position;\r
-                                               }\r
-                                               // Add measure from last event\r
-                                               //\r
-                                               ticks_per_beat = ticks_per_whole_note >> timesig_lower_index;\r
-                       duration = current_tick - prev_tick;\r
-                       beats = (int)( duration / ticks_per_beat );\r
-                       last_extra_tick = (int)(duration % ticks_per_beat);\r
-                       measures = beats / timesig_upper;\r
-                       extra_beats = (byte)(beats % timesig_upper);\r
-                       last_measure += measures;\r
-                       if( next_timesig_tick > tick_position ) break;  // Not reached to next time signature\r
-                       //\r
-                       // Reached to the next time signature, so get it.\r
-                       if( ( data = ((MetaMessage)msg).getData() ).length > 0 ) { // To skip EOT, check the data length.\r
-                               timesig_upper = data[0];\r
-                               timesig_lower_index = data[1];\r
-                       }\r
-                       if( current_tick == tick_position )  break;  // Calculation complete\r
-                       //\r
-                       // Calculation incomplete, so prepare for next\r
-                       //\r
-                       if( extra_beats > 0 ) {\r
+               int lastMeasure = 0;\r
+               int eventIndex = 0;\r
+               timesigUpper = 4;\r
+               timesigLowerIndex = 2; // =log2(4)\r
+               if( tracks[TIME_SIGNATURE] != null ) {\r
+                       do {\r
+                               // Check current time-signature event\r
+                               if( eventIndex < tracks[TIME_SIGNATURE].size() ) {\r
+                                       message = (event = tracks[TIME_SIGNATURE].get(eventIndex)).getMessage();\r
+                                       currentTick = nextTimesigTick = event.getTick();\r
+                                       if(currentTick > tickPosition || (message.getStatus() == 0xFF && ((MetaMessage)message).getType() == 0x2F /* EOT */)) {\r
+                                               currentTick = tickPosition;\r
+                                       }\r
+                               }\r
+                               else { // No event\r
+                                       currentTick = nextTimesigTick = tickPosition;\r
+                               }\r
+                               // Add measure from last event\r
                                //\r
-                               // Extra beats are treated as 1 measure\r
-                               last_measure++;\r
-                       }\r
-                       prev_tick = current_tick;\r
-                       i_evt++;\r
-                                       } while( true );\r
+                               int beatTickLength = wholeNoteTickLength >> timesigLowerIndex;\r
+                               duration = currentTick - prevTick;\r
+                               int beats = (int)( duration / beatTickLength );\r
+                               lastExtraTick = (int)(duration % beatTickLength);\r
+                               int measures = beats / timesigUpper;\r
+                               extraBeats = (byte)(beats % timesigUpper);\r
+                               lastMeasure += measures;\r
+                               if( nextTimesigTick > tickPosition ) break;  // Not reached to next time signature\r
+                               //\r
+                               // Reached to the next time signature, so get it.\r
+                               if( ( data = ((MetaMessage)message).getData() ).length > 0 ) { // To skip EOT, check the data length.\r
+                                       timesigUpper = data[0];\r
+                                       timesigLowerIndex = data[1];\r
                                }\r
-                               last_beat = extra_beats;\r
-                               return last_measure;\r
-       }\r
-\r
-       // 小節位置を MIDI tick に変換\r
-       public long measureToTick( int measure ) {\r
-               return measureToTick( measure, 0, 0 );\r
-       }\r
-       public long measureToTick( int measure, int beat, int extra_tick ) {\r
+                               if( currentTick == tickPosition )  break;  // Calculation complete\r
+                               //\r
+                               // Calculation incomplete, so prepare for next\r
+                               //\r
+                               if( extraBeats > 0 ) {\r
+                                       //\r
+                                       // Extra beats are treated as 1 measure\r
+                                       lastMeasure++;\r
+                               }\r
+                               prevTick = currentTick;\r
+                               eventIndex++;\r
+                       } while( true );\r
+               }\r
+               lastBeat = extraBeats;\r
+               return lastMeasure;\r
+       }\r
+       /**\r
+        * 小節位置を MIDI tick に変換します。\r
+        * @param measure 小節位置\r
+        * @return MIDI tick\r
+        */\r
+       public long measureToTick(int measure) {\r
+               return measureToTick(measure, 0, 0);\r
+       }\r
+       /**\r
+        * 指定の小節位置、拍、拍内tickを、そのシーケンス全体の MIDI tick に変換します。\r
+        * @param measure 小節位置\r
+        * @param beat 拍\r
+        * @param extraTick 拍内tick\r
+        * @return そのシーケンス全体の MIDI tick\r
+        */\r
+       public long measureToTick(int measure, int beat, int extraTick) {\r
                MidiEvent evt = null;\r
                MidiMessage msg = null;\r
                byte[] data = null;\r
@@ -2778,32 +2842,32 @@ class SequenceIndex {
                long estimated_ticks;\r
                int ticks_per_beat;\r
                int i_evt = 0;\r
-               timesig_upper = 4;\r
-               timesig_lower_index = 2; // =log2(4)\r
-                               do {\r
-                                       ticks_per_beat = ticks_per_whole_note >> timesig_lower_index;\r
-                                       estimated_ticks = ((measure * timesig_upper) + beat) * ticks_per_beat + extra_tick;\r
-                                       if( timesig_positions == null || i_evt > timesig_positions.size() ) {\r
-                                               return duration_sum + estimated_ticks;\r
-                                       }\r
-                                       msg = (evt = timesig_positions.get(i_evt)).getMessage();\r
-                                       if( msg.getStatus() == 0xFF && ((MetaMessage)msg).getType() == 0x2F /* EOT */ ) {\r
-                                               return duration_sum + estimated_ticks;\r
-                                       }\r
-                                       duration = (tick = evt.getTick()) - prev_tick;\r
-                                       if( duration >= estimated_ticks ) {\r
-                                               return duration_sum + estimated_ticks;\r
-                                       }\r
-                                       // Re-calculate measure (ignore extra beats/ticks)\r
-                                       measure -= ( duration / (ticks_per_beat * timesig_upper) );\r
-                                       duration_sum += duration;\r
-                                       //\r
-                                       // Get next time-signature\r
-                                       data = ( (MetaMessage)msg ).getData();\r
-                                       timesig_upper = data[0];\r
-                                       timesig_lower_index = data[1];\r
-                                       prev_tick = tick;\r
-                                       i_evt++;\r
-                               } while( true );\r
+               timesigUpper = 4;\r
+               timesigLowerIndex = 2; // =log2(4)\r
+               do {\r
+                       ticks_per_beat = wholeNoteTickLength >> timesigLowerIndex;\r
+                       estimated_ticks = ((measure * timesigUpper) + beat) * ticks_per_beat + extraTick;\r
+                       if( tracks[TIME_SIGNATURE] == null || i_evt > tracks[TIME_SIGNATURE].size() ) {\r
+                               return duration_sum + estimated_ticks;\r
+                       }\r
+                       msg = (evt = tracks[TIME_SIGNATURE].get(i_evt)).getMessage();\r
+                       if( msg.getStatus() == 0xFF && ((MetaMessage)msg).getType() == 0x2F /* EOT */ ) {\r
+                               return duration_sum + estimated_ticks;\r
+                       }\r
+                       duration = (tick = evt.getTick()) - prev_tick;\r
+                       if( duration >= estimated_ticks ) {\r
+                               return duration_sum + estimated_ticks;\r
+                       }\r
+                       // Re-calculate measure (ignore extra beats/ticks)\r
+                       measure -= ( duration / (ticks_per_beat * timesigUpper) );\r
+                       duration_sum += duration;\r
+                       //\r
+                       // Get next time-signature\r
+                       data = ( (MetaMessage)msg ).getData();\r
+                       timesigUpper = data[0];\r
+                       timesigLowerIndex = data[1];\r
+                       prev_tick = tick;\r
+                       i_evt++;\r
+               } while( true );\r
        }\r
 }\r
index 4e7c118..06f3ba0 100644 (file)
@@ -988,7 +988,7 @@ class MidiChannelButtonSelecter extends JList<Integer> {
 //\r
 ////////////////////////////////////\r
 class TickPositionModel implements ChangeListener {\r
-       private SequenceIndex seq_index;\r
+       private SequenceTickIndex seq_index;\r
        private boolean is_changing = false;\r
        public SpinnerNumberModel\r
        tick_model, measure_model, beat_model, extra_tick_model;\r
@@ -1017,9 +1017,9 @@ class TickPositionModel implements ChangeListener {
                                                        tick_model.getNumber().longValue()\r
                                                        )\r
                                        );\r
-                       beat_model.setValue( seq_index.last_beat + 1 );\r
+                       beat_model.setValue( seq_index.lastBeat + 1 );\r
                        is_changing = false;\r
-                       extra_tick_model.setValue( seq_index.last_extra_tick );\r
+                       extra_tick_model.setValue( seq_index.lastExtraTick );\r
                        return;\r
                }\r
                if( is_changing ) return;\r
@@ -1033,10 +1033,10 @@ class TickPositionModel implements ChangeListener {
        }\r
        // Methods\r
        //\r
-       public SequenceIndex getSequenceIndex() {\r
+       public SequenceTickIndex getSequenceIndex() {\r
                return seq_index;\r
        }\r
-       public void setSequenceIndex( SequenceIndex seq_index ) {\r
+       public void setSequenceIndex( SequenceTickIndex seq_index ) {\r
                this.seq_index = seq_index;\r
                extra_tick_model.setMaximum( 4 * seq_index.getResolution() - 1 );\r
        }\r
@@ -1307,48 +1307,44 @@ class TempoSelecter extends JPanel implements MouseListener {
        public void clear() { setTempo( DEFAULT_QPM ); }\r
 }\r
 \r
-/////////////////////////////\r
-//\r
-// Time Signature - 拍子選択\r
-//\r
-/////////////////////////////\r
-class TimeSignatureLabel extends JLabel {\r
-       private byte upper = -1;\r
-       private byte lower_index = -1;\r
-       public void setTimeSignature(byte upper, byte lower_index) {\r
-               if( this.upper == upper && this.lower_index == lower_index ) {\r
-                       return;\r
+/**\r
+ * 拍子選択ビュー\r
+ */\r
+class TimeSignatureSelecter extends JPanel {\r
+       SpinnerNumberModel upperTimesigSpinnerModel = new SpinnerNumberModel(4, 1, 32, 1);\r
+       private JSpinner upperTimesigSpinner = new JSpinner(\r
+               upperTimesigSpinnerModel\r
+       ) {\r
+               {\r
+                       setToolTipText("Time signature (upper digit) - 拍子の分子");\r
+               }\r
+       };\r
+       JComboBox<String> lowerTimesigCombobox = new JComboBox<String>() {\r
+               {\r
+                       setToolTipText("Time signature (lower digit) - 拍子の分母");\r
+                       for( int i=0; i<6; i++ ) addItem( "/" + (1<<i) );\r
+                       setSelectedIndex(2);\r
+               }\r
+       };\r
+       private class TimeSignatureLabel extends JLabel {\r
+               private byte upper = -1;\r
+               private byte lower_index = -1;\r
+               {\r
+                       setToolTipText("Time signature - 拍子");\r
+               }\r
+               public void setTimeSignature(byte upper, byte lower_index) {\r
+                       if( this.upper == upper && this.lower_index == lower_index ) {\r
+                               return;\r
+                       }\r
+                       setText("<html><font size=\"+1\">" + upper + "/" + (1 << lower_index) + "</font></html>");\r
                }\r
-               setText(\r
-                               "<html><font size=\"+1\">" +\r
-                                               upper + "/" + (1 << lower_index) +\r
-                                               "</font></html>"\r
-                               );\r
        }\r
-}\r
-class TimeSignatureSelecter extends JPanel {\r
-       SpinnerNumberModel upperTimesigSpinnerModel;\r
-       JSpinner upper_timesig_spinner;\r
-       JComboBox<String> lowerTimesigCombobox;\r
-       TimeSignatureLabel      timesig_value_label;\r
+       private TimeSignatureLabel timesigValueLabel = new TimeSignatureLabel();\r
        private boolean editable;\r
-\r
        public TimeSignatureSelecter() {\r
-               upperTimesigSpinnerModel = new SpinnerNumberModel( 4, 1, 32, 1 );\r
-               upper_timesig_spinner = new JSpinner( upperTimesigSpinnerModel );\r
-               upper_timesig_spinner.setToolTipText("Time signature (upper digit) - 拍子の分子");\r
-               lowerTimesigCombobox = new JComboBox<String>();\r
-               lowerTimesigCombobox.setToolTipText("Time signature (lower digit) - 拍子の分母");\r
-               for( int i=0; i<6; i++ ) {\r
-                       lowerTimesigCombobox.addItem( "/" + (1<<i) );\r
-               }\r
-               timesig_value_label = new TimeSignatureLabel();\r
-               timesig_value_label.setToolTipText("Time signature - 拍子");\r
-               lowerTimesigCombobox.setSelectedIndex(2);\r
-               //\r
-               add( upper_timesig_spinner );\r
-               add( lowerTimesigCombobox );\r
-               add( timesig_value_label );\r
+               add(upperTimesigSpinner);\r
+               add(lowerTimesigCombobox);\r
+               add(timesigValueLabel);\r
                setEditable(true);\r
        }\r
        public void clear() {\r
@@ -1378,7 +1374,7 @@ class TimeSignatureSelecter extends JPanel {
        public void setValue( byte upper, byte lower_index ) {\r
                upperTimesigSpinnerModel.setValue( upper );\r
                lowerTimesigCombobox.setSelectedIndex( lower_index );\r
-               timesig_value_label.setTimeSignature( upper, lower_index );\r
+               timesigValueLabel.setTimeSignature( upper, lower_index );\r
        }\r
        public void setValue( byte[] data ) {\r
                setValue( data[0], data[1] );\r
@@ -1386,13 +1382,11 @@ class TimeSignatureSelecter extends JPanel {
        public boolean isEditable() { return editable; }\r
        public void setEditable( boolean editable ) {\r
                this.editable = editable;\r
-               upper_timesig_spinner.setVisible(editable);\r
+               upperTimesigSpinner.setVisible(editable);\r
                lowerTimesigCombobox.setVisible(editable);\r
-               timesig_value_label.setVisible(!editable);\r
+               timesigValueLabel.setVisible(!editable);\r
                if( !editable ) {\r
-                       timesig_value_label.setTimeSignature(\r
-                                       getUpperByte(), getLowerByte()\r
-                                       );\r
+                       timesigValueLabel.setTimeSignature(getUpperByte(), getLowerByte());\r
                }\r
        }\r
 }\r
index 96da953..e630b0e 100644 (file)
@@ -2,6 +2,8 @@
 import java.awt.Color;\r
 import java.awt.event.ActionEvent;\r
 import java.awt.event.ActionListener;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
 \r
 import javax.sound.midi.InvalidMidiDataException;\r
 import javax.sound.midi.MetaEventListener;\r
@@ -51,163 +53,141 @@ enum TimeLabelFormat {
 /**\r
  * シーケンサの現在位置(分:秒)を表示するビュー\r
  */\r
-class TimeIndicator extends JPanel {\r
-       private TimeLabel timePositionLabel;\r
-       private TimeLabel timeLengthLabel;\r
+class TimeIndicator extends JPanel implements ChangeListener {\r
+       /**\r
+        * 時間(分:秒)表示ラベル\r
+        */\r
+       private static class TimeLabel extends JLabel {\r
+               /**\r
+                * 時間表示の形式\r
+                */\r
+               private TimeLabelFormat formatType;\r
+               /**\r
+                * 時間の値(秒)\r
+                */\r
+               private int valueInSec;\r
+               /**\r
+                * 時間表示ラベルを構築します。\r
+                * @param formatType 表示形式\r
+                */\r
+               public TimeLabel(TimeLabelFormat formatType) {\r
+                       super();\r
+                       if( (this.formatType = formatType) == TimeLabelFormat.POSITION ) {\r
+                               setFont( getFont().deriveFont(getFont().getSize2D() + 4) );\r
+                               setForeground( new Color(0x80,0x00,0x00) );\r
+                               setToolTipText("Time position - 現在位置(分:秒)");\r
+                       }\r
+                       else {\r
+                               setToolTipText("Time length - 曲の長さ(分:秒)");\r
+                       }\r
+                       setText(formatType.toTimeString(valueInSec));\r
+               }\r
+               /**\r
+                * 時間の値を秒単位で設定します。\r
+                * @param sec 秒単位の時間\r
+                */\r
+               public void setTimeInSecond(int sec) {\r
+                       if( valueInSec == sec )\r
+                               return;\r
+                       setText(formatType.toTimeString(sec));\r
+               }\r
+       }\r
+       private TimeLabel timePositionLabel = new TimeLabel(TimeLabelFormat.POSITION);\r
+       private TimeLabel timeLengthLabel = new TimeLabel(TimeLabelFormat.LENGTH);\r
        private SequencerTimeRangeModel model;\r
-       public TimeIndicator() {\r
-               timePositionLabel = new TimeLabel(TimeLabelFormat.POSITION);\r
-               timeLengthLabel = new TimeLabel(TimeLabelFormat.LENGTH);\r
+       /**\r
+        * シーケンサの現在位置(分:秒)を表示するビューを構築します。\r
+        * @param model スライダー用の時間範囲データモデル\r
+        */\r
+       public TimeIndicator(SequencerTimeRangeModel model) {\r
                setLayout(new BoxLayout(this, BoxLayout.X_AXIS));\r
                add(timePositionLabel);\r
                add(timeLengthLabel);\r
+               (this.model = model).addChangeListener(this);\r
        }\r
-       public TimeIndicator(SequencerTimeRangeModel model) {\r
-               this();\r
-               (this.model = model).addChangeListener(\r
-                       new ChangeListener() {\r
-                               public void stateChanged(ChangeEvent e) {\r
-                                       SequencerTimeRangeModel model = TimeIndicator.this.model;\r
-                                       timeLengthLabel.setTimeInSecond(model.getMaximum()/1000);\r
-                                       timePositionLabel.setTimeInSecond(model.getValue()/1000);\r
-                               }\r
-                       }\r
-               );\r
+       public void stateChanged(ChangeEvent e) {\r
+               timeLengthLabel.setTimeInSecond(model.getMaximum()/1000);\r
+               timePositionLabel.setTimeInSecond(model.getValue()/1000);\r
        }\r
 }\r
 \r
 /**\r
- * 時間(分:秒)表示ラベル\r
+ * 小節表示ビュー\r
  */\r
-class TimeLabel extends JLabel {\r
+class MeasureIndicator extends JPanel implements ChangeListener {\r
        /**\r
-        * 時間表示の形式\r
+        * 小節表示ラベル\r
         */\r
-       private TimeLabelFormat formatType;\r
-       /**\r
-        * 時間の値(秒)\r
-        */\r
-       private int valueInSec = -1;\r
-       /**\r
-        * 時間表示ラベルを構築します。\r
-        * @param formatType 表示形式\r
-        */\r
-       public TimeLabel(TimeLabelFormat formatType) {\r
-               super();\r
-               if( (this.formatType = formatType) == TimeLabelFormat.POSITION ) {\r
-                       float largePointSize = getFont().getSize2D() + 4;\r
-                       setFont( getFont().deriveFont(largePointSize) );\r
-                       setForeground( new Color(0x80,0x00,0x00) );\r
-                       setToolTipText("Time position - 現在位置(分:秒)");\r
+       private static class MeasureLabel extends JLabel {\r
+               private TimeLabelFormat formatType;\r
+               private int measure = -1;\r
+               private int beat = 0;\r
+               public MeasureLabel(TimeLabelFormat formatType) {\r
+                       if( (this.formatType = formatType) == TimeLabelFormat.POSITION ) {\r
+                               setFont( getFont().deriveFont(getFont().getSize2D() + 4) );\r
+                               setForeground( new Color(0x80,0x00,0x00) );\r
+                               setText( "0001:01" );\r
+                               setToolTipText("Measure:beat position - 何小節目:何拍目");\r
+                       }\r
+                       else {\r
+                               setText( "/0000" );\r
+                               setToolTipText("Measure length - 小節の数");\r
+                       }\r
                }\r
-               else {\r
-                       setToolTipText("Time length - 曲の長さ(分:秒)");\r
+               public void setMeasure(int measure) {\r
+                       setMeasure(measure,0);\r
+               }\r
+               public void setMeasure(int measure, int beat) {\r
+                       if( this.measure == measure && this.beat == beat ) {\r
+                               return;\r
+                       }\r
+                       this.beat = beat;\r
+                       this.measure = measure;\r
+                       if( formatType == TimeLabelFormat.LENGTH )\r
+                               setText(String.format("/%04d", measure));\r
+                       else\r
+                               setText(String.format("%04d:%02d", measure+1, beat+1));\r
                }\r
-               setText(formatType.toTimeString(0));\r
-       }\r
-       /**\r
-        * 時間の値をマイクロ秒単位で設定します。\r
-        * @param us マイクロ秒単位の時間\r
-        */\r
-       public void setTimeInMicrosecond(long us) {\r
-               setTimeInSecond( (int)(us/1000000) );\r
        }\r
+       private MeasureLabel measurePositionLabel = new MeasureLabel(TimeLabelFormat.POSITION);\r
+       private MeasureLabel measureLengthLabel = new MeasureLabel(TimeLabelFormat.LENGTH);\r
+       private SequencerTimeRangeModel model;\r
        /**\r
-        * 時間の値を秒単位で設定します。\r
-        * @param sec 秒単位の時間\r
+        * シーケンサの現在の小節位置を表示するビューを構築します。\r
+        * @param model スライダー用の時間範囲データモデル\r
         */\r
-       public void setTimeInSecond(int sec) {\r
-               if( valueInSec == sec )\r
-                       return;\r
-               if( (valueInSec = sec) < 0 )\r
-                       setText(null);\r
-               else\r
-                       setText(formatType.toTimeString(sec));\r
-       }\r
-}\r
-\r
-/**\r
- * 小節表示ビュー\r
- */\r
-class MeasureIndicator extends JPanel {\r
-       private SequencerTimeRangeModel model;\r
-       private MeasureLabel measurePositionLabel;\r
-       private MeasureLabel measureLengthLabel;\r
-       public MeasureIndicator() {\r
-               measurePositionLabel = new MeasureLabel(TimeLabelFormat.POSITION);\r
-               measureLengthLabel = new MeasureLabel(TimeLabelFormat.LENGTH);\r
-               setLayout( new BoxLayout( this, BoxLayout.X_AXIS ) );\r
-               add( measurePositionLabel );\r
-               add( measureLengthLabel );\r
-       }\r
        public MeasureIndicator(SequencerTimeRangeModel model) {\r
-               this();\r
-               (this.model = model).addChangeListener(new ChangeListener() {\r
-                       @Override\r
-                       public void stateChanged(ChangeEvent e) {\r
-                               SequencerTimeRangeModel model = MeasureIndicator.this.model;\r
-                               Sequencer sequencer = model.deviceManager.getSequencer();\r
-                               MidiSequenceModel seqModel =\r
-                                       model.deviceManager.timeRangeModel.getSequenceModel();\r
-                               SequenceIndex seqIndex = (\r
-                                       seqModel == null ? null : seqModel.getSequenceIndex()\r
-                               );\r
-                               if( ! sequencer.isRunning() || sequencer.isRecording() ) {\r
-                                       measureLengthLabel.setMeasure(\r
-                                               seqIndex == null ? 0 : seqIndex.tickToMeasure(\r
-                                                       sequencer.getTickLength()\r
-                                               )\r
-                                       );\r
-                               }\r
-                               if( seqIndex == null ) {\r
-                                       measurePositionLabel.setMeasure( 0, 0 );\r
-                               }\r
-                               else {\r
-                                       int measurePosition = seqIndex.tickToMeasure(\r
-                                               sequencer.getTickPosition()\r
-                                       );\r
-                                       measurePositionLabel.setMeasure(\r
-                                               measurePosition, seqIndex.last_beat\r
-                                       );\r
-                               }\r
-                       }\r
-               });\r
+               setLayout(new BoxLayout(this, BoxLayout.X_AXIS));\r
+               add(measurePositionLabel);\r
+               add(measureLengthLabel);\r
+               (this.model = model).addChangeListener(this);\r
        }\r
-}\r
-/**\r
- * 小節表示ラベル\r
- */\r
-class MeasureLabel extends JLabel {\r
-       private TimeLabelFormat formatType;\r
-       private int measure = -1;\r
-       private int beat = 0;\r
-       public MeasureLabel(TimeLabelFormat formatType) {\r
-               if( (this.formatType = formatType) == TimeLabelFormat.POSITION ) {\r
-                       float large_point_size = getFont().getSize2D() + 4;\r
-                       setFont( getFont().deriveFont(large_point_size) );\r
-                       setForeground( new Color(0x80,0x00,0x00) );\r
-                       setText( "0001:01" );\r
-                       setToolTipText("Measure:beat position - 何小節目:何拍目");\r
+       @Override\r
+       public void stateChanged(ChangeEvent e) {\r
+               Sequencer sequencer = model.deviceModelList.getSequencer();\r
+               MidiSequenceTableModel seqModel =\r
+                       model.deviceModelList.timeRangeModel.getSequenceTableModel();\r
+               SequenceTickIndex seqIndex = (\r
+                       seqModel == null ? null : seqModel.getSequenceTickIndex()\r
+               );\r
+               if( ! sequencer.isRunning() || sequencer.isRecording() ) {\r
+                       measureLengthLabel.setMeasure(\r
+                               seqIndex == null ? 0 : seqIndex.tickToMeasure(\r
+                                       sequencer.getTickLength()\r
+                               )\r
+                       );\r
                }\r
-               else {\r
-                       setText( "/0000" );\r
-                       setToolTipText("Measure length - 小節の数");\r
+               if( seqIndex == null ) {\r
+                       measurePositionLabel.setMeasure( 0, 0 );\r
                }\r
-       }\r
-       public void setMeasure(int measure) {\r
-               setMeasure(measure,0);\r
-       }\r
-       public void setMeasure(int measure, int beat) {\r
-               if( this.measure == measure && this.beat == beat ) {\r
-                       return;\r
+               else {\r
+                       int measurePosition = seqIndex.tickToMeasure(\r
+                               sequencer.getTickPosition()\r
+                       );\r
+                       measurePositionLabel.setMeasure(\r
+                               measurePosition, seqIndex.lastBeat\r
+                       );\r
                }\r
-               this.beat = beat;\r
-               if( (this.measure = measure) < 0 )\r
-                       setText( null );\r
-               else if( formatType == TimeLabelFormat.LENGTH )\r
-                       setText( String.format("/%04d", measure) );\r
-               else\r
-                       setText( String.format("%04d:%02d", measure+1, beat+1) );\r
        }\r
 }\r
 \r
@@ -275,116 +255,217 @@ class SpeedSlider extends JPanel implements ActionListener {
 }\r
 \r
 /**\r
- * 時間範囲データモデル\r
+ * スライダー用の時間範囲データモデル\r
  */\r
-class SequencerTimeRangeModel implements BoundedRangeModel {\r
-       static final int INTERVAL_MS = 20;\r
-       MidiDeviceManager deviceManager;\r
+class SequencerTimeRangeModel\r
+       implements BoundedRangeModel, MetaEventListener, ActionListener\r
+{\r
+       /**\r
+        * 更新インターバル [ミリ秒]\r
+        */\r
+       private static final int INTERVAL_MS = 20;\r
+       /**\r
+        * MIDIデバイスモデルリスト\r
+        */\r
+       MidiDeviceModelList deviceModelList;\r
+       /**\r
+        * シーケンサ\r
+        */\r
        private Sequencer sequencer;\r
-       javax.swing.Timer       timer;\r
-       private boolean valueIsAdjusting = false;\r
-       private EventListenerList listenerList = new EventListenerList();\r
+       /**\r
+        * このデータモデルをシーケンサに同期させるためのサンプリングタイマー\r
+        */\r
+       javax.swing.Timer timer = new javax.swing.Timer(INTERVAL_MS, this);\r
+       /**\r
+        * 開始終了アクション\r
+        */\r
        public StartStopAction startStopAction = new StartStopAction();\r
-       class StartStopAction extends AbstractAction {\r
-               Icon play_icon = new ButtonIcon(ButtonIcon.PLAY_ICON);\r
-               Icon pause_icon = new ButtonIcon(ButtonIcon.PAUSE_ICON);\r
+       /**\r
+        * 開始終了アクション\r
+        */\r
+       private class StartStopAction extends AbstractAction {\r
+               private Map<Boolean,Icon> iconMap = new HashMap<Boolean,Icon>() {\r
+                       {\r
+                               put(Boolean.FALSE, new ButtonIcon(ButtonIcon.PLAY_ICON));\r
+                               put(Boolean.TRUE, new ButtonIcon(ButtonIcon.PAUSE_ICON));\r
+                       }\r
+               };\r
                {\r
                        putValue(\r
                                SHORT_DESCRIPTION,\r
                                "Start/Stop recording or playing - 録音または再生の開始/停止"\r
                        );\r
-                       putValue( LARGE_ICON_KEY, play_icon );\r
-                       putValue( SELECTED_KEY, false );\r
+                       setRunning(false);\r
                }\r
+               @Override\r
                public void actionPerformed(ActionEvent event) {\r
-                       if( timer.isRunning() ) stop(); else start();\r
+                       if(timer.isRunning()) stop(); else start();\r
                }\r
-               public void setRunning(boolean is_running) {\r
-                       putValue( LARGE_ICON_KEY, is_running ? pause_icon : play_icon );\r
-                       putValue( SELECTED_KEY, is_running );\r
+               /**\r
+                * 開始されているかどうかを設定します。\r
+                * @param isRunning 開始されていたらtrue\r
+                */\r
+               public void setRunning(boolean isRunning) {\r
+                       putValue(LARGE_ICON_KEY, iconMap.get(isRunning));\r
+                       putValue(SELECTED_KEY, isRunning);\r
                }\r
        }\r
-       public Action move_backward_action = new AbstractAction() {\r
+       /**\r
+        * 1小節戻るアクション\r
+        */\r
+       public Action moveBackwardAction = new AbstractAction() {\r
                {\r
-                       putValue( SHORT_DESCRIPTION, "Move backward 1 measure - 1小節戻る" );\r
-                       putValue( LARGE_ICON_KEY, new ButtonIcon(ButtonIcon.BACKWARD_ICON) );\r
-               }\r
-               public void actionPerformed( ActionEvent event ) {\r
-                       moveMeasure(-1);\r
+                       putValue(SHORT_DESCRIPTION, "Move backward 1 measure - 1小節戻る");\r
+                       putValue(LARGE_ICON_KEY, new ButtonIcon(ButtonIcon.BACKWARD_ICON));\r
                }\r
+               @Override\r
+               public void actionPerformed(ActionEvent event) { moveMeasure(-1); }\r
        };\r
-       public Action move_forward_action = new AbstractAction() {\r
+       /**\r
+        *1小節進むアクション\r
+        */\r
+       public Action moveForwardAction = new AbstractAction() {\r
                {\r
-                       putValue( SHORT_DESCRIPTION, "Move forward 1 measure - 1小節進む" );\r
-                       putValue( LARGE_ICON_KEY, new ButtonIcon(ButtonIcon.FORWARD_ICON) );\r
-               }\r
-               public void actionPerformed( ActionEvent event ) {\r
-                       moveMeasure(1);\r
+                       putValue(SHORT_DESCRIPTION, "Move forward 1 measure - 1小節進む");\r
+                       putValue(LARGE_ICON_KEY, new ButtonIcon(ButtonIcon.FORWARD_ICON));\r
                }\r
+               @Override\r
+               public void actionPerformed(ActionEvent event) { moveMeasure(1); }\r
        };\r
-       public Action toggle_repeat_action = new AbstractAction() {\r
+       /**\r
+        * 小節位置を移動します。\r
+        * @param measureOffset 小節位置の移動量(負数も指定可)\r
+        */\r
+       private void moveMeasure(int measureOffset) {\r
+               if( measureOffset == 0 || seqModel == null )\r
+                       return;\r
+               SequenceTickIndex seqIndex = seqModel.getSequenceTickIndex();\r
+               int measurePosition = seqIndex.tickToMeasure(sequencer.getTickPosition());\r
+               long newTickPosition = seqIndex.measureToTick(measurePosition + measureOffset);\r
+               if( newTickPosition < 0 ) {\r
+                       // 下限\r
+                       newTickPosition = 0;\r
+               }\r
+               else {\r
+                       long tickLength = sequencer.getTickLength();\r
+                       if( newTickPosition > tickLength ) {\r
+                               // 上限\r
+                               newTickPosition = tickLength - 1;\r
+                       }\r
+               }\r
+               sequencer.setTickPosition(newTickPosition);\r
+               fireStateChanged();\r
+       }\r
+       /**\r
+        * 繰り返し再生ON/OFF切り替えアクション\r
+        */\r
+       public Action toggleRepeatAction = new AbstractAction() {\r
                {\r
-                       putValue( SHORT_DESCRIPTION, "Repeat - 繰り返し再生" );\r
-                       putValue( LARGE_ICON_KEY, new ButtonIcon(ButtonIcon.REPEAT_ICON) );\r
-                       putValue( SELECTED_KEY, false );\r
+                       putValue(SHORT_DESCRIPTION, "Repeat - 繰り返し再生");\r
+                       putValue(LARGE_ICON_KEY, new ButtonIcon(ButtonIcon.REPEAT_ICON));\r
+                       putValue(SELECTED_KEY, false);\r
                }\r
+               @Override\r
                public void actionPerformed(ActionEvent event) { }\r
        };\r
-       public SequencerTimeRangeModel( MidiDeviceManager device_manager ) {\r
-               this.deviceManager = device_manager;\r
-               this.sequencer = device_manager.getSequencer();\r
-               timer = new javax.swing.Timer(\r
-                       INTERVAL_MS,\r
-                       new ActionListener() {\r
-                               public void actionPerformed(ActionEvent e) {\r
-                                       if( ! valueIsAdjusting ) fireStateChanged();\r
-                               }\r
-                       }\r
-               );\r
-               timer.setCoalesce(true);\r
-               sequencer.addMetaEventListener(\r
-                       new MetaEventListener() {\r
-                               public void meta(MetaMessage msg) {\r
-                                       if( msg.getType() != 0x2F /* End-Of-Track */)\r
-                                               return;\r
-                                       timer.stop();\r
-                                       startStopAction.setRunning(false);\r
-                                       sequencer.setMicrosecondPosition(0);\r
-                                       if(\r
-                                               (Boolean)toggle_repeat_action.getValue( Action.SELECTED_KEY ) ||\r
-                                               SequencerTimeRangeModel.this.deviceManager.editorDialog.loadNext(1)\r
-                                       ) start();\r
-                                       else fireStateChanged();\r
-                               }\r
-                       }\r
-               );\r
+       /**\r
+        * 新しい {@link SequencerTimeRangeModel} を構築します。\r
+        * @param deviceModelList MIDIデバイスモデルリスト\r
+        */\r
+       public SequencerTimeRangeModel(MidiDeviceModelList deviceModelList) {\r
+               this.deviceModelList = deviceModelList;\r
+               sequencer = deviceModelList.getSequencer();\r
+               sequencer.addMetaEventListener(this);\r
        }\r
+       @Override\r
+       public void meta(MetaMessage msg) {\r
+               if( msg.getType() != 0x2F ) return;\r
+               /* End-Of-Track */\r
+               timer.stop();\r
+               startStopAction.setRunning(false);\r
+               sequencer.setMicrosecondPosition(0);\r
+               if(\r
+                       (Boolean)toggleRepeatAction.getValue(Action.SELECTED_KEY)\r
+                       ||\r
+                       deviceModelList.editorDialog.loadNext(1)\r
+               )\r
+                       start();\r
+               else\r
+                       fireStateChanged();\r
+       }\r
+       @Override\r
        public int getExtent() { return 0; }\r
-       public int getMaximum() { return (int)(getMicrosecondLength()/1000L); }\r
+       @Override\r
        public int getMinimum() { return 0; }\r
-       public int getValue() { return (int)(getMicrosecondPosition()/1000L); }\r
-       public boolean getValueIsAdjusting() { return valueIsAdjusting; }\r
-       public void setExtent(int new_extent) {}\r
-       public void setMaximum(int new_maximum) {}\r
-       public void setMinimum(int new_minimum) {}\r
+       private long getMicrosecondLength() {\r
+               //\r
+               // Sequencer.getMicrosecondLength() returns NEGATIVE value\r
+               //  when over 0x7FFFFFFF microseconds (== 35.7913941166666... minutes),\r
+               //  should be corrected when negative\r
+               //\r
+               long usLength = sequencer.getMicrosecondLength();\r
+               return usLength < 0 ? 0x100000000L + usLength : usLength ;\r
+       }\r
+       @Override\r
+       public int getMaximum() {\r
+               return (int)(getMicrosecondLength()/1000L);\r
+       }\r
+       private long getMicrosecondPosition() {\r
+               long usPosition = sequencer.getMicrosecondPosition();\r
+               return usPosition < 0 ? 0x100000000L + usPosition : usPosition ;\r
+       }\r
+       @Override\r
+       public int getValue() {\r
+               return (int)(getMicrosecondPosition()/1000L);\r
+       }\r
+       @Override\r
+       public void setExtent(int newExtent) {}\r
+       @Override\r
+       public void setMaximum(int newMaximum) {}\r
+       @Override\r
+       public void setMinimum(int newMinimum) {}\r
+       @Override\r
        public void setRangeProperties(int value, int extent, int min, int max, boolean adjusting) {\r
                sequencer.setMicrosecondPosition( 1000L * (long)value );\r
                valueIsAdjusting = adjusting;\r
                fireStateChanged();\r
        }\r
-       public void setValue(int new_value) {\r
-               sequencer.setMicrosecondPosition( 1000L * (long)new_value );\r
+       @Override\r
+       public void setValue(int newValue) {\r
+               sequencer.setMicrosecondPosition( 1000L * (long)newValue );\r
                fireStateChanged();\r
        }\r
+       /**\r
+        * 値調整中のときtrue\r
+        */\r
+       private boolean valueIsAdjusting = false;\r
+       @Override\r
+       public boolean getValueIsAdjusting() {\r
+               return valueIsAdjusting;\r
+       }\r
+       @Override\r
        public void setValueIsAdjusting(boolean b) {\r
                valueIsAdjusting = b;\r
        }\r
+       @Override\r
+       public void actionPerformed(ActionEvent e) {\r
+               if( ! valueIsAdjusting ) fireStateChanged();\r
+       }\r
+       /**\r
+        * イベントリスナーのリスト\r
+        */\r
+       protected EventListenerList listenerList = new EventListenerList();\r
+       @Override\r
        public void addChangeListener(ChangeListener listener) {\r
                listenerList.add(ChangeListener.class, listener);\r
        }\r
+       @Override\r
        public void removeChangeListener(ChangeListener listener) {\r
                listenerList.remove(ChangeListener.class, listener);\r
        }\r
+       /**\r
+        * 状態が変わったことをリスナーに通知します。\r
+        */\r
        public void fireStateChanged() {\r
                Object[] listeners = listenerList.getListenerList();\r
                for (int i = listeners.length-2; i>=0; i-=2) {\r
@@ -393,22 +474,11 @@ class SequencerTimeRangeModel implements BoundedRangeModel {
                        }\r
                }\r
        }\r
-       long getMicrosecondLength() {\r
-               //\r
-               // Sequencer.getMicrosecondLength() returns NEGATIVE value\r
-               //  when over 0x7FFFFFFF microseconds (== 35.7913941166666... minutes),\r
-               //  should be corrected when negative\r
-               //\r
-               long us_len = sequencer.getMicrosecondLength();\r
-               return us_len < 0 ? 0x100000000L + us_len : us_len ;\r
-       }\r
-       long getMicrosecondPosition() {\r
-               long us_pos = sequencer.getMicrosecondPosition();\r
-               return us_pos < 0 ? 0x100000000L + us_pos : us_pos ;\r
+       private MidiSequenceTableModel seqModel = null;\r
+       public MidiSequenceTableModel getSequenceTableModel() {\r
+               return seqModel;\r
        }\r
-       private MidiSequenceModel seq_model = null;\r
-       public MidiSequenceModel getSequenceModel() { return seq_model; }\r
-       public boolean setSequenceModel( MidiSequenceModel seq_model ) {\r
+       public boolean setSequenceModel(MidiSequenceTableModel seqModel) {\r
                //\r
                // javax.sound.midi:Sequencer.setSequence() のドキュメントにある\r
                // 「このメソッドは、Sequencer が閉じている場合でも呼び出すことができます。 」\r
@@ -416,53 +486,30 @@ class SequencerTimeRangeModel implements BoundedRangeModel {
                // 連鎖的に stop() が呼ばれるために IllegalStateException sequencer not open が出る。\r
                // この現象を回避するため、あらかじめチェックしてから setSequence() を呼び出している。\r
                //\r
-               if( seq_model != null || sequencer.isOpen() ) {\r
+               if( seqModel != null || sequencer.isOpen() ) {\r
                        try {\r
                                // Set new MIDI data\r
-                               sequencer.setSequence(\r
-                                               seq_model == null ? null : seq_model.getSequence()\r
-                                               );\r
+                               sequencer.setSequence(seqModel==null ? null : seqModel.getSequence());\r
                        } catch ( InvalidMidiDataException e ) {\r
                                e.printStackTrace();\r
                                return false;\r
                        }\r
                }\r
-               this.seq_model = seq_model;\r
+               this.seqModel = seqModel;\r
                fireStateChanged();\r
                return true;\r
        }\r
-       // 小節位置の相対移動\r
-       public void moveMeasure( int measure_offset ) {\r
-               if( measure_offset == 0 || seq_model == null ) return;\r
-               SequenceIndex seq_index = seq_model.getSequenceIndex();\r
-               long new_tick_pos =\r
-                               seq_index.measureToTick(\r
-                                               measure_offset + seq_index.tickToMeasure(\r
-                                                               sequencer.getTickPosition()\r
-                                                               )\r
-                                               );\r
-               if( new_tick_pos < 0 ) new_tick_pos = 0;\r
-               else {\r
-                       long tick_len = sequencer.getTickLength();\r
-                       if( new_tick_pos > tick_len ) new_tick_pos = tick_len - 1;\r
-               }\r
-               sequencer.setTickPosition( new_tick_pos );\r
-               fireStateChanged();\r
-       }\r
 \r
-       // 開始/終了\r
-       public boolean isStartable() {\r
-               return sequencer.isOpen() && sequencer.getSequence() != null ;\r
-       }\r
        public void start() {\r
-               if( ! isStartable() ) {\r
+               if( ! sequencer.isOpen() || sequencer.getSequence() == null ) {\r
                        startStopAction.setRunning(false);\r
                        return;\r
                }\r
                startStopAction.setRunning(true);\r
                timer.start();\r
-               if( deviceManager.isRecordable() ) {\r
-                       deviceManager.resetMicrosecondPosition();\r
+               if( deviceModelList.isRecordable() ) {\r
+                       for( MidiConnecterListModel model : deviceModelList )\r
+                               model.resetMicrosecondPosition();\r
                        System.gc();\r
                        sequencer.startRecording();\r
                }\r
@@ -472,7 +519,8 @@ class SequencerTimeRangeModel implements BoundedRangeModel {
                fireStateChanged();\r
        }\r
        public void stop() {\r
-               if( sequencer.isOpen() ) sequencer.stop();\r
+               if( sequencer.isOpen() )\r
+                       sequencer.stop();\r
                timer.stop();\r
                startStopAction.setRunning(false);\r
                fireStateChanged();\r
index 20a354a..481170c 100644 (file)
@@ -85,7 +85,7 @@ class AppletFrame extends JFrame implements AppletStub, AppletContext {
                applet.editorDialog.seqListModel.addTableModelListener(\r
                        new TableModelListener() {\r
                                public void tableChanged(TableModelEvent e) {\r
-                                       if( e.getColumn() == SequenceListModel.COLUMN_FILENAME )\r
+                                       if( e.getColumn() == SequenceListTableModel.COLUMN_FILENAME )\r
                                                setFilenameToTitle();\r
                                }\r
                        }\r
@@ -103,7 +103,7 @@ class AppletFrame extends JFrame implements AppletStub, AppletContext {
                applet.start();\r
        }\r
        private void setFilenameToTitle() {\r
-               MidiSequenceModel seqModel = applet.deviceManager.timeRangeModel.getSequenceModel();\r
+               MidiSequenceTableModel seqModel = applet.deviceManager.timeRangeModel.getSequenceTableModel();\r
                String filename = ( seqModel == null ? null : seqModel.getFilename() );\r
                String title = ChordHelperApplet.VersionInfo.NAME;\r
                if( filename != null && ! filename.isEmpty() ) {\r
index cbeacc4..0e90379 100644 (file)
@@ -36,73 +36,63 @@ import javax.swing.SpinnerNumberModel;
 import javax.swing.event.ChangeEvent;\r
 import javax.swing.event.ChangeListener;\r
 \r
-class NewSequenceDialog extends JDialog\r
-implements ActionListener\r
-{\r
-       Insets  zero_insets = new Insets(0,0,0,0);\r
-\r
+class NewSequenceDialog extends JDialog implements ActionListener {\r
+       public static final Insets      ZERO_INSETS = new Insets(0,0,0,0);\r
        JTextArea               chord_text;\r
        JTextField              seq_name_text;\r
        PPQSelectionComboBox    ppq_combo_box;\r
        TimeSignatureSelecter   timesig_selecter;\r
        TempoSelecter           tempo_selecter;\r
        MeasureSelecter measure_selecter;\r
-       JButton\r
-       add_new_button,\r
-       transpose_up_button, transpose_down_button, enharmonic_button,\r
-       random_chord_button, toggle_major_minor_button;\r
+       JButton add_new_button;\r
+       JButton transpose_up_button;\r
+       JButton transpose_down_button;\r
+       JButton enharmonic_button;\r
+       JButton random_chord_button;\r
+       JButton toggle_major_minor_button;\r
        JPanel new_file_panel;\r
        TrackSpecPanel track_spec_panel;\r
        JTabbedPane tabbed_pane;\r
        MidiEditor midi_editor;\r
 \r
-       public NewSequenceDialog( MidiEditor midi_editor ) {\r
+       public NewSequenceDialog(MidiEditor midi_editor) {\r
                this.midi_editor = midi_editor;\r
                setTitle("Generate new sequence - " + ChordHelperApplet.VersionInfo.NAME);\r
                tabbed_pane = new JTabbedPane();\r
-\r
                ppq_combo_box = new PPQSelectionComboBox();\r
                seq_name_text = new JTextField();\r
                timesig_selecter = new TimeSignatureSelecter();\r
                tempo_selecter = new TempoSelecter();\r
                measure_selecter = new MeasureSelecter();\r
-               String initial_string =\r
-                               "Key: C\nC G/B | Am Em/G | F C/E | Dm7 G7 C % | F G7 | Csus4 C\n";\r
-               chord_text = new JTextArea( initial_string, 18, 30 );\r
-               JScrollPane chord_text_scroll_area =\r
-                               new JScrollPane( (Component)chord_text );\r
-\r
-               add_new_button = new JButton(\r
-                               "Generate & Add to PlayList",\r
-                               new ButtonIcon(ButtonIcon.EJECT_ICON)\r
-                               );\r
-               add_new_button.setMargin(zero_insets);\r
+               chord_text = new JTextArea( "Key: C\nC G/B | Am Em/G | F C/E | Dm7 G7 C % | F G7 | Csus4 C\n", 18, 30 );\r
+               JScrollPane chord_text_scroll_area = new JScrollPane( (Component)chord_text );\r
+\r
+               add_new_button = new JButton("Generate & Add to PlayList", new ButtonIcon(ButtonIcon.EJECT_ICON));\r
+               add_new_button.setMargin(ZERO_INSETS);\r
                add_new_button.addActionListener(this);\r
                transpose_up_button = new JButton(" + Up ");\r
-               transpose_up_button.setMargin(zero_insets);\r
+               transpose_up_button.setMargin(ZERO_INSETS);\r
                transpose_up_button.addActionListener(this);\r
                transpose_down_button = new JButton(" - Down ");\r
-               transpose_down_button.setMargin(zero_insets);\r
+               transpose_down_button.setMargin(ZERO_INSETS);\r
                transpose_down_button.addActionListener(this);\r
                enharmonic_button = new JButton(" Enharmonic ");\r
-               enharmonic_button.setMargin(zero_insets);\r
+               enharmonic_button.setMargin(ZERO_INSETS);\r
                enharmonic_button.addActionListener(this);\r
                random_chord_button = new JButton("Randomize (Tempo, Time signature, Chord progression)");\r
-               random_chord_button.setMargin(zero_insets);\r
+               random_chord_button.setMargin(ZERO_INSETS);\r
                random_chord_button.addActionListener(this);\r
                toggle_major_minor_button = new JButton("Relative key");\r
-               toggle_major_minor_button.setMargin(zero_insets);\r
+               toggle_major_minor_button.setMargin(ZERO_INSETS);\r
                toggle_major_minor_button.addActionListener(this);\r
 \r
                JPanel sequence_name_panel = new JPanel();\r
-               sequence_name_panel.setLayout(\r
-                               new BoxLayout( sequence_name_panel, BoxLayout.LINE_AXIS )\r
-                               );\r
+               sequence_name_panel.setLayout(new BoxLayout(sequence_name_panel, BoxLayout.LINE_AXIS));\r
                sequence_name_panel.add( new JLabel("Sequence name:") );\r
                sequence_name_panel.add( seq_name_text );\r
 \r
                JPanel new_file_panel_2 = new JPanel();\r
-               new_file_panel_2.setLayout( new BoxLayout( new_file_panel_2, BoxLayout.LINE_AXIS ) );\r
+               new_file_panel_2.setLayout(new BoxLayout(new_file_panel_2, BoxLayout.LINE_AXIS));\r
                new_file_panel_2.add( new JLabel("Resolution in PPQ =") );\r
                new_file_panel_2.add( ppq_combo_box );\r
                new_file_panel_2.add( measure_selecter );\r
@@ -156,21 +146,15 @@ implements ActionListener
                dts.velocity = 127;\r
                track_spec_panel.addTrackSpec(dts);\r
                //\r
-               mts = new Music.MelodyTrackSpec(\r
-                               0, "Bass track", new Music.Range(36,48)\r
-                               );\r
+               mts = new Music.MelodyTrackSpec(0, "Bass track", new Music.Range(36,48));\r
                mts.is_bass = true;\r
                mts.velocity = 96;\r
                track_spec_panel.addTrackSpec(mts);\r
                //\r
-               mts =  new Music.MelodyTrackSpec(\r
-                               1, "Chord track", new Music.Range(60,72)\r
-                               );\r
+               mts =  new Music.MelodyTrackSpec(1, "Chord track", new Music.Range(60,72));\r
                track_spec_panel.addTrackSpec(mts);\r
                //\r
-               mts = new Music.MelodyTrackSpec(\r
-                               2, "Melody track", new Music.Range(60,84)\r
-                               );\r
+               mts = new Music.MelodyTrackSpec(2, "Melody track", new Music.Range(60,84));\r
                mts.random_melody = true;\r
                mts.beat_pattern = 0xFFFF;\r
                mts.continuous_beat_pattern = 0x820A;\r